]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RemoverUtil.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / util / RemoverUtil.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.layer0.util;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.Resource;
22 import org.simantics.db.WriteGraph;
23 import org.simantics.db.common.CommentMetadata;
24 import org.simantics.db.common.request.UniqueRead;
25 import org.simantics.db.common.request.WriteRequest;
26 import org.simantics.db.common.request.WriteResultRequest;
27 import org.simantics.db.common.utils.NameUtils;
28 import org.simantics.db.exception.DatabaseException;
29 import org.simantics.db.layer0.adapter.Remover;
30 import org.simantics.db.layer0.adapter.impl.AbstractRemover;
31 import org.simantics.db.layer0.adapter.impl.EntityRemover;
32 import org.simantics.db.layer0.exception.CannotRemoveException;
33 import org.simantics.db.layer0.internal.SimanticsInternal;
34 import org.simantics.utils.strings.EString;
35
36 /**
37  * Utility for working with {@link Remover}s.
38  * 
39  * @author Tuukka Lehtonen
40  * 
41  * @see Remover
42  * @see AbstractRemover
43  */
44 public final class RemoverUtil {
45
46         public static boolean canRemove(ReadGraph graph, Resource resource) throws DatabaseException {
47         Remover remover = RemoverUtil.getPossibleRemover(graph, resource);
48         if (remover != null) {
49             String problem = remover.canRemove(graph, new HashMap<>(4));
50             if (problem != null) return false;
51         }
52         return true;
53         }
54         
55     public static void remove(WriteGraph graph, Resource resource) throws DatabaseException {
56         if (!tryRemover(graph, resource))
57             EntityRemover.remove(graph, resource, true);
58     }
59
60     public static boolean tryRemover(WriteGraph graph, Resource resource) throws DatabaseException {
61         Remover remover = getPossibleRemover(graph, resource);
62         if (remover != null) {
63             remover.remove(graph);
64             return true;
65         }
66         return false;
67     }
68
69     /**
70      * @param graph
71      * @param resource
72      * @return
73      * @throws DatabaseException
74      * @since 1.6
75      */
76     public static Remover getPossibleRemover(ReadGraph graph, Resource resource) throws DatabaseException {
77         return graph.getPossibleAdapter(resource, Remover.class);
78     }
79
80     public static String testRemoval(final Collection<Resource> rs) throws DatabaseException {
81         return SimanticsInternal.getSession().syncRequest(new UniqueRead<String>() {
82             @Override
83             public String perform(ReadGraph graph) throws DatabaseException {
84                 return testRemoval(graph, rs, null);
85             }
86         });
87     }
88
89     public static String testRemoval(ReadGraph graph, final Collection<Resource> rs, List<Remover> removers) throws DatabaseException {
90         if (removers == null)
91             removers = new ArrayList<>(rs.size());
92
93         for (Resource r : rs) {
94             Remover remover = graph.getPossibleAdapter(r, Remover.class);
95             if (remover != null)
96                 removers.add(remover);
97         }
98
99         Map<Object, Object> aux = new HashMap<>();
100         List<String> errors = new ArrayList<>(2);
101         for (Remover remover : removers) {
102             String error = remover.canRemove(graph, aux);
103             if (error != null)
104                 errors.add(error);
105         }
106         if (!errors.isEmpty()) {
107             return EString.implode(errors);
108         }
109
110         return null;
111     }
112
113     public static String testRemoval(ReadGraph graph, final Collection<Resource> rs) throws DatabaseException {
114         return testRemoval(graph, rs, null);
115     }
116
117     public static String checkedRemoval(final Collection<Resource> rs) throws DatabaseException {
118         String problems = testRemoval(rs);
119         if (problems != null) return problems; 
120
121         SimanticsInternal.getSession().syncRequest(new WriteRequest() {
122
123             @Override
124             public void perform(WriteGraph graph) throws DatabaseException {
125                 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
126                 for (Resource r : rs) {
127                     // Add comment to change set.
128                     graph.addMetadata(cm.add("Removing " + r + "."));
129                 }
130
131                 List<Remover> removers = new ArrayList<>(rs.size());
132                 String error = testRemoval(graph, rs, removers);
133                 if (error != null)
134                     throw new CannotRemoveException(error);
135
136                 for (Remover remover : removers)
137                     remover.remove(graph);
138             }
139
140         });
141
142         return null;
143     }
144
145     /**
146      * Try to remove the provided collection of resources. Removal will commence
147      * only if all resources in the provided collection have the exact same
148      * principal types.
149      * 
150      * @param rs
151      *            collection of resources to remove in one go
152      * @return <code>true</code> if removal was successful or <code>false</code>
153      *         if the principal types of all resources in the provided
154      *         collection did not match
155      * @throws CannotRemoveException
156      *             if removal cannot commence because at least one of the
157      *             {@link Remover} instances adapted from the provided resource
158      *             set succeeds.
159      * @throws DatabaseException
160      */
161     public static boolean tryCollectionRemover(final Collection<Resource> rs) throws DatabaseException {
162         return SimanticsInternal.getSession().syncRequest(new WriteResultRequest<Boolean>() {
163             @Override
164             public Boolean perform(WriteGraph graph) throws DatabaseException {
165                 graph.markUndoPoint();
166
167                 List<Remover> removers = new ArrayList<>();
168                 Map<Remover, String> removedResources = new HashMap<>();
169                 for (Resource r : rs) {
170                     Remover remover = graph.getPossibleAdapter(r, Remover.class);
171                     if (remover != null) {
172                         removers.add(remover);
173                         removedResources.put(remover, NameUtils.getSafeName(graph, r, true));
174                     }
175                 }
176
177                 Map<Object, Object> aux = new HashMap<>();
178                 List<String> errors = new ArrayList<>(removers.size());
179                 for (Remover remover : removers) {
180                     String error = remover.canRemove(graph, aux);
181                     if (error != null)
182                         errors.add(error);
183                 }
184                 if (!errors.isEmpty()) {
185                     throw new CannotRemoveException(EString.implode(errors));
186                 }
187
188                 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
189                 for (Remover remover : removers) {
190                     remover.remove(graph);
191                     graph.addMetadata(cm.add("Removed " + removedResources.get(remover) + "."));
192                 }
193
194                 return true;
195             }
196         });
197     }
198
199 }