]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.debug.ui / src / org / simantics / debug / ui / SearchResourceDialog.java
diff --git a/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java b/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java
new file mode 100644 (file)
index 0000000..8c88468
--- /dev/null
@@ -0,0 +1,461 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2013 Association for Decentralized Information Management\r
+ * in 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
+ *     Semantum Oy - index based searching and graph manipulation (#4255)\r
+ *******************************************************************************/\r
+package org.simantics.debug.ui;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.TreeSet;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.eclipse.jface.dialogs.IDialogSettings;\r
+import org.eclipse.jface.resource.JFaceResources;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.resource.ResourceManager;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.LabelProvider;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.ui.IMemento;\r
+import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;\r
+import org.simantics.Simantics;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.primitiverequest.Adapter;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.request.BinaryRead;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.migration.OntologiesFromLibrary;\r
+import org.simantics.db.layer0.variable.Variables.Role;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.db.service.SerialisationSupport;\r
+import org.simantics.debug.ui.ResourceSearch.IResourceFilter;\r
+import org.simantics.debug.ui.internal.Activator;\r
+import org.simantics.debug.ui.internal.DebugUtils;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.operation.Layer0X;\r
+import org.simantics.scl.runtime.function.Function;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.workbench.dialogs.ResourceLabelProvider;\r
+import org.simantics.utils.Container;\r
+import org.simantics.utils.ui.BundleUtils;\r
+\r
+/**\r
+ * TODO Add Debugger Composite as preview!\r
+ */\r
+public class SearchResourceDialog extends FilteredItemsSelectionDialog {\r
+\r
+    private static final String SEARCH_RESOURCE_DIALOG = "SearchResourceDialog"; //$NON-NLS-1$\r
+\r
+    Session session;\r
+    IStructuredSelection selection;\r
+    ResourceManager resourceManager;\r
+\r
+    // Needed in a subclass\r
+    protected IResourceFilter resourceFilter = ResourceSearch.FILTER_ALL;\r
+\r
+    LabelProvider detailsLabelProvider = new LabelProvider() {\r
+        @Override\r
+        public String getText(Object element) {\r
+            if (element == null)\r
+                return "null";\r
+            // This may happen if multiple choice is enabled\r
+            if (element instanceof String)\r
+                return (String) element;\r
+            @SuppressWarnings("unchecked")\r
+            Container<Resource> rc = (Container<Resource>) element;\r
+            final Resource r = rc.get();\r
+            try {\r
+                return session.syncRequest(new Read<String>() {\r
+                    @Override\r
+                    public String perform(ReadGraph g) throws DatabaseException {\r
+                        String name = NameUtils.getSafeName(g, r);\r
+                        String uri = g.getPossibleURI(r);\r
+                        String label = "[" + r.getResourceId() + "] - " + name;\r
+                        if (uri != null)\r
+                            label = label + " - " + uri;\r
+                        return label;\r
+                    }\r
+                });\r
+            } catch (DatabaseException e) {\r
+                Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Resource label provider failed unexpectedly.", e));\r
+                return "";\r
+            }\r
+        }\r
+    };\r
+\r
+    static class ElementLabelProvider extends ResourceLabelProvider {\r
+        public ElementLabelProvider(Display display) {\r
+            super(display);\r
+        }\r
+        @Override\r
+        public String getText(Object element) {\r
+            if (element==null)\r
+                return "null";\r
+            return element.toString();\r
+        }\r
+        @Override\r
+        public Image getImage(Object element) {\r
+            if (element == null)\r
+                return null;\r
+            @SuppressWarnings("unchecked")\r
+            Container<Resource> rc = (Container<Resource>) element;\r
+            final Resource r = rc.get();\r
+            return super.getImage(r);\r
+        }\r
+    };\r
+\r
+    ElementLabelProvider labelProvider;\r
+\r
+    public SearchResourceDialog(Session s, boolean multi, Shell shell, String title) {\r
+        this(s, multi, shell, title, null);\r
+    }\r
+\r
+    public SearchResourceDialog(Session s, boolean multi, Shell shell, String title, IStructuredSelection selection) {\r
+        super(shell, multi);\r
+        this.session = s;\r
+        resourceManager = new LocalResourceManager(JFaceResources.getResources());\r
+        this.labelProvider = new ElementLabelProvider(shell.getDisplay());\r
+        setMessage("Enter ID, URI or name");\r
+        setListLabelProvider(labelProvider);\r
+        setDetailsLabelProvider(detailsLabelProvider);\r
+        setImage((Image) resourceManager.get(BundleUtils.getImageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/cog_blue.png")));\r
+        setTitle(title);\r
+        //setInitialPattern("*", FilteredItemsSelectionDialog.FULL_SELECTION);\r
+        setSelectionHistory(new ResourceSelectionHistory());\r
+        this.selection = selection;\r
+        setSeparatorLabel("Previously selected above, others below");\r
+    }\r
+\r
+    @Override\r
+    protected void configureShell(Shell shell) {\r
+        super.configureShell(shell);\r
+        shell.addDisposeListener(new DisposeListener() {\r
+            @Override\r
+            public void widgetDisposed(DisposeEvent e) {\r
+                resourceManager.dispose();\r
+            }\r
+        });\r
+    }\r
+\r
+    class ResourceSelectionHistory extends FilteredItemsSelectionDialog.SelectionHistory {\r
+\r
+        @Override\r
+        protected Object restoreItemFromMemento(IMemento memento) {\r
+            String dada = memento.getTextData();\r
+            try {\r
+                SerialisationSupport support = SimanticsUI.getSession().getService(SerialisationSupport.class);\r
+                final Resource r = support.getResource(Long.parseLong(dada));\r
+                if (r == null) {\r
+                    return null;\r
+                }\r
+\r
+                String name = session.syncRequest(new Read<String>() {\r
+                    @Override\r
+                    public String perform(ReadGraph g) throws DatabaseException {\r
+                        if (!resourceFilter.acceptResource(g, r)) {\r
+                            return null;\r
+                        }\r
+                        String name = null;\r
+                        try {\r
+                            try {\r
+                                name = g.adapt(r, String.class);\r
+                            } catch (Exception ex) {\r
+                                System.out.println("Exception thrown from restoreItemFromMemento");\r
+                            }\r
+                            if (name != null) {\r
+                                return name;\r
+                            }\r
+                        } catch (Throwable t) {}\r
+                        return "" + r.getResourceId();\r
+                    }\r
+                });\r
+                if (name==null) return null;\r
+                return new LabeledResource(name, r);\r
+            } catch (NumberFormatException e) {\r
+                e.printStackTrace();\r
+                return null;\r
+            } catch (DatabaseException e) {\r
+                e.printStackTrace();\r
+                return null;\r
+            }\r
+        }\r
+\r
+        @SuppressWarnings("unchecked")\r
+        @Override\r
+        protected void storeItemToMemento(Object item, IMemento memento) {\r
+            if(item instanceof Container) {\r
+                try {\r
+                    SerialisationSupport support = SimanticsUI.getSession().getService(SerialisationSupport.class);\r
+                    memento.putTextData(String.valueOf(support.getRandomAccessId(((Container<Resource>)item).get())));\r
+                } catch (DatabaseException e) {\r
+                    e.printStackTrace();\r
+                }\r
+            }\r
+        }\r
+    };\r
+\r
+    @Override\r
+    protected Control createExtendedContentArea(Composite parent) {\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    protected ItemsFilter createFilter() {\r
+        // NOTE: filter must be created here.\r
+        return new ItemsFilter() {\r
+            @Override\r
+            public boolean matchItem(Object item) {\r
+                //return matches(item.toString());\r
+                return true;\r
+            }\r
+\r
+            // If this method returns true, it means fillContentProvider will\r
+            // not be called again, but the existing results are just re-filtered.\r
+            @Override\r
+            public boolean isSubFilter(ItemsFilter filter) {\r
+                //System.out.println(getPattern() + " vs. " + filter.getPattern());\r
+                return false;\r
+            }\r
+\r
+            @Override\r
+            public boolean isConsistentItem(Object item) {\r
+                return true;\r
+            }\r
+\r
+            @Override\r
+            public boolean equalsFilter(ItemsFilter filter) {\r
+                return false;\r
+            }\r
+        };\r
+    }\r
+\r
+    @Override\r
+    protected void fillContentProvider(final AbstractContentProvider contentProvider,\r
+            final ItemsFilter itemsFilter, final IProgressMonitor progressMonitor)\r
+                    throws CoreException {\r
+        final String pattern = itemsFilter.getPattern();\r
+        final boolean findUris = pattern.trim().startsWith("http:/");\r
+        final long referencedResourceId = referencedResourceId(pattern);\r
+        final boolean findIds = referencedResourceId != 0;\r
+\r
+        progressMonitor.beginTask("Searching", IProgressMonitor.UNKNOWN);\r
+\r
+        try {\r
+            session.syncRequest(new ReadRequest() {\r
+                @Override\r
+                public void run(ReadGraph graph) throws DatabaseException {\r
+                    // Find by ID first.\r
+                    if (findIds) {\r
+                        try {\r
+                            Resource r = graph.getService(SerialisationSupport.class).getResource(referencedResourceId);\r
+                            contentProvider.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r), itemsFilter);\r
+                            //contentProvider.add(new LabeledResource(pattern, r), itemsFilter);\r
+                        } catch (DatabaseException e) {\r
+                            // No resource for specified id.\r
+                        }\r
+                    }\r
+                    if (findUris) {\r
+                        String uri = pattern;\r
+                        if (uri.endsWith(Role.CHILD.getIdentifier())) {\r
+                            uri = uri.substring(0, uri.length() - 1);\r
+                        }\r
+                        Resource r = graph.getPossibleResource(uri);\r
+                        if (r != null) {\r
+                            contentProvider.add(new LabeledResource(DebugUtils.getSafeURI(graph, r), r), itemsFilter );\r
+\r
+                            Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(r));\r
+                            for (Resource child : children.values()) {\r
+                                contentProvider.add(new LabeledResource(DebugUtils.getSafeURI(graph, child), child), itemsFilter );\r
+                            }\r
+                        }\r
+                    } else {\r
+                        Resource project = Simantics.peekProjectResource();\r
+                        if (project != null) {\r
+                            IResourceFilter rf = resourceFilter;\r
+                            String filter = getFilterForResourceFilter(rf);\r
+                            if (!filter.isEmpty())\r
+                                filter += " AND ";\r
+                            filter += "Name:" + pattern + "*";\r
+\r
+                            Layer0 L0 = Layer0.getInstance(graph);\r
+                            \r
+                            HashSet<Resource> indexRoots = new HashSet<Resource>();\r
+                            indexRoots.addAll(graph.syncRequest(new ObjectsWithType(project, L0.ConsistsOf, L0.IndexRoot)));\r
+                            indexRoots.addAll(graph.syncRequest(new OntologiesFromLibrary(graph.getRootLibrary())));\r
+                            for (Resource indexRoot : indexRoots) {\r
+                                Collection<Resource> hits = new ArrayList<Resource>(find(graph, indexRoot, filter));\r
+                                hits.add(indexRoot);\r
+                                for (Resource r : hits) {\r
+                                    if (rf != null && !rf.acceptResource(graph, r))\r
+                                        continue;\r
+                                    contentProvider.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r), itemsFilter);\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+\r
+                public Collection<Resource> find(ReadGraph graph, Resource index, String filter) throws DatabaseException {\r
+                    Collection<Resource> indexResult = graph.syncRequest(new QueryIndex(index, filter), TransientCacheListener.<Collection<Resource>>instance());\r
+\r
+//                    Layer0 L0 = Layer0.getInstance(graph);\r
+//                    Collection<Resource> linkedRoots = graph.syncRequest(new ObjectsWithType(index, L0.IsLinkedTo, L0.IndexRoot));\r
+//                    if (linkedRoots.isEmpty())\r
+                        return indexResult;\r
+\r
+//                    Collection<Resource> result = indexResult;\r
+//                    for (Resource dep : linkedRoots) {\r
+//                        Collection<Resource> linkedIndexResults = find(graph, dep, filter);\r
+//                        if (linkedIndexResults.isEmpty())\r
+//                            continue;\r
+//                        if (result == indexResult) {\r
+//                            result = new ArrayList<Resource>(indexResult.size() + linkedIndexResults.size());\r
+//                            result.addAll(indexResult);\r
+//                        } else {\r
+//                        }\r
+//                        result.addAll(linkedIndexResults);\r
+//                    }\r
+//                    return result;\r
+                }\r
+\r
+            });\r
+        } catch (DatabaseException ex) {\r
+            Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));\r
+        }\r
+\r
+        progressMonitor.done();\r
+    }\r
+\r
+    /**\r
+     * A (cacheable) query to optimize single index queries for immutable\r
+     * indexes such as ontologies.\r
+     */\r
+    static class QueryIndex extends BinaryRead<Resource, String, Collection<Resource>> {\r
+\r
+        public QueryIndex(Resource index, String filter) {\r
+            super(index, filter);\r
+        }\r
+\r
+        @Override\r
+        public Collection<Resource> perform(ReadGraph graph)\r
+                throws DatabaseException {\r
+            Layer0X L0X = Layer0X.getInstance(graph);\r
+\r
+            @SuppressWarnings({ "unchecked", "rawtypes" })\r
+            Function dependencies = graph.syncRequest(new Adapter(L0X.Dependencies, Function.class), TransientCacheListener.<Function>instance());\r
+\r
+            @SuppressWarnings("unchecked")\r
+            Collection<Map<String, Object>> results = (Collection<Map<String, Object>>)dependencies.apply(graph, parameter, parameter2);\r
+            if (results == null || results.isEmpty())\r
+                return Collections.emptyList();\r
+\r
+            // TreeSet to keep the results in deterministic order.\r
+            Set<Resource> resultSet = new TreeSet<Resource>();\r
+            for (Map<String, Object> entry : results) {\r
+                Resource res = (Resource)entry.get("Resource");\r
+                if (res != null && !resultSet.contains(res))\r
+                    resultSet.add(res);\r
+            }\r
+\r
+            return new ArrayList<Resource>(resultSet);\r
+        }\r
+\r
+    }\r
+\r
+    Pattern ID_PATTERN = Pattern.compile("\\$([0-9]+)");\r
+\r
+    private long referencedResourceId(String pattern) {\r
+        Matcher m = ID_PATTERN.matcher(pattern);\r
+        if (m.matches()) {\r
+           String id = m.group(1);\r
+           try {\r
+               return Long.parseLong(id);\r
+           } catch (NumberFormatException nfe) {\r
+           }\r
+        }\r
+        return 0;\r
+    }\r
+\r
+    @Override\r
+    protected IDialogSettings getDialogSettings() {\r
+        IDialogSettings settings = Activator.getDefault().getDialogSettings()\r
+        .getSection(SEARCH_RESOURCE_DIALOG);\r
+        if (settings == null) {\r
+            settings = Activator.getDefault().getDialogSettings()\r
+            .addNewSection(SEARCH_RESOURCE_DIALOG);\r
+        }\r
+        return settings;\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    @Override\r
+    public String getElementName(Object item) {\r
+        return ((Container<Resource>)item).get().getResourceId()+"";\r
+        //return item.toString();\r
+    }\r
+\r
+    @SuppressWarnings("rawtypes")\r
+    @Override\r
+    protected Comparator getItemsComparator() {\r
+        return new Comparator() {\r
+            @Override\r
+            public int compare(Object arg0, Object arg1) {\r
+                return arg0.toString().compareTo(arg1.toString());\r
+            }\r
+        };\r
+    }\r
+\r
+    @Override\r
+    protected IStatus validateItem(Object item) {\r
+        return Status.OK_STATUS;\r
+    }\r
+\r
+    public IResourceFilter getResourceFilter() {\r
+        return resourceFilter;\r
+    }\r
+\r
+    public void setResourceFilter(IResourceFilter resourceFilter) {\r
+        this.resourceFilter = resourceFilter;\r
+    }\r
+\r
+    private String getFilterForResourceFilter(IResourceFilter filter) {\r
+        if (filter == null || filter == ResourceSearch.FILTER_ALL)\r
+            return "";\r
+        if (filter == ResourceSearch.FILTER_RELATIONS)\r
+            return "Types:Relation"; \r
+        if (filter == ResourceSearch.FILTER_TYPES)\r
+            return "Types:Type"; \r
+        return "";\r
+    }\r
+\r
+}\r