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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.layer0.util;
\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
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
41 * Utility for working with {@link Remover}s.
\r
43 * @author Tuukka Lehtonen
\r
46 * @see AbstractRemover
\r
48 public final class RemoverUtil {
\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
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
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
77 * @throws DatabaseException
\r
80 public static Remover getPossibleRemover(ReadGraph graph, Resource resource) throws DatabaseException {
\r
81 return graph.getPossibleAdapter(resource, Remover.class);
\r
84 public static String testRemoval(final Collection<Resource> rs) throws DatabaseException {
\r
85 return SimanticsInternal.getSession().syncRequest(new UniqueRead<String>() {
\r
87 public String perform(ReadGraph graph) throws DatabaseException {
\r
88 return testRemoval(graph, rs, null);
\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
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
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
110 if (!errors.isEmpty()) {
\r
111 return EString.implode(errors);
\r
117 public static String testRemoval(ReadGraph graph, final Collection<Resource> rs) throws DatabaseException {
\r
118 return testRemoval(graph, rs, null);
\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
125 SimanticsInternal.getSession().syncRequest(new WriteRequest() {
\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
135 List<Remover> removers = new ArrayList<Remover>(rs.size());
\r
136 String error = testRemoval(graph, rs, removers);
\r
138 throw new CannotRemoveException(error);
\r
140 for (Remover remover : removers)
\r
141 remover.remove(graph);
\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
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
163 * @throws DatabaseException
\r
165 public static boolean tryCollectionRemover(final Collection<Resource> rs) throws DatabaseException {
\r
166 return SimanticsInternal.getSession().syncRequest(new WriteResultRequest<Boolean>() {
\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
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
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
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
209 if (!errors.isEmpty()) {
\r
210 throw new CannotRemoveException(EString.implode(errors));
\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