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