-/*******************************************************************************\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
+/*******************************************************************************
+ * Copyright (c) 2007, 2019 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
+ * Semantum Oy - index based searching and graph manipulation (#4255)
+ *******************************************************************************/
+package org.simantics.debug.ui;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.common.primitiverequest.PossibleAdapter;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.common.request.BinaryRead;
+import org.simantics.db.common.request.ObjectsWithType;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.common.uri.UnescapedChildMapOfResource;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.genericrelation.Dependencies;
+import org.simantics.db.layer0.genericrelation.IndexQueries;
+import org.simantics.db.layer0.migration.OntologiesFromLibrary;
+import org.simantics.db.layer0.variable.Variables.Role;
+import org.simantics.db.request.Read;
+import org.simantics.db.service.SerialisationSupport;
+import org.simantics.debug.ui.ResourceSearch.IResourceFilter;
+import org.simantics.debug.ui.internal.Activator;
+import org.simantics.debug.ui.internal.DebugUtils;
+import org.simantics.layer0.Layer0;
+import org.simantics.operation.Layer0X;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.ui.selection.ResourceWorkbenchSelectionElement;
+import org.simantics.ui.workbench.dialogs.ResourceLabelProvider;
+import org.simantics.utils.Container;
+import org.simantics.utils.ui.BundleUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TODO Add Debugger Composite as preview!
+ */
+public class SearchResourceDialog extends FilteredItemsSelectionDialog {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SearchResourceDialog.class);
+
+ /**
+ * The default maximum amount of Dependencies index hits to produce as results.
+ */
+ private static final int DEFAULT_MAX_INDEX_HITS = 1000;
+
+ private static final Pattern ID_PATTERN = Pattern.compile("\\$([0-9]+)"); //$NON-NLS-1$
+
+ private static final String SEARCH_RESOURCE_DIALOG = "SearchResourceDialog"; //$NON-NLS-1$
+
+ private static final int SHOW_IN_BROWSER_ID = IDialogConstants.CLIENT_ID + 1;
+
+ private static final String SHOW_IN_BROWSER_LABEL = Messages.SearchResourceDialog_ShowInBrowser;
+
+ private Session session;
+ @SuppressWarnings("unused")
+ private IStructuredSelection selection;
+ private ResourceManager resourceManager;
+ private IResourceFilter resourceFilter = ResourceSearch.FILTER_ALL;
+
+ LabelProvider detailsLabelProvider = new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (element == null)
+ return "null"; //$NON-NLS-1$
+ // This may happen if multiple choice is enabled
+ if (element instanceof String)
+ return (String) element;
+ @SuppressWarnings("unchecked")
+ Container<Resource> rc = (Container<Resource>) element;
+ final Resource r = rc.get();
+ try {
+ return session.syncRequest(new Read<String>() {
+ @Override
+ public String perform(ReadGraph g) throws DatabaseException {
+ String name = NameUtils.getSafeName(g, r);
+ String uri = DebugUtils.getPossibleRootRelativePath(g, r);
+ return
+ "[" + r.getResourceId() + "] - " //$NON-NLS-1$ //$NON-NLS-2$
+ + name
+ + (uri != null ? " - " : "") //$NON-NLS-1$ //$NON-NLS-2$
+ + (uri != null ? uri : ""); //$NON-NLS-1$
+ }
+ });
+ } catch (DatabaseException e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SearchResourceDialog_ActivatorResourceLabelProviderFailed, e));
+ return ""; //$NON-NLS-1$
+ }
+ }
+ };
+
+ static class ElementLabelProvider extends ResourceLabelProvider {
+ public ElementLabelProvider(Display display) {
+ super(display);
+ }
+ @Override
+ public String getText(Object element) {
+ if (element==null)
+ return "null"; //$NON-NLS-1$
+ return element.toString();
+ }
+ @Override
+ public Image getImage(Object element) {
+ if (element == null)
+ return null;
+ @SuppressWarnings("unchecked")
+ Container<Resource> rc = (Container<Resource>) element;
+ final Resource r = rc.get();
+ return super.getImage(r);
+ }
+ };
+
+ ElementLabelProvider labelProvider;
+
+ public SearchResourceDialog(Session s, boolean multi, Shell shell, String title) {
+ this(s, multi, shell, title, null);
+ }
+
+ public SearchResourceDialog(Session s, boolean multi, Shell shell, String title, IStructuredSelection selection) {
+ super(shell, multi);
+ this.session = s;
+ this.selection = selection;
+ this.labelProvider = new ElementLabelProvider(shell.getDisplay());
+ setMessage(Messages.SearchResourceDialog_EnterNameResURIOrId);
+ setListLabelProvider(labelProvider);
+ setDetailsLabelProvider(detailsLabelProvider);
+ setTitle(title);
+ //setInitialPattern("*", FilteredItemsSelectionDialog.FULL_SELECTION);
+ setSelectionHistory(new ResourceSelectionHistory());
+ setSeparatorLabel(Messages.SearchResourceDialog_SeperatorLblPreviouslySelected);
+ }
+
+ @Override
+ protected void configureShell(Shell shell) {
+ this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), shell);
+ setImage((Image) resourceManager.get(BundleUtils.getImageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/cog_blue.png"))); //$NON-NLS-1$
+ super.configureShell(shell);
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
+ true);
+ createButton(parent, SHOW_IN_BROWSER_ID, SHOW_IN_BROWSER_LABEL,
+ true);
+ createButton(parent, IDialogConstants.CANCEL_ID,
+ IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ @Override
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == SHOW_IN_BROWSER_ID) {
+ okPressed();
+ LabeledResource lr = (LabeledResource) getFirstResult();
+ if (lr != null) {
+ ShowInBrowser.defaultExecute(new StructuredSelection(new ResourceWorkbenchSelectionElement(lr.resource)));
+ }
+ return;
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ class ResourceSelectionHistory extends FilteredItemsSelectionDialog.SelectionHistory {
+
+ @Override
+ protected Object restoreItemFromMemento(IMemento memento) {
+ String data = memento.getTextData();
+ try {
+ SerialisationSupport support = Simantics.getSession().getService(SerialisationSupport.class);
+ Resource r = support.getResource(Long.parseLong(data));
+ if (r == null)
+ return null;
+
+ String name = session.syncRequest(new UniqueRead<String>() {
+ @Override
+ public String perform(ReadGraph g) throws DatabaseException {
+ if (!resourceFilter.acceptResource(g, r))
+ return null;
+ try {
+ try {
+ return DebugUtils.getSafeLabel(g, r);
+ } catch (Exception ex) {
+ System.out.println("Exception thrown from restoreItemFromMemento"); //$NON-NLS-1$
+ }
+ } catch (Throwable t) {}
+ return "" + r.getResourceId(); //$NON-NLS-1$
+ }
+ });
+ if (name==null) return null;
+ return new LabeledResource(name, r);
+ } catch (NumberFormatException | DatabaseException e) {
+ LOGGER.info("Search memento restoration failed.", e); //$NON-NLS-1$
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void storeItemToMemento(Object item, IMemento memento) {
+ if(item instanceof Container) {
+ try {
+ SerialisationSupport support = Simantics.getSession().getService(SerialisationSupport.class);
+ memento.putTextData(String.valueOf(support.getRandomAccessId(((Container<Resource>)item).get())));
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+
+ @Override
+ protected Control createExtendedContentArea(Composite parent) {
+ return null;
+ }
+
+ @Override
+ protected ItemsFilter createFilter() {
+ // NOTE: filter must be created here.
+ return new ItemsFilterWithSearchResults();
+ }
+
+ private class ItemsFilterWithSearchResults extends ItemsFilter {
+ private Set<Object> searchResults = new HashSet<Object>();
+
+ public ItemsFilterWithSearchResults() {
+
+ final String pattern = getPattern();
+ final boolean findUris = pattern.trim().startsWith("http:/"); //$NON-NLS-1$
+ final long referencedResourceId = referencedResourceId(pattern);
+ final boolean findIds = referencedResourceId != 0;
+
+ searchResults.clear();
+ if (pattern.isEmpty()) return;
+ //progressMonitor.beginTask("Searching", IProgressMonitor.UNKNOWN);
+
+ try {
+ session.syncRequest(new ReadRequest() {
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ // Find by ID first.
+ if (findIds) {
+ try {
+ Resource r = graph.getService(SerialisationSupport.class).getResource(referencedResourceId);
+ searchResults.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r));
+ } catch (DatabaseException e) {
+ // No resource for specified id.
+ }
+ }
+ if (findUris) {
+ String uri = pattern;
+ if (uri.endsWith(Role.CHILD.getIdentifier())) {
+ uri = uri.substring(0, uri.length() - 1);
+ }
+ Resource r = graph.getPossibleResource(uri);
+ if (r != null) {
+ searchResults.add(new LabeledResource(DebugUtils.getSafeURI(graph, r), r));
+
+ Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(r));
+ for (Resource child : children.values()) {
+ searchResults.add(new LabeledResource(DebugUtils.getSafeURI(graph, child), child));
+ }
+ }
+ } else {
+ String[] terms = pattern.trim().split("\\s+"); //$NON-NLS-1$
+ if (terms.length == 0) return;
+
+ Resource project = Simantics.peekProjectResource();
+ if (project != null) {
+ Layer0 L0 = Layer0.getInstance(graph);
+ IResourceFilter rf = resourceFilter;
+ String filter = getFilterForResourceFilter(L0, rf);
+ if (!filter.isEmpty())
+ filter += " AND "; //$NON-NLS-1$
+
+ filter += Dependencies.FIELD_NAME_SEARCH + ":("; //$NON-NLS-1$
+ filter += Arrays.stream(terms).map(term -> "+" + IndexQueries.escape(term.toLowerCase(), false) + "*").collect(Collectors.joining(" ")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ filter +=")"; //$NON-NLS-1$
+
+ Set<Resource> indexRoots = new HashSet<>();
+ indexRoots.addAll(graph.syncRequest(new ObjectsWithType(project, L0.ConsistsOf, L0.IndexRoot)));
+ indexRoots.addAll(graph.syncRequest(new OntologiesFromLibrary(graph.getRootLibrary())));
+ for (Resource indexRoot : indexRoots) {
+ Collection<Resource> hits = find(graph, indexRoot, filter);
+ for (Resource r : hits) {
+ if (rf != null && !rf.acceptResource(graph, r))
+ continue;
+ searchResults.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r));
+ }
+ }
+ }
+ }
+ }
+
+ public Collection<Resource> find(ReadGraph graph, Resource index, String filter) throws DatabaseException {
+ //TimeLogger.resetTimeAndLog("find(" + graph.getURI(index) + ", " + filter + ")");
+ Collection<Resource> indexResult = graph.syncRequest(new QueryIndex(index, filter), TransientCacheListener.<Collection<Resource>>instance());
+ //TimeLogger.log("found " + indexResult.size());
+ return indexResult;
+ }
+
+ });
+ } catch (DatabaseException ex) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));
+ }
+
+ }
+
+ @Override
+ public boolean matchItem(Object item) {
+ return searchResults.contains(item);
+ }
+
+ @Override
+ public boolean isSubFilter(ItemsFilter filter) {
+ return false;
+ }
+
+ @Override
+ public boolean isConsistentItem(Object item) {
+ return true;
+ }
+
+ @Override
+ public boolean equalsFilter(ItemsFilter filter) {
+ return false;
+ }
+
+ public void fillContentProvider(final AbstractContentProvider contentProvider) {
+ for (Object item : searchResults) {
+ contentProvider.add(item, this);
+ }
+ }
+ }
+
+ @Override
+ protected void fillContentProvider(final AbstractContentProvider contentProvider,
+ final ItemsFilter itemsFilter, final IProgressMonitor progressMonitor)
+ throws CoreException {
+ ((ItemsFilterWithSearchResults) itemsFilter).fillContentProvider(contentProvider);
+ progressMonitor.done();
+ }
+
+ /**
+ * A (cacheable) query to optimize single index queries for immutable
+ * indexes such as ontologies.
+ */
+ static class QueryIndex extends BinaryRead<Resource, String, Collection<Resource>> {
+
+ public QueryIndex(Resource index, String filter) {
+ super(index, filter);
+ }
+
+ @Override
+ public Collection<Resource> perform(ReadGraph graph)
+ throws DatabaseException {
+ Layer0X L0X = Layer0X.getInstance(graph);
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Function dependencies = graph.syncRequest(new PossibleAdapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
+ if (dependencies == null)
+ return Collections.emptyList();
+
+ @SuppressWarnings("unchecked")
+ List<Resource> results = (List<Resource>) dependencies.apply(graph, parameter, parameter2, DEFAULT_MAX_INDEX_HITS);
+ if (results == null || results.isEmpty())
+ return Collections.emptyList();
+
+ // TreeSet to keep the results in deterministic order and to prevent duplicates.
+ Set<Resource> resultSet = new TreeSet<>();
+ for (Resource res : results) {
+ if (res != null && !resultSet.contains(res))
+ resultSet.add(res);
+ }
+ return new ArrayList<Resource>(resultSet);
+ }
+
+ }
+
+ private long referencedResourceId(String pattern) {
+ Matcher m = ID_PATTERN.matcher(pattern);
+ if (m.matches()) {
+ String id = m.group(1);
+ try {
+ return Long.parseLong(id);
+ } catch (NumberFormatException nfe) {
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ protected IDialogSettings getDialogSettings() {
+ IDialogSettings settings = Activator.getDefault().getDialogSettings()
+ .getSection(SEARCH_RESOURCE_DIALOG);
+ if (settings == null) {
+ settings = Activator.getDefault().getDialogSettings()
+ .addNewSection(SEARCH_RESOURCE_DIALOG);
+ }
+ return settings;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String getElementName(Object item) {
+ return ((Container<Resource>)item).get().getResourceId()+""; //$NON-NLS-1$
+ //return item.toString();
+ }
+
+ @Override
+ protected Comparator<?> getItemsComparator() {
+ return (arg0, arg1) -> {
+ return arg0.toString().compareTo(arg1.toString());
+ };
+ }
+
+ @Override
+ protected IStatus validateItem(Object item) {
+ return Status.OK_STATUS;
+ }
+
+ public IResourceFilter getResourceFilter() {
+ return resourceFilter;
+ }
+
+ public void setResourceFilter(IResourceFilter resourceFilter) {
+ this.resourceFilter = resourceFilter;
+ }
+
+ private String getFilterForResourceFilter(Layer0 l0, IResourceFilter filter) {
+ if (filter == null || filter == ResourceSearch.FILTER_ALL)
+ return ""; //$NON-NLS-1$
+ if (filter == ResourceSearch.FILTER_RELATIONS)
+ return IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, l0.Relation);
+ if (filter == ResourceSearch.FILTER_TYPES)
+ return IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, l0.Type);
+ return ""; //$NON-NLS-1$
+ }
+
+}