1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * Foster Wheeler Energia Oy - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.interop.test;
\r
14 import java.io.IOException;
\r
15 import java.util.ArrayList;
\r
16 import java.util.HashMap;
\r
17 import java.util.List;
\r
18 import java.util.Map;
\r
20 import org.eclipse.jface.action.Action;
\r
21 import org.eclipse.jface.action.IAction;
\r
22 import org.eclipse.jface.action.IMenuCreator;
\r
23 import org.eclipse.jface.action.IMenuListener;
\r
24 import org.eclipse.jface.action.IMenuManager;
\r
25 import org.eclipse.jface.action.MenuManager;
\r
26 import org.eclipse.jface.dialogs.Dialog;
\r
27 import org.eclipse.jface.dialogs.IDialogConstants;
\r
28 import org.eclipse.jface.dialogs.MessageDialog;
\r
29 import org.eclipse.jface.layout.GridDataFactory;
\r
30 import org.eclipse.jface.resource.ImageDescriptor;
\r
31 import org.eclipse.jface.util.IPropertyChangeListener;
\r
32 import org.eclipse.jface.viewers.ILabelProvider;
\r
33 import org.eclipse.jface.viewers.IStructuredContentProvider;
\r
34 import org.eclipse.jface.viewers.IStructuredSelection;
\r
35 import org.eclipse.jface.viewers.LabelProvider;
\r
36 import org.eclipse.jface.viewers.ListViewer;
\r
37 import org.eclipse.jface.viewers.Viewer;
\r
38 import org.eclipse.jface.window.IShellProvider;
\r
39 import org.eclipse.swt.SWT;
\r
40 import org.eclipse.swt.dnd.DND;
\r
41 import org.eclipse.swt.dnd.DropTarget;
\r
42 import org.eclipse.swt.dnd.DropTargetAdapter;
\r
43 import org.eclipse.swt.dnd.DropTargetEvent;
\r
44 import org.eclipse.swt.dnd.TextTransfer;
\r
45 import org.eclipse.swt.dnd.Transfer;
\r
46 import org.eclipse.swt.events.HelpListener;
\r
47 import org.eclipse.swt.events.MenuDetectEvent;
\r
48 import org.eclipse.swt.events.MenuDetectListener;
\r
49 import org.eclipse.swt.events.SelectionAdapter;
\r
50 import org.eclipse.swt.events.SelectionEvent;
\r
51 import org.eclipse.swt.layout.FillLayout;
\r
52 import org.eclipse.swt.layout.GridData;
\r
53 import org.eclipse.swt.layout.GridLayout;
\r
54 import org.eclipse.swt.widgets.Button;
\r
55 import org.eclipse.swt.widgets.Composite;
\r
56 import org.eclipse.swt.widgets.Control;
\r
57 import org.eclipse.swt.widgets.Display;
\r
58 import org.eclipse.swt.widgets.Event;
\r
59 import org.eclipse.swt.widgets.Group;
\r
60 import org.eclipse.swt.widgets.Label;
\r
61 import org.eclipse.swt.widgets.Menu;
\r
62 import org.eclipse.swt.widgets.Shell;
\r
63 import org.eclipse.swt.widgets.Text;
\r
64 import org.eclipse.ui.part.ViewPart;
\r
65 import org.simantics.db.ReadGraph;
\r
66 import org.simantics.db.Resource;
\r
67 import org.simantics.db.Session;
\r
68 import org.simantics.db.Statement;
\r
69 import org.simantics.db.common.ResourceArray;
\r
70 import org.simantics.db.common.request.ReadRequest;
\r
71 import org.simantics.db.common.utils.NameUtils;
\r
72 import org.simantics.db.exception.DatabaseException;
\r
73 import org.simantics.db.exception.InvalidResourceReferenceException;
\r
74 import org.simantics.db.exception.ServiceException;
\r
75 import org.simantics.db.exception.ValidationException;
\r
76 import org.simantics.db.request.Read;
\r
77 import org.simantics.db.service.SerialisationSupport;
\r
78 import org.simantics.layer0.Layer0;
\r
79 import org.simantics.ui.SimanticsUI;
\r
80 import org.simantics.ui.dnd.LocalObjectTransfer;
\r
81 import org.simantics.ui.dnd.ResourceReferenceTransfer;
\r
82 import org.simantics.ui.dnd.ResourceTransferUtils;
\r
83 import org.simantics.ui.utils.ResourceAdaptionUtils;
\r
84 import org.simantics.utils.datastructures.BijectionMap;
\r
85 import org.simantics.utils.datastructures.Pair;
\r
86 import org.simantics.utils.ui.ExceptionUtils;
\r
89 * Simple multiline text viewer for seeing differences in two subgraphs.
\r
91 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
\r
94 public class GraphComparatorViewer extends ViewPart{
\r
96 private Session session;
\r
98 private Composite composite;
\r
100 private Label resourceText1;
\r
101 private Label resourceText2;
\r
103 private Text text1;
\r
104 private Text text2;
\r
107 private List<Resource> traversed = new ArrayList<Resource>();
\r
108 private List<Resource> tested = new ArrayList<Resource>();
\r
109 private List<Resource> strong = new ArrayList<Resource>();
\r
110 private List<Resource> nonTraversed = new ArrayList<Resource>();
\r
111 private List<Resource> nonTested = new ArrayList<Resource>();
\r
115 public void createPartControl(Composite parent) {
\r
116 composite = new Composite(parent, SWT.NONE);
\r
117 composite.setLayout(new GridLayout(2, false));
\r
119 session = SimanticsUI.getSession();
\r
121 Composite topComposite = new Composite(composite, SWT.BORDER);
\r
122 topComposite.setLayout(new GridLayout(3, false));
\r
123 text1 = new Text(composite, SWT.MULTI|SWT.V_SCROLL);
\r
124 text2 = new Text(composite, SWT.MULTI|SWT.V_SCROLL);
\r
126 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).span(2, 1).applyTo(topComposite);
\r
127 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(text1);
\r
128 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(text2);
\r
130 resourceText1 = createDropLabel(topComposite);
\r
131 resourceText2 = createDropLabel(topComposite);
\r
133 Button button = new Button(topComposite, SWT.PUSH);
\r
134 button.setText("Compare");
\r
135 button.addSelectionListener(new SelectionAdapter() {
\r
137 public void widgetSelected(SelectionEvent e) {
\r
144 getViewSite().getActionBars().getToolBarManager().add(new Action("Config") {
\r
146 public void run() {
\r
147 ConfigurationDialog dialog = new ConfigurationDialog(getSite().getShell());
\r
154 private void defaultConf() {
\r
159 nonTraversed.clear();
\r
161 session.syncRequest(new ReadRequest() {
\r
163 public void run(ReadGraph graph) throws DatabaseException {
\r
164 Layer0 l0 = Layer0.getInstance(graph);
\r
165 traversed.add(l0.ConsistsOf);
\r
166 tested.add(l0.IsWeaklyRelatedTo);
\r
169 } catch (Exception e) {
\r
170 ExceptionUtils.logAndShowError(e);
\r
174 private void compare() {
\r
177 final Resource r1 = (Resource)resourceText1.getData();
\r
178 final Resource r2 = (Resource)resourceText2.getData();
\r
179 if (r1 == null || r2 == null) {
\r
181 text1.setText("Missing input!");
\r
183 text2.setText("Missing input!");
\r
187 session.asyncRequest(new ReadRequest() {
\r
190 public void run(final ReadGraph graph) throws DatabaseException {
\r
191 GraphComparator comparator = new GraphComparator(r1,r2);
\r
193 comparator.addTested(tested);
\r
194 comparator.addTraversed(traversed);
\r
195 comparator.addNonTested(nonTested);
\r
196 comparator.addNonTraversed(nonTraversed);
\r
197 comparator.addStrong(strong);
\r
199 comparator.test(graph);
\r
200 BijectionMap<Statement, Statement> map = comparator.getComparableStatements();
\r
201 Map<Statement, Integer> indices = new HashMap<Statement, Integer>();
\r
202 final StringBuilder sb1 = new StringBuilder();
\r
203 final StringBuilder sb2 = new StringBuilder();
\r
206 GraphChanges changes = comparator.getChanges();
\r
208 for (Pair<Statement,Statement> mod : changes.getModifications()) {
\r
212 Statement s = mod.first;
\r
213 sub = NameUtils.getSafeName(graph, s.getSubject());
\r
214 String pre = NameUtils.getSafeName(graph, s.getPredicate());
\r
215 String obj = NameUtils.getSafeName(graph, s.getObject());
\r
216 if (map.containsLeft(s)) {
\r
218 indices.put(s, index);
\r
219 sb1.append("["+index + "] ");
\r
221 sb1.append(sub + " - " + pre + " - " + obj);
\r
222 sb1.append(" ["+s.getSubject().getResourceId() + " " + s.getPredicate().getResourceId() + " " + s.getObject().getResourceId()+"]");
\r
224 } catch (ValidationException e) {
\r
225 e.printStackTrace();
\r
226 } catch (ServiceException e) {
\r
227 e.printStackTrace();
\r
233 Statement s = mod.second;
\r
234 sub = NameUtils.getSafeName(graph, s.getSubject());
\r
235 String pre = NameUtils.getSafeName(graph, s.getPredicate());
\r
236 String obj = NameUtils.getSafeName(graph, s.getObject());
\r
237 if (map.containsRight(s)) {
\r
238 index = indices.get(map.getLeft(s));
\r
239 sb2.append("["+index + "] ");
\r
241 sb2.append(sub + " - " + pre + " - " + obj);
\r
242 sb2.append(" ["+s.getSubject().getResourceId() + " " + s.getPredicate().getResourceId() + " " + s.getObject().getResourceId()+"]");
\r
244 } catch (ValidationException e) {
\r
245 e.printStackTrace();
\r
246 } catch (ServiceException e) {
\r
247 e.printStackTrace();
\r
251 for (Statement s : changes.getDeletions()) {
\r
255 sub = NameUtils.getSafeName(graph, s.getSubject());
\r
256 String pre = NameUtils.getSafeName(graph, s.getPredicate());
\r
257 String obj = NameUtils.getSafeName(graph, s.getObject());
\r
258 if (map.containsLeft(s)) {
\r
260 indices.put(s, index);
\r
261 sb1.append("["+index + "] ");
\r
263 sb1.append(sub + " - " + pre + " - " + obj);
\r
264 sb1.append(" ["+s.getSubject().getResourceId() + " " + s.getPredicate().getResourceId() + " " + s.getObject().getResourceId()+"]");
\r
266 } catch (ValidationException e) {
\r
267 e.printStackTrace();
\r
268 } catch (ServiceException e) {
\r
269 e.printStackTrace();
\r
274 for (Statement s : changes.getAdditions()) {
\r
277 sub = NameUtils.getSafeName(graph, s.getSubject());
\r
278 String pre = NameUtils.getSafeName(graph, s.getPredicate());
\r
279 String obj = NameUtils.getSafeName(graph, s.getObject());
\r
280 if (map.containsRight(s)) {
\r
281 index = indices.get(map.getLeft(s));
\r
282 sb2.append("["+index + "] ");
\r
284 sb2.append(sub + " - " + pre + " - " + obj);
\r
285 sb2.append(" ["+s.getSubject().getResourceId() + " " + s.getPredicate().getResourceId() + " " + s.getObject().getResourceId()+"]");
\r
287 } catch (ValidationException e) {
\r
288 e.printStackTrace();
\r
289 } catch (ServiceException e) {
\r
290 e.printStackTrace();
\r
294 Display.getDefault().asyncExec(new Runnable() {
\r
296 public void run() {
\r
297 text1.setText(sb1.toString());
\r
298 text2.setText(sb2.toString());
\r
307 public void setFocus() {
\r
308 composite.setFocus();
\r
312 public void dispose() {
\r
318 // copy-paste from GraphDebugger
\r
319 public Label createDropLabel(Composite parent) {
\r
320 final Label label = new Label(parent, SWT.BORDER);
\r
321 label.setAlignment(SWT.CENTER);
\r
322 label.setText("Drag a resource here to examine it in this debugger!");
\r
323 label.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
\r
324 GridData data = new GridData(SWT.FILL, SWT.TOP, true, false);
\r
325 data.heightHint = 16;
\r
326 label.setLayoutData(data);
\r
328 // Add resource id drop support to the drop-area.
\r
329 DropTarget dropTarget = new DropTarget(label, DND.DROP_LINK | DND.DROP_COPY);
\r
330 dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance(), ResourceReferenceTransfer.getInstance(), LocalObjectTransfer.getTransfer() });
\r
331 dropTarget.addDropListener(new DropTargetAdapter() {
\r
333 public void dragEnter(DropTargetEvent event) {
\r
334 event.detail = DND.DROP_LINK;
\r
335 //label.setBackground(green);
\r
339 public void dragLeave(DropTargetEvent event) {
\r
340 label.setBackground(null);
\r
344 public void drop(DropTargetEvent event) {
\r
345 label.setBackground(null);
\r
346 ResourceArray[] data = parseEventData(event);
\r
347 if (data == null || data.length != 1) {
\r
348 event.detail = DND.DROP_NONE;
\r
351 final ResourceArray array = data[0];
\r
352 final Resource r = array.resources[array.resources.length - 1];
\r
356 label.setText(session.syncRequest(new Read<String>() {
\r
358 public String perform(ReadGraph graph)
\r
359 throws DatabaseException {
\r
360 return NameUtils.getSafeName(graph, r);
\r
363 } catch (DatabaseException e) {
\r
364 e.printStackTrace();
\r
368 private ResourceArray[] parseEventData(DropTargetEvent event) {
\r
369 //System.out.println("DATA: " + event.data);
\r
370 if (event.data instanceof String) {
\r
372 SerialisationSupport support = session.getService(SerialisationSupport.class);
\r
373 return ResourceTransferUtils.readStringTransferable(support.getResourceSerializer(), (String) event.data).toResourceArrayArray();
\r
374 } catch (IllegalArgumentException e) {
\r
375 e.printStackTrace();
\r
376 } catch (IOException e) {
\r
377 e.printStackTrace();
\r
378 } catch (InvalidResourceReferenceException e) {
\r
379 e.printStackTrace();
\r
382 ResourceArray[] ret = ResourceAdaptionUtils.toResourceArrays(event.data);
\r
383 if (ret.length > 0)
\r
394 private class ConfigurationDialog extends Dialog {
\r
396 protected ConfigurationDialog(Shell parentShell) {
\r
397 super(parentShell);
\r
401 protected void createButtonsForButtonBar(Composite parent) {
\r
402 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
\r
407 protected Control createDialogArea(Composite parent) {
\r
408 Composite composite = (Composite) super.createDialogArea(parent);
\r
409 composite.setLayout(new FillLayout(SWT.VERTICAL));
\r
411 Group group = new Group(composite, SWT.NONE);
\r
412 group.setText("Traversed");
\r
413 group.setLayout(new FillLayout());
\r
414 ListViewer traversedViewer = new ListViewer(group);
\r
416 group = new Group(composite, SWT.NONE);
\r
417 group.setText("Tested");
\r
418 group.setLayout(new FillLayout());
\r
419 ListViewer testedViewer = new ListViewer(group);
\r
421 group = new Group(composite, SWT.NONE);
\r
422 group.setText("Strong");
\r
423 group.setLayout(new FillLayout());
\r
424 ListViewer strongViewer = new ListViewer(group);
\r
426 group = new Group(composite, SWT.NONE);
\r
427 group.setText("NonTraversed");
\r
428 group.setLayout(new FillLayout());
\r
429 ListViewer nonTraversedViewer = new ListViewer(group);
\r
431 group = new Group(composite, SWT.NONE);
\r
432 group.setText("NonTested");
\r
433 group.setLayout(new FillLayout());
\r
434 ListViewer nonTestedViewer = new ListViewer(group);
\r
436 traversedViewer.setContentProvider(new ResourceListContentProvider());
\r
437 traversedViewer.setLabelProvider(new ResourceLabelProvider());
\r
439 testedViewer.setContentProvider(new ResourceListContentProvider());
\r
440 testedViewer.setLabelProvider(new ResourceLabelProvider());
\r
442 strongViewer.setContentProvider(new ResourceListContentProvider());
\r
443 strongViewer.setLabelProvider(new ResourceLabelProvider());
\r
445 nonTraversedViewer.setContentProvider(new ResourceListContentProvider());
\r
446 nonTraversedViewer.setLabelProvider(new ResourceLabelProvider());
\r
448 nonTestedViewer.setContentProvider(new ResourceListContentProvider());
\r
449 nonTestedViewer.setLabelProvider(new ResourceLabelProvider());
\r
451 MenuManager strongManager = new MenuManager();
\r
452 strongManager.setRemoveAllWhenShown(true);
\r
453 strongManager.addMenuListener(new ListPopupListener(strongViewer));
\r
454 strongViewer.getControl().setMenu(strongManager.createContextMenu(strongViewer.getControl()));
\r
456 MenuManager nonTestedManager = new MenuManager();
\r
457 nonTestedManager.setRemoveAllWhenShown(true);
\r
458 nonTestedManager.addMenuListener(new ListPopupListener(nonTestedViewer));
\r
459 nonTestedViewer.getControl().setMenu(nonTestedManager.createContextMenu(nonTestedViewer.getControl()));
\r
461 MenuManager nonTraversedManager = new MenuManager();
\r
462 nonTraversedManager.setRemoveAllWhenShown(true);
\r
463 nonTraversedManager.addMenuListener(new ListPopupListener(nonTraversedViewer));
\r
464 nonTraversedViewer.getControl().setMenu(nonTraversedManager.createContextMenu(nonTraversedViewer.getControl()));
\r
466 MenuManager testedManager = new MenuManager();
\r
467 testedManager.setRemoveAllWhenShown(true);
\r
468 testedManager.addMenuListener(new ListPopupListener(testedViewer));
\r
469 testedViewer.getControl().setMenu(testedManager.createContextMenu(testedViewer.getControl()));
\r
471 MenuManager traversedManager = new MenuManager();
\r
472 traversedManager.setRemoveAllWhenShown(true);
\r
473 traversedManager.addMenuListener(new ListPopupListener(traversedViewer));
\r
474 traversedViewer.getControl().setMenu(traversedManager.createContextMenu(traversedViewer.getControl()));
\r
476 traversedViewer.setInput(traversed);
\r
477 testedViewer.setInput(tested);
\r
478 strongViewer.setInput(strong);
\r
479 nonTestedViewer.setInput(nonTested);
\r
480 nonTraversedViewer.setInput(nonTraversed);
\r
487 private class ListPopupListener implements IMenuListener {
\r
488 private ListViewer viewer;
\r
490 public ListPopupListener(ListViewer viewer) {
\r
491 this.viewer = viewer;
\r
495 public void menuAboutToShow(IMenuManager manager) {
\r
496 IStructuredSelection s = (IStructuredSelection)viewer.getSelection();
\r
497 List<Object> list = (List<Object>)viewer.getInput();
\r
498 manager.add(new AddAction(viewer, list));
\r
499 if (!s.isEmpty()) {
\r
500 Object element = s.getFirstElement();
\r
501 manager.add(new DeleteAction(viewer, list, element));
\r
507 private class DeleteAction extends Action {
\r
508 private Viewer viewer;
\r
509 private List<?> list;
\r
510 private Object obj;
\r
511 public DeleteAction(Viewer viewer, List<?> list, Object obj) {
\r
515 this.viewer = viewer;
\r
519 public void run() {
\r
525 private class AddAction extends Action {
\r
526 private Viewer viewer;
\r
527 private List<Object> list;
\r
528 public AddAction(Viewer viewer, List<Object> list) {
\r
531 this.viewer = viewer;
\r
535 public void run() {
\r
536 RelationChooseDialog dialog = new RelationChooseDialog(getSite().getShell());
\r
537 if (dialog.open() == RelationChooseDialog.OK) {
\r
538 final String uri = dialog.getUri();
\r
540 Resource res = session.syncRequest(new Read<Resource>() {
\r
542 public Resource perform(ReadGraph graph)
\r
543 throws DatabaseException {
\r
545 return graph.getResource(uri);
\r
546 } catch (Exception e) {
\r
555 MessageDialog.openError(getSite().getShell(), "Error", "Relation '" + uri + "' not found.");
\r
557 } catch (Exception e) {
\r
567 private class RelationChooseDialog extends Dialog {
\r
569 private String uri = null;
\r
571 public RelationChooseDialog(IShellProvider parentShell) {
\r
572 super(parentShell);
\r
575 public RelationChooseDialog(Shell parentShell) {
\r
576 super(parentShell);
\r
580 protected Control createDialogArea(Composite parent) {
\r
581 Composite composite = (Composite) super.createDialogArea(parent);
\r
582 composite.setLayout(new GridLayout(2, false));
\r
583 Label label = new Label(composite, SWT.NONE);
\r
584 label.setText("URI:");
\r
586 text = new Text(composite, SWT.SINGLE | SWT.BORDER);
\r
587 text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
\r
593 protected void okPressed() {
\r
594 uri = text.getText();
\r
598 public String getUri() {
\r
604 private class ResourceListContentProvider implements IStructuredContentProvider {
\r
606 @SuppressWarnings("unchecked")
\r
608 public Object[] getElements(Object inputElement) {
\r
609 List<Resource> list = (List<Resource>)inputElement;
\r
610 return list.toArray();
\r
614 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
\r
619 public void dispose() {
\r
624 private class ResourceLabelProvider extends LabelProvider {
\r
627 public String getText(Object element) {
\r
628 final Resource res = (Resource) element;
\r
630 return session.syncRequest(new Read<String>() {
\r
632 public String perform(ReadGraph graph) throws DatabaseException {
\r
633 return NameUtils.getSafeName(graph, res);
\r
636 } catch (DatabaseException e) {
\r
637 return "Error: " + e.getMessage();
\r