/******************************************************************************* * 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.List; import java.util.Map; 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.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(); 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; } }); } }