X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.debug.ui%2Fsrc%2Forg%2Fsimantics%2Fdebug%2Fui%2FGraphDebugger.java;h=559b0e70275fe9ce3430eabc5a68ccd662202621;hp=4d2a19dfee2aee2a23f995036fd527aeeb39c902;hb=7e18cf26899ede3bb984f88c70d70faa1d61e514;hpb=6a4a43b278d6819c660182eb4954524d1757e077 diff --git a/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/GraphDebugger.java b/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/GraphDebugger.java index 4d2a19dfe..559b0e702 100644 --- a/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/GraphDebugger.java +++ b/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/GraphDebugger.java @@ -1,1551 +1,1542 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.debug.ui; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.lang.reflect.Array; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Path; -import org.eclipse.jface.action.IStatusLineManager; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.IDialogSettings; -import org.eclipse.jface.dialogs.IInputValidator; -import org.eclipse.jface.dialogs.InputDialog; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.jface.resource.ColorDescriptor; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.resource.LocalResourceManager; -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTError; -import org.eclipse.swt.browser.Browser; -import org.eclipse.swt.browser.LocationAdapter; -import org.eclipse.swt.browser.LocationEvent; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.DropTarget; -import org.eclipse.swt.dnd.DropTargetAdapter; -import org.eclipse.swt.dnd.DropTargetEvent; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.KeyAdapter; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IWorkbenchSite; -import org.simantics.databoard.Bindings; -import org.simantics.databoard.Databoard; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.error.BindingException; -import org.simantics.databoard.serialization.Serializer; -import org.simantics.databoard.type.ArrayType; -import org.simantics.databoard.type.Datatype; -import org.simantics.databoard.type.StringType; -import org.simantics.databoard.util.ObjectUtils; -import org.simantics.db.AsyncRequestProcessor; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.Statement; -import org.simantics.db.VirtualGraph; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.ResourceArray; -import org.simantics.db.common.procedure.adapter.ProcedureAdapter; -import org.simantics.db.common.request.Queries; -import org.simantics.db.common.request.ReadRequest; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.uri.ResourceToPossibleURI; -import org.simantics.db.common.utils.ListUtils; -import org.simantics.db.common.utils.NameUtils; -import org.simantics.db.common.utils.OrderedSetUtils; -import org.simantics.db.event.ChangeEvent; -import org.simantics.db.event.ChangeListener; -import org.simantics.db.exception.AdaptionException; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.exception.ResourceNotFoundException; -import org.simantics.db.exception.ValidationException; -import org.simantics.db.layer0.adapter.StringModifier; -import org.simantics.db.layer0.variable.RVI; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.service.ClusteringSupport; -import org.simantics.db.service.GraphChangeListenerSupport; -import org.simantics.db.service.SerialisationSupport; -import org.simantics.db.service.VirtualGraphSupport; -import org.simantics.db.service.XSupport; -import org.simantics.debug.ui.internal.Activator; -import org.simantics.debug.ui.internal.DebugUtils; -import org.simantics.debug.ui.internal.HashMultiMap; -import org.simantics.layer0.Layer0; -import org.simantics.ui.dnd.LocalObjectTransfer; -import org.simantics.ui.dnd.ResourceReferenceTransfer; -import org.simantics.ui.dnd.ResourceTransferUtils; -import org.simantics.ui.utils.ResourceAdaptionUtils; -import org.simantics.utils.Container; -import org.simantics.utils.FileUtils; -import org.simantics.utils.datastructures.BijectionMap; -import org.simantics.utils.datastructures.Callback; -import org.simantics.utils.strings.AlphanumComparator; -import org.simantics.utils.ui.ErrorLogger; -import org.simantics.utils.ui.PathUtils; -import org.simantics.utils.ui.workbench.WorkbenchUtils; - - -public class GraphDebugger extends Composite { - - public interface HistoryListener { - void historyChanged(); - } - - private static final String STATEMENT_PART_SEPARATOR = ","; - private final static String DEFAULT_DEBUGGER_CSS_FILE = "debugger.css"; - private final static String DEFAULT_DEBUGGER_CSS_PATH = "css/" + DEFAULT_DEBUGGER_CSS_FILE; - - private static int RESOURCE_NAME_MAX_LENGTH = 1000; - private static int RESOURCE_VALUE_MAX_SIZE = 16384; - - private final LocalResourceManager resourceManager; - - private String cssPath; - - private Browser browser; - private final ColorDescriptor green = ColorDescriptor.createFrom(new RGB(0x57, 0xbc, 0x95)); - - private final boolean displayClusters = true; - - private final BijectionMap links = new BijectionMap(); - private final LinkedList backHistory = new LinkedList(); - private final LinkedList forwardHistory = new LinkedList(); - private Resource currentElement = null; - - /** - * The Session used to access the graph. Received from outside of this - * class and therefore it is not disposed here, just used. - */ - private final Session session; - - private final CopyOnWriteArrayList historyListeners = new CopyOnWriteArrayList(); - - private final AsyncRequestProcessor updater; - - protected Layer0 L0; - - protected IWorkbenchSite site; - - private final ChangeListener changeListener = new ChangeListener() { - @Override - public void graphChanged(ChangeEvent e) { - // This makes sure that the transaction for updating this - // GraphDebugger get executed in a serialized fashion. - updater.asyncRequest(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - updateContent(graph, currentElement); - } - - }); - - } - }; - - /** - * @param parent - * @param style - * @param session - * @param resource the initial resource to debug or null for - * initially blank UI. - * @param site the workbench site that contains this debugger, for workbench - * service access - */ - public GraphDebugger(Composite parent, int style, final Session session, Resource resource, IWorkbenchSite site) { - this(parent, style, session, resource); - this.site = site; - } - - /** - * @param parent - * @param style - * @param session - * @param resource the initial resource to debug or null for - * initially blank UI. - */ - public GraphDebugger(Composite parent, int style, final Session session, Resource resource) { - super(parent, style); - Assert.isNotNull(session, "session is null"); - this.session = session; - this.currentElement = resource; - this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent); - - updater = session;//.getService(MergingGraphRequestProcessor.class); - - initializeCSS(); - - addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class); - support.removeListener(changeListener); - } - }); - } - - /** - * When given to setStatus, indicates that the message shouldn't be touched - * since null has a different meaning. - */ - private static final String DONT_TOUCH = "DONT_TOUCH"; - - protected void setStatus(String message, String error) { - IStatusLineManager status = WorkbenchUtils.getStatusLine(site); - if (status != null) { - if (message != DONT_TOUCH) - status.setMessage(message); - if (error != DONT_TOUCH) - status.setErrorMessage(error); - } - } - - public void defaultInitializeUI() { - setLayout(new GridLayout(2, false)); - setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - createResourceText(this); - createDropLabel(this); - createBrowser(this); - - } - - protected void initializeCSS() { - // Extract default css to a temporary location if necessary. - try { - IPath absolutePath = PathUtils.getAbsolutePath(Activator.PLUGIN_ID, DEFAULT_DEBUGGER_CSS_PATH); - if (absolutePath != null) { - cssPath = absolutePath.toFile().toURI().toString(); - } else { - File tempDir = FileUtils.getOrCreateTemporaryDirectory(false); - File css = new File(tempDir, DEFAULT_DEBUGGER_CSS_FILE); - if (!css.exists()) { - URL url = FileLocator.find(Activator.getDefault().getBundle(), new Path(DEFAULT_DEBUGGER_CSS_PATH), null); - if (url == null) - throw new FileNotFoundException("Could not find '" + DEFAULT_DEBUGGER_CSS_PATH + "' in bundle '" + Activator.PLUGIN_ID + "'"); - cssPath = FileUtils.copyResource(url, css, true).toURI().toString(); - } else { - cssPath = css.toURI().toString(); - } - } - } catch (IOException e) { - // CSS extraction failed, let's just live without it then. - ErrorLogger.defaultLogWarning(e); - } - } - - private static final String PROMPT_TEXT = "Enter resource ID (RID) or URI"; - - public void createResourceText(final Composite parent) { - final Text text = new Text(parent, SWT.BORDER); - text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); - text.setText(PROMPT_TEXT); - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, false).applyTo(text); - - text.addFocusListener(new FocusListener() { - @Override - public void focusLost(FocusEvent e) { - if (text.getText().trim().equals("")) { - text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); - text.setText(PROMPT_TEXT); - } - } - @Override - public void focusGained(FocusEvent e) { - if (text.getText().trim().equals(PROMPT_TEXT)) { - text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_BLACK)); - text.setText(""); - } - text.selectAll(); - } - }); - text.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.keyCode == SWT.CR) { - String input = text.getText(); - setLookupInput(input); - } - } - }); - - final Button button = new Button(parent, SWT.FLAT); - button.setText("&Lookup"); - button.setEnabled(false); - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(button); - - text.addKeyListener(new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - if (e.keyCode == 13) { - String input = text.getText(); - setLookupInput(input); - button.setFocus(); - } - } - }); - - button.addSelectionListener(new SelectionListener() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - } - @Override - public void widgetSelected(SelectionEvent e) { - String input = text.getText(); - setLookupInput(input); - } - }); - - text.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - String input = text.getText().trim(); - if (!input.equals(PROMPT_TEXT) && !input.equals("")) - button.setEnabled(true); - else - button.setEnabled(false); - } - }); - } - - public void setLookupInput(String input) { - // There's no harm in trimming out spaces from both ends of the input. - input = input.trim(); - - SerialisationSupport support = session.getService(SerialisationSupport.class); - if (input.startsWith("$")) { - try { - Resource r = support.getResource(Long.parseLong(input.substring(1))); - changeLocation(r); - } catch (NumberFormatException e1) { - // Ignore, may happen for crap input - setStatus(DONT_TOUCH, "Invalid '$'-prefixed input, expected resource ID"); - } catch (Exception e1) { - ErrorLogger.defaultLogError(e1); - setStatus(DONT_TOUCH, "Resource ID lookup failed. See Error Log."); - } - return; - } - - String[] parts = input.split("-"); - - if (parts.length == 1) { - try { - int resourceKey = Integer.parseInt(parts[0].trim()); - Resource r = support.getResource(resourceKey); - // Some validation, not enough though - ClusteringSupport cs = session.getService(ClusteringSupport.class); - long cluster = cs.getCluster(r); - if(cluster > 0) { - changeLocation(r); - } - } catch (NumberFormatException e1) { - // Ignore, may happen for crap input - setStatus(DONT_TOUCH, "Invalid input, expected transient resource ID"); - } catch (Exception e1) { - ErrorLogger.defaultLogError(e1); - setStatus(DONT_TOUCH, "Transient resource ID lookup failed. See Error Log."); - } - } else if (parts.length == 2) { - try { - int resourceIndex = Integer.parseInt(parts[1]); - long clusterId = Long.parseLong(parts[0]); - ClusteringSupport cs = session.getService(ClusteringSupport.class); - Resource r = cs.getResourceByIndexAndCluster(resourceIndex, clusterId); - changeLocation(r); - } catch (NumberFormatException e1) { - // Ignore, may happen for crap input - setStatus(DONT_TOUCH, "Invalid input, expected index & cluster IDs"); - } catch (Exception e1) { - ErrorLogger.defaultLogError(e1); - setStatus(DONT_TOUCH, "Index & cluster -based lookup failed. See Error Log."); - } - } - - // Try to see if the input data is an URI reference - try { - // First check that the input really is a proper URI. - String uri = input; - if (!input.equals("http:/") && input.endsWith("/")) - uri = input.substring(0, input.length() - 1); - new URI(uri); - Resource r = session.syncRequest( Queries.resource( uri ) ); - changeLocation(r); - return; - } catch (URISyntaxException e) { - // Ignore, this is not a proper URI at all. - } catch (ResourceNotFoundException e1) { - // Ok, this was an URI, but no resource was found. - setStatus(DONT_TOUCH, "Resource for URI '" + input + "' not found"); - return; - } catch (DatabaseException e1) { - setStatus(DONT_TOUCH, "URI lookup failed. See Error Log."); - ErrorLogger.defaultLogError(e1); - } - - setStatus(DONT_TOUCH, "Invalid input, resource ID or URI expected"); - } - - public Label createDropLabel(Composite parent) { - final Label label = new Label(parent, SWT.BORDER); - label.setAlignment(SWT.CENTER); - label.setText("Drag a resource here to examine it in this debugger!"); - label.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(2, 1).grab(true, false).applyTo(label); - - // Add resource id drop support to the drop-area. - DropTarget dropTarget = new DropTarget(label, DND.DROP_LINK | DND.DROP_COPY); - dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance(), ResourceReferenceTransfer.getInstance(), LocalObjectTransfer.getTransfer() }); - dropTarget.addDropListener(new DropTargetAdapter() { - @Override - public void dragEnter(DropTargetEvent event) { - event.detail = DND.DROP_LINK; - label.setBackground((Color) resourceManager.get(green)); - return; - } - @Override - public void dragLeave(DropTargetEvent event) { - label.setBackground(null); - } - - @Override - public void drop(DropTargetEvent event) { - label.setBackground(null); - ResourceArray[] data = parseEventData(event); - if (data == null || data.length != 1) { - event.detail = DND.DROP_NONE; - return; - } - final ResourceArray array = data[0]; - final Resource r = array.resources[array.resources.length - 1]; - - changeLocation(r); - } - - private ResourceArray[] parseEventData(DropTargetEvent event) { - //System.out.println("DATA: " + event.data); - if (event.data instanceof String) { - try { - SerialisationSupport support = session.getService(SerialisationSupport.class); - return ResourceTransferUtils.readStringTransferable(support, (String) event.data).toResourceArrayArray(); - } catch (IllegalArgumentException e) { - ErrorLogger.defaultLogError(e); - } catch (DatabaseException e) { - ErrorLogger.defaultLogError(e); - } - } - ResourceArray[] ret = ResourceAdaptionUtils.toResourceArrays(event.data); - if (ret.length > 0) - return ret; - return null; - } - }); - - return label; - } - - public Browser createBrowser(Composite parent) { - try { - browser = new Browser(parent, SWT.MOZILLA); - } catch (SWTError e) { - //System.out.println("Could not instantiate Browser: " + e.getMessage()); - browser = new Browser(parent, SWT.NONE); - } - GridDataFactory.fillDefaults().span(2, 1).grab(true, true).applyTo(browser); - - // Left/right arrows for back/forward - browser.addKeyListener(new KeyAdapter() { -// -// @Override -// public void keyPressed(KeyEvent e) { -// if (e.keyCode == SWT.F5) { -// refreshBrowser(); -// } -// } -// } - @Override - public void keyReleased(KeyEvent e) { -// System.out.println("key, char: " + e.keyCode + ", " + (int) e.character + " (" + e.character + ")"); - if (e.keyCode == SWT.BS) { - back(); - } - - if (e.keyCode == SWT.F5) { - refreshBrowser(); - } - - if ((e.stateMask & SWT.ALT) != 0) { - if (e.keyCode == SWT.ARROW_RIGHT) - forward(); - if (e.keyCode == SWT.ARROW_LEFT) - back(); - } - } - }); - - // Add listener for debugging functionality - browser.addLocationListener(new LocationAdapter() { - @Override - public void changing(LocationEvent event) { - String location = event.location; - if (location.startsWith("simantics:browser")) - location = "about:" + location.substring(17); - //System.out.println("changing: location=" + location); - - // Do not follow links that are meant as actions that are - // handled below. - event.doit = false; - if ("about:blank".equals(location)) { - // Just changing to the same old blank url is ok since it - // allows the browser to refresh itself. - event.doit = true; - } - - if (location.startsWith("about:-link")) { - String target = location.replace("about:-link", ""); - Resource element = links.getRight(target); - if (element == currentElement) { - event.doit = false; - return; - } - changeLocation(element); - } else if (location.startsWith("about:-remove")) { - String target = location.replace("about:-remove", ""); - String n[] = target.split(STATEMENT_PART_SEPARATOR); - if (n.length != 3) - return; - - final Resource s = links.getRight(n[0]); - final Resource p = links.getRight(n[1]); - final Resource o = links.getRight(n[2]); - - // Make sure this is what the use wants. - MessageDialog md = new MessageDialog( - getShell(), - "Confirm action...", - null, - "This action will remove the selected statement.\nAre you sure you want to proceed with this action?", - MessageDialog.QUESTION, new String[] { "Cancel", "Continue" }, 0); - if (md.open() != 1) { - return; - } - - session.asyncRequest(new WriteRequest() { - - @Override - public void perform(WriteGraph g) throws DatabaseException { - try { - List ls = OrderedSetUtils.toList(g, s); - if(ls.contains(o)) - OrderedSetUtils.remove(g, s, o); - } catch (DatabaseException e) { - - } - try { - List ls = ListUtils.toList(g, s); - if(ls.contains(o)) - ListUtils.removeElement(g, s, o); - } catch (DatabaseException e) { - - } - g.denyStatement(s, p, o); - } - - }, new Callback() { - - @Override - public void run(DatabaseException parameter) { - refreshBrowser(); - } - - }); - } else if (location.startsWith("about:-edit-value")) { - String target = location.replace("about:-edit-value", ""); - final Resource o = links.getRight(target); - - session.asyncRequest(new ReadRequest() { - - String previousValue; - - @Override - public void run(ReadGraph graph) throws DatabaseException { - - previousValue = getResourceName(graph, o); - final StringModifier modifier = graph.adapt(o, StringModifier.class); - getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - InputDialog dialog = new InputDialog( - getShell(), - "Edit Value", - null, - previousValue, - new IInputValidator() { - @Override - public String isValid(String newText) { - return modifier.isValid(newText); - } - }) { - private static final String DIALOG = "DebuggerEditValueDialog"; //$NON-NLS-1$ - private IDialogSettings dialogBoundsSettings; - @Override - protected IDialogSettings getDialogBoundsSettings() { - if (dialogBoundsSettings == null) { - IDialogSettings settings = Activator.getDefault().getDialogSettings(); - dialogBoundsSettings = settings.getSection(DIALOG); - if (dialogBoundsSettings == null) - dialogBoundsSettings = settings.addNewSection(DIALOG); - } - return dialogBoundsSettings; - } - @Override - protected Point getInitialSize() { - Point defaultSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true); - Point result = super.getInitialSize(); - if (defaultSize.equals(result)) - return new Point(600, 400); - return result; - } - protected int getShellStyle() { - return super.getShellStyle() | SWT.RESIZE; - } - protected org.eclipse.swt.widgets.Control createDialogArea(Composite parent) { - Composite composite = (Composite) super.createDialogArea(parent); - getText().setLayoutData( - new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL - | GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); - { - Label label = new Label(composite, SWT.NONE); - label.moveAbove(getText()); - label.setText("Input new property value. For numeric vector values, separate numbers with comma (',')."); - GridData data = new GridData(GridData.GRAB_HORIZONTAL - | GridData.HORIZONTAL_ALIGN_FILL - | GridData.VERTICAL_ALIGN_CENTER); - data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); - label.setLayoutData(data); - label.setFont(parent.getFont()); - } - return composite; - } - protected int getInputTextStyle() { - return SWT.MULTI | SWT.BORDER; - } - }; - int ok = dialog.open(); - if (ok != Dialog.OK) - return; - - final String value = dialog.getValue(); - session.asyncRequest(new WriteRequest() { - @Override - public void perform(WriteGraph g) throws DatabaseException { - //modifier.modify( g, htmlEscape( value ) ); - modifier.modify( g, value ); - } - }, new Callback() { - @Override - public void run(DatabaseException parameter) { - if (parameter != null) - ErrorLogger.defaultLogError(parameter); - refreshBrowser(); - } - }); - return; - } - }); - } - - }, new ProcedureAdapter() { - @Override - public void exception(Throwable t) { - ErrorLogger.defaultLogError(t); - } - }); - - } - } - }); - - // Schedule a request that updates the browser content. - refreshBrowser(); - GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class); - support.removeListener(changeListener); - - return browser; - } - - public void refreshBrowser() { - if (currentElement == null) - return; - - // Schedule a request that updates the browser content. - updater.asyncRequest(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - updateContent(graph, currentElement); - } - - }); - - } - - public Resource getDebuggerLocation() { - return currentElement; - } - - public void changeLocation(Resource element) { - if (currentElement != null) { - backHistory.addLast(currentElement); - } - currentElement = element; - forwardHistory.clear(); - - refreshBrowser(); - setStatus(DONT_TOUCH, null); - fireHistoryChanged(); - } - - public void addHistoryListener(HistoryListener l) { - historyListeners.add(l); - } - - public void removeHistoryListener(HistoryListener l) { - historyListeners.remove(l); - } - - private void fireHistoryChanged() { - for (HistoryListener l : historyListeners) - l.historyChanged(); - } - - public boolean hasBackHistory() { - return backHistory.isEmpty(); - } - - public boolean hasForwardHistory() { - return forwardHistory.isEmpty(); - } - - public void back() { - if (backHistory.isEmpty()) - return; - - forwardHistory.addFirst(currentElement); - currentElement = backHistory.removeLast(); - - refreshBrowser(); - fireHistoryChanged(); - } - - public void forward() { - if (forwardHistory.isEmpty()) - return; - - backHistory.addLast(currentElement); - currentElement = forwardHistory.removeFirst(); - - refreshBrowser(); - fireHistoryChanged(); - } - - protected String toName(Object o) { - Class clazz = o.getClass(); - if (clazz.isArray()) { - int length = Array.getLength(o); - if (length > RESOURCE_NAME_MAX_LENGTH) { - if (o instanceof byte[]) { - byte[] arr = (byte[]) o; - byte[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); - return truncated("byte", Arrays.toString(arr2), arr.length); - } else if (o instanceof int[]) { - int[] arr = (int[]) o; - int[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); - return truncated("int", Arrays.toString(arr2), arr.length); - } else if (o instanceof long[]) { - long[] arr = (long[]) o; - long[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); - return truncated("long", Arrays.toString(arr2), arr.length); - } else if (o instanceof float[]) { - float[] arr = (float[]) o; - float[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); - return truncated("float", Arrays.toString(arr2), arr.length); - } else if (o instanceof double[]) { - double[] arr = (double[]) o; - double[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); - return truncated("double", Arrays.toString(arr2), arr.length); - } else if (o instanceof boolean[]) { - boolean[] arr = (boolean[]) o; - boolean[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); - return truncated("boolean", Arrays.toString(arr2), arr.length); - } else if (o instanceof Object[]) { - Object[] arr = (Object[]) o; - Object[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); - return truncated("Object", Arrays.toString(arr2), arr.length); - } else { - return "Unknown big array " + o.getClass(); - } - } else { - return o.getClass().getComponentType() + "[" + length + "] = " + ObjectUtils.toString(o); - } - } - return null; - } - - protected String truncated(String type, String string, int originalLength) { - return type + "[" + RESOURCE_NAME_MAX_LENGTH + "/" + originalLength + "] = " + string; - } - - public static String htmlEscape(String s) - { - return s.replace("&", "&").replace("<", "<").replace(">", ">").replace("\n", "
"); - } - - /** - * Get resource name(?) - * - * @param graph - * @param r - * @return - */ - protected String getResourceName(ReadGraph graph, Resource r) { - try { - - String name = null; - //System.out.println("hasValue(" + NameUtils.getSafeName(graph, r, true)); - if (graph.hasValue(r)) { - // too large array may cause application to run out of memory. - //System.out.println("getValue(" + NameUtils.getSafeName(graph, r, true)); - Datatype type = graph.getPossibleRelatedValue(r, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); - if (type!=null) { - Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class ); - if (type.equals( rviBinding.type() )) { - RVI rvi = graph.getValue(r, rviBinding); - - try { - Variable v = Variables.getConfigurationContext( graph, currentElement ); - name = rvi.asString(graph, v); -// name = rvi.resolve(graph, v).getURI(graph); - } catch (DatabaseException dbe ) { - name = rvi.toString( graph ); - } - } else { - long valueSize = NameUtils.getPossibleValueSize(graph, r); - if (valueSize > RESOURCE_NAME_MAX_LENGTH) { -// Binding b = Bindings.getBinding(type); -// Object v = graph.getValue(r, b); -// Serializer s = Bindings.getSerializerUnchecked(b); -// int size = s.getSize(v); - name = "Approx. " + valueSize + " byte literal of type " + type.toSingleLineString(); - } else { - Binding b = Bindings.getBinding(type); - Object v = graph.getValue(r, b); - if (b.type() instanceof StringType) { - name = (String) graph.getValue(r, b); - } else { - name = b.toString(v, false); - } - if (type instanceof ArrayType){ - name = name.substring(1, name.length()-1); - } - } - } - } else { - Object o = graph.getValue(r); - name = toName(o); - } - - if(name.isEmpty()) { - name = ""; - } - - } - // Does resource have a file ?? - if (name == null) { -// try { -// Accessor accessor = graph.getAccessor(r); -// name = "File of type " + accessor.type().toSingleLineString(); -// } catch (DatabaseException e) { -// // No file, try next alternative. -// } - } - if (name == null) { - //name = graph.adapt(r, String.class); - //if(name.isEmpty()) - name = DebugUtils.getSafeLabel(graph, r); - if (name.isEmpty()) - name = ""; - } -// ClusteringSupport support = graph.getSession().getService(ClusteringSupport.class); -// if(name == null) -// return "[" + r.getResourceId() + " - " + support.getCluster(r) + "]"; - if(displayClusters) { -// SessionDebug debug = graph.getSession().getDebug(); -// name += " (" + debug.getCluster(r) + ")"; - } - return name; - } catch (AdaptionException e) { -// e.printStackTrace(); - String name = safeReadableString(graph, r); -// try { -// MessageService.defaultLog(new DetailStatus(IDetailStatus.DEBUG, Activator.PLUGIN_ID, 0, NLS.bind(Messages.Name_adaption_problem, MessageUtil.resource(session, r, "this resource")), e)); -// } catch (ReferenceSerializationException e1) { -// e1.printStackTrace(); -// ErrorLogger.defaultLogWarning(e1); -// } - return name; - } catch (Exception e) { - ErrorLogger.defaultLogError(e); - String name = safeReadableString(graph, r); -// try { -// MessageService.defaultLog(new DetailStatus(IDetailStatus.DEBUG, Activator.PLUGIN_ID, 0, NLS.bind(Messages.Name_formulation_problem, MessageUtil.resource(session, r, "this resource")), e)); -// } catch (ReferenceSerializationException e1) { -// e1.printStackTrace(); -// ErrorLogger.defaultLogWarning(e1); -// } - return name; - } - } - - private String getResourceRef(ReadGraph graph, Resource r) throws DatabaseException { - String name; - try { - Layer0 L0 = Layer0.getInstance(graph); - if (graph.isInstanceOf(r, L0.Assertion)) { - Resource pred = graph.getSingleObject(r, L0.HasPredicate); - // Don't know how I encountered this but it seems to be possible in some cases.. - // Resource obj = graph.getSingleObject(r, L0.HasObject); - Resource obj = graph.getPossibleObject(r, L0.HasObject); - String tmp = htmlEscape( getResourceName(graph, pred) + " -> " + (obj == null ? "No object ?" : getResourceName(graph, obj)) + " (Assertion)" ); - name = tmp.substring(0, Math.min(80, tmp.length())); - } else { - String resourceName = getResourceName(graph, r); - if(resourceName.equals("Inverse")) { - Resource inverse = graph.getPossibleInverse(r); - if(inverse != null && graph.hasStatement(inverse, L0.ConsistsOf, r)) - resourceName = getResourceName(graph, inverse) + "/Inverse"; - } - String tmp = htmlEscape( resourceName ); - name = tmp.substring(0, Math.min(80, tmp.length())); - } - - } catch (OutOfMemoryError e) { - name = "OutOfMemoryError"; - } - String ret = "" - + name - + ""; - if (graph.isInstanceOf(r, L0.Literal)) { - ret += " " - + "(edit)" - + ""; - } - return ret; - } - - private String getStatementRemoveRef(Resource s, Resource p, Resource o) { - return "X"; - } - - private void updatePred(StringBuffer content, ReadGraph graph, Resource subj, Resource pred, List stats) throws DatabaseException { - // Generate output content from statements - String[][] objects = new String[stats.size()][]; - for (int i = 0; i < stats.size(); ++i) { - Resource stmSubject = stats.get(i)[0]; - Resource object = stats.get(i)[1]; - - objects[i] = new String[4]; - objects[i][0] = getLinkString(object); - objects[i][1] = htmlEscape( getResourceName(graph, object) ); - objects[i][2] = getResourceRef(graph, object); - - // Make a note if the statement was acquired. - if(!stmSubject.equals(subj)) { - objects[i][3] = " (in " + getResourceRef(graph, stmSubject) + ")"; - } - } - - // Sort statements by object name - Arrays.sort(objects, new Comparator() { - @Override - public int compare(String[] o1, String[] o2) { - return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(o1[1], o2[1]); - } - }); - - // Output table rows - for (int i = 0; i < objects.length; ++i) { - content.append(""); - // Predicate column - if (i == 0) - content.append("").append(getResourceRef(graph, pred)).append(""); - - // Object column - if (objects[i][3] == null) content.append(""); - else content.append(""); - - content.append(objects[i][2]); - if (objects[i][3] != null) - content.append(objects[i][3]); - - content.append(""); - - VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); - VirtualGraph vg = vgs.getGraph(graph, subj, pred, links.getRight(objects[i][0])); - - if(vg != null) { - content.append("").append(vg.toString()).append(""); - } else { - content.append("DB"); - } - - - // Statement remove -link column - // Only allowed for non-acquired statements. - if (objects[i][3] == null) { - content.append(""); - content.append(getStatementRemoveRef(subj, pred, links.getRight(objects[i][0]))); - content.append(""); - } - content.append(""); - } - } - - private void updateTag(StringBuffer content, ReadGraph graph, Resource subj, Resource tag) throws DatabaseException { - - // Generate output content from statements - String ref = getResourceRef(graph, tag); - - content.append(""); - content.append("").append(ref).append(""); - //content.append("" + name + ""); - content.append(""); - content.append(getStatementRemoveRef(subj, tag, subj)); - content.append(""); - content.append(""); - - } - - private void updateOrderedSet(StringBuffer content, ReadGraph graph, Resource subj) throws DatabaseException { - //List list = OrderedSetUtils.toList(graph, subj); - /* - // Generate output content from statements - String[][] objects = new String[stats.size()][]; - for (int i = 0; i < stats.size(); ++i) { - Resource stmSubject = stats.get(i)[0]; - Resource object = stats.get(i)[1]; - - objects[i] = new String[4]; - objects[i][0] = getLinkString(object); - objects[i][1] = getResourceName(graph, object); - objects[i][2] = getResourceRef(graph, object); - - // Make a note if the statement was acquired. - if(!stmSubject.equals(subj)) { - objects[i][3] = " (acquired from " + getResourceRef(graph, stmSubject) + ")"; - } - } - - // Sort statements by object name - Arrays.sort(objects, new Comparator() { - @Override - public int compare(String[] o1, String[] o2) { - return o1[1].compareTo(o2[1]); - } - });*/ - - List list = new ArrayList(); - Resource cur = subj; - while(true) { - try { - cur = OrderedSetUtils.next(graph, subj, cur); - } catch(DatabaseException e) { - list.add("BROKEN ORDERED SET:
" + e.getMessage() + ""); - Resource inv = graph.getPossibleInverse(subj); - for(Statement stat : graph.getStatements(cur, L0.IsRelatedTo)) { - if(stat.getSubject().equals(cur)) { - if(stat.getPredicate().equals(subj)) { - list.add("next " + getResourceRef(graph, stat.getObject())); - } - else if(stat.getPredicate().equals(inv)) { - list.add("prev " + getResourceRef(graph, stat.getObject())); - } - } - } - break; - } - if(cur.equals(subj)) - break; - list.add(getResourceRef(graph, cur)); - } - - // Output table rows - for (int i = 0; i < list.size() ; ++i) { - content.append(""); - // Predicate column - if (i == 0) - content.append("Ordered Set Elements"); - - // Object column - content.append(""); - content.append(list.get(i)); - content.append(""); - - // Statement remove -link column - // Only allowed for non-acquired statements. - /*if (objects[i][3] == null) { - content.append(""); - content.append(getStatementRemoveRef(subj, pred, links.getRight(objects[i][0]))); - content.append(""); - }*/ - content.append(""); - } - } - - private void updateLinkedList(StringBuffer content, ReadGraph graph, Resource subj) throws DatabaseException { - - List list = new ArrayList(); - - try { - List resources = ListUtils.toList(graph, subj); - for(Resource element : resources) { - list.add(getResourceRef(graph, element)); - } - } catch (DatabaseException e) { - throw new ValidationException(e); - } - - // Output table rows - for (int i = 0; i < list.size() ; ++i) { - content.append(""); - // Predicate column - if (i == 0) - content.append("Linked List Elements"); - - // Object column - content.append(""); - content.append(list.get(i)); - content.append("DB"); - - // Statement remove -link column - // Only allowed for non-acquired statements. - /*if (objects[i][3] == null) { - content.append(""); - content.append(getStatementRemoveRef(subj, pred, links.getRight(objects[i][0]))); - content.append(""); - }*/ - content.append(""); - } - } - - protected synchronized void updateContent(final ReadGraph graph, Resource... resources) throws DatabaseException { - L0 = Layer0.getInstance(graph); - - links.clear(); - StringBuffer content = new StringBuffer(); - - // Generate HTML -page - content.append("\n\n") - .append(getHead()) - .append("\n\n") - .append("\n") - .append("
\n\n"); - - for (Resource r : resources) { - if (r == null) - continue; - - String uri = null; - try { - uri = graph.syncRequest(new ResourceToPossibleURI(r)); - } catch (Exception e) { - ErrorLogger.defaultLogError(e); - uri = "Cannot get URI: " + e.getMessage(); - } - - // Top DIV - content.append("
\n"); - content.append("\n"); - if (uri != null) { - content.append("\n"); - } - - XSupport xs = graph.getService(XSupport.class); - boolean immutable = xs.getImmutable(r); - - Collection statements = graph.getStatements(r, L0.IsWeaklyRelatedTo); - HashMultiMap map = new HashMultiMap(); - for(org.simantics.db.Statement statement : statements) { - Resource predicate = null; - Resource subject = null; - Resource obj = null; - try { - predicate = statement.getPredicate(); - subject = statement.getSubject(); - obj = statement.getObject(); - map.add(predicate, new Resource[] {subject, obj}); - } catch (Throwable e) { - ErrorLogger.defaultLogError("Cannot find statement " + subject + " " + predicate + " " + obj, e); - } - } - SerialisationSupport ss = graph.getSession().getService(SerialisationSupport.class); - ClusteringSupport support = graph.getSession().getService(ClusteringSupport.class); - content.append(""); - if (immutable) - content.append(""); - content.append("\n"); - - boolean isClusterSet = support.isClusterSet(r); - Resource parentSet = support.getClusterSetOfCluster(r); - String parentSetURI = parentSet != null ? graph.getPossibleURI(parentSet) : null; - - content.append(""); - if (isClusterSet) - content.append(""); - content.append("\n"); - - // If the resource has a value, show it. - String resourceValue = getResourceValue(graph, r); - if (resourceValue != null) { - content - .append("\n"); - } - - // Close #top - content.append("
URI").append(uri).append("
Identifiers"); - content.append("") - .append(" RID = $").append(r.getResourceId()) - .append(" Resource Key = ").append(ss.getTransientId(r)) - .append(" CID = ").append(support.getCluster(r)); - content.append("[IMMUTABLE]
Clustering"); - content.append(""); - - if(parentSetURI != null) - content.append(" Containing cluster set = ").append(parentSetURI); - else if (parentSet != null) - content.append(" Containing cluster set = ").append(parentSet.toString()); - else - content.append(" Not in any cluster set "); - - content.append("[CLUSTER SET]
Attached value") - .append(htmlEscape(resourceValue)) - .append("
\n"); - content.append("
\n"); - - content.append("\n
\n"); - content.append("\n") - .append("") - .append(""); - - boolean isOrderedSet = graph.isInstanceOf(r, L0.OrderedSet); - boolean isLinkedList = graph.isInstanceOf(r, L0.List); -// map.remove(r); - - // BASIC INFORMATION: - for (Resource pred : - new Resource[] {L0.HasName, L0.InstanceOf, - L0.Inherits, L0.SubrelationOf, - L0.PartOf, L0.ConsistsOf}) - if (map.containsKey(pred)) - updatePred(content, graph, r, pred, map.remove(pred)); - - // TAGS - content.append(""); - for(Statement stm : statements) { - if(stm.getSubject().equals(stm.getObject())) { - updateTag(content, graph, r, stm.getPredicate()); - map.remove(stm.getPredicate()); - } - } - - // ORDERED SETS - content.append(""); - for(Statement stm : statements) { - Resource predicate = stm.getPredicate(); - if(graph.isInstanceOf(stm.getPredicate(), L0.OrderedSet)) { - updateTag(content, graph, r, stm.getPredicate()); - if(map.get(stm.getPredicate()) != null && map.get(stm.getPredicate()).size() == 1) - map.remove(stm.getPredicate()); - } - Resource inverse = graph.getPossibleInverse(predicate); - if (inverse != null) { - if(graph.isInstanceOf(inverse, L0.OrderedSet)) { - if(map.get(stm.getPredicate()) != null && map.get(stm.getPredicate()).size() == 1) - map.remove(stm.getPredicate()); - } - } else { - // FIXME : should we infor missing inverse - } - } - - // IS RELATED TO - content.append(""); - - // ELEMENTS OF ORDERED SET - if(isOrderedSet) { - //content.append(""); - try { - updateOrderedSet(content, graph, r); - } catch (ValidationException e) { - content.append(""); - } - } - - // ELEMENTS OF LINKED LIST - if(isLinkedList) { - //content.append(""); - try { - updateLinkedList(content, graph, r); - } catch (ValidationException e) { - content.append(""); - } - } - - // IS RELATED TO (other) - Resource[] preds = map.keySet().toArray(new Resource[0]); - final Map strmap = new HashMap(preds.length); - for(Resource pred : preds) { - String str = htmlEscape( getResourceName(graph, pred) ); - if(str == null) - str = ""; - strmap.put(pred, str); - } - Arrays.sort(preds, new Comparator() { - @Override - public int compare(Resource o1, Resource o2) { - return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(strmap.get(o1), strmap.get(o2)); - } - }); - for(Resource pred : preds) - if(graph.isSubrelationOf(pred, L0.IsRelatedTo)) - updatePred(content, graph, r, pred, map.get(pred)); - - // OTHER STATEMENTS - content.append(""); - for(Resource pred : preds) - if(!graph.isSubrelationOf(pred, L0.IsRelatedTo)) - updatePred(content, graph, r, pred, map.get(pred)); - content.append("
PredicateObjectGraph
Basic information
Tags
Ordered Sets
Is Related To
Ordered set
BROKEN ORDERED SET:
").append(e.getMessage()).append("
Ordered set
BROKEN LINKED LIST:
").append(e.getMessage()).append("
Other statements
\n"); - } - // Close #data - content.append("
\n\n"); - // Close #mainContent - content.append("
\n"); - content.append("\n\n"); - - // Update content - final String finalContent = content.toString(); - if (!isDisposed()) { - getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - if (!browser.isDisposed()) - browser.setText(finalContent); - } - }); - } - } - - private String getResourceValue(ReadGraph graph, Resource r) { - try { - if (graph.hasValue(r)) { - // too large array may cause application to run out of memory. - //System.out.println("getValue(" + NameUtils.getSafeName(graph, r, true)); - Datatype type = graph.getPossibleRelatedValue(r, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); - if (type != null) { - Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class ); - if (type.equals( rviBinding.type() )) { - RVI rvi = graph.getValue(r, rviBinding); - try { - Variable v = Variables.getConfigurationContext( graph, r ); - return rvi.asString(graph, v); - } catch (DatabaseException dbe ) { - return rvi.toString( graph ); - } - } else { - Binding b = Bindings.getBinding(type); - Object v = graph.getValue(r, b); - Serializer s = Bindings.getSerializerUnchecked(b); - int size = s.getSize(v); - if (size > RESOURCE_VALUE_MAX_SIZE) { - return "Approx. " + size + " byte literal of type " + type.toSingleLineString(); - } else { - return b.toString(v, false); - } - } - } else { - Object o = graph.getValue(r); - return toName(o); - } - } - return null; - } catch (DatabaseException e) { - return e.getMessage(); - } catch (IOException e) { - return e.getMessage(); - } catch (BindingException e) { - return e.getMessage(); - } - } - - private static String safeReadableString(ReadGraph g, Resource r) { - try { - return NameUtils.getSafeName(g, r); - } catch(Throwable throwable) { - ErrorLogger.defaultLogError(throwable); - return ""+throwable.getClass().getName()+" "+throwable.getMessage()+""; - } - } - -// private static String safeReadableString(IEntity t) { -// try { -// return ResourceDebugUtils.getReadableNameForEntity(t); -// } catch(Throwable throwable) { -// throwable.printStackTrace(); -// return ""+throwable.getClass().getName()+" "+throwable.getMessage()+""; -// } -// } - - private String getLinkString(Container t) { - String link = links.getLeft(t.get()); - if(link == null) { - link = UUID.randomUUID().toString(); - links.map(link, t.get()); - } - return link; - } - -// private String getPropertyEditString(Container t) { -// String link = links.getLeft(t.get()); -// if(link == null) { -// link = UUID.randomUUID().toString(); -// links.map(link, t.get()); -// } -// return link; -// } - - private String getStatementString(Resource _s, Resource _p, Resource _o) { - String s = getLinkString(_s); - String p = getLinkString(_p); - String o = getLinkString(_o); - return s + STATEMENT_PART_SEPARATOR + p + STATEMENT_PART_SEPARATOR + o; - } - -// private String getStatementString(Statement stm) { -// String s = getLinkString(stm.getSubject()); -// String p = getLinkString(stm.getPredicate()); -// String o = getLinkString(stm.getObject()); -// return s + STATEMENT_PART_SEPARATOR + p + STATEMENT_PART_SEPARATOR + o; -// } - -// private String toOutgoingTableRow(IEntity subject, Statement stm) { -// boolean isAcquired = !subject.equals(stm.getSubject()); -// -// String plainCell = "%s"; -// String hrefCell = "%s"; -// String formatTemplate = isAcquired -// ? "\n{0}\n{1}\n{1}\n{1}\n" -// : "\n{1}\n{1}\n{1}\n{1}\n"; -// String format = NLS.bind(formatTemplate, plainCell, hrefCell); -//// System.out.println("format: " + format); -// -// IEntity s = stm.getSubject(); -// IEntity p = stm.getPredicate(); -// IEntity o = stm.getObject(); -// -//// String timePart = "[" + timeToString(t.getBegin()) + ", " + timeToString(t.getEnd()) + "]"; -// -// try { -// return !isAcquired -// ? String.format(format, -// "about:blank-remove" + getStatementString(stm), "Remove", -// "about:blank-link" + getLinkString(s), safeReadableString(s), -// "about:blank-link" + getLinkString(p), safeReadableString(p), -// "about:blank-link" + getLinkString(o), safeReadableString(o)) -// : String.format(format, -// "Acquired", -// "about:blank-link" + getLinkString(s), safeReadableString(s), -// "about:blank-link" + getLinkString(p), safeReadableString(p), -// "about:blank-link" + getLinkString(o), safeReadableString(o) -// ); -// } catch (Throwable throwable) { -// return ""+throwable.getClass().getName()+" "+throwable.getMessage()+""; -// } -// } - -// private String intervalToString(Interval time) { -// return timeToString(time.getBegin()) + ", " + timeToString(time.getEnd()); -// } -// -// DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); -// -// private String timeToString(long time) { -// if (time == Long.MIN_VALUE) -// return "-∞"; -// if (time == Long.MAX_VALUE) -// return "+∞"; -// //return String.valueOf(time); -// Date d = new Date(time); -// return dateTimeFormat.format(d); -// } - - private String getHead() { - String result = ""; - if (cssPath != null) { - result = ""; - } - return result; - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 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.debug.ui; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Array; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.ColorDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTError; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.browser.LocationAdapter; +import org.eclipse.swt.browser.LocationEvent; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.DropTargetAdapter; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.Databoard; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.serialization.Serializer; +import org.simantics.databoard.type.ArrayType; +import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.type.StringType; +import org.simantics.databoard.util.ObjectUtils; +import org.simantics.db.AsyncRequestProcessor; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.Statement; +import org.simantics.db.VirtualGraph; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.ResourceArray; +import org.simantics.db.common.procedure.adapter.ProcedureAdapter; +import org.simantics.db.common.request.Queries; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.uri.ResourceToPossibleURI; +import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.event.ChangeEvent; +import org.simantics.db.event.ChangeListener; +import org.simantics.db.exception.AdaptionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.ResourceNotFoundException; +import org.simantics.db.exception.ValidationException; +import org.simantics.db.layer0.adapter.StringModifier; +import org.simantics.db.layer0.variable.RVI; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.service.ClusteringSupport; +import org.simantics.db.service.GraphChangeListenerSupport; +import org.simantics.db.service.SerialisationSupport; +import org.simantics.db.service.VirtualGraphSupport; +import org.simantics.db.service.XSupport; +import org.simantics.debug.ui.internal.Activator; +import org.simantics.debug.ui.internal.DebugUtils; +import org.simantics.debug.ui.internal.HashMultiMap; +import org.simantics.layer0.Layer0; +import org.simantics.ui.dnd.LocalObjectTransfer; +import org.simantics.ui.dnd.ResourceReferenceTransfer; +import org.simantics.ui.dnd.ResourceTransferUtils; +import org.simantics.ui.utils.ResourceAdaptionUtils; +import org.simantics.utils.Container; +import org.simantics.utils.FileUtils; +import org.simantics.utils.datastructures.BijectionMap; +import org.simantics.utils.strings.AlphanumComparator; +import org.simantics.utils.ui.ErrorLogger; +import org.simantics.utils.ui.PathUtils; +import org.simantics.utils.ui.workbench.WorkbenchUtils; + + +public class GraphDebugger extends Composite { + + public interface HistoryListener { + void historyChanged(); + } + + private static final String STATEMENT_PART_SEPARATOR = ","; //$NON-NLS-1$ + private final static String DEFAULT_DEBUGGER_CSS_FILE = "debugger.css"; //$NON-NLS-1$ + private final static String DEFAULT_DEBUGGER_CSS_PATH = "css/" + DEFAULT_DEBUGGER_CSS_FILE; //$NON-NLS-1$ + + private static int RESOURCE_NAME_MAX_LENGTH = 1000; + private static int RESOURCE_VALUE_MAX_SIZE = 16384; + + private final LocalResourceManager resourceManager; + + private String cssPath; + + private Browser browser; + private final ColorDescriptor green = ColorDescriptor.createFrom(new RGB(0x57, 0xbc, 0x95)); + + private final boolean displayClusters = true; + + private final BijectionMap links = new BijectionMap(); + private final LinkedList backHistory = new LinkedList(); + private final LinkedList forwardHistory = new LinkedList(); + private Resource currentElement = null; + + /** + * The Session used to access the graph. Received from outside of this + * class and therefore it is not disposed here, just used. + */ + private final Session session; + + private final CopyOnWriteArrayList historyListeners = new CopyOnWriteArrayList(); + + private final AsyncRequestProcessor updater; + + protected Layer0 L0; + + protected IWorkbenchSite site; + + private final ChangeListener changeListener = new ChangeListener() { + @Override + public void graphChanged(ChangeEvent e) { + // This makes sure that the transaction for updating this + // GraphDebugger get executed in a serialized fashion. + updater.asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + updateContent(graph, currentElement); + } + + }); + + } + }; + + /** + * @param parent + * @param style + * @param session + * @param resource the initial resource to debug or null for + * initially blank UI. + * @param site the workbench site that contains this debugger, for workbench + * service access + */ + public GraphDebugger(Composite parent, int style, final Session session, Resource resource, IWorkbenchSite site) { + this(parent, style, session, resource); + this.site = site; + } + + /** + * @param parent + * @param style + * @param session + * @param resource the initial resource to debug or null for + * initially blank UI. + */ + public GraphDebugger(Composite parent, int style, final Session session, Resource resource) { + super(parent, style); + Assert.isNotNull(session, "session is null"); //$NON-NLS-1$ + this.session = session; + this.currentElement = resource; + this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent); + + updater = session;//.getService(MergingGraphRequestProcessor.class); + + initializeCSS(); + + addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class); + support.removeListener(changeListener); + } + }); + } + + /** + * When given to setStatus, indicates that the message shouldn't be touched + * since null has a different meaning. + */ + private static final String DONT_TOUCH = "DONT_TOUCH"; //$NON-NLS-1$ + + protected void setStatus(String message, String error) { + IStatusLineManager status = WorkbenchUtils.getStatusLine(site); + if (status != null) { + if (message != DONT_TOUCH) + status.setMessage(message); + if (error != DONT_TOUCH) + status.setErrorMessage(error); + } + } + + public void defaultInitializeUI() { + setLayout(new GridLayout(2, false)); + setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + createResourceText(this); + createDropLabel(this); + createBrowser(this); + + } + + protected void initializeCSS() { + // Extract default css to a temporary location if necessary. + try { + IPath absolutePath = PathUtils.getAbsolutePath(Activator.PLUGIN_ID, DEFAULT_DEBUGGER_CSS_PATH); + if (absolutePath != null) { + cssPath = absolutePath.toFile().toURI().toString(); + } else { + File tempDir = FileUtils.getOrCreateTemporaryDirectory(false); + File css = new File(tempDir, DEFAULT_DEBUGGER_CSS_FILE); + if (!css.exists()) { + URL url = FileLocator.find(Activator.getDefault().getBundle(), new Path(DEFAULT_DEBUGGER_CSS_PATH), null); + if (url == null) + throw new FileNotFoundException("Could not find '" + DEFAULT_DEBUGGER_CSS_PATH + "' in bundle '" + Activator.PLUGIN_ID + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + cssPath = FileUtils.copyResource(url, css, true).toURI().toString(); + } else { + cssPath = css.toURI().toString(); + } + } + } catch (IOException e) { + // CSS extraction failed, let's just live without it then. + ErrorLogger.defaultLogWarning(e); + } + } + + private static final String PROMPT_TEXT = Messages.GraphDebugger_EnterResourceIDorURI; + + public void createResourceText(final Composite parent) { + final Text text = new Text(parent, SWT.BORDER); + text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); + text.setText(PROMPT_TEXT); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, false).applyTo(text); + + text.addFocusListener(new FocusListener() { + @Override + public void focusLost(FocusEvent e) { + if (text.getText().trim().equals("")) { //$NON-NLS-1$ + text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); + text.setText(PROMPT_TEXT); + } + } + @Override + public void focusGained(FocusEvent e) { + if (text.getText().trim().equals(PROMPT_TEXT)) { + text.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_BLACK)); + text.setText(""); //$NON-NLS-1$ + } + text.selectAll(); + } + }); + text.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.CR) { + String input = text.getText(); + setLookupInput(input); + } + } + }); + + final Button button = new Button(parent, SWT.FLAT); + button.setText(Messages.GraphDebugger_Lookup); + button.setEnabled(false); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(button); + + text.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == 13) { + String input = text.getText(); + setLookupInput(input); + button.setFocus(); + } + } + }); + + button.addSelectionListener(new SelectionListener() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + @Override + public void widgetSelected(SelectionEvent e) { + String input = text.getText(); + setLookupInput(input); + } + }); + + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + String input = text.getText().trim(); + if (!input.equals(PROMPT_TEXT) && !input.equals("")) //$NON-NLS-1$ + button.setEnabled(true); + else + button.setEnabled(false); + } + }); + } + + public void setLookupInput(String input) { + // There's no harm in trimming out spaces from both ends of the input. + input = input.trim(); + + SerialisationSupport support = session.getService(SerialisationSupport.class); + if (input.startsWith("$")) { //$NON-NLS-1$ + try { + Resource r = support.getResource(Long.parseLong(input.substring(1))); + changeLocation(r); + } catch (NumberFormatException e1) { + // Ignore, may happen for crap input + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusInvalidPrefixedInput); + } catch (Exception e1) { + ErrorLogger.defaultLogError(e1); + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusResourceIDFailed); + } + return; + } + + String[] parts = input.split("-"); //$NON-NLS-1$ + + if (parts.length == 1) { + try { + int resourceKey = Integer.parseInt(parts[0].trim()); + Resource r = support.getResource(resourceKey); + // Some validation, not enough though + ClusteringSupport cs = session.getService(ClusteringSupport.class); + long cluster = cs.getCluster(r); + if(cluster > 0) { + changeLocation(r); + } + } catch (NumberFormatException e1) { + // Ignore, may happen for crap input + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusInvalidInput); + } catch (Exception e1) { + ErrorLogger.defaultLogError(e1); + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusTransientResourceID); + } + } else if (parts.length == 2) { + try { + int resourceIndex = Integer.parseInt(parts[1]); + long clusterId = Long.parseLong(parts[0]); + ClusteringSupport cs = session.getService(ClusteringSupport.class); + Resource r = cs.getResourceByIndexAndCluster(resourceIndex, clusterId); + changeLocation(r); + } catch (NumberFormatException e1) { + // Ignore, may happen for crap input + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusInvalidInputExpectIdxClusterIds); + } catch (Exception e1) { + ErrorLogger.defaultLogError(e1); + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusIndexLookpuFailed); + } + } + + // Try to see if the input data is an URI reference + try { + // First check that the input really is a proper URI. + String uri = input; + if (!input.equals("http:/") && input.endsWith("/")) //$NON-NLS-1$ //$NON-NLS-2$ + uri = input.substring(0, input.length() - 1); + new URI(uri); + Resource r = session.syncRequest( Queries.resource( uri ) ); + changeLocation(r); + return; + } catch (URISyntaxException e) { + // Ignore, this is not a proper URI at all. + } catch (ResourceNotFoundException e1) { + // Ok, this was an URI, but no resource was found. + setStatus(DONT_TOUCH, NLS.bind( Messages.GraphDebugger_StatusResourceforURI , input )); + return; + } catch (DatabaseException e1) { + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusURIlookupFailed); + ErrorLogger.defaultLogError(e1); + } + + setStatus(DONT_TOUCH, Messages.GraphDebugger_StatusInvalidInputResIdORURIExpected); + } + + public Label createDropLabel(Composite parent) { + final Label label = new Label(parent, SWT.BORDER); + label.setAlignment(SWT.CENTER); + label.setText(Messages.GraphDebugger_LabelDragResource); + label.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(2, 1).grab(true, false).applyTo(label); + + // Add resource id drop support to the drop-area. + DropTarget dropTarget = new DropTarget(label, DND.DROP_LINK | DND.DROP_COPY); + dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance(), ResourceReferenceTransfer.getInstance(), LocalObjectTransfer.getTransfer() }); + dropTarget.addDropListener(new DropTargetAdapter() { + @Override + public void dragEnter(DropTargetEvent event) { + event.detail = DND.DROP_LINK; + label.setBackground((Color) resourceManager.get(green)); + return; + } + @Override + public void dragLeave(DropTargetEvent event) { + label.setBackground(null); + } + + @Override + public void drop(DropTargetEvent event) { + label.setBackground(null); + ResourceArray[] data = parseEventData(event); + if (data == null || data.length != 1) { + event.detail = DND.DROP_NONE; + return; + } + final ResourceArray array = data[0]; + final Resource r = array.resources[array.resources.length - 1]; + + changeLocation(r); + } + + private ResourceArray[] parseEventData(DropTargetEvent event) { + //System.out.println("DATA: " + event.data); + if (event.data instanceof String) { + try { + SerialisationSupport support = session.getService(SerialisationSupport.class); + return ResourceTransferUtils.readStringTransferable(support, (String) event.data).toResourceArrayArray(); + } catch (IllegalArgumentException e) { + ErrorLogger.defaultLogError(e); + } catch (DatabaseException e) { + ErrorLogger.defaultLogError(e); + } + } + ResourceArray[] ret = ResourceAdaptionUtils.toResourceArrays(event.data); + if (ret.length > 0) + return ret; + return null; + } + }); + + return label; + } + + public Browser createBrowser(Composite parent) { + try { + browser = new Browser(parent, SWT.WEBKIT); + } catch (SWTError e) { + //System.out.println("Could not instantiate Browser: " + e.getMessage()); + browser = new Browser(parent, SWT.NONE); + } + GridDataFactory.fillDefaults().span(2, 1).grab(true, true).applyTo(browser); + + // Left/right arrows for back/forward + browser.addKeyListener(new KeyAdapter() { +// +// @Override +// public void keyPressed(KeyEvent e) { +// if (e.keyCode == SWT.F5) { +// refreshBrowser(); +// } +// } +// } + @Override + public void keyReleased(KeyEvent e) { +// System.out.println("key, char: " + e.keyCode + ", " + (int) e.character + " (" + e.character + ")"); + if (e.keyCode == SWT.BS) { + back(); + } + + if (e.keyCode == SWT.F5) { + refreshBrowser(); + } + + if ((e.stateMask & SWT.ALT) != 0) { + if (e.keyCode == SWT.ARROW_RIGHT) + forward(); + if (e.keyCode == SWT.ARROW_LEFT) + back(); + } + } + }); + + // Add listener for debugging functionality + browser.addLocationListener(new LocationAdapter() { + @Override + public void changing(LocationEvent event) { + String location = event.location; + if (location.startsWith("simantics:browser")) //$NON-NLS-1$ + location = "about:" + location.substring(17); //$NON-NLS-1$ + //System.out.println("changing: location=" + location); + + // Do not follow links that are meant as actions that are + // handled below. + event.doit = false; + if ("about:blank".equals(location)) { //$NON-NLS-1$ + // Just changing to the same old blank url is ok since it + // allows the browser to refresh itself. + event.doit = true; + } + + if (location.startsWith("about:-link")) { //$NON-NLS-1$ + String target = location.replace("about:-link", ""); //$NON-NLS-1$ //$NON-NLS-2$ + Resource element = links.getRight(target); + if (element == currentElement) { + event.doit = false; + return; + } + changeLocation(element); + } else if (location.startsWith("about:-remove")) { //$NON-NLS-1$ + String target = location.replace("about:-remove", ""); //$NON-NLS-1$ //$NON-NLS-2$ + String n[] = target.split(STATEMENT_PART_SEPARATOR); + if (n.length != 3) + return; + + final Resource s = links.getRight(n[0]); + final Resource p = links.getRight(n[1]); + final Resource o = links.getRight(n[2]); + + // Make sure this is what the use wants. + MessageDialog md = new MessageDialog( + getShell(), + Messages.GraphDebugger_ConfirmActionsDots, + null, + Messages.GraphDebugger_ConfirmActionsDotsMsg, + MessageDialog.QUESTION, new String[] { Messages.GraphDebugger_Cancel, Messages.GraphDebugger_Continue }, 0); + if (md.open() != 1) { + return; + } + + session.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) throws DatabaseException { + try { + List ls = OrderedSetUtils.toList(g, s); + if(ls.contains(o)) + OrderedSetUtils.remove(g, s, o); + } catch (DatabaseException e) { + + } + try { + List ls = ListUtils.toList(g, s); + if(ls.contains(o)) + ListUtils.removeElement(g, s, o); + } catch (DatabaseException e) { + + } + g.denyStatement(s, p, o); + } + + }, parameter -> refreshBrowser() + ); + } else if (location.startsWith("about:-edit-value")) { //$NON-NLS-1$ + String target = location.replace("about:-edit-value", ""); //$NON-NLS-1$ //$NON-NLS-2$ + final Resource o = links.getRight(target); + + session.asyncRequest(new ReadRequest() { + + String previousValue; + + @Override + public void run(ReadGraph graph) throws DatabaseException { + + previousValue = getResourceName(graph, o); + final StringModifier modifier = graph.adapt(o, StringModifier.class); + getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + InputDialog dialog = new InputDialog( + getShell(), + Messages.GraphDebugger_EditValue, + null, + previousValue, + new IInputValidator() { + @Override + public String isValid(String newText) { + return modifier.isValid(newText); + } + }) { + private static final String DIALOG = "DebuggerEditValueDialog"; //$NON-NLS-1$ + private IDialogSettings dialogBoundsSettings; + @Override + protected IDialogSettings getDialogBoundsSettings() { + if (dialogBoundsSettings == null) { + IDialogSettings settings = Activator.getDefault().getDialogSettings(); + dialogBoundsSettings = settings.getSection(DIALOG); + if (dialogBoundsSettings == null) + dialogBoundsSettings = settings.addNewSection(DIALOG); + } + return dialogBoundsSettings; + } + @Override + protected Point getInitialSize() { + Point defaultSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + Point result = super.getInitialSize(); + if (defaultSize.equals(result)) + return new Point(600, 400); + return result; + } + protected int getShellStyle() { + return super.getShellStyle() | SWT.RESIZE; + } + protected org.eclipse.swt.widgets.Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + getText().setLayoutData( + new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL + | GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); + { + Label label = new Label(composite, SWT.NONE); + label.moveAbove(getText()); + label.setText(Messages.GraphDebugger_InputNewPropertyValue); + GridData data = new GridData(GridData.GRAB_HORIZONTAL + | GridData.HORIZONTAL_ALIGN_FILL + | GridData.VERTICAL_ALIGN_CENTER); + data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); + label.setLayoutData(data); + label.setFont(parent.getFont()); + } + return composite; + } + protected int getInputTextStyle() { + return SWT.MULTI | SWT.BORDER; + } + }; + int ok = dialog.open(); + if (ok != Dialog.OK) + return; + + final String value = dialog.getValue(); + session.asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph g) throws DatabaseException { + //modifier.modify( g, htmlEscape( value ) ); + modifier.modify( g, value ); + } + }, parameter -> { + if (parameter != null) + ErrorLogger.defaultLogError(parameter); + refreshBrowser(); + }); + return; + } + }); + } + + }, new ProcedureAdapter() { + @Override + public void exception(Throwable t) { + ErrorLogger.defaultLogError(t); + } + }); + + } + } + }); + + // Schedule a request that updates the browser content. + refreshBrowser(); + GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class); + support.removeListener(changeListener); + + return browser; + } + + public void refreshBrowser() { + if (currentElement == null) + return; + + // Schedule a request that updates the browser content. + updater.asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + updateContent(graph, currentElement); + } + + }); + + } + + public Resource getDebuggerLocation() { + return currentElement; + } + + public void changeLocation(Resource element) { + if (currentElement != null) { + backHistory.addLast(currentElement); + } + currentElement = element; + forwardHistory.clear(); + + refreshBrowser(); + setStatus(DONT_TOUCH, null); + fireHistoryChanged(); + } + + public void addHistoryListener(HistoryListener l) { + historyListeners.add(l); + } + + public void removeHistoryListener(HistoryListener l) { + historyListeners.remove(l); + } + + private void fireHistoryChanged() { + for (HistoryListener l : historyListeners) + l.historyChanged(); + } + + public boolean hasBackHistory() { + return backHistory.isEmpty(); + } + + public boolean hasForwardHistory() { + return forwardHistory.isEmpty(); + } + + public void back() { + if (backHistory.isEmpty()) + return; + + forwardHistory.addFirst(currentElement); + currentElement = backHistory.removeLast(); + + refreshBrowser(); + fireHistoryChanged(); + } + + public void forward() { + if (forwardHistory.isEmpty()) + return; + + backHistory.addLast(currentElement); + currentElement = forwardHistory.removeFirst(); + + refreshBrowser(); + fireHistoryChanged(); + } + + protected String toName(Object o) { + Class clazz = o.getClass(); + if (clazz.isArray()) { + int length = Array.getLength(o); + if (length > RESOURCE_NAME_MAX_LENGTH) { + if (o instanceof byte[]) { + byte[] arr = (byte[]) o; + byte[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); + return truncated("byte", Arrays.toString(arr2), arr.length); //$NON-NLS-1$ + } else if (o instanceof int[]) { + int[] arr = (int[]) o; + int[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); + return truncated("int", Arrays.toString(arr2), arr.length); //$NON-NLS-1$ + } else if (o instanceof long[]) { + long[] arr = (long[]) o; + long[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); + return truncated("long", Arrays.toString(arr2), arr.length); //$NON-NLS-1$ + } else if (o instanceof float[]) { + float[] arr = (float[]) o; + float[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); + return truncated("float", Arrays.toString(arr2), arr.length); //$NON-NLS-1$ + } else if (o instanceof double[]) { + double[] arr = (double[]) o; + double[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); + return truncated("double", Arrays.toString(arr2), arr.length); //$NON-NLS-1$ + } else if (o instanceof boolean[]) { + boolean[] arr = (boolean[]) o; + boolean[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); + return truncated("boolean", Arrays.toString(arr2), arr.length); //$NON-NLS-1$ + } else if (o instanceof Object[]) { + Object[] arr = (Object[]) o; + Object[] arr2 = Arrays.copyOf(arr, RESOURCE_NAME_MAX_LENGTH); + return truncated("Object", Arrays.toString(arr2), arr.length); //$NON-NLS-1$ + } else { + return "Unknown big array " + o.getClass(); //$NON-NLS-1$ + } + } else { + return o.getClass().getComponentType() + "[" + length + "] = " + ObjectUtils.toString(o); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + return null; + } + + protected String truncated(String type, String string, int originalLength) { + return type + "[" + RESOURCE_NAME_MAX_LENGTH + "/" + originalLength + "] = " + string; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + public static String htmlEscape(String s) + { + return s.replace("&", "&").replace("<", "<").replace(">", ">").replace("\n", "
"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + } + + /** + * Get resource name(?) + * + * @param graph + * @param r + * @return + */ + protected String getResourceName(ReadGraph graph, Resource r) { + try { + + String name = null; + //System.out.println("hasValue(" + NameUtils.getSafeName(graph, r, true)); + if (graph.hasValue(r)) { + // too large array may cause application to run out of memory. + //System.out.println("getValue(" + NameUtils.getSafeName(graph, r, true)); + Datatype type = graph.getPossibleRelatedValue(r, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); + if (type!=null) { + Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class ); + if (type.equals( rviBinding.type() )) { + RVI rvi = graph.getValue(r, rviBinding); + + try { + Variable v = Variables.getConfigurationContext( graph, currentElement ); + name = rvi.asString(graph, v); +// name = rvi.resolve(graph, v).getURI(graph); + } catch (DatabaseException dbe ) { + name = rvi.toString( graph ); + } + } else { + long valueSize = NameUtils.getPossibleValueSize(graph, r); + if (valueSize > RESOURCE_NAME_MAX_LENGTH) { +// Binding b = Bindings.getBinding(type); +// Object v = graph.getValue(r, b); +// Serializer s = Bindings.getSerializerUnchecked(b); +// int size = s.getSize(v); + name = "Approx. " + valueSize + " byte literal of type " + type.toSingleLineString(); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + Binding b = Bindings.getBinding(type); + Object v = graph.getValue(r, b); + if (b.type() instanceof StringType) { + name = (String) graph.getValue(r, b); + } else { + name = b.toString(v, false); + } + if (type instanceof ArrayType){ + name = name.substring(1, name.length()-1); + } + } + } + } else { + Object o = graph.getValue(r); + name = toName(o); + } + + if(name.isEmpty()) { + name = ""; //$NON-NLS-1$ + } + + } + // Does resource have a file ?? + if (name == null) { +// try { +// Accessor accessor = graph.getAccessor(r); +// name = "File of type " + accessor.type().toSingleLineString(); +// } catch (DatabaseException e) { +// // No file, try next alternative. +// } + } + if (name == null) { + //name = graph.adapt(r, String.class); + //if(name.isEmpty()) + name = DebugUtils.getSafeLabel(graph, r); + if (name.isEmpty()) + name = ""; //$NON-NLS-1$ + } +// ClusteringSupport support = graph.getSession().getService(ClusteringSupport.class); +// if(name == null) +// return "[" + r.getResourceId() + " - " + support.getCluster(r) + "]"; + if(displayClusters) { +// SessionDebug debug = graph.getSession().getDebug(); +// name += " (" + debug.getCluster(r) + ")"; + } + return name; + } catch (AdaptionException e) { +// e.printStackTrace(); + String name = safeReadableString(graph, r); +// try { +// MessageService.defaultLog(new DetailStatus(IDetailStatus.DEBUG, Activator.PLUGIN_ID, 0, NLS.bind(Messages.Name_adaption_problem, MessageUtil.resource(session, r, "this resource")), e)); +// } catch (ReferenceSerializationException e1) { +// e1.printStackTrace(); +// ErrorLogger.defaultLogWarning(e1); +// } + return name; + } catch (Exception e) { + ErrorLogger.defaultLogError(e); + String name = safeReadableString(graph, r); +// try { +// MessageService.defaultLog(new DetailStatus(IDetailStatus.DEBUG, Activator.PLUGIN_ID, 0, NLS.bind(Messages.Name_formulation_problem, MessageUtil.resource(session, r, "this resource")), e)); +// } catch (ReferenceSerializationException e1) { +// e1.printStackTrace(); +// ErrorLogger.defaultLogWarning(e1); +// } + return name; + } + } + + private String getResourceRef(ReadGraph graph, Resource r) throws DatabaseException { + String name; + try { + Layer0 L0 = Layer0.getInstance(graph); + if (graph.isInstanceOf(r, L0.Assertion)) { + Resource pred = graph.getPossibleObject(r, L0.HasPredicate); + // Don't know how I encountered this but it seems to be possible in some cases.. + // Resource obj = graph.getSingleObject(r, L0.HasObject); + Resource obj = graph.getPossibleObject(r, L0.HasObject); + String tmp = htmlEscape( (pred == null ? "No predicate ?" : getResourceName(graph, pred)) + " -> " + (obj == null ? "No object ?" : getResourceName(graph, obj)) + " (Assertion)" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + name = tmp.substring(0, Math.min(80, tmp.length())); + } else { + String resourceName = getResourceName(graph, r); + if(resourceName.equals("Inverse")) { //$NON-NLS-1$ + Resource inverse = graph.getPossibleInverse(r); + if(inverse != null && graph.hasStatement(inverse, L0.ConsistsOf, r)) + resourceName = getResourceName(graph, inverse) + "/Inverse"; //$NON-NLS-1$ + } + String tmp = htmlEscape( resourceName ); + name = tmp.substring(0, Math.min(80, tmp.length())); + } + + } catch (OutOfMemoryError e) { + name = "OutOfMemoryError"; //$NON-NLS-1$ + } + String ret = "" //$NON-NLS-1$ //$NON-NLS-2$ + + name + + ""; //$NON-NLS-1$ + if (graph.isInstanceOf(r, L0.Literal)) { + ret += " " //$NON-NLS-1$ //$NON-NLS-2$ + + "(edit)" //$NON-NLS-1$ + + ""; //$NON-NLS-1$ + } + return ret; + } + + private String getStatementRemoveRef(Resource s, Resource p, Resource o) { + return "X"; //$NON-NLS-1$ + } + + private void updatePred(StringBuffer content, ReadGraph graph, Resource subj, Resource pred, List stats) throws DatabaseException { + // Generate output content from statements + String[][] objects = new String[stats.size()][]; + for (int i = 0; i < stats.size(); ++i) { + Resource stmSubject = stats.get(i)[0]; + Resource object = stats.get(i)[1]; + + objects[i] = new String[4]; + objects[i][0] = getLinkString(object); + objects[i][1] = htmlEscape( getResourceName(graph, object) ); + objects[i][2] = getResourceRef(graph, object); + + // Make a note if the statement was acquired. + if(!stmSubject.equals(subj)) { + objects[i][3] = " (in " + getResourceRef(graph, stmSubject) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + // Sort statements by object name + Arrays.sort(objects, new Comparator() { + @Override + public int compare(String[] o1, String[] o2) { + return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(o1[1], o2[1]); + } + }); + + // Output table rows + for (int i = 0; i < objects.length; ++i) { + content.append(""); //$NON-NLS-1$ + // Predicate column + if (i == 0) + content.append("").append(getResourceRef(graph, pred)).append(""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + // Object column + if (objects[i][3] == null) content.append(""); //$NON-NLS-1$ + else content.append(""); //$NON-NLS-1$ + + content.append(objects[i][2]); + if (objects[i][3] != null) + content.append(objects[i][3]); + + content.append(""); //$NON-NLS-1$ + + VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); + VirtualGraph vg = vgs.getGraph(graph, subj, pred, links.getRight(objects[i][0])); + + if(vg != null) { + content.append("").append(vg.toString()).append(""); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + content.append("DB"); //$NON-NLS-1$ + } + + + // Statement remove -link column + // Only allowed for non-acquired statements. + if (objects[i][3] == null) { + content.append(""); //$NON-NLS-1$ + content.append(getStatementRemoveRef(subj, pred, links.getRight(objects[i][0]))); + content.append(""); //$NON-NLS-1$ + } + content.append(""); //$NON-NLS-1$ + } + } + + private void updateTag(StringBuffer content, ReadGraph graph, Resource subj, Resource tag) throws DatabaseException { + + // Generate output content from statements + String ref = getResourceRef(graph, tag); + + content.append(""); //$NON-NLS-1$ + content.append("").append(ref).append(""); //$NON-NLS-1$ //$NON-NLS-2$ + //content.append("" + name + ""); + content.append(""); //$NON-NLS-1$ + content.append(getStatementRemoveRef(subj, tag, subj)); + content.append(""); //$NON-NLS-1$ + content.append(""); //$NON-NLS-1$ + + } + + private void updateOrderedSet(StringBuffer content, ReadGraph graph, Resource subj) throws DatabaseException { + //List list = OrderedSetUtils.toList(graph, subj); + /* + // Generate output content from statements + String[][] objects = new String[stats.size()][]; + for (int i = 0; i < stats.size(); ++i) { + Resource stmSubject = stats.get(i)[0]; + Resource object = stats.get(i)[1]; + + objects[i] = new String[4]; + objects[i][0] = getLinkString(object); + objects[i][1] = getResourceName(graph, object); + objects[i][2] = getResourceRef(graph, object); + + // Make a note if the statement was acquired. + if(!stmSubject.equals(subj)) { + objects[i][3] = " (acquired from " + getResourceRef(graph, stmSubject) + ")"; + } + } + + // Sort statements by object name + Arrays.sort(objects, new Comparator() { + @Override + public int compare(String[] o1, String[] o2) { + return o1[1].compareTo(o2[1]); + } + });*/ + + List list = new ArrayList(); + Resource cur = subj; + while(true) { + try { + cur = OrderedSetUtils.next(graph, subj, cur); + } catch(DatabaseException e) { + list.add("BROKEN ORDERED SET:
" + e.getMessage() + ""); //$NON-NLS-1$ //$NON-NLS-2$ + Resource inv = graph.getPossibleInverse(subj); + for(Statement stat : graph.getStatements(cur, L0.IsRelatedTo)) { + if(stat.getSubject().equals(cur)) { + if(stat.getPredicate().equals(subj)) { + list.add("next " + getResourceRef(graph, stat.getObject())); //$NON-NLS-1$ + } + else if(stat.getPredicate().equals(inv)) { + list.add("prev " + getResourceRef(graph, stat.getObject())); //$NON-NLS-1$ + } + } + } + break; + } + if(cur.equals(subj)) + break; + list.add(getResourceRef(graph, cur)); + } + + // Output table rows + for (int i = 0; i < list.size() ; ++i) { + content.append(""); //$NON-NLS-1$ + // Predicate column + if (i == 0) + content.append("Ordered Set Elements"); //$NON-NLS-1$ //$NON-NLS-2$ + + // Object column + content.append(""); //$NON-NLS-1$ + content.append(list.get(i)); + content.append(""); //$NON-NLS-1$ + + // Statement remove -link column + // Only allowed for non-acquired statements. + /*if (objects[i][3] == null) { + content.append(""); + content.append(getStatementRemoveRef(subj, pred, links.getRight(objects[i][0]))); + content.append(""); + }*/ + content.append(""); //$NON-NLS-1$ + } + } + + private void updateLinkedList(StringBuffer content, ReadGraph graph, Resource subj) throws DatabaseException { + + List list = new ArrayList(); + + try { + List resources = ListUtils.toList(graph, subj); + for(Resource element : resources) { + list.add(getResourceRef(graph, element)); + } + } catch (DatabaseException e) { + throw new ValidationException(e); + } + + // Output table rows + for (int i = 0; i < list.size() ; ++i) { + content.append(""); //$NON-NLS-1$ + // Predicate column + if (i == 0) + content.append("Linked List Elements"); //$NON-NLS-1$ //$NON-NLS-2$ + + // Object column + content.append(""); //$NON-NLS-1$ + content.append(list.get(i)); + content.append("DB"); //$NON-NLS-1$ + + // Statement remove -link column + // Only allowed for non-acquired statements. + /*if (objects[i][3] == null) { + content.append(""); + content.append(getStatementRemoveRef(subj, pred, links.getRight(objects[i][0]))); + content.append(""); + }*/ + content.append(""); //$NON-NLS-1$ + } + } + + protected synchronized void updateContent(final ReadGraph graph, Resource... resources) throws DatabaseException { + L0 = Layer0.getInstance(graph); + + links.clear(); + StringBuffer content = new StringBuffer(); + + // Generate HTML -page + content.append("\n\n") //$NON-NLS-1$ + .append(getHead()) + .append("\n\n") //$NON-NLS-1$ + .append("\n") //$NON-NLS-1$ + .append("
\n\n"); //$NON-NLS-1$ + + for (Resource r : resources) { + if (r == null) + continue; + + String uri = null; + try { + uri = graph.syncRequest(new ResourceToPossibleURI(r)); + } catch (Exception e) { + ErrorLogger.defaultLogError(e); + uri = "Cannot get URI: " + e.getMessage(); //$NON-NLS-1$ + } + + // Top DIV + content.append("
\n"); //$NON-NLS-1$ + content.append("\n"); //$NON-NLS-1$ + if (uri != null) { + content.append("\n"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + XSupport xs = graph.getService(XSupport.class); + boolean immutable = xs.getImmutable(r); + + Collection statements = graph.getStatements(r, L0.IsWeaklyRelatedTo); + HashMultiMap map = new HashMultiMap(); + for(org.simantics.db.Statement statement : statements) { + Resource predicate = null; + Resource subject = null; + Resource obj = null; + try { + predicate = statement.getPredicate(); + subject = statement.getSubject(); + obj = statement.getObject(); + map.add(predicate, new Resource[] {subject, obj}); + } catch (Throwable e) { + ErrorLogger.defaultLogError("Cannot find statement " + subject + " " + predicate + " " + obj, e); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + SerialisationSupport ss = graph.getSession().getService(SerialisationSupport.class); + ClusteringSupport support = graph.getSession().getService(ClusteringSupport.class); + content.append(""); //$NON-NLS-1$ + if (immutable) + content.append(""); //$NON-NLS-1$ + content.append("\n"); //$NON-NLS-1$ + + boolean isClusterSet = support.isClusterSet(r); + Resource parentSet = support.getClusterSetOfCluster(r); + String parentSetURI = parentSet != null ? graph.getPossibleURI(parentSet) : null; + + content.append(""); //$NON-NLS-1$ + if (isClusterSet) + content.append(""); //$NON-NLS-1$ + content.append("\n"); //$NON-NLS-1$ + + // If the resource has a value, show it. + String resourceValue = getResourceValue(graph, r); + if (resourceValue != null) { + content + .append("\n"); //$NON-NLS-1$ + } + + // Close #top + content.append("
URI").append(uri).append("
Identifiers"); //$NON-NLS-1$ + content.append("") //$NON-NLS-1$ + .append(" RID = $").append(r.getResourceId()) //$NON-NLS-1$ + .append(" Resource Key = ").append(ss.getTransientId(r)) //$NON-NLS-1$ + .append(" CID = ").append(support.getCluster(r)); //$NON-NLS-1$ + content.append("[IMMUTABLE]
Clustering"); //$NON-NLS-1$ + content.append(""); //$NON-NLS-1$ + + if(parentSetURI != null) + content.append(" Containing cluster set = ").append(parentSetURI); //$NON-NLS-1$ + else if (parentSet != null) + content.append(" Containing cluster set = ").append(parentSet.toString()); //$NON-NLS-1$ + else + content.append(" Not in any cluster set "); //$NON-NLS-1$ + + content.append("[CLUSTER SET]
Attached value") //$NON-NLS-1$ + .append(htmlEscape(resourceValue)) + .append("
\n"); //$NON-NLS-1$ + content.append("
\n"); //$NON-NLS-1$ + + content.append("\n
\n"); //$NON-NLS-1$ + content.append("\n") //$NON-NLS-1$ + .append("") //$NON-NLS-1$ + .append(""); //$NON-NLS-1$ + + boolean isOrderedSet = graph.isInstanceOf(r, L0.OrderedSet); + boolean isLinkedList = graph.isInstanceOf(r, L0.List); +// map.remove(r); + + // BASIC INFORMATION: + for (Resource pred : + new Resource[] {L0.HasName, L0.InstanceOf, + L0.Inherits, L0.SubrelationOf, + L0.PartOf, L0.ConsistsOf}) + if (map.containsKey(pred)) + updatePred(content, graph, r, pred, map.remove(pred)); + + // TAGS + content.append(""); //$NON-NLS-1$ + for(Statement stm : statements) { + if(stm.getSubject().equals(stm.getObject())) { + updateTag(content, graph, r, stm.getPredicate()); + map.remove(stm.getPredicate()); + } + } + + // ORDERED SETS + content.append(""); //$NON-NLS-1$ + for(Statement stm : statements) { + Resource predicate = stm.getPredicate(); + if(graph.isInstanceOf(stm.getPredicate(), L0.OrderedSet)) { + updateTag(content, graph, r, stm.getPredicate()); + if(map.get(stm.getPredicate()) != null && map.get(stm.getPredicate()).size() == 1) + map.remove(stm.getPredicate()); + } + Resource inverse = graph.getPossibleInverse(predicate); + if (inverse != null) { + if(graph.isInstanceOf(inverse, L0.OrderedSet)) { + if(map.get(stm.getPredicate()) != null && map.get(stm.getPredicate()).size() == 1) + map.remove(stm.getPredicate()); + } + } else { + // FIXME : should we infor missing inverse + } + } + + // IS RELATED TO + content.append(""); //$NON-NLS-1$ + + // ELEMENTS OF ORDERED SET + if(isOrderedSet) { + //content.append(""); + try { + updateOrderedSet(content, graph, r); + } catch (ValidationException e) { + content.append(""); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + // ELEMENTS OF LINKED LIST + if(isLinkedList) { + //content.append(""); + try { + updateLinkedList(content, graph, r); + } catch (ValidationException e) { + content.append(""); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + // IS RELATED TO (other) + Resource[] preds = map.keySet().toArray(new Resource[0]); + final Map strmap = new HashMap(preds.length); + for(Resource pred : preds) { + String str = htmlEscape( getResourceName(graph, pred) ); + if(str == null) + str = ""; //$NON-NLS-1$ + strmap.put(pred, str); + } + Arrays.sort(preds, new Comparator() { + @Override + public int compare(Resource o1, Resource o2) { + return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(strmap.get(o1), strmap.get(o2)); + } + }); + for(Resource pred : preds) + if(graph.isSubrelationOf(pred, L0.IsRelatedTo)) + updatePred(content, graph, r, pred, map.get(pred)); + + // OTHER STATEMENTS + content.append(""); //$NON-NLS-1$ + for(Resource pred : preds) + if(!graph.isSubrelationOf(pred, L0.IsRelatedTo)) + updatePred(content, graph, r, pred, map.get(pred)); + content.append("
PredicateObjectGraph
Basic information
Tags
Ordered Sets
Is Related To
Ordered set
BROKEN ORDERED SET:
").append(e.getMessage()).append("
Ordered set
BROKEN LINKED LIST:
").append(e.getMessage()).append("
Other statements
\n"); //$NON-NLS-1$ + } + // Close #data + content.append("
\n\n"); //$NON-NLS-1$ + // Close #mainContent + content.append("
\n"); //$NON-NLS-1$ + content.append("\n\n"); //$NON-NLS-1$ + + // Update content + final String finalContent = content.toString(); + if (!isDisposed()) { + getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + if (!browser.isDisposed()) + browser.setText(finalContent); + } + }); + } + } + + private String getResourceValue(ReadGraph graph, Resource r) { + try { + if (graph.hasValue(r)) { + // too large array may cause application to run out of memory. + //System.out.println("getValue(" + NameUtils.getSafeName(graph, r, true)); + Datatype type = graph.getPossibleRelatedValue(r, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); + if (type != null) { + Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class ); + if (type.equals( rviBinding.type() )) { + RVI rvi = graph.getValue(r, rviBinding); + try { + Variable v = Variables.getConfigurationContext( graph, r ); + return rvi.asString(graph, v); + } catch (DatabaseException dbe ) { + return rvi.toString( graph ); + } + } else { + Binding b = Bindings.getBinding(type); + Object v = graph.getValue(r, b); + Serializer s = Bindings.getSerializerUnchecked(b); + int size = s.getSize(v); + if (size > RESOURCE_VALUE_MAX_SIZE) { + return "Approx. " + size + " byte literal of type " + type.toSingleLineString(); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + return b.toString(v, false); + } + } + } else { + Object o = graph.getValue(r); + return toName(o); + } + } + return null; + } catch (DatabaseException e) { + return e.getMessage(); + } catch (IOException e) { + return e.getMessage(); + } catch (BindingException e) { + return e.getMessage(); + } + } + + private static String safeReadableString(ReadGraph g, Resource r) { + try { + return NameUtils.getSafeName(g, r); + } catch(Throwable throwable) { + ErrorLogger.defaultLogError(throwable); + return ""+throwable.getClass().getName()+" "+throwable.getMessage()+""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + +// private static String safeReadableString(IEntity t) { +// try { +// return ResourceDebugUtils.getReadableNameForEntity(t); +// } catch(Throwable throwable) { +// throwable.printStackTrace(); +// return ""+throwable.getClass().getName()+" "+throwable.getMessage()+""; +// } +// } + + private String getLinkString(Container t) { + String link = links.getLeft(t.get()); + if(link == null) { + link = UUID.randomUUID().toString(); + links.map(link, t.get()); + } + return link; + } + +// private String getPropertyEditString(Container t) { +// String link = links.getLeft(t.get()); +// if(link == null) { +// link = UUID.randomUUID().toString(); +// links.map(link, t.get()); +// } +// return link; +// } + + private String getStatementString(Resource _s, Resource _p, Resource _o) { + String s = getLinkString(_s); + String p = getLinkString(_p); + String o = getLinkString(_o); + return s + STATEMENT_PART_SEPARATOR + p + STATEMENT_PART_SEPARATOR + o; + } + +// private String getStatementString(Statement stm) { +// String s = getLinkString(stm.getSubject()); +// String p = getLinkString(stm.getPredicate()); +// String o = getLinkString(stm.getObject()); +// return s + STATEMENT_PART_SEPARATOR + p + STATEMENT_PART_SEPARATOR + o; +// } + +// private String toOutgoingTableRow(IEntity subject, Statement stm) { +// boolean isAcquired = !subject.equals(stm.getSubject()); +// +// String plainCell = "%s"; +// String hrefCell = "%s"; +// String formatTemplate = isAcquired +// ? "\n{0}\n{1}\n{1}\n{1}\n" +// : "\n{1}\n{1}\n{1}\n{1}\n"; +// String format = NLS.bind(formatTemplate, plainCell, hrefCell); +//// System.out.println("format: " + format); +// +// IEntity s = stm.getSubject(); +// IEntity p = stm.getPredicate(); +// IEntity o = stm.getObject(); +// +//// String timePart = "[" + timeToString(t.getBegin()) + ", " + timeToString(t.getEnd()) + "]"; +// +// try { +// return !isAcquired +// ? String.format(format, +// "about:blank-remove" + getStatementString(stm), "Remove", +// "about:blank-link" + getLinkString(s), safeReadableString(s), +// "about:blank-link" + getLinkString(p), safeReadableString(p), +// "about:blank-link" + getLinkString(o), safeReadableString(o)) +// : String.format(format, +// "Acquired", +// "about:blank-link" + getLinkString(s), safeReadableString(s), +// "about:blank-link" + getLinkString(p), safeReadableString(p), +// "about:blank-link" + getLinkString(o), safeReadableString(o) +// ); +// } catch (Throwable throwable) { +// return ""+throwable.getClass().getName()+" "+throwable.getMessage()+""; +// } +// } + +// private String intervalToString(Interval time) { +// return timeToString(time.getBegin()) + ", " + timeToString(time.getEnd()); +// } +// +// DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); +// +// private String timeToString(long time) { +// if (time == Long.MIN_VALUE) +// return "-∞"; +// if (time == Long.MAX_VALUE) +// return "+∞"; +// //return String.valueOf(time); +// Date d = new Date(time); +// return dateTimeFormat.format(d); +// } + + private String getHead() { + String result = ""; //$NON-NLS-1$ + if (cssPath != null) { + result = ""; //$NON-NLS-1$ //$NON-NLS-2$ + } + return result; + } + +}