--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2013 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.annotation.ui;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.simantics.Simantics;\r
+import org.simantics.annotation.ontology.AnnotationResource;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.util.URIStringUtils;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.UnaryRead;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.Layer0Utils;\r
+import org.simantics.db.layer0.util.RemoverUtil;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.VariableBuilder;\r
+import org.simantics.db.layer0.variable.VariableMap;\r
+import org.simantics.db.layer0.variable.VariableMapImpl;\r
+import org.simantics.db.layer0.variable.Variables;\r
+import org.simantics.db.service.VirtualGraphSupport;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.modeling.ModelingUtils;\r
+import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;\r
+import org.simantics.scenegraph.utils.NodeUtil;\r
+import org.simantics.scl.reflection.annotations.SCLValue;\r
+import org.simantics.scl.runtime.function.FunctionImpl1;\r
+import org.simantics.scl.runtime.tuple.Tuple;\r
+import org.simantics.scl.runtime.tuple.Tuple2;\r
+import org.simantics.scl.runtime.tuple.Tuple3;\r
+import org.simantics.utils.datastructures.Pair;\r
+import org.simantics.utils.strings.AlphanumComparator;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+import org.simantics.views.swt.client.base.ISWTViewNode;\r
+import org.simantics.views.swt.client.impl.SWTExplorer;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+/**\r
+ * @author Antti Villberg\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class SCL {\r
+\r
+ final public static String EMPTY = "";\r
+ final public static String MAPPED = "Mapped";\r
+ final public static String SELECTED = "Selected";\r
+\r
+ final public static String NO_ANNOTATIONS = "No annotations";\r
+\r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> [(String, Resource)]")\r
+ public static List<Tuple> availableSources(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {\r
+ \r
+ Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);\r
+ if (selection == null)\r
+ return Collections.emptyList();\r
+ List<Tuple3> sources = availableSourcesImpl(graph, selection);\r
+ if (sources.isEmpty())\r
+ return Collections.emptyList();\r
+ List<Tuple> result = new ArrayList<Tuple>(sources.size());\r
+ for(Tuple3 anno : sources) {\r
+ result.add(new Tuple2(anno.get(0),""));\r
+ }\r
+ return result;\r
+ \r
+ }\r
+\r
+ /**\r
+ * Gathers available annotation sources and always returns them in the same\r
+ * order.\r
+ * \r
+ * @param graph\r
+ * @param selection\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ private static List<Tuple3> availableSourcesImpl(ReadGraph graph, Variable selection) throws DatabaseException {\r
+ List<Variable> vars = gatherSourceVariables(graph, selection);\r
+ if (vars.isEmpty())\r
+ return Collections.emptyList();\r
+ int size = vars.size();\r
+ ArrayList<Tuple3> result = new ArrayList<Tuple3>(size);\r
+ result.add(new Tuple3(sourceLabel(graph, vars.get(0)), SELECTED, vars.get(0)));\r
+ for (int i = 1; i < size; ++i) {\r
+ Variable v = vars.get(i);\r
+ result.add(new Tuple3(sourceLabel(graph, v), MAPPED, v));\r
+ }\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Gathers variables starting from source in a particular order each time.\r
+ * First configuration components and second diagram elements.\r
+ * \r
+ * @param graph\r
+ * @param source\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ private static List<Variable> gatherSourceVariables(ReadGraph graph, Variable source) throws DatabaseException {\r
+ Resource represents = source.getPossibleRepresents(graph);\r
+ if (represents == null)\r
+ return Collections.singletonList(source);\r
+\r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ ArrayList<Variable> result = new ArrayList<Variable>(4);\r
+ for (Resource r : ModelingUtils.getElementCorrespondendences(graph, represents))\r
+ addPossibleVariable(graph, r, result);\r
+ for(Resource r : graph.getObjects(represents, MOD.DiagramToComposite))\r
+ addPossibleVariable(graph, r, result);\r
+ result.add(source);\r
+ for(Resource r : graph.getObjects(represents, MOD.ComponentToElement))\r
+ addPossibleVariable(graph, r, result);\r
+ for(Resource r : graph.getObjects(represents, MOD.CompositeToDiagram))\r
+ addPossibleVariable(graph, r, result);\r
+ return result;\r
+ }\r
+\r
+ private static void addPossibleVariable(ReadGraph graph, Resource r, List<Variable> result) throws DatabaseException {\r
+ Variable v = Variables.getPossibleVariable(graph, r);\r
+ if (v != null)\r
+ result.add(v);\r
+ }\r
+\r
+ private static String sourceLabel(ReadGraph graph, Variable variable) throws DatabaseException {\r
+ Resource represents = variable.getPossibleRepresents(graph);\r
+ if(represents != null) {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ if(graph.isInstanceOf(represents, DIA.Diagram)) return "Diagram";\r
+ else if(graph.isInstanceOf(represents, DIA.Flag)) return "Flag Element";\r
+ else if(graph.isInstanceOf(represents, DIA.RouteGraphConnection)) return "Connection Element";\r
+ else if(graph.isInstanceOf(represents, DIA.Monitor)) return "Monitor Element";\r
+ else if(graph.isInstanceOf(represents, DIA.Element)) return "Diagram Element";\r
+ else return variable.getName(graph);\r
+ } else {\r
+ return variable.getURI(graph);\r
+ }\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ private static <T> T selectedSource(ReadGraph graph, Variable selection) throws DatabaseException {\r
+\r
+ String name = selectedSourceName(graph, selection);\r
+ for(Tuple tuple : availableSourcesImpl(graph, selection)) {\r
+ if(tuple.get(1).equals(name)) return (T)tuple.get(2);\r
+ }\r
+ \r
+ return null;\r
+ \r
+ }\r
+ \r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+ public static String selectedSource(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+ String name = selectedSourceName(graph, selection);\r
+ for(Tuple tuple : availableSourcesImpl(graph, selection)) {\r
+ if(tuple.get(1).equals(name)) return (String)tuple.get(0);\r
+ }\r
+ \r
+ return EMPTY;\r
+\r
+ }\r
+\r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+ public static Object selectedSourceModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ return new FunctionImpl1<Object, Object>() {\r
+\r
+ @Override\r
+ public Object apply(Object sourceKey) {\r
+ try {\r
+ Session s = Simantics.getSession();\r
+ VirtualGraph vg = s.getService(VirtualGraphSupport.class).getWorkspacePersistent("preferences");\r
+ s.syncRequest(new SetDefaultAnnotationSourceRequest(vg, context, sourceKey));\r
+ } catch (DatabaseException e) {\r
+ Activator.getDefault().getLog().log(\r
+ new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to update default annotation source, see exception for details.", e));\r
+ }\r
+ return null;\r
+ }\r
+\r
+ };\r
+\r
+ }\r
+\r
+ private static class SetDefaultAnnotationSourceRequest extends WriteRequest {\r
+\r
+ private Variable context;\r
+ private Object sourceKey;\r
+\r
+ public SetDefaultAnnotationSourceRequest(VirtualGraph vg, Variable context, Object sourceKey) {\r
+ super(vg);\r
+ this.context = context;\r
+ this.sourceKey = sourceKey;\r
+ }\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ AnnotationResource ANNO = AnnotationResource.getInstance(graph);\r
+ Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+ Resource model = Variables.getPossibleIndexRoot(graph, selection);\r
+\r
+ List<Tuple3> annos = availableSourcesImpl(graph, selection);\r
+ for(Tuple3 anno : annos) {\r
+ if(anno.get(0).equals(sourceKey)) {\r
+ graph.claimLiteral(model, ANNO.DefaultAnnotationSource, (String)anno.get(1), Bindings.STRING);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ private static final Comparator<? super Tuple3> AVAILABLE_ANNOTATION_SORTER = new Comparator<Tuple3>() {\r
+ @Override\r
+ public int compare(Tuple3 o1, Tuple3 o2) {\r
+ String s1 = (String) o1.c2;\r
+ String s2 = (String) o2.c2;\r
+ return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(s1, s2);\r
+ }\r
+ };\r
+\r
+ /**\r
+ * @param graph\r
+ * @param selection\r
+ * @return list of (Variable annotation, Resource annotation, String name) tuples\r
+ * @throws DatabaseException\r
+ */\r
+ private static Collection<Tuple3> availableAnnotationsImpl(ReadGraph graph, Variable selection) throws DatabaseException {\r
+\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ AnnotationResource ANNO = AnnotationResource.getInstance(graph);\r
+\r
+ selection = selectedSource(graph, selection);\r
+ \r
+ ArrayList<Tuple3> result = new ArrayList<Tuple3>();\r
+ for (Variable child : selection.getChildren(graph)) {\r
+ Resource represents = child.getPossibleRepresents(graph);\r
+ if (represents != null && graph.isInstanceOf(represents, ANNO.Annotation)) {\r
+ String name = graph.getPossibleRelatedValue(represents, L0.HasName);\r
+ if (name != null)\r
+ result.add(new Tuple3(child, represents, name));\r
+ }\r
+ }\r
+ for (Variable property : selection.getProperties(graph)) {\r
+ Resource propertyResource = property.getPossibleRepresents(graph);\r
+ if (propertyResource != null && graph.isInstanceOf(propertyResource, ANNO.Annotation)) {\r
+ String propertyName = property.getName(graph);\r
+ result.add(new Tuple3(property, propertyResource, propertyName));\r
+ }\r
+ }\r
+\r
+ // Sort returned annotations by annotation property name to keep the results stable.\r
+ Collections.sort(result, AVAILABLE_ANNOTATION_SORTER);\r
+\r
+ return result;\r
+\r
+ }\r
+\r
+ private static Pair<Resource, String> defaultAnnotationTypeAndName(ReadGraph graph, Variable selection) throws DatabaseException {\r
+ AnnotationResource ANNO = AnnotationResource.getInstance(graph);\r
+ Resource model = Variables.getPossibleIndexRoot(graph, selection);\r
+ Resource type = graph.getPossibleObject(model, ANNO.HasDefaultAnnotationType);\r
+ String name = graph.getPossibleRelatedValue(model, ANNO.HasDefaultAnnotationName, Bindings.STRING);\r
+ return Pair.make(type, name);\r
+ }\r
+\r
+ private static String selectedAnnotationName(ReadGraph graph, Variable selection) throws DatabaseException {\r
+ Pair<Resource, String> typeAndName = defaultAnnotationTypeAndName(graph, selection);\r
+ Collection<Tuple3> available = availableAnnotationsImpl(graph, selection);\r
+ if (!available.isEmpty()) {\r
+ if (available.size() == 1 || typeAndName.first == null)\r
+ return (String) available.iterator().next().c2;\r
+ String firstTypeMatch = null;\r
+ for (Tuple3 anno : available) {\r
+ if (graph.isInstanceOf((Resource) anno.c1, typeAndName.first)) {\r
+ if (firstTypeMatch == null)\r
+ firstTypeMatch = (String) anno.c2;\r
+ if (typeAndName.second != null && typeAndName.second.equals(anno.c2)) {\r
+ // Ok, it just doesn't match better than this.\r
+ return (String) anno.c2;\r
+ }\r
+ }\r
+ }\r
+ if (firstTypeMatch != null)\r
+ return firstTypeMatch;\r
+ // Nothing => return the first one from list\r
+ return (String)available.iterator().next().c2;\r
+ }\r
+ return NO_ANNOTATIONS;\r
+ }\r
+\r
+ private static String selectedSourceName(ReadGraph graph, Variable selection) throws DatabaseException {\r
+ \r
+ AnnotationResource ANNO = AnnotationResource.getInstance(graph);\r
+ Resource model = Variables.getPossibleIndexRoot(graph, selection);\r
+ if (model == null)\r
+ return EMPTY;\r
+ String name = graph.getPossibleRelatedValue(model, ANNO.DefaultAnnotationSource, Bindings.STRING);\r
+ if(name != null) {\r
+ for(Tuple tuple : availableSourcesImpl(graph, selection)) {\r
+ if(tuple.get(1).equals(name)) return name;\r
+ }\r
+ }\r
+\r
+ Set<String> available = new THashSet<String>();\r
+ for(Tuple tuple : availableSourcesImpl(graph, selection)) available.add((String)tuple.get(1));\r
+ if(available.isEmpty()) return EMPTY;\r
+ \r
+ if(available.contains(MAPPED)) return MAPPED;\r
+ else return available.iterator().next();\r
+ \r
+ }\r
+\r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+ public static Object explorerInput(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+ String selected = selectedAnnotationName(graph, selection);\r
+ for(Tuple3 anno : availableAnnotationsImpl(graph, selection)) {\r
+ if(selected.equals(anno.c2)) {\r
+ return anno.c0;\r
+ }\r
+ }\r
+ return null;\r
+\r
+ }\r
+\r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+ public static String descriptionText(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ String result = "";\r
+ Variable sel = getSelectedAnnotationVariable(graph, context);\r
+ if(sel != null) {\r
+\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ Resource literal = sel.getPossibleRepresents(graph);\r
+ if(literal != null) {\r
+ Resource container = graph.getPossibleObject(literal, L0.PartOf);\r
+ if(container != null) {\r
+ Resource model = Variables.getPossibleIndexRoot(graph, sel);\r
+ String modelURI = graph.getURI(model);\r
+ String path = graph.getURI(literal);\r
+ if(path.startsWith(modelURI)) path = path.substring(modelURI.length()+1);\r
+ result += URIStringUtils.unescape(path); \r
+ } else {\r
+ result += "The annotation is not attached to a library";\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ return result;\r
+\r
+ }\r
+\r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+ public static Object explorerInput2(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ return ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+\r
+ }\r
+\r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> [(String, Resource)]")\r
+ public static List<Tuple> availableAnnotations(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {\r
+ Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+ ArrayList<Tuple> result = new ArrayList<Tuple>();\r
+ for(Tuple3 anno : availableAnnotationsImpl(graph, selection)) {\r
+ result.add(new Tuple2(anno.c2, anno.c1));\r
+ }\r
+ if(result.isEmpty()) result.add(new Tuple2(NO_ANNOTATIONS, ""));\r
+ return result;\r
+ }\r
+\r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+ public static String selectedAnnotation(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ final Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+ return selectedAnnotationName(graph, selection);\r
+\r
+ }\r
+ \r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+ public static Object selectedAnnotationModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ return new FunctionImpl1<Object, Object>() {\r
+\r
+ @Override\r
+ public Object apply(final Object _key) {\r
+\r
+ Session s = Simantics.getSession();\r
+ VirtualGraph vg = s.getService(VirtualGraphSupport.class).getWorkspacePersistent("preferences");\r
+ s.async(new WriteRequest(vg) {\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ AnnotationResource ANNO = AnnotationResource.getInstance(graph);\r
+ String key = (String)_key;\r
+ Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+ for(Tuple3 anno : availableAnnotationsImpl(graph, selection)) {\r
+ if(key.equals(anno.c2)) {\r
+ Resource type = graph.getPossibleType((Resource) anno.c1, ANNO.Annotation);\r
+ Resource model = Variables.getPossibleIndexRoot(graph, selection);\r
+ graph.deny(model, ANNO.HasDefaultAnnotationType);\r
+ graph.claim(model, ANNO.HasDefaultAnnotationType, type);\r
+ graph.denyValue(model, ANNO.HasDefaultAnnotationName);\r
+ graph.claimLiteral(model, ANNO.HasDefaultAnnotationName, key, Bindings.STRING);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ });\r
+\r
+ return null;\r
+\r
+ }\r
+\r
+ };\r
+\r
+ }\r
+ \r
+ private static Resource getSelectionResource(Variable context) throws DatabaseException {\r
+ return Simantics.getSession().syncRequest(new UnaryRead<Variable,Resource>(context) {\r
+\r
+ @Override\r
+ public Resource perform(ReadGraph graph) throws DatabaseException {\r
+ Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, parameter);\r
+ Variable source = selectedSource(graph, selection);\r
+ return source.getPossibleRepresents(graph);\r
+ }\r
+ \r
+ });\r
+ }\r
+\r
+ static class AddModifier extends FunctionImpl1<Object, Object> {\r
+ \r
+ private final Variable context;\r
+ \r
+ public AddModifier(Variable context) {\r
+ this.context = context;\r
+ }\r
+ \r
+ private void doAdd(final Variable variable) throws DatabaseException {\r
+ \r
+ if(variable != null) {\r
+ // We have a selected annotation\r
+ AnnotationUtils.newAnnotation(variable);\r
+ } else {\r
+ // No annotation selected\r
+ Resource parent = getSelectionResource(context);\r
+ if(parent != null)\r
+ AnnotationUtils.newAnnotation(parent);\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ public Object apply(Object p0) {\r
+ \r
+ ISWTViewNode node = (ISWTViewNode)p0;\r
+ SWTExplorer properties = (SWTExplorer)NodeUtil.browsePossible(node, "./Properties");\r
+ if(properties == null) return null;\r
+ try {\r
+ doAdd((Variable)properties.input);\r
+ } catch (DatabaseException e) {\r
+ Logger.defaultLogError(e);\r
+ }\r
+ return null;\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+ public static Object newAnnotationModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+ return new AddModifier(context);\r
+ }\r
+\r
+ private static Variable getSelectedAnnotationVariable(ReadGraph graph, Variable context) throws DatabaseException {\r
+ Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);\r
+ String selected = selectedAnnotationName(graph, selection);\r
+ for(Tuple3 anno : availableAnnotationsImpl(graph, selection)) {\r
+ if(anno.c2.equals(selected)) {\r
+ return (Variable)anno.c0;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+ public static Object removeAnnotationModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ return new RemoveModifier();\r
+ \r
+ }\r
+\r
+ public static class SaveModifier extends FunctionImpl1<Object, Object> {\r
+ \r
+ private boolean doSave(final Variable variable) {\r
+ \r
+ if(!AnnotationUtils.isAnnotation(variable)) return false;\r
+ \r
+ final Map<Resource, Pair<String, ImageDescriptor>> map = AnnotationUtils.findLibraries(variable);\r
+ if(map == null) return false;\r
+\r
+ AnnotationUtils.queryLibrary(map, selected -> {\r
+ Simantics.getSession().async(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ Resource represents = variable.getPossibleRepresents(graph);\r
+ if(represents != null && !selected.second.isEmpty()) {\r
+ saveAnnotation(graph, represents, selected.first, selected.second); \r
+ }\r
+ }\r
+ });\r
+ });\r
+\r
+ return true;\r
+ }\r
+ \r
+ public static Resource saveAnnotation(WriteGraph graph, Resource annotation, Resource library, String name) throws DatabaseException {\r
+ \r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ if(graph.hasStatement(annotation, L0.PartOf)) {\r
+ graph.deny(annotation, L0.PartOf);\r
+ }\r
+ graph.claim(library, L0.ConsistsOf, L0.PartOf, annotation);\r
+ graph.claimLiteral(annotation, L0.HasName, name, Bindings.STRING);\r
+ \r
+ return annotation;\r
+ }\r
+ \r
+\r
+ @Override\r
+ public Object apply(Object p0) {\r
+ \r
+ ISWTViewNode node = (ISWTViewNode)p0;\r
+ SWTExplorer properties = (SWTExplorer)NodeUtil.browsePossible(node, "./Properties");\r
+ if(properties == null) return null;\r
+ ISelection selection = properties.lastSelection;\r
+ if(selection == null || selection.isEmpty()) {\r
+ doSave((Variable)properties.input);\r
+ return null;\r
+ }\r
+ \r
+ Collection<Variable> vars = ISelectionUtils.filterSetSelection(selection, Variable.class);\r
+ if(vars.size() != 1) return null;\r
+\r
+ Variable selected = vars.iterator().next();\r
+ if(!doSave(selected))\r
+ doSave((Variable)properties.input);\r
+ \r
+ return null;\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ static class RemoveModifier extends FunctionImpl1<Object, Object> {\r
+\r
+ private boolean doRemove(final Variable variable) {\r
+\r
+ if(!AnnotationUtils.isAnnotation(variable))\r
+ return false;\r
+\r
+ Simantics.getSession().async(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ graph.markUndoPoint();\r
+ Resource represents = variable.getPossibleRepresents(graph);\r
+ if(represents != null) {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ AnnotationResource ANNO = AnnotationResource.getInstance(graph);\r
+ if(graph.isInstanceOf(represents, ANNO.Annotation)) {\r
+ Resource subject = variable.getParent(graph).getRepresents(graph);\r
+ Resource predicate = variable.getPossiblePredicateResource(graph);\r
+ if(predicate != null) {\r
+ // This is a property annotation (no entry) - unlink\r
+ graph.deny(subject, predicate);\r
+ Layer0Utils.addCommentMetadata(graph, "Unlinked a property annotation " + graph.getRelatedValue2(predicate, L0.HasName, Bindings.STRING) + " " + predicate.toString() + " from " + graph.getRelatedValue2(subject, L0.HasName, Bindings.STRING) + " " + subject.toString());\r
+ } else {\r
+ // This should be an entry annotation - remove from container\r
+ graph.deny(subject, ANNO.Annotation_HasEntry, represents);\r
+ Layer0Utils.addCommentMetadata(graph, "Removed an entry annotation " + graph.getRelatedValue2(subject, L0.HasName, Bindings.STRING) + " " + subject.toString() + " from its container " + graph.getRelatedValue2(represents, L0.HasName, Bindings.STRING));\r
+ }\r
+ // If the annotation is not in any library remove it\r
+ if(!graph.hasStatement(represents, L0.PartOf))\r
+ RemoverUtil.remove(graph, represents);\r
+ }\r
+ }\r
+\r
+ }\r
+ \r
+ });\r
+\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public Object apply(Object p0) {\r
+\r
+ ISWTViewNode node = (ISWTViewNode)p0;\r
+ SWTExplorer properties = (SWTExplorer)NodeUtil.browsePossible(node, "./Properties");\r
+ if(properties == null) return null;\r
+ ISelection selection = properties.lastSelection;\r
+ if(selection == null || selection.isEmpty()) {\r
+ doRemove((Variable)properties.input);\r
+ return null;\r
+ }\r
+\r
+ Collection<Variable> vars = ISelectionUtils.filterSetSelection(selection, Variable.class);\r
+ if(vars.size() != 1) return null;\r
+\r
+ Variable selected = vars.iterator().next();\r
+ if(!doRemove(selected))\r
+ doRemove((Variable)properties.input);\r
+\r
+ return null;\r
+\r
+ }\r
+\r
+ }\r
+ \r
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+ public static Object saveAnnotationModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {\r
+\r
+ return new SaveModifier();\r
+\r
+ }\r
+\r
+ @SCLValue(type = "VariableMap")\r
+ public static VariableMap domainChildren = new VariableMapImpl() {\r
+\r
+ private Map<String,Resource> children(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ AnnotationResource ANNO = AnnotationResource.getInstance(graph);\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ Collection<Resource> objects = graph.getObjects(resource, ANNO.Annotation_HasEntry); \r
+ THashMap<String, Resource> result = new THashMap<String, Resource>(objects.size());\r
+ for(Resource r : objects) {\r
+ String name = graph.getPossibleRelatedValue(r, L0.HasName, Bindings.STRING);\r
+ if(name != null) {\r
+ if (result.put(name, r) != null)\r
+ System.err.println(this + ": The database contains siblings with the same name " + name + " (resource=$" + resource.getResourceId() +").");\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ @Override\r
+ public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+ Map<String, Resource> children = children(graph,context.getRepresents(graph));\r
+ Resource child = children.get(name);\r
+ if(child == null) return null;\r
+ VariableBuilder variableBuilder = graph.adapt(child, VariableBuilder.class);\r
+ return variableBuilder.buildChild(graph, context, null, child);\r
+ }\r
+\r
+ @Override\r
+ public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+ Map<String,Resource> childMap = children(graph,context.getRepresents(graph));\r
+ if(childMap.isEmpty()) return map;\r
+ if(map == null) map = new THashMap<String,Variable>();\r
+ for(Map.Entry<String, Resource> entry : childMap.entrySet()) {\r
+ String name = entry.getKey();\r
+ Resource child = entry.getValue();\r
+ VariableBuilder variableBuilder = graph.adapt(child, VariableBuilder.class);\r
+ Variable var = variableBuilder.buildChild(graph, context, null, child);\r
+ if(var != null) {\r
+ map.put(name, var);\r
+ } else {\r
+ System.err.println("No adapter for " + child + " in " + context.getURI(graph));\r
+ }\r
+ }\r
+ return map;\r
+ }\r
+ \r
+ };\r
+\r
+}\r