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