/******************************************************************************* * 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.adapter.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.PasteHandlerAdapter; import org.simantics.db.layer0.internal.SimanticsInternal; import org.simantics.db.layer0.util.ClipboardUtils; import org.simantics.db.layer0.util.ModelTransferableGraphSource; import org.simantics.db.layer0.util.PasteEventHandler; import org.simantics.db.layer0.util.RemoverUtil; import org.simantics.db.layer0.util.SimanticsClipboard; import org.simantics.db.layer0.util.SimanticsClipboard.Representation; import org.simantics.db.layer0.util.SimanticsKeys; import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec; import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec.SeedSpecType; import org.simantics.graph.db.IImportAdvisor; import org.simantics.graph.db.IImportAdvisor2; import org.simantics.graph.db.IImportAdvisor2.RootInfo; import org.simantics.graph.db.TransferableGraphException; import org.simantics.graph.db.TransferableGraphSource; import org.simantics.graph.db.TransferableGraphs; import org.simantics.graph.representation.Identity; import org.simantics.graph.representation.Root; import org.simantics.graph.representation.TransferableGraph1; import org.simantics.graph.representation.TransferableGraphUtils; import org.simantics.layer0.Layer0; public class DefaultPasteHandler extends PasteHandlerAdapter { protected Resource resource; public DefaultPasteHandler(Resource resource) { this.resource = resource; } public static void defaultExecute(TransferableGraph1 tg, Resource resource, IImportAdvisor advisor) throws DatabaseException, TransferableGraphException { TransferableGraphs.importGraph1(SimanticsInternal.getSession(), tg, advisor); } public static void defaultExecute(WriteGraph graph, TransferableGraph1 tg, Resource resource, IImportAdvisor advisor) throws DatabaseException { TransferableGraphs.importGraph1(graph, tg, advisor); } public void execute(WriteGraph graph, TransferableGraph1 tg, Resource resource, IImportAdvisor advisor) throws DatabaseException { defaultExecute(graph, tg, resource, advisor); } /** * Override this in your inherited class if post processing is done. */ public void onPasteBegin(WriteGraph graph) throws DatabaseException { } /** * Override this in your inherited class if post processing is done * advisor.getTarget() returns an object under which data is copied * advisor.getRoot() returns the object which have been pasted. * @param representations TODO */ public void onPaste(WriteGraph graph, IImportAdvisor2 advisor, Set representations) throws DatabaseException { } /** * Override this in your inherited class if post processing is done. */ public void onPasteEnd(WriteGraph graph) throws DatabaseException { } public IImportAdvisor2 getAdvisor(ReadGraph graph, TransferableGraph1 tg, Resource target, PasteEventHandler handler) throws DatabaseException { Collection roots = TransferableGraphUtils.getRoots(tg); if(roots.size() == 1) { Root root = (Root)roots.iterator().next().definition; Resource type = graph.getPossibleResource(root.type); ImportAdvisorFactory factory = graph.getPossibleAdapter(type, ImportAdvisorFactory.class); if(factory != null) { if(handler != null) return handler.createAdvisor(graph, factory, target); else return factory.create(graph, target, Collections.emptyMap()); } } return new DefaultPasteImportAdvisor(target); } public Collection pasteObject(WriteGraph graph, Set object, PasteEventHandler handler) throws DatabaseException { Collection result = new ArrayList<>(); TransferableGraphSource tgs = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH_SOURCE); if (tgs != null) { TransferableGraph1 tg = TransferableGraphs.create(graph, tgs); IImportAdvisor2 advisor = getAdvisor(graph, tg, resource, handler); execute(graph, tg, resource, advisor); Collection roots = advisor.getRootInfo(); if(handler != null) { for(RootInfo r : roots) handler.postProcess(graph, r.resource); } onPaste(graph, advisor, object); if(tgs instanceof ModelTransferableGraphSource) { ModelTransferableGraphSource mtgs = (ModelTransferableGraphSource)tgs; loop: for(SeedSpec spec : mtgs.getConfiguration().seeds) { if(SeedSpecType.SPECIAL_ROOT.equals(spec.specType)) continue; for(RootInfo info : roots) { if(spec.name.equals(info.root.name)) { result.add(info.resource); continue loop; } } // Fallback result.clear(); result.addAll(advisor.getRoots()); break; } } else { result.addAll(advisor.getRoots()); } } return result; } @Override public Collection pasteFromClipboard(WriteGraph graph, SimanticsClipboard clipboard, PasteEventHandler handler) throws DatabaseException { Collection result = new ArrayList<>(); // Check if root resource is allowed for pasting checkIfRootAllowsPaste(graph); Map hints = Collections.singletonMap(ClipboardUtils.HINT_TARGET_RESOURCE, resource); onPasteBegin(graph); final Set cuts = new HashSet<>(); for(Set object : clipboard.getContents()) { Collection cut = ClipboardUtils.accept(object, SimanticsKeys.KEY_CUT_RESOURCES); TransferableGraphSource tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH_SOURCE, hints); if(tg != null) { result.addAll(pasteObject(graph, object, handler)); if (cut != null) cuts.addAll(cut); } else { Layer0 L0 = Layer0.getInstance(graph); for(Resource r : cut) { graph.deny(r, L0.PartOf); graph.claim(resource, L0.ConsistsOf, L0.PartOf, r); result.add(r); } } } onPasteEnd(graph); if(!cuts.isEmpty()) { for (Resource cut : cuts) RemoverUtil.remove(graph, cut); } return result; } protected void checkIfRootAllowsPaste(ReadGraph graph) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); // check if root is published Boolean published = graph.getPossibleRelatedValue(resource, L0.Entity_published); if (published != null && published) { throw new DatabaseException("Target resource " + NameUtils.getSafeName(graph, resource) + " is published and does not allow paste."); } } @SuppressWarnings("rawtypes") @Override public Object getAdapter(Class adapter) { if(Resource.class == adapter) return resource; return null; } }