X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Futil%2FRemoverUtil.java;fp=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Futil%2FRemoverUtil.java;h=bfa1b98422e9598ad2035e100dbb4321ef510c44;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RemoverUtil.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RemoverUtil.java new file mode 100644 index 000000000..bfa1b9842 --- /dev/null +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RemoverUtil.java @@ -0,0 +1,224 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.db.layer0.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.CommentMetadata; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.request.WriteResultRequest; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.Remover; +import org.simantics.db.layer0.adapter.impl.AbstractRemover; +import org.simantics.db.layer0.adapter.impl.EntityRemover; +import org.simantics.db.layer0.exception.CannotRemoveException; +import org.simantics.db.layer0.internal.SimanticsInternal; +import org.simantics.utils.strings.AlphanumComparator; +import org.simantics.utils.strings.EString; + +/** + * Utility for working with {@link Remover}s. + * + * @author Tuukka Lehtonen + * + * @see Remover + * @see AbstractRemover + */ +public final class RemoverUtil { + + public static boolean canRemove(ReadGraph graph, Resource resource) throws DatabaseException { + Remover remover = RemoverUtil.getPossibleRemover(graph, resource); + if (remover != null) { + String problem = remover.canRemove(graph, new HashMap(4)); + if (problem != null) return false; + } + return true; + } + + public static void remove(WriteGraph graph, Resource resource) throws DatabaseException { + if (!tryRemover(graph, resource)) + EntityRemover.remove(graph, resource, true); + } + + public static boolean tryRemover(WriteGraph graph, Resource resource) throws DatabaseException { + Remover remover = getPossibleRemover(graph, resource); + if (remover != null) { + remover.remove(graph); + return true; + } + return false; + } + + /** + * @param graph + * @param resource + * @return + * @throws DatabaseException + * @since 1.6 + */ + public static Remover getPossibleRemover(ReadGraph graph, Resource resource) throws DatabaseException { + return graph.getPossibleAdapter(resource, Remover.class); + } + + public static String testRemoval(final Collection rs) throws DatabaseException { + return SimanticsInternal.getSession().syncRequest(new UniqueRead() { + @Override + public String perform(ReadGraph graph) throws DatabaseException { + return testRemoval(graph, rs, null); + } + }); + } + + public static String testRemoval(ReadGraph graph, final Collection rs, List removers) throws DatabaseException { + if (removers == null) + removers = new ArrayList(rs.size()); + + for (Resource r : rs) { + Remover remover = graph.getPossibleAdapter(r, Remover.class); + if (remover != null) + removers.add(remover); + } + + Map aux = new HashMap(); + List errors = new ArrayList(2); + for (Remover remover : removers) { + String error = remover.canRemove(graph, aux); + if (error != null) + errors.add(error); + } + if (!errors.isEmpty()) { + return EString.implode(errors); + } + + return null; + } + + public static String testRemoval(ReadGraph graph, final Collection rs) throws DatabaseException { + return testRemoval(graph, rs, null); + } + + public static String checkedRemoval(final Collection rs) throws DatabaseException { + String problems = testRemoval(rs); + if (problems != null) return problems; + + SimanticsInternal.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + for (Resource r : rs) { + // Add comment to change set. + graph.addMetadata(cm.add("Removing " + r + ".")); + } + + List removers = new ArrayList(rs.size()); + String error = testRemoval(graph, rs, removers); + if (error != null) + throw new CannotRemoveException(error); + + for (Remover remover : removers) + remover.remove(graph); + } + + }); + + return null; + } + + /** + * Try to remove the provided collection of resources. Removal will commence + * only if all resources in the provided collection have the exact same + * principal types. + * + * @param rs + * collection of resources to remove in one go + * @return true if removal was successful or false + * if the principal types of all resources in the provided + * collection did not match + * @throws CannotRemoveException + * if removal cannot commence because at least one of the + * {@link Remover} instances adapted from the provided resource + * set succeeds. + * @throws DatabaseException + */ + public static boolean tryCollectionRemover(final Collection rs) throws DatabaseException { + return SimanticsInternal.getSession().syncRequest(new WriteResultRequest() { + @Override + public Boolean perform(WriteGraph graph) throws DatabaseException { + graph.markUndoPoint(); + // 1. make sure that all resources are of the same type + Collection principalTypes = null; + for (Resource r : rs) { + Collection pts = graph.getPrincipalTypes(r); + if (principalTypes == null) { + principalTypes = pts; + } else if (!principalTypes.equals(pts)) { + //return false; + StringBuilder sb = new StringBuilder(); + 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"); + Set differentTypes = new HashSet(); + Set typeNames = new TreeSet(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + for (Resource t : rs) + differentTypes.addAll(graph.getPrincipalTypes(t)); + for (Resource t : differentTypes) + typeNames.add(NameUtils.getSafeName(graph, t)); + for (String typeName : typeNames) + sb.append("\t").append(typeName).append("\n"); + throw new CannotRemoveException(sb.toString()); + } + } + + List removers = new ArrayList(); + Map removedResources = new HashMap(); + for (Resource r : rs) { + Remover remover = graph.getPossibleAdapter(r, Remover.class); + if (remover != null) { + removers.add(remover); + removedResources.put(remover, NameUtils.getSafeName(graph, r, true)); + } + } + + Map aux = new HashMap(); + List errors = new ArrayList(removers.size()); + for (Remover remover : removers) { + String error = remover.canRemove(graph, aux); + if (error != null) + errors.add(error); + } + if (!errors.isEmpty()) { + throw new CannotRemoveException(EString.implode(errors)); + } + + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + for (Remover remover : removers) { + remover.remove(graph); + graph.addMetadata(cm.add("Removed " + removedResources.get(remover) + ".")); + } + + return true; + } + }); + } + +}