1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.layer0.util;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.List;
21 import java.util.TreeSet;
23 import org.simantics.db.ReadGraph;
24 import org.simantics.db.Resource;
25 import org.simantics.db.WriteGraph;
26 import org.simantics.db.common.CommentMetadata;
27 import org.simantics.db.common.request.UniqueRead;
28 import org.simantics.db.common.request.WriteRequest;
29 import org.simantics.db.common.request.WriteResultRequest;
30 import org.simantics.db.common.utils.NameUtils;
31 import org.simantics.db.exception.DatabaseException;
32 import org.simantics.db.layer0.adapter.Remover;
33 import org.simantics.db.layer0.adapter.impl.AbstractRemover;
34 import org.simantics.db.layer0.adapter.impl.EntityRemover;
35 import org.simantics.db.layer0.exception.CannotRemoveException;
36 import org.simantics.db.layer0.internal.SimanticsInternal;
37 import org.simantics.utils.strings.AlphanumComparator;
38 import org.simantics.utils.strings.EString;
41 * Utility for working with {@link Remover}s.
43 * @author Tuukka Lehtonen
46 * @see AbstractRemover
48 public final class RemoverUtil {
50 public static boolean canRemove(ReadGraph graph, Resource resource) throws DatabaseException {
51 Remover remover = RemoverUtil.getPossibleRemover(graph, resource);
52 if (remover != null) {
53 String problem = remover.canRemove(graph, new HashMap<Object, Object>(4));
54 if (problem != null) return false;
59 public static void remove(WriteGraph graph, Resource resource) throws DatabaseException {
60 if (!tryRemover(graph, resource))
61 EntityRemover.remove(graph, resource, true);
64 public static boolean tryRemover(WriteGraph graph, Resource resource) throws DatabaseException {
65 Remover remover = getPossibleRemover(graph, resource);
66 if (remover != null) {
67 remover.remove(graph);
77 * @throws DatabaseException
80 public static Remover getPossibleRemover(ReadGraph graph, Resource resource) throws DatabaseException {
81 return graph.getPossibleAdapter(resource, Remover.class);
84 public static String testRemoval(final Collection<Resource> rs) throws DatabaseException {
85 return SimanticsInternal.getSession().syncRequest(new UniqueRead<String>() {
87 public String perform(ReadGraph graph) throws DatabaseException {
88 return testRemoval(graph, rs, null);
93 public static String testRemoval(ReadGraph graph, final Collection<Resource> rs, List<Remover> removers) throws DatabaseException {
95 removers = new ArrayList<Remover>(rs.size());
97 for (Resource r : rs) {
98 Remover remover = graph.getPossibleAdapter(r, Remover.class);
100 removers.add(remover);
103 Map<Object, Object> aux = new HashMap<Object, Object>();
104 List<String> errors = new ArrayList<String>(2);
105 for (Remover remover : removers) {
106 String error = remover.canRemove(graph, aux);
110 if (!errors.isEmpty()) {
111 return EString.implode(errors);
117 public static String testRemoval(ReadGraph graph, final Collection<Resource> rs) throws DatabaseException {
118 return testRemoval(graph, rs, null);
121 public static String checkedRemoval(final Collection<Resource> rs) throws DatabaseException {
122 String problems = testRemoval(rs);
123 if (problems != null) return problems;
125 SimanticsInternal.getSession().syncRequest(new WriteRequest() {
128 public void perform(WriteGraph graph) throws DatabaseException {
129 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
130 for (Resource r : rs) {
131 // Add comment to change set.
132 graph.addMetadata(cm.add("Removing " + r + "."));
135 List<Remover> removers = new ArrayList<Remover>(rs.size());
136 String error = testRemoval(graph, rs, removers);
138 throw new CannotRemoveException(error);
140 for (Remover remover : removers)
141 remover.remove(graph);
150 * Try to remove the provided collection of resources. Removal will commence
151 * only if all resources in the provided collection have the exact same
155 * collection of resources to remove in one go
156 * @return <code>true</code> if removal was successful or <code>false</code>
157 * if the principal types of all resources in the provided
158 * collection did not match
159 * @throws CannotRemoveException
160 * if removal cannot commence because at least one of the
161 * {@link Remover} instances adapted from the provided resource
163 * @throws DatabaseException
165 public static boolean tryCollectionRemover(final Collection<Resource> rs) throws DatabaseException {
166 return SimanticsInternal.getSession().syncRequest(new WriteResultRequest<Boolean>() {
168 public Boolean perform(WriteGraph graph) throws DatabaseException {
169 graph.markUndoPoint();
170 // 1. make sure that all resources are of the same type
171 Collection<Resource> principalTypes = null;
172 for (Resource r : rs) {
173 Collection<Resource> pts = graph.getPrincipalTypes(r);
174 if (principalTypes == null) {
175 principalTypes = pts;
176 } else if (!principalTypes.equals(pts)) {
178 StringBuilder sb = new StringBuilder();
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");
180 Set<Resource> differentTypes = new HashSet<Resource>();
181 Set<String> typeNames = new TreeSet<String>(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR);
182 for (Resource t : rs)
183 differentTypes.addAll(graph.getPrincipalTypes(t));
184 for (Resource t : differentTypes)
185 typeNames.add(NameUtils.getSafeName(graph, t));
186 for (String typeName : typeNames)
187 sb.append("\t").append(typeName).append("\n");
188 throw new CannotRemoveException(sb.toString());
192 List<Remover> removers = new ArrayList<Remover>();
193 Map<Remover, String> removedResources = new HashMap<Remover, String>();
194 for (Resource r : rs) {
195 Remover remover = graph.getPossibleAdapter(r, Remover.class);
196 if (remover != null) {
197 removers.add(remover);
198 removedResources.put(remover, NameUtils.getSafeName(graph, r, true));
202 Map<Object, Object> aux = new HashMap<Object, Object>();
203 List<String> errors = new ArrayList<String>(removers.size());
204 for (Remover remover : removers) {
205 String error = remover.canRemove(graph, aux);
209 if (!errors.isEmpty()) {
210 throw new CannotRemoveException(EString.implode(errors));
213 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
214 for (Remover remover : removers) {
215 remover.remove(graph);
216 graph.addMetadata(cm.add("Removed " + removedResources.get(remover) + "."));