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%2FAnnotationUtils.java;h=a876f6e72c31e2ac79f1a0dfb57bcb528d34093e;hp=2abd2d6706d90d28e3f97ff49053197312dd16c7;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.annotation.ui/src/org/simantics/annotation/ui/AnnotationUtils.java b/bundles/org.simantics.annotation.ui/src/org/simantics/annotation/ui/AnnotationUtils.java index 2abd2d670..a876f6e72 100644 --- a/bundles/org.simantics.annotation.ui/src/org/simantics/annotation/ui/AnnotationUtils.java +++ b/bundles/org.simantics.annotation.ui/src/org/simantics/annotation/ui/AnnotationUtils.java @@ -1,578 +1,578 @@ -/******************************************************************************* - * Copyright (c) 2012 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.annotation.ui; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.function.Consumer; - -import org.eclipse.jface.dialogs.IDialogSettings; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.PlatformUI; -import org.simantics.Simantics; -import org.simantics.annotation.ontology.AnnotationResource; -import org.simantics.annotation.ui.internal.SaveAnnotationDialog; -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.WriteGraph; -import org.simantics.db.common.CommentMetadata; -import org.simantics.db.common.request.PossibleIndexRoot; -import org.simantics.db.common.request.ReadRequest; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.utils.Logger; -import org.simantics.db.common.utils.NameUtils; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.adapter.Instances; -import org.simantics.db.layer0.request.PossibleModel; -import org.simantics.db.layer0.request.VariableRead; -import org.simantics.db.layer0.util.Layer0Utils; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.layer0.Layer0; -import org.simantics.selectionview.SelectionViewResources; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.ui.workbench.dialogs.ResourceSelectionDialog3; -import org.simantics.utils.datastructures.Pair; - -/** - * @author Teemu Mätäsniemi - * @author Antti Villberg - * @author Tuukka Lehtonen - */ -public class AnnotationUtils { - - /** - * @param graph - * @param parent - * @return (r1, r2) pair where r1 is the created annotation property - * relation and and r2 is the created annotation type - * @throws DatabaseException - */ - public static Pair newAnnotationType(WriteGraph graph, final Resource parent) throws DatabaseException { - graph.markUndoPoint(); - Layer0 L0 = Layer0.getInstance(graph); - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - SelectionViewResources SEL = SelectionViewResources.getInstance(graph); - StructuralResource2 STR = StructuralResource2.getInstance(graph); - - Resource indexRoot = graph.sync(new PossibleIndexRoot(parent)); - - // Get supertype for annotation type - Resource propertySubrelation = graph.getPossibleObject(indexRoot, ANNO.HasAnnotationPropertySubrelation); - if (propertySubrelation == null) - propertySubrelation = L0.HasProperty; - Resource supertype = graph.getPossibleObject(indexRoot, ANNO.HasAnnotationTypeSupertype); - if (supertype == null) - supertype = ANNO.Annotation; - - Resource property = graph.newResource(); - String name = NameUtils.findFreshName(graph, "newAnnotationProperty", parent, L0.ConsistsOf); - graph.addLiteral(property, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); - graph.claim(property, L0.SubrelationOf, propertySubrelation); - - Resource type = graph.newResource(); - graph.claim(type, L0.Inherits, null, supertype); - graph.addLiteral(type, L0.HasName, L0.NameOf, L0.String, UUID.randomUUID().toString(), Bindings.STRING); - graph.claim(type, STR.ComponentType_HasDefaultPropertyRelationType, SEL.GenericParameterType); - - graph.claim(property, L0.HasRange, type); - - graph.claim(type, L0.ConsistsOf, property); - graph.claim(parent, L0.ConsistsOf, type); - - CommentMetadata cm = graph.getMetadata(CommentMetadata.class); - graph.addMetadata(cm.add("Added new annotationType " + type + " with property relation " + property + " ")); - - return Pair.make(property, type); - } - - public static void newAnnotation(ReadGraph graph, Resource parent, Resource model) throws DatabaseException { - - Map> map = new HashMap<>(); - findAnnotationTypes(graph, model, map); - findAnnotations(graph, model, map); - queryUserSelectedAnnotationType(map, selected -> { - Simantics.getSession().async(new WriteRequest() { - @Override - public void perform(WriteGraph g) throws DatabaseException { - newAnnotation(g, parent, selected); - } - }); - }); - - } - - private static boolean isEntryAnnotation(ReadGraph graph, Resource selected) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - if(graph.isInstanceOf(selected, ANNO.Annotation)) { - Resource type = graph.getSingleType(selected, ANNO.Annotation); - return !graph.hasStatement(type, L0.HasRange_Inverse); - } else if (graph.isInstanceOf(selected, ANNO.AnnotationType)) { - return !graph.hasStatement(selected, L0.HasRange_Inverse); - } else { - throw new DatabaseException("Incompatible resource " + selected); - } - } - - public static void newAnnotation(ReadGraph graph, Variable position, Resource model) throws DatabaseException { - - Map> map = new HashMap<>(); - findAnnotationTypes(graph, model, map); - findAnnotations(graph, model, map); - queryUserSelectedAnnotationType(map, selected -> { - Simantics.getSession().async(new WriteRequest() { - @Override - public void perform(WriteGraph g) throws DatabaseException { - g.markUndoPoint(); - if(isEntryAnnotation(g, selected)) { - newAnnotation(g, position.getRepresents(g), selected); - Layer0Utils.addCommentMetadata(g, "Attached new annotation to " + g.getRelatedValue2(position.getRepresents(g), Layer0.getInstance(g).HasName, Bindings.STRING)); - } else { - newAnnotation(g, position.getParent(g).getRepresents(g), selected); - Layer0Utils.addCommentMetadata(g, "Attached new annotation to " + g.getRelatedValue2(position.getParent(g).getRepresents(g), Layer0.getInstance(g).HasName, Bindings.STRING)); - } - } - }); - }); - - } - - /** - * Creates a new annotation instance for the specified parent after the user - * selects the annotation type from the list of all annotation types in the - * specified model. The annotation types are resolved from the model - * dependency index. - * - * @param parent - * @param model - * @throws DatabaseException - */ - public static void newAnnotation(Resource parent, Resource model) throws DatabaseException { - if (model == null) - return; - Simantics.getSession().syncRequest(new ReadRequest() { - @Override - public void run(ReadGraph graph) throws DatabaseException { - newAnnotation(graph, parent, model); - } - }); - } - - public static void newAnnotation(Resource parent) throws DatabaseException { - Simantics.getSession().syncRequest(new ReadRequest() { - @Override - public void run(ReadGraph graph) throws DatabaseException { - Resource model = graph.sync(new PossibleModel(parent)); - if(model == null) return; - newAnnotation(graph, parent, model); - } - }); - } - - public static void newAnnotation(Variable position) throws DatabaseException { - Simantics.getSession().syncRequest(new ReadRequest() { - @Override - public void run(ReadGraph graph) throws DatabaseException { - Resource model = Variables.getModel(graph, position); - if(model == null) return; - newAnnotation(graph, position, model); - } - }); - } - - public static void newAnnotationInstance(Resource parent, Resource model) throws DatabaseException { - if (model == null) - return; - Simantics.getSession().syncRequest(new ReadRequest() { - @Override - public void run(ReadGraph graph) throws DatabaseException { - Map> map = new HashMap<>(); - findAnnotationTypes(graph, model, map); - queryUserSelectedAnnotationType(map, selected -> { - Simantics.getSession().async(new WriteRequest() { - @Override - public void perform(WriteGraph g) throws DatabaseException { - g.markUndoPoint(); - newAnnotationInstance(g, parent, selected); - } - }); - }); - } - }); - } - - /** - * @param graph - * @param model - * @return - * @throws DatabaseException - */ - protected static void findAnnotationTypes(ReadGraph graph, Resource model, Map> map) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - - Instances query = graph.adapt(ANNO.AnnotationType, Instances.class); - - String modelURI = graph.getURI(model); - - ImageDescriptor descriptor = graph.adapt(ANNO.Images_AnnotationType, ImageDescriptor.class); - - for(Resource _res : query.find(graph, model)) { - // Don't allow instantiation of abstract annotation types. - if (graph.hasStatement(_res, L0.Abstract)) - continue; - - // Don't allow instantiation of non-user-selectable annotation types - Boolean userSelectable = graph.getPossibleRelatedValue2(_res, ANNO.AnnotationType_systemAnnotation, Bindings.BOOLEAN); - if (Boolean.TRUE.equals(userSelectable)) - continue; - - Resource res = graph.getPossibleObject(_res, L0.HasRange_Inverse); - if(res == null) { - - // Entry type - - String name = graph.getPossibleRelatedValue(_res, L0.HasName, Bindings.STRING); - if (name == null) - continue; - String label = graph.getPossibleRelatedValue2(_res, L0.HasLabel, Bindings.STRING); - - if (label != null && !name.equals(label)) { - name = label + " (" + name + ")"; - } - - Resource parent = graph.getPossibleObject(_res, L0.PartOf); - if(parent == null) continue; - - String parentURI = graph.getURI(parent); - if(parentURI.startsWith(modelURI)) { - parentURI = parentURI.substring(modelURI.length()); - if(parentURI.startsWith("/")) parentURI = parentURI.substring(1); - } - - name = name + " - " + URIStringUtils.unescape(parentURI); - - map.put(_res, Pair.make(name, descriptor)); - - } else { - - // Property type - - String name = graph.getPossibleRelatedValue(res, L0.HasName, Bindings.STRING); - if (name == null) - continue; - String label = graph.getPossibleRelatedValue2(res, L0.HasLabel, Bindings.STRING); - - if (label != null && !name.equals(label)) { - name = label + " (" + name + ")"; - } - - Resource parent = graph.getPossibleObject(_res, L0.PartOf); - if(parent == null) continue; - - String parentURI = graph.getURI(parent); - if(parentURI.startsWith(modelURI)) { - parentURI = parentURI.substring(modelURI.length()); - if(parentURI.startsWith("/")) parentURI = parentURI.substring(1); - } - - name = name + " - " + URIStringUtils.unescape(parentURI); - - map.put(_res, Pair.make(name, descriptor)); - - } - - } - - } - - protected static void findAnnotations(ReadGraph graph, Resource model, Map> map) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - - Instances query = graph.adapt(ANNO.Annotation, Instances.class); - - String modelURI = graph.getURI(model); - - ImageDescriptor descriptor = graph.adapt(ANNO.Images_Annotation, ImageDescriptor.class); - - for(Resource _res : query.find(graph, model)) { - String name = graph.getPossibleRelatedValue(_res, L0.HasName, Bindings.STRING); - if (name == null) - continue; - String label = graph.getPossibleRelatedValue2(_res, L0.HasLabel, Bindings.STRING); - if (label != null && !name.equals(label)) { - name = label + " (" + name + ")"; - } - - Resource parent = graph.getPossibleObject(_res, L0.PartOf); - if(parent == null) continue; - - String parentURI = graph.getPossibleURI(parent); - if(parentURI == null) continue; - - if(parentURI.startsWith(modelURI)) { - parentURI = parentURI.substring(modelURI.length()); - if(parentURI.startsWith("/")) parentURI = parentURI.substring(1); - } - - Resource type = graph.getPossibleType(_res, ANNO.Annotation); - if(type != null) { - // Don't list instances of non-user-selectable annotation types - Boolean userSelectable = graph.getPossibleRelatedValue2(type, ANNO.AnnotationType_systemAnnotation, Bindings.BOOLEAN); - if (Boolean.TRUE.equals(userSelectable)) - continue; - - Resource relation = graph.getPossibleObject(type, L0.HasRange_Inverse); - if(relation != null) { - String rName = graph.getPossibleRelatedValue(relation, L0.HasName, Bindings.STRING); - if(rName != null) { - name = name + " - " + rName; - } - } - } - - name = name + " - " + URIStringUtils.unescape(parentURI); - - map.put(_res, Pair.make(name, descriptor)); - - } - - } - - protected static boolean isAnnotation(Variable variable) { - if (variable == null) - return false; - try { - return Simantics.sync(new VariableRead(variable) { - - @Override - public Boolean perform(ReadGraph graph) throws DatabaseException { - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - Resource represents = variable.getPossibleRepresents(graph); - if(represents == null) return false; - return graph.isInstanceOf(represents, ANNO.Annotation); - } - - }); - } catch (DatabaseException e) { - return false; - } - } - - protected static Map> findLibraries(Variable variable) { - - try { - - return Simantics.sync(new VariableRead>>(variable) { - - @Override - public Map> perform(ReadGraph graph) throws DatabaseException { - - Map> result = new HashMap<>(); - - Layer0 L0 = Layer0.getInstance(graph); - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - - Resource model = Variables.getModel(graph, variable); - Instances query = graph.adapt(L0.Library, Instances.class); - - String modelURI = graph.getURI(model); - int modelPos = modelURI.length(); - - ImageDescriptor descriptor = graph.adapt(ANNO.Images_Annotation, ImageDescriptor.class); - - for(Resource lib : query.find(graph, model)) { - - String path = graph.getURI(lib); - if(!path.startsWith(modelURI)) continue; - String suffix = URIStringUtils.unescape(path.substring(modelPos)); - if(suffix.startsWith("/")) suffix = suffix.substring(1); - result.put(lib, Pair.make(suffix, descriptor)); - - } - - return result; - - } - }); - - } catch (DatabaseException e) { - Logger.defaultLogError(e); - } - - return null; - - } - - public static Resource newAnnotation(WriteGraph graph, Resource container, Resource valueOrProperty) throws DatabaseException { - graph.markUndoPoint(); - Layer0 L0 = Layer0.getInstance(graph); - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - - if(graph.isInstanceOf(valueOrProperty, ANNO.Annotation)) { - - Resource type = graph.getPossibleType(valueOrProperty, ANNO.Annotation); - if(type == null) return null; - Resource property = graph.getPossibleObject(type, L0.HasRange_Inverse); - if(property == null) { - graph.claim(container, ANNO.Annotation_HasEntry, valueOrProperty); - } else { - graph.deny(container, property); - graph.claim(container, property, valueOrProperty); - } - Layer0Utils.addCommentMetadata(graph, "Created new annotation value/property " + valueOrProperty + " to " + graph.getRelatedValue2(container, L0.HasName, Bindings.STRING)); - return valueOrProperty; - - } else if (graph.isInstanceOf(valueOrProperty, ANNO.AnnotationType)) { - - Resource predicate = graph.getPossibleObject(valueOrProperty, L0.HasRange_Inverse); - if(predicate != null) { - Resource value = graph.newResource(); - graph.claim(value, L0.InstanceOf, valueOrProperty); - graph.deny(container, predicate); - graph.claim(container, predicate, value); - Layer0Utils.addCommentMetadata(graph, "Created new annotation type " + value + " to " + graph.getRelatedValue2(container, L0.HasName, Bindings.STRING)); - return value; - } else { - Resource value = graph.newResource(); - graph.claim(value, L0.InstanceOf, valueOrProperty); - String name = NameUtils.findFreshEscapedName(graph, "Value", container, ANNO.Annotation_HasEntry); - graph.addLiteral(value, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); - graph.claim(container, ANNO.Annotation_HasEntry, value); - Layer0Utils.addCommentMetadata(graph, "Created new annotation entry " + value + " to " + graph.getRelatedValue2(container, L0.HasName, Bindings.STRING)); - return value; - } - - } else { - - Resource valueType = graph.getSingleObject(valueOrProperty, L0.HasRange); - Resource value = graph.newResource(); - graph.claim(value, L0.InstanceOf, valueType); - graph.deny(container, valueOrProperty); - graph.claim(container, valueOrProperty, value); - return value; - - } - - } - - public static Resource newAnnotationInstance(WriteGraph graph, Resource container, Resource annotationProperty) throws DatabaseException { - return newAnnotationInstance(graph, container, null, annotationProperty); - } - - public static Resource newAnnotationInstance(WriteGraph graph, Resource container, String name, Resource annotationProperty) throws DatabaseException { - return newAnnotationInstance(graph, container, name, annotationProperty, true); - } - - public static Resource newAnnotationInstance(WriteGraph graph, Resource container, String name, Resource annotationProperty, boolean addCommentMetadata) throws DatabaseException { - //graph.markUndoPoint(); - Layer0 L0 = Layer0.getInstance(graph); - AnnotationResource ANNO = AnnotationResource.getInstance(graph); - - if(graph.isInstanceOf(annotationProperty, ANNO.AnnotationType)) { - - Resource predicate = graph.getPossibleObject(annotationProperty, L0.HasRange_Inverse); - - String proposition = predicate != null ? (String)graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING) : - (String)graph.getRelatedValue(annotationProperty, L0.HasName, Bindings.STRING); - - Resource value = graph.newResource(); - graph.claim(value, L0.InstanceOf, annotationProperty); - if(name == null) - name = NameUtils.findFreshName(graph, proposition + " value", container); - graph.addLiteral(value, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); - - graph.claim(container, L0.ConsistsOf, value); - - if (addCommentMetadata) { - CommentMetadata cm = graph.getMetadata(CommentMetadata.class); - graph.addMetadata(cm.add("Added new annotationValue named " + name + ", resource " + value)); - } - - return value; - - } else { - - String propertyName = graph.getRelatedValue(annotationProperty, L0.HasName, Bindings.STRING); - - Resource valueType = graph.getSingleObject(annotationProperty, L0.HasRange); - Resource value = graph.newResource(); - graph.claim(value, L0.InstanceOf, valueType); - if(name == null) - name = NameUtils.findFreshName(graph, propertyName + " value", container); - graph.addLiteral(value, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); - - graph.claim(container, L0.ConsistsOf, value); - - if (addCommentMetadata) { - CommentMetadata cm = graph.getMetadata(CommentMetadata.class); - graph.addMetadata(cm.add("Added new annotationValue named " + name + ", resource " + value)); - } - - return value; - - } - - } - - /** - * @param map - * @param selectionCallback - */ - public static void queryUserSelectedAnnotationType( - Map> map, - Consumer selectionCallback) - { - Display.getDefault().asyncExec(() -> { - Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); - ResourceSelectionDialog3 dialog = new ResourceSelectionDialog3(shell, map, "Select annotation type from list") { - @Override - protected IDialogSettings getBaseDialogSettings() { - return Activator.getDefault().getDialogSettings(); - } - }; - if (dialog.open() == Window.OK) { - Object[] result = dialog.getResult(); - if (result != null && result.length == 1) { - selectionCallback.accept((Resource) result[0]); - } - } - }); - } - - public static void queryLibrary( - Map> map, - Consumer> selectionCallback) - { - Display.getDefault().asyncExec(() -> { - Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); - SaveAnnotationDialog page = new SaveAnnotationDialog(shell, map, "Select library"); - if (page.open() == Window.OK) { - Object[] result = page.getResult(); - if (result != null && result.length == 1) { - selectionCallback.accept(Pair.make((Resource)result[0], page.getName())); - } - } - }); - } - -} +/******************************************************************************* + * Copyright (c) 2012 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.annotation.ui; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.simantics.Simantics; +import org.simantics.annotation.ontology.AnnotationResource; +import org.simantics.annotation.ui.internal.SaveAnnotationDialog; +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.WriteGraph; +import org.simantics.db.common.CommentMetadata; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.Logger; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.Instances; +import org.simantics.db.layer0.request.PossibleModel; +import org.simantics.db.layer0.request.VariableRead; +import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.layer0.Layer0; +import org.simantics.selectionview.SelectionViewResources; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.ui.workbench.dialogs.ResourceSelectionDialog3; +import org.simantics.utils.datastructures.Pair; + +/** + * @author Teemu Mätäsniemi + * @author Antti Villberg + * @author Tuukka Lehtonen + */ +public class AnnotationUtils { + + /** + * @param graph + * @param parent + * @return (r1, r2) pair where r1 is the created annotation property + * relation and and r2 is the created annotation type + * @throws DatabaseException + */ + public static Pair newAnnotationType(WriteGraph graph, final Resource parent) throws DatabaseException { + graph.markUndoPoint(); + Layer0 L0 = Layer0.getInstance(graph); + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + SelectionViewResources SEL = SelectionViewResources.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + Resource indexRoot = graph.sync(new PossibleIndexRoot(parent)); + + // Get supertype for annotation type + Resource propertySubrelation = graph.getPossibleObject(indexRoot, ANNO.HasAnnotationPropertySubrelation); + if (propertySubrelation == null) + propertySubrelation = L0.HasProperty; + Resource supertype = graph.getPossibleObject(indexRoot, ANNO.HasAnnotationTypeSupertype); + if (supertype == null) + supertype = ANNO.Annotation; + + Resource property = graph.newResource(); + String name = NameUtils.findFreshName(graph, "newAnnotationProperty", parent, L0.ConsistsOf); + graph.addLiteral(property, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); + graph.claim(property, L0.SubrelationOf, propertySubrelation); + + Resource type = graph.newResource(); + graph.claim(type, L0.Inherits, null, supertype); + graph.addLiteral(type, L0.HasName, L0.NameOf, L0.String, UUID.randomUUID().toString(), Bindings.STRING); + graph.claim(type, STR.ComponentType_HasDefaultPropertyRelationType, SEL.GenericParameterType); + + graph.claim(property, L0.HasRange, type); + + graph.claim(type, L0.ConsistsOf, property); + graph.claim(parent, L0.ConsistsOf, type); + + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add("Added new annotationType " + type + " with property relation " + property + " ")); + + return Pair.make(property, type); + } + + public static void newAnnotation(ReadGraph graph, Resource parent, Resource model) throws DatabaseException { + + Map> map = new HashMap<>(); + findAnnotationTypes(graph, model, map); + findAnnotations(graph, model, map); + queryUserSelectedAnnotationType(map, selected -> { + Simantics.getSession().async(new WriteRequest() { + @Override + public void perform(WriteGraph g) throws DatabaseException { + newAnnotation(g, parent, selected); + } + }); + }); + + } + + private static boolean isEntryAnnotation(ReadGraph graph, Resource selected) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + if(graph.isInstanceOf(selected, ANNO.Annotation)) { + Resource type = graph.getSingleType(selected, ANNO.Annotation); + return !graph.hasStatement(type, L0.HasRange_Inverse); + } else if (graph.isInstanceOf(selected, ANNO.AnnotationType)) { + return !graph.hasStatement(selected, L0.HasRange_Inverse); + } else { + throw new DatabaseException("Incompatible resource " + selected); + } + } + + public static void newAnnotation(ReadGraph graph, Variable position, Resource model) throws DatabaseException { + + Map> map = new HashMap<>(); + findAnnotationTypes(graph, model, map); + findAnnotations(graph, model, map); + queryUserSelectedAnnotationType(map, selected -> { + Simantics.getSession().async(new WriteRequest() { + @Override + public void perform(WriteGraph g) throws DatabaseException { + g.markUndoPoint(); + if(isEntryAnnotation(g, selected)) { + newAnnotation(g, position.getRepresents(g), selected); + Layer0Utils.addCommentMetadata(g, "Attached new annotation to " + g.getRelatedValue2(position.getRepresents(g), Layer0.getInstance(g).HasName, Bindings.STRING)); + } else { + newAnnotation(g, position.getParent(g).getRepresents(g), selected); + Layer0Utils.addCommentMetadata(g, "Attached new annotation to " + g.getRelatedValue2(position.getParent(g).getRepresents(g), Layer0.getInstance(g).HasName, Bindings.STRING)); + } + } + }); + }); + + } + + /** + * Creates a new annotation instance for the specified parent after the user + * selects the annotation type from the list of all annotation types in the + * specified model. The annotation types are resolved from the model + * dependency index. + * + * @param parent + * @param model + * @throws DatabaseException + */ + public static void newAnnotation(Resource parent, Resource model) throws DatabaseException { + if (model == null) + return; + Simantics.getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + newAnnotation(graph, parent, model); + } + }); + } + + public static void newAnnotation(Resource parent) throws DatabaseException { + Simantics.getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + Resource model = graph.sync(new PossibleModel(parent)); + if(model == null) return; + newAnnotation(graph, parent, model); + } + }); + } + + public static void newAnnotation(Variable position) throws DatabaseException { + Simantics.getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + Resource model = Variables.getModel(graph, position); + if(model == null) return; + newAnnotation(graph, position, model); + } + }); + } + + public static void newAnnotationInstance(Resource parent, Resource model) throws DatabaseException { + if (model == null) + return; + Simantics.getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + Map> map = new HashMap<>(); + findAnnotationTypes(graph, model, map); + queryUserSelectedAnnotationType(map, selected -> { + Simantics.getSession().async(new WriteRequest() { + @Override + public void perform(WriteGraph g) throws DatabaseException { + g.markUndoPoint(); + newAnnotationInstance(g, parent, selected); + } + }); + }); + } + }); + } + + /** + * @param graph + * @param model + * @return + * @throws DatabaseException + */ + protected static void findAnnotationTypes(ReadGraph graph, Resource model, Map> map) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + + Instances query = graph.adapt(ANNO.AnnotationType, Instances.class); + + String modelURI = graph.getURI(model); + + ImageDescriptor descriptor = graph.adapt(ANNO.Images_AnnotationType, ImageDescriptor.class); + + for(Resource _res : query.find(graph, model)) { + // Don't allow instantiation of abstract annotation types. + if (graph.hasStatement(_res, L0.Abstract)) + continue; + + // Don't allow instantiation of non-user-selectable annotation types + Boolean userSelectable = graph.getPossibleRelatedValue2(_res, ANNO.AnnotationType_systemAnnotation, Bindings.BOOLEAN); + if (Boolean.TRUE.equals(userSelectable)) + continue; + + Resource res = graph.getPossibleObject(_res, L0.HasRange_Inverse); + if(res == null) { + + // Entry type + + String name = graph.getPossibleRelatedValue(_res, L0.HasName, Bindings.STRING); + if (name == null) + continue; + String label = graph.getPossibleRelatedValue2(_res, L0.HasLabel, Bindings.STRING); + + if (label != null && !name.equals(label)) { + name = label + " (" + name + ")"; + } + + Resource parent = graph.getPossibleObject(_res, L0.PartOf); + if(parent == null) continue; + + String parentURI = graph.getURI(parent); + if(parentURI.startsWith(modelURI)) { + parentURI = parentURI.substring(modelURI.length()); + if(parentURI.startsWith("/")) parentURI = parentURI.substring(1); + } + + name = name + " - " + URIStringUtils.unescape(parentURI); + + map.put(_res, Pair.make(name, descriptor)); + + } else { + + // Property type + + String name = graph.getPossibleRelatedValue(res, L0.HasName, Bindings.STRING); + if (name == null) + continue; + String label = graph.getPossibleRelatedValue2(res, L0.HasLabel, Bindings.STRING); + + if (label != null && !name.equals(label)) { + name = label + " (" + name + ")"; + } + + Resource parent = graph.getPossibleObject(_res, L0.PartOf); + if(parent == null) continue; + + String parentURI = graph.getURI(parent); + if(parentURI.startsWith(modelURI)) { + parentURI = parentURI.substring(modelURI.length()); + if(parentURI.startsWith("/")) parentURI = parentURI.substring(1); + } + + name = name + " - " + URIStringUtils.unescape(parentURI); + + map.put(_res, Pair.make(name, descriptor)); + + } + + } + + } + + protected static void findAnnotations(ReadGraph graph, Resource model, Map> map) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + + Instances query = graph.adapt(ANNO.Annotation, Instances.class); + + String modelURI = graph.getURI(model); + + ImageDescriptor descriptor = graph.adapt(ANNO.Images_Annotation, ImageDescriptor.class); + + for(Resource _res : query.find(graph, model)) { + String name = graph.getPossibleRelatedValue(_res, L0.HasName, Bindings.STRING); + if (name == null) + continue; + String label = graph.getPossibleRelatedValue2(_res, L0.HasLabel, Bindings.STRING); + if (label != null && !name.equals(label)) { + name = label + " (" + name + ")"; + } + + Resource parent = graph.getPossibleObject(_res, L0.PartOf); + if(parent == null) continue; + + String parentURI = graph.getPossibleURI(parent); + if(parentURI == null) continue; + + if(parentURI.startsWith(modelURI)) { + parentURI = parentURI.substring(modelURI.length()); + if(parentURI.startsWith("/")) parentURI = parentURI.substring(1); + } + + Resource type = graph.getPossibleType(_res, ANNO.Annotation); + if(type != null) { + // Don't list instances of non-user-selectable annotation types + Boolean userSelectable = graph.getPossibleRelatedValue2(type, ANNO.AnnotationType_systemAnnotation, Bindings.BOOLEAN); + if (Boolean.TRUE.equals(userSelectable)) + continue; + + Resource relation = graph.getPossibleObject(type, L0.HasRange_Inverse); + if(relation != null) { + String rName = graph.getPossibleRelatedValue(relation, L0.HasName, Bindings.STRING); + if(rName != null) { + name = name + " - " + rName; + } + } + } + + name = name + " - " + URIStringUtils.unescape(parentURI); + + map.put(_res, Pair.make(name, descriptor)); + + } + + } + + protected static boolean isAnnotation(Variable variable) { + if (variable == null) + return false; + try { + return Simantics.sync(new VariableRead(variable) { + + @Override + public Boolean perform(ReadGraph graph) throws DatabaseException { + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + Resource represents = variable.getPossibleRepresents(graph); + if(represents == null) return false; + return graph.isInstanceOf(represents, ANNO.Annotation); + } + + }); + } catch (DatabaseException e) { + return false; + } + } + + protected static Map> findLibraries(Variable variable) { + + try { + + return Simantics.sync(new VariableRead>>(variable) { + + @Override + public Map> perform(ReadGraph graph) throws DatabaseException { + + Map> result = new HashMap<>(); + + Layer0 L0 = Layer0.getInstance(graph); + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + + Resource model = Variables.getModel(graph, variable); + Instances query = graph.adapt(L0.Library, Instances.class); + + String modelURI = graph.getURI(model); + int modelPos = modelURI.length(); + + ImageDescriptor descriptor = graph.adapt(ANNO.Images_Annotation, ImageDescriptor.class); + + for(Resource lib : query.find(graph, model)) { + + String path = graph.getURI(lib); + if(!path.startsWith(modelURI)) continue; + String suffix = URIStringUtils.unescape(path.substring(modelPos)); + if(suffix.startsWith("/")) suffix = suffix.substring(1); + result.put(lib, Pair.make(suffix, descriptor)); + + } + + return result; + + } + }); + + } catch (DatabaseException e) { + Logger.defaultLogError(e); + } + + return null; + + } + + public static Resource newAnnotation(WriteGraph graph, Resource container, Resource valueOrProperty) throws DatabaseException { + graph.markUndoPoint(); + Layer0 L0 = Layer0.getInstance(graph); + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + + if(graph.isInstanceOf(valueOrProperty, ANNO.Annotation)) { + + Resource type = graph.getPossibleType(valueOrProperty, ANNO.Annotation); + if(type == null) return null; + Resource property = graph.getPossibleObject(type, L0.HasRange_Inverse); + if(property == null) { + graph.claim(container, ANNO.Annotation_HasEntry, valueOrProperty); + } else { + graph.deny(container, property); + graph.claim(container, property, valueOrProperty); + } + Layer0Utils.addCommentMetadata(graph, "Created new annotation value/property " + valueOrProperty + " to " + graph.getRelatedValue2(container, L0.HasName, Bindings.STRING)); + return valueOrProperty; + + } else if (graph.isInstanceOf(valueOrProperty, ANNO.AnnotationType)) { + + Resource predicate = graph.getPossibleObject(valueOrProperty, L0.HasRange_Inverse); + if(predicate != null) { + Resource value = graph.newResource(); + graph.claim(value, L0.InstanceOf, valueOrProperty); + graph.deny(container, predicate); + graph.claim(container, predicate, value); + Layer0Utils.addCommentMetadata(graph, "Created new annotation type " + value + " to " + graph.getRelatedValue2(container, L0.HasName, Bindings.STRING)); + return value; + } else { + Resource value = graph.newResource(); + graph.claim(value, L0.InstanceOf, valueOrProperty); + String name = NameUtils.findFreshEscapedName(graph, "Value", container, ANNO.Annotation_HasEntry); + graph.addLiteral(value, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); + graph.claim(container, ANNO.Annotation_HasEntry, value); + Layer0Utils.addCommentMetadata(graph, "Created new annotation entry " + value + " to " + graph.getRelatedValue2(container, L0.HasName, Bindings.STRING)); + return value; + } + + } else { + + Resource valueType = graph.getSingleObject(valueOrProperty, L0.HasRange); + Resource value = graph.newResource(); + graph.claim(value, L0.InstanceOf, valueType); + graph.deny(container, valueOrProperty); + graph.claim(container, valueOrProperty, value); + return value; + + } + + } + + public static Resource newAnnotationInstance(WriteGraph graph, Resource container, Resource annotationProperty) throws DatabaseException { + return newAnnotationInstance(graph, container, null, annotationProperty); + } + + public static Resource newAnnotationInstance(WriteGraph graph, Resource container, String name, Resource annotationProperty) throws DatabaseException { + return newAnnotationInstance(graph, container, name, annotationProperty, true); + } + + public static Resource newAnnotationInstance(WriteGraph graph, Resource container, String name, Resource annotationProperty, boolean addCommentMetadata) throws DatabaseException { + //graph.markUndoPoint(); + Layer0 L0 = Layer0.getInstance(graph); + AnnotationResource ANNO = AnnotationResource.getInstance(graph); + + if(graph.isInstanceOf(annotationProperty, ANNO.AnnotationType)) { + + Resource predicate = graph.getPossibleObject(annotationProperty, L0.HasRange_Inverse); + + String proposition = predicate != null ? (String)graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING) : + (String)graph.getRelatedValue(annotationProperty, L0.HasName, Bindings.STRING); + + Resource value = graph.newResource(); + graph.claim(value, L0.InstanceOf, annotationProperty); + if(name == null) + name = NameUtils.findFreshName(graph, proposition + " value", container); + graph.addLiteral(value, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); + + graph.claim(container, L0.ConsistsOf, value); + + if (addCommentMetadata) { + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add("Added new annotationValue named " + name + ", resource " + value)); + } + + return value; + + } else { + + String propertyName = graph.getRelatedValue(annotationProperty, L0.HasName, Bindings.STRING); + + Resource valueType = graph.getSingleObject(annotationProperty, L0.HasRange); + Resource value = graph.newResource(); + graph.claim(value, L0.InstanceOf, valueType); + if(name == null) + name = NameUtils.findFreshName(graph, propertyName + " value", container); + graph.addLiteral(value, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); + + graph.claim(container, L0.ConsistsOf, value); + + if (addCommentMetadata) { + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add("Added new annotationValue named " + name + ", resource " + value)); + } + + return value; + + } + + } + + /** + * @param map + * @param selectionCallback + */ + public static void queryUserSelectedAnnotationType( + Map> map, + Consumer selectionCallback) + { + Display.getDefault().asyncExec(() -> { + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + ResourceSelectionDialog3 dialog = new ResourceSelectionDialog3(shell, map, "Select annotation type from list") { + @Override + protected IDialogSettings getBaseDialogSettings() { + return Activator.getDefault().getDialogSettings(); + } + }; + if (dialog.open() == Window.OK) { + Object[] result = dialog.getResult(); + if (result != null && result.length == 1) { + selectionCallback.accept((Resource) result[0]); + } + } + }); + } + + public static void queryLibrary( + Map> map, + Consumer> selectionCallback) + { + Display.getDefault().asyncExec(() -> { + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + SaveAnnotationDialog page = new SaveAnnotationDialog(shell, map, "Select library"); + if (page.open() == Window.OK) { + Object[] result = page.getResult(); + if (result != null && result.length == 1) { + selectionCallback.accept(Pair.make((Resource)result[0], page.getName())); + } + } + }); + } + +}