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