package org.simantics.ui.selection; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.handlers.HandlerUtil; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessor; import org.simantics.db.Resource; import org.simantics.db.common.primitiverequest.IsInstanceOf; import org.simantics.db.common.primitiverequest.Supertypes; import org.simantics.db.common.primitiverequest.Types; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.PossibleURI; import org.simantics.db.layer0.request.PossibleVariableRepresents; import org.simantics.db.layer0.request.VariableRead; import org.simantics.db.layer0.request.VariableURI; import org.simantics.db.layer0.variable.Variable; import org.simantics.utils.ui.ISelectionUtils; public class WorkbenchSelectionUtils { public static Resource getPossibleResource(ExecutionEvent event) throws DatabaseException { ISelection selection = HandlerUtil.getCurrentSelection(event); return getPossibleResource(selection); } public static Variable getPossibleVariable(ExecutionEvent event) throws DatabaseException { ISelection selection = HandlerUtil.getCurrentSelection(event); return getPossibleVariable(selection); } public static List getWorkbenchSelectionElements(ISelection selection) { return ISelectionUtils.filterSelection(selection, WorkbenchSelectionElement.class); } public static String getPossibleJSON(Object selection) throws DatabaseException { WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection); return element != null ? getPossibleJSON(element) : null; } public static Resource getPossibleResource(Object selection) throws DatabaseException { WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection); return element != null ? getPossibleResource(element) : null; } public static Variable getPossibleVariable(Object selection) throws DatabaseException { WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection); return element != null ? getPossibleVariable(element) : null; } public static Resource getPossibleResourceFromSelection(RequestProcessor processor, Object selection) throws DatabaseException { WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection); return element != null ? getPossibleResource(processor, element) : null; } public static Variable getPossibleVariableFromSelection(RequestProcessor processor, Object selection) throws DatabaseException { WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection); return element != null ? getPossibleVariable(processor, element) : null; } public static Variable getPossibleVariable(Object[] selection) throws DatabaseException { if(selection.length != 1) return null; if(!(selection[0] instanceof WorkbenchSelectionElement)) return null; return getPossibleVariable((WorkbenchSelectionElement)selection[0]); } public static T getPossibleElement(Object[] selection, WorkbenchSelectionContentType contentType) throws DatabaseException { if(selection.length != 1) return null; if(!(selection[0] instanceof WorkbenchSelectionElement)) return null; WorkbenchSelectionElement wse = (WorkbenchSelectionElement)selection[0]; return wse.getContent(contentType); } public static String getPossibleJSON(WorkbenchSelectionElement wse) throws DatabaseException { return getPossibleJSON(Simantics.getSession(), wse); } public static Resource getPossibleResource(WorkbenchSelectionElement wse) throws DatabaseException { return getPossibleResource(Simantics.getSession(), wse); } public static Variable getPossibleVariable(WorkbenchSelectionElement wse) throws DatabaseException { return getPossibleVariable(Simantics.getSession(), wse); } public static Variable getPossibleVariableSCL(ReadGraph graph, WorkbenchSelectionElement wse) throws DatabaseException { return getPossibleVariable(graph, wse); } public static Resource getPossibleResourceSCL(ReadGraph graph, WorkbenchSelectionElement wse) throws DatabaseException { return getPossibleResource(graph, wse); } public static String getPossibleJSON(RequestProcessor processor, Object input) throws DatabaseException { Variable var = getPossibleVariable(processor, input); Resource res = getPossibleResource(processor, input); String typesStr = getTypeResourceString(processor, res, var); if(var != null) { String uri = processor.syncRequest(new VariableURI(var)); return toJSONObjectString( "type", "\"Variable\"", "uri", safeQuotedString(uri), "typeResources", typesStr); } if(res != null) { String uri = processor.syncRequest(new PossibleURI(res)); return toJSONObjectString( "type", "\"Resource\"", "uri", safeQuotedString(uri), "typeResources", typesStr); } return "{ \"type\": \"Unknown\" }"; } public static Resource getPossibleResource(RequestProcessor processor, Object input) throws DatabaseException { return getPossibleResource(processor, input, null); } public static Resource getPossibleResource(RequestProcessor processor, Object input, Resource type) throws DatabaseException { if(input instanceof Collection && !((Collection)input).isEmpty()) { Object element = ((Collection)input).iterator().next(); if(element instanceof Resource) return (Resource)element; } Resource resource = getPossibleElement(input, new AnyResource(processor)); if(resource == null) return resource; if(type != null) { if(processor.sync(new IsInstanceOf(resource, type))) return resource; else return null; } return resource; } public static Variable getPossibleVariable(RequestProcessor processor, Object input) throws DatabaseException { return getPossibleElement(input, new AnyVariable(processor)); } public static T getPossibleElement(Object input, WorkbenchSelectionContentType contentType) { Object single = getPossibleSingleElement(input); if(single == null) return null; if(single instanceof WorkbenchSelectionElement) { WorkbenchSelectionElement element = (WorkbenchSelectionElement)single; return (T)element.getContent(contentType); } return null; } public static WorkbenchSelectionElement getPossibleSelectionElement(Object input) { if(input instanceof WorkbenchSelectionElement) return (WorkbenchSelectionElement)input; if(input instanceof Collection) { Collection c = (Collection)input; if(c.size() == 1) { Object o = c.iterator().next(); if(o instanceof WorkbenchSelectionElement) return (WorkbenchSelectionElement)o; } } return null; } // Internal helpers private static Object getPossibleSingleElement(Object input) { if(input instanceof WorkbenchSelectionElement) return input; if(input instanceof Collection) { Collection c = (Collection)input; if(c.size() == 1) return c.iterator().next(); } return null; } private static WorkbenchSelectionElement getPossibleWorkbenchSelectionElement(Object selection) { return getPossibleObject(selection, WorkbenchSelectionElement.class); } @SuppressWarnings("unchecked") private static T getPossibleObject(Object selection, Class clazz) { return clazz.isInstance(selection) ? (T) selection : ISelectionUtils.filterSingleSelection(selection, clazz); } private static class PossibleVariableType extends VariableRead { public PossibleVariableType(Variable var) { super(var); } @Override public Resource perform(ReadGraph graph) throws DatabaseException { return variable.getPossibleType(graph); } } private static String toJSONObjectString(String... keyValuePairs) { int len = keyValuePairs.length; assert (len & 1) == 0; StringBuilder sb = new StringBuilder(128); sb.append("{ "); int entryCount = 0; for (int i = 0; i < len; i += 2) { String value = keyValuePairs[i+1]; if (value != null && !value.isEmpty()) { if (entryCount > 0) sb.append(", "); sb.append("\"").append(keyValuePairs[i]).append("\": ").append(value); ++entryCount; } } sb.append(" }"); return sb.toString(); } private static String escapeQuotes(String s) { return s.indexOf('"') >= 0 ? s.replaceAll("\"", "\\\\\"") : s; } private static String safeQuotedString(String s) { return s != null && !s.isEmpty() ? "\"" + escapeQuotes(s) + "\"" : ""; } private static String toJSONStringArray(List strings) throws DatabaseException { // Sort the type strings to produce stable results if (strings.isEmpty()) return ""; return strings.stream() .map(WorkbenchSelectionUtils::escapeQuotes) .sorted() .collect(Collectors.joining("\", \"", "[\"", "\"]")); } private static String getTypeResourceString(RequestProcessor processor, Resource r, Variable v) throws DatabaseException { return toJSONStringArray( toPossibleURIs(processor, getTypes(processor, r, v))); } private static Set getTypes(RequestProcessor processor, Resource r, Variable v) throws DatabaseException { if (r == null && v != null) r = processor.syncRequest(new PossibleVariableRepresents(v)); if (r != null) return processor.syncRequest(new Types(r)); r = v != null ? processor.syncRequest(new PossibleVariableType(v)) : null; return r != null ? processor.syncRequest(new Supertypes(r)) : Collections.emptySet(); } private static List toPossibleURIs(RequestProcessor processor, Collection resources) throws DatabaseException { if (resources.isEmpty()) return Collections.emptyList(); List result = new ArrayList<>(resources.size()); for (Resource r : resources) { String uri = processor.syncRequest(new PossibleURI(r)); if (uri != null) result.add(uri); } return result; } }