]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/ModelingUtils.java
Another version of shared ontology import which returns the roots (SCL)
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / ModelingUtils.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling;
13
14 import java.io.File;
15 import java.io.IOException;
16 import java.text.DateFormat;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.Date;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.TreeMap;
27
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.eclipse.core.runtime.Path;
32 import org.eclipse.jface.dialogs.Dialog;
33 import org.eclipse.jface.dialogs.IDialogConstants;
34 import org.eclipse.jface.dialogs.MessageDialog;
35 import org.eclipse.jface.layout.GridDataFactory;
36 import org.eclipse.jface.layout.GridLayoutFactory;
37 import org.eclipse.jface.resource.ImageDescriptor;
38 import org.eclipse.jface.viewers.IStructuredSelection;
39 import org.eclipse.jface.viewers.StructuredSelection;
40 import org.eclipse.jface.window.Window;
41 import org.eclipse.jface.wizard.WizardDialog;
42 import org.eclipse.swt.SWT;
43 import org.eclipse.swt.widgets.Composite;
44 import org.eclipse.swt.widgets.Control;
45 import org.eclipse.swt.widgets.Display;
46 import org.eclipse.swt.widgets.FileDialog;
47 import org.eclipse.swt.widgets.Shell;
48 import org.eclipse.ui.IWorkbenchWizard;
49 import org.eclipse.ui.PlatformUI;
50 import org.eclipse.ui.wizards.IWizardDescriptor;
51 import org.simantics.Simantics;
52 import org.simantics.annotation.ontology.AnnotationResource;
53 import org.simantics.databoard.Bindings;
54 import org.simantics.databoard.binding.Binding;
55 import org.simantics.databoard.binding.mutable.Variant;
56 import org.simantics.databoard.container.DataContainer;
57 import org.simantics.databoard.container.DataContainers;
58 import org.simantics.databoard.container.DataFormatException;
59 import org.simantics.databoard.container.FormatHandler;
60 import org.simantics.databoard.serialization.SerializationException;
61 import org.simantics.databoard.type.Datatype;
62 import org.simantics.databoard.util.URIStringUtils;
63 import org.simantics.datatypes.literal.GUID;
64 import org.simantics.db.MetadataI;
65 import org.simantics.db.ReadGraph;
66 import org.simantics.db.RequestProcessor;
67 import org.simantics.db.Resource;
68 import org.simantics.db.Session;
69 import org.simantics.db.Statement;
70 import org.simantics.db.WriteGraph;
71 import org.simantics.db.common.Indexing;
72 import org.simantics.db.common.NamedResource;
73 import org.simantics.db.common.QueryMemoryWatcher;
74 import org.simantics.db.common.changeset.GenericChangeListener;
75 import org.simantics.db.common.primitiverequest.IsInstanceOf;
76 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
77 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
78 import org.simantics.db.common.request.IndexRoot;
79 import org.simantics.db.common.request.ObjectsWithType;
80 import org.simantics.db.common.request.PossibleIndexRoot;
81 import org.simantics.db.common.request.ReadRequest;
82 import org.simantics.db.common.request.ResourceRead2;
83 import org.simantics.db.common.request.WriteRequest;
84 import org.simantics.db.common.request.WriteResultRequest;
85 import org.simantics.db.common.utils.ListUtils;
86 import org.simantics.db.common.utils.Logger;
87 import org.simantics.db.common.utils.NameUtils;
88 import org.simantics.db.common.utils.OrderedSetUtils;
89 import org.simantics.db.common.utils.VersionInfo;
90 import org.simantics.db.common.utils.VersionInfoRequest;
91 import org.simantics.db.common.utils.Versions;
92 import org.simantics.db.exception.DatabaseException;
93 import org.simantics.db.layer0.SelectionHints;
94 import org.simantics.db.layer0.adapter.CopyHandler;
95 import org.simantics.db.layer0.adapter.GenericRelationIndex;
96 import org.simantics.db.layer0.adapter.Instances;
97 import org.simantics.db.layer0.adapter.impl.DefaultPasteImportAdvisor;
98 import org.simantics.db.layer0.adapter.impl.EntityInstances.QueryIndex;
99 import org.simantics.db.layer0.adapter.impl.ImportAdvisorFactory;
100 import org.simantics.db.layer0.genericrelation.DependenciesRelation.DependencyChangesRequest;
101 import org.simantics.db.layer0.genericrelation.DependencyChanges;
102 import org.simantics.db.layer0.genericrelation.IndexedRelations;
103 import org.simantics.db.layer0.migration.MigratedImportResult;
104 import org.simantics.db.layer0.migration.MigrationUtils;
105 import org.simantics.db.layer0.request.ActivateModel;
106 import org.simantics.db.layer0.request.ActiveModels;
107 import org.simantics.db.layer0.request.Configuration;
108 import org.simantics.db.layer0.request.IsLinkedTo;
109 import org.simantics.db.layer0.request.PossibleModel;
110 import org.simantics.db.layer0.util.ClipboardUtils;
111 import org.simantics.db.layer0.util.DraftStatusBean;
112 import org.simantics.db.layer0.util.ExternalDownloadBean;
113 import org.simantics.db.layer0.util.Layer0Utils;
114 import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest;
115 import org.simantics.db.layer0.util.PasteEventHandler;
116 import org.simantics.db.layer0.util.RemoverUtil;
117 import org.simantics.db.layer0.util.SimanticsClipboard;
118 import org.simantics.db.layer0.util.SimanticsClipboard.Representation;
119 import org.simantics.db.layer0.util.SimanticsClipboardImpl;
120 import org.simantics.db.layer0.util.SimanticsKeys;
121 import org.simantics.db.layer0.util.TransferableGraphConfiguration2;
122 import org.simantics.db.layer0.variable.Variable;
123 import org.simantics.db.layer0.variable.Variables;
124 import org.simantics.db.request.Read;
125 import org.simantics.db.service.ClusterControl;
126 import org.simantics.db.service.CollectionSupport;
127 import org.simantics.db.service.GraphChangeListenerSupport;
128 import org.simantics.db.service.QueryControl;
129 import org.simantics.db.service.VirtualGraphSupport;
130 import org.simantics.diagram.stubs.DiagramResource;
131 import org.simantics.diagram.stubs.G2DResource;
132 import org.simantics.diagram.synchronization.graph.AddElement;
133 import org.simantics.graph.db.IImportAdvisor2;
134 import org.simantics.graph.db.ImportAdvisors;
135 import org.simantics.graph.db.MissingDependencyException;
136 import org.simantics.graph.db.StreamingTransferableGraphFileReader;
137 import org.simantics.graph.db.TransferableGraphException;
138 import org.simantics.graph.db.TransferableGraphSource;
139 import org.simantics.graph.db.TransferableGraphs;
140 import org.simantics.graph.representation.Identity;
141 import org.simantics.graph.representation.Root;
142 import org.simantics.graph.representation.TransferableGraph1;
143 import org.simantics.graph.representation.TransferableGraphUtils;
144 import org.simantics.issues.common.IssueSourceUtils;
145 import org.simantics.issues.ontology.IssueResource;
146 import org.simantics.layer0.Layer0;
147 import org.simantics.layer0.utils.direct.GraphUtils;
148 import org.simantics.modeling.adapters.ChangeInformation;
149 import org.simantics.modeling.template2d.ontology.Template2dResource;
150 import org.simantics.modeling.utils.OntologicalRequirementTracker;
151 import org.simantics.operation.Layer0X;
152 import org.simantics.project.ontology.ProjectResource;
153 import org.simantics.scenegraph.profile.ProfileUtils;
154 import org.simantics.scl.runtime.function.Function1;
155 import org.simantics.scl.runtime.tuple.Tuple;
156 import org.simantics.simulation.ontology.SimulationResource;
157 import org.simantics.structural.stubs.StructuralResource2;
158 import org.simantics.structural2.scl.StructuralComponent;
159 import org.simantics.structural2.utils.StructuralUtils;
160 import org.simantics.ui.SimanticsUI;
161 import org.simantics.utils.ObjectUtils;
162 import org.simantics.utils.datastructures.Pair;
163 import org.simantics.utils.datastructures.Triple;
164 import org.simantics.utils.datastructures.hints.HintContext;
165 import org.simantics.utils.ui.dialogs.ListDialog;
166
167 /**
168  * @author Hannu Niemistö
169  */
170 public class ModelingUtils {
171
172         private ReadGraph g;
173         private WriteGraph wg;
174         public Layer0 b;
175         private StructuralResource2 sr;
176         private DiagramResource dr;
177         public ModelingResources mr;
178         public SimulationResource SIMU;
179
180         public ModelingUtils(WriteGraph g) {
181                 wg = g;
182                 this.g = g;
183                 b = Layer0.getInstance(g);
184                 sr = StructuralResource2.getInstance(g);
185                 dr = DiagramResource.getInstance(g);
186                 mr = ModelingResources.getInstance(g);
187                 SIMU = SimulationResource.getInstance(g);
188         }
189
190         @Deprecated
191         public Resource createSymbol2(String name) throws DatabaseException {
192                 return createSymbol2(name, dr.Composite);
193         }
194
195         @Deprecated
196         public Resource createSymbol2(String name, Resource diagramType) throws DatabaseException {
197             return createSymbol2(name, diagramType, dr.DefinedElement);
198         }
199         @Deprecated
200         public Resource createSymbol2(String name, Resource diagramType, Resource symbolType) throws DatabaseException {
201                 G2DResource g2d = G2DResource.getInstance(g);
202
203 //              Resource visibleTag = wg.newResource();
204 //              wg.claim(visibleTag, b.SubrelationOf, null, dr.IsVisible);
205 //              Resource focusableTag = wg.newResource();
206 //              wg.claim(focusableTag, b.SubrelationOf, null, dr.IsFocusable);
207
208                 Double boxDimension = 6.0;
209                 Collection<Statement> grid = g.getAssertedStatements(diagramType, dr.HasGridSize);
210                 if(grid.size() == 1) {
211                         Double d = g.getPossibleValue(grid.iterator().next().getObject(), Bindings.DOUBLE);
212                         if(d != null) boxDimension = 2*d;
213                 }
214
215
216                 Resource element  = GraphUtils.create(wg,
217                                 b.InstanceOf, dr.SVGElement,
218                                 g2d.HasSVGDocument,
219                                 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" +
220                                                 // REMOVED by Tuukka, because This will cause
221                                                 // parsers to get on the net and get the doctype
222                                                 // definitions which can stall the UI for a long time.
223                                                 // Besides, we're not using the validation for anything
224                                                 // so it's useless to us.
225                                                 //"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" +
226                                                 "<svg xmlns=\"http://www.w3.org/2000/svg\" overflow=\"visible\" version=\"1.1\">" +
227                                                 "<rect x=\"-" + boxDimension + "\" y=\"-" + boxDimension + "\" width=\"" + (2*boxDimension) + "\" height=\"" + (2*boxDimension) + "\" fill=\"none\" stroke=\"rgb(0,0,0)\" stroke-width=\"0.1\"/>" +
228                                                 "</svg>"
229                                 );
230
231 //              wg.claim(element, visibleTag, element);
232 //              wg.claim(element, focusableTag, element);
233
234                 Resource orderedSet = OrderedSetUtils.create(wg, diagramType, element);
235
236 //              wg.claim(orderedSet, dr.HasLayer, GraphUtils.create2(wg, dr.Layer,
237 //                              b.HasName, "Default",
238 //                              dr.IsActive, Boolean.TRUE,
239 //                              dr.HasVisibleTag, visibleTag,
240 //                              dr.HasFocusableTag, focusableTag));
241
242                 Resource result = GraphUtils.create(wg,
243                                 b.HasName, name,
244                                 b.HasLabel, "",
245                                 sr.IsDefinedBy, orderedSet);
246
247                 wg.claim(result, b.ConsistsOf, orderedSet);
248                 wg.claimLiteral(orderedSet, b.HasName, "__DIAGRAM__", Bindings.STRING);
249                 AddElement.claimFreshElementName(wg, orderedSet, element);
250                 wg.claim(orderedSet, b.ConsistsOf, element);
251
252                 wg.claim(result, b.Inherits, null, symbolType);
253                 return result;
254         }
255
256         public static Collection<Resource> getElementCorrespondendences(ReadGraph g, Resource element) throws DatabaseException {
257                 DiagramResource dr = DiagramResource.getInstance(g);
258                 ModelingResources mr = ModelingResources.getInstance(g);
259                 if(g.isInstanceOf(element, dr.Connection)) {
260                         Resource mappedComponent = g.getPossibleObject(element, mr.ElementToComponent);
261                         if(mappedComponent != null) return Collections.singletonList(mappedComponent);
262                         Resource mappedConnection = g.getPossibleObject(element, mr.DiagramConnectionToConnection);
263                         if(mappedConnection == null)
264                                 return Collections.emptyList();
265                         ArrayList<Resource> result = new ArrayList<Resource>();
266                         Collection<Resource> relatedMappedConnections = StructuralUtils.getRelatedConnections(g, mappedConnection);
267                         for(Resource relatedMappedConnection : relatedMappedConnections)
268                                 for(Resource relatedConnection : g.getObjects(relatedMappedConnection, mr.ConnectionToDiagramConnection))
269                                         result.addAll(g.getObjects(relatedConnection, mr.ElementToComponent));
270                         return result;
271                 }
272                 else
273                         return g.getObjects(element, mr.ElementToComponent);
274         }
275
276         public static Resource getPossibleElement(ReadGraph g, Resource component) throws DatabaseException {
277                 ModelingResources mr = ModelingResources.getInstance(g);
278                 return g.getPossibleObject(component, mr.ComponentToElement);
279         }
280
281         public static Resource getPossibleElementCorrespondendence(ReadGraph g, Resource element) throws DatabaseException {
282                 Collection<Resource> corrs = getElementCorrespondendences(g, element);
283                 if(corrs.size() != 1) return null;
284                 else return corrs.iterator().next();
285         }
286
287         public static Resource getSingleElementCorrespondendence(ReadGraph g, Resource element) throws DatabaseException {
288                 Collection<Resource> corrs = getElementCorrespondendences(g, element);
289                 if(corrs.size() != 1) throw new DatabaseException("Expected 1 element correspondence, got " + corrs.size());
290                 else return corrs.iterator().next();
291         }
292
293         public static Resource createExperiment(WriteGraph graph, Resource model) throws DatabaseException {
294
295                 Layer0 L0 = Layer0.getInstance(graph);
296                 SimulationResource SIMU = SimulationResource.getInstance(graph);
297                 Resource experiment = graph.newResource();
298                 graph.claim(experiment, L0.InstanceOf, SIMU.Experiment);
299                 graph.claimLiteral(experiment, L0.HasName, "Experiment");
300                 graph.claim(model, L0.ConsistsOf, experiment);
301                 return experiment;
302
303         }
304
305         public static Resource createModel(WriteGraph graph, Resource type) throws DatabaseException {
306                 return createModel(graph, type, Simantics.getProjectResource(), null);
307         }
308                 
309         public static Resource createModel(WriteGraph graph, Resource type, String name) throws DatabaseException {
310                 return createModel(graph, type, Simantics.getProjectResource(), name);
311         }
312
313         public static Resource createModel(WriteGraph graph, Resource type, final Resource target, String name) throws DatabaseException {
314
315                 Layer0 L0 = Layer0.getInstance(graph);
316                 SimulationResource SIMU = SimulationResource.getInstance(graph);
317                 StructuralResource2 STR = StructuralResource2.getInstance(graph);
318                 ModelingResources MOD = ModelingResources.getInstance(graph);
319
320                 if(name == null)
321                         name = NameUtils.findFreshName(graph, "Model", target, L0.ConsistsOf, "%s%d");
322
323                 final Resource model = graph.newResource();
324                 graph.newClusterSet(model);
325                 graph.claim(model, L0.InstanceOf, null, type);
326                 graph.claimLiteral(model, L0.HasName, name);
327
328                 graph.claim(target, L0.ConsistsOf, model);
329
330                 Resource configurationType = graph.getPossibleObject(model, MOD.StructuralModel_HasConfigurationType);
331                 if(configurationType == null) configurationType = STR.Composite;
332
333                 Resource configuration = graph.newResource();
334                 graph.claimLiteral(configuration, L0.HasName, "Configuration", Bindings.STRING);
335                 graph.claim(configuration, L0.InstanceOf, null, configurationType);
336                 graph.claim(model, L0.ConsistsOf, configuration);
337                 graph.claim(model, SIMU.HasConfiguration, configuration);
338
339                 Resource joinClusterSet = graph.newResource();
340                 graph.newClusterSet(joinClusterSet);
341                 graph.claim(joinClusterSet, L0.InstanceOf, L0.ClusterSet);
342                 graph.claim(model, STR.HasJoinClusterSet, joinClusterSet);
343
344                 linkOntologyDependenciesToModel(graph, model, target);
345                 
346                 Resource ontology = graph.syncRequest(new PossibleIndexRoot(type));
347                 if(ontology != null) {
348                         graph.claim(model, L0.IsLinkedTo, ontology);
349                 }
350
351                 VirtualGraphSupport support = graph.getService(VirtualGraphSupport.class);
352                 graph.asyncRequest(new WriteRequest(support.getWorkspacePersistent("activations")) {
353
354                         @Override
355                         public void perform(WriteGraph graph) throws DatabaseException {
356                                 Layer0X L0X = Layer0X.getInstance(graph);
357                                 Collection<Resource> actives = graph.syncRequest(new ActiveModels(target));
358                                 if(actives.isEmpty()) {
359                                         graph.claim(model,  L0X.IsActivatedBy, target);
360                                 }
361                         }
362
363                 });
364
365                 return model;
366
367         }
368         
369         public static void linkOntologyDependenciesToModel(WriteGraph graph, Resource model, Resource target) 
370                         throws DatabaseException {
371                 Layer0 L0 = Layer0.getInstance(graph);
372                 ProjectResource PROJ = ProjectResource.getInstance(graph);
373                 for(Resource dep : graph.getObjects(target, L0.IsLinkedTo)) {
374                         if(graph.isInstanceOf(dep, PROJ.NamespaceRequirement)) {
375                                 for(Resource req : graph.getObjects(dep, PROJ.RequiresNamespace)) {
376                                         String uri = graph.getPossibleValue(req, Bindings.STRING);
377                                         if(uri != null) {
378                                                 Resource ns = graph.getResource(uri);
379                                                 if(ns != null) {
380                                                         graph.claim(model, L0.IsLinkedTo, null, ns);
381                                                 }
382                                         }
383                                 }
384                         }
385                 }
386         }
387         
388         public static void addSCLMainToModel(WriteGraph graph, Resource model) 
389                         throws DatabaseException {
390                 addSCLMainToModel(graph, model, "SCLMain", "include \"Simantics/All\"\n");
391         }
392         
393         public static void addSCLMainToModel(WriteGraph graph, Resource model, String name, String contents) 
394                         throws DatabaseException {
395                 Layer0 L0 = Layer0.getInstance(graph);
396         Resource sclmain = GraphUtils.create2(graph, L0.SCLModule, L0.PartOf, model, L0.HasName, name);
397         graph.claimLiteral(sclmain, L0.SCLModule_definition, contents, Bindings.STRING);
398         }
399
400     public static Resource createLocalLibrary(WriteGraph graph, Resource container, String name) throws DatabaseException {
401         Layer0 L0 = Layer0.getInstance(graph);
402         ModelingResources MOD = ModelingResources.getInstance(graph);
403         Resource library = graph.newResource();
404         graph.claim(library, L0.InstanceOf, null, L0.Library);
405         graph.addLiteral(library, L0.HasName, L0.NameOf, "Library", Bindings.STRING);
406         if (container != null) {
407             graph.claim(container, L0.ConsistsOf, L0.PartOf, library);
408             graph.claim(container, MOD.HasLocalLibrary, MOD.IsLocalLibraryOf, library);
409         }
410         return library;
411     }
412
413         public static void importModel(String fileName) {
414
415                 Resource project = SimanticsUI.getProject().get();
416
417                 try (StreamingTransferableGraphFileReader importer = new StreamingTransferableGraphFileReader(new File(fileName))) {
418                         TransferableGraphSource tg = importer.readTG();
419
420                         final DefaultPasteImportAdvisor advisor = new DefaultPasteImportAdvisor(project) {
421                                 @Override
422                                 public void analyzeType(ReadGraph graph, Root root) throws DatabaseException {
423                                 }
424                                 @Override
425                                 public Resource analyzeRoot(ReadGraph graph, Root root) throws DatabaseException {
426                                         library = Simantics.getProjectResource();
427                                         String newName = newName(graph, library, root.name);
428                                         nameMappings.put(root.name, newName);
429                                         return null;
430                                 }
431                         };
432                         TransferableGraphs.importGraph1(Simantics.getSession(), tg, advisor);
433
434                 } catch (MissingDependencyException e) {
435
436                         final Set<String> missingURIs = e.getMissingURIs();
437
438                         class ErrorMessageDialog extends MessageDialog {
439
440                                 public ErrorMessageDialog(Shell shell) {
441                                         super(shell, 
442                                                         "Unsatisfied dependencies", null, 
443                                                         "The following dependencies were missing. Please import the dependencies and try again.", 
444                                                         MessageDialog.ERROR, new String[] { "Continue" }, 0);
445                                 }
446
447                                 @Override
448                                 protected Control createCustomArea(Composite composite) {
449                                         GridLayoutFactory.fillDefaults().applyTo(composite);
450                                         
451                                         org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(composite, SWT.BORDER | SWT.READ_ONLY);
452                                         GridDataFactory.fillDefaults().grab(true, true).applyTo(list);
453                                         for(String s : missingURIs) list.add(s);
454                                         return composite;
455                                 }
456
457                         }
458
459                         Display display = Display.getCurrent();
460                         if(display != null) {
461                                 ErrorMessageDialog md = new ErrorMessageDialog(display.getActiveShell());
462                                 md.open();
463                         } else {
464                                 Display.getDefault().asyncExec(new Runnable() {
465
466                                         @Override
467                                         public void run() {
468                                                 Shell shell = Display.getCurrent().getActiveShell();
469                                                 ErrorMessageDialog md = new ErrorMessageDialog(shell);
470                                                 md.open();
471                                         }
472                                         
473                                 });
474                         }
475                         
476
477                 } catch (Exception e) {
478                         Logger.defaultLogError(e);
479                 }
480
481         }
482
483         public static void primeVirtualGraphs() {
484                 VirtualGraphSupport support = Simantics.getSession().getService(VirtualGraphSupport.class);
485                 support.getWorkspacePersistent("activations");
486                 support.getWorkspacePersistent("experiments");
487                 support.getWorkspacePersistent("issues");
488                 support.getWorkspacePersistent("preferences");
489         }
490
491         public static Resource createProfileEntry(WriteGraph graph, String name, Resource style, Resource group) throws DatabaseException {
492
493                 Layer0 L0 = Layer0.getInstance(graph);
494                 DiagramResource DIA = DiagramResource.getInstance(graph);
495
496                 Resource entry = graph.newResource();
497                 graph.claim(entry, L0.InstanceOf, null, DIA.GroupStyleProfileEntry);
498                 graph.claimLiteral(entry, L0.HasName, name);
499                 graph.claimLiteral(entry, L0.HasLabel, name);
500                 graph.claim(entry, DIA.ProfileEntry_HasStyle, style);
501                 graph.claim(entry, DIA.ProfileEntry_HasGroup, group);
502
503                 return entry;
504
505         }
506
507         public static Resource createProfile(WriteGraph graph, String profileName, Resource... entries) throws DatabaseException {
508
509                 Layer0 L0 = Layer0.getInstance(graph);
510                 DiagramResource DIA = DiagramResource.getInstance(graph);
511
512                 Resource list = ListUtils.create(graph, DIA.Profile, entries);
513
514                 Resource profile = graph.newResource();
515                 graph.claim(profile, L0.InstanceOf, null, DIA.Profile);
516                 graph.claimLiteral(profile, L0.HasName, profileName);
517                 graph.claim(profile, DIA.HasEntries, null, list);
518
519                 return profile;
520
521         }
522         
523         public static Resource createProfile(WriteGraph graph, String profileName, Collection<Resource> entries) throws DatabaseException {
524             return createProfile(graph, profileName, entries.toArray(new Resource[entries.size()]));
525         }
526
527         public static Resource createToplevelProfile(WriteGraph graph, Resource model, String name, Resource ... profiles) throws DatabaseException {
528
529                 Resource work = createProfile(graph, name, profiles);
530
531                 Layer0 L0 = Layer0.getInstance(graph);
532                 DiagramResource DIA = DiagramResource.getInstance(graph);
533
534                 graph.deny(model, DIA.HasActiveProfile);
535                 graph.claim(model, DIA.HasActiveProfile, work);
536                 graph.claim(model, L0.ConsistsOf, L0.PartOf, work);
537
538                 return work;
539
540         }
541         
542         public static Resource createToplevelProfile(WriteGraph graph, Resource model, String name, Collection<Resource> profiles) throws DatabaseException {
543             return createToplevelProfile(graph, model, name, profiles.toArray(new Resource[profiles.size()]));
544         }
545
546         public static void activateProfileEntries(WriteGraph graph, final Resource profile, final Resource ... entries) {
547
548                 VirtualGraphSupport support = graph.getService(VirtualGraphSupport.class);
549                 graph.asyncRequest(new WriteRequest(support.getWorkspacePersistent("profiles")) {
550
551                         @Override
552                         public void perform(WriteGraph graph) throws DatabaseException {
553                                 SimulationResource SIMU = SimulationResource.getInstance(graph);
554                                 for(Resource entry : entries)
555                                         graph.claim(profile, SIMU.IsActive, entry);
556                         }
557
558                 });
559
560         }
561         
562         public static void activateProfileEntries(WriteGraph graph, Resource profile, Collection<Resource> entries) {
563             activateProfileEntries(graph, profile, entries.toArray(new Resource[entries.size()]));
564         }
565         
566         public static void toggleProfileGroup(WriteGraph graph, Resource runtimeProfile, String groupName, boolean enabled) throws DatabaseException {
567                 Layer0 L0 = Layer0.getInstance(graph);
568                 for (Resource group : ProfileUtils.getProfileChildren(graph, runtimeProfile)) {
569                         String name = graph.getRelatedValue2(group, L0.HasName);
570                         if (name.equals(groupName)) {
571                                 toggleProfileGroup(graph, runtimeProfile, group, enabled);
572                                 return;
573                         }
574                 }
575         }
576         
577         public static void toggleProfileGroup(WriteGraph graph, Resource runtimeProfile, Resource group, boolean enabled) throws DatabaseException {
578         DiagramResource DIA = DiagramResource.getInstance(graph);
579                 
580         if(graph.isInstanceOf(group, DIA.Profile)) {
581                 
582                 for(Resource child : ProfileUtils.getProfileChildren(graph, group)) {
583                         toggleProfileGroup(graph, runtimeProfile, child, enabled);
584                 }
585                 
586         } else if(graph.isInstanceOf(group, DIA.ProfileEntry)) {
587
588             if(enabled) {
589                 graph.claim(runtimeProfile, SimulationResource.getInstance(graph).IsActive, null, group);
590             } else {
591                 graph.denyStatement(runtimeProfile, SimulationResource.getInstance(graph).IsActive, group);
592             }
593
594                 }
595         }
596
597     public static void untrackDependencies() {
598         untrackDependencies(Simantics.getSession());
599     }
600
601         public static void untrackDependencies(RequestProcessor processor) {
602         
603         try {
604             processor.syncRequest(new ReadRequest() {
605
606                 @Override
607                 public void run(ReadGraph graph) throws DatabaseException {
608                     Layer0X L0X = Layer0X.getInstance(graph);
609                     GenericRelationIndex index = graph.adapt(L0X.DependenciesRelation, GenericRelationIndex.class);
610                     index.untrack(graph.getSession(), graph.getRootLibrary());
611                 }
612                 
613             });
614         } catch (DatabaseException e) {
615             Logger.defaultLogError(e);
616         }
617
618     }
619
620     public static void trackDependencies() {
621         trackDependencies(Simantics.getSession());
622     }
623
624         public static void trackDependencies(RequestProcessor processor) {
625             
626             try {
627             processor.syncRequest(new ReadRequest() {
628
629                 @Override
630                 public void run(ReadGraph graph) throws DatabaseException {
631                     Layer0X L0X = Layer0X.getInstance(graph);
632                     GenericRelationIndex index = graph.adapt(L0X.DependenciesRelation, GenericRelationIndex.class);
633                     index.trackAndIndex(graph.getSession(), graph.getRootLibrary());
634                 }
635                 
636             });
637         } catch (DatabaseException e) {
638             Logger.defaultLogError(e);
639         }
640
641         }
642
643     public static void trackOntologicalRequirements() {
644         Session session = Simantics.getSession();
645         GraphChangeListenerSupport changeListenerSupport = session.getService(GraphChangeListenerSupport.class);
646         changeListenerSupport.addMetadataListener( OntologicalRequirementListener.getInstance() );
647     }
648
649     public static void untrackOntologicalRequirements() {
650         Session session = Simantics.getSession();
651         GraphChangeListenerSupport changeListenerSupport = session.getService(GraphChangeListenerSupport.class);
652         changeListenerSupport.removeMetadataListener( OntologicalRequirementListener.getInstance() );
653     }
654
655     public static class OntologicalRequirementListener extends GenericChangeListener<DependencyChangesRequest, DependencyChanges> {
656
657         private static OntologicalRequirementListener INSTANCE;
658
659         public static OntologicalRequirementListener getInstance() {
660             if(INSTANCE == null) {
661                 INSTANCE = new OntologicalRequirementListener();
662             }
663             return INSTANCE;
664         }
665
666         private OntologicalRequirementListener() {
667         }
668
669         private OntologicalRequirementTracker changeInformationUpdater = new OntologicalRequirementTracker();
670
671         @Override
672         public boolean preEventRequest() {
673             return !Indexing.isDependenciesIndexingDisabled();
674         }
675
676         @Override
677         public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException {
678             changeInformationUpdater.update(graph, metadata, event);
679         }
680
681     }
682
683     public static void removeIndex(WriteGraph graph, Resource model) throws DatabaseException {
684         Layer0X L0X = Layer0X.getInstance(graph);
685         IndexedRelations ir = graph.getService(IndexedRelations.class);
686         // Deletes index files
687         ir.reset(null, graph, L0X.DependenciesRelation, model);
688     }
689     
690     public static void resetIssueSources(WriteGraph graph, Resource model) throws DatabaseException {
691         Layer0 L0 = Layer0.getInstance(graph);
692         IssueResource ISSUE = IssueResource.getInstance(graph);
693         for(Resource source : graph.sync(new ObjectsWithType(model, L0.ConsistsOf, ISSUE.ContinuousIssueSource))) {
694             IssueSourceUtils.update(graph, source);
695         }
696     }
697     
698     public static void copyAnnotationTypes(WriteGraph graph, Resource sourceModel, Resource targetModel) throws DatabaseException {
699
700         Layer0 L0 = Layer0.getInstance(graph);
701         AnnotationResource ANNO = AnnotationResource.getInstance(graph);
702
703         Instances query = graph.adapt(ANNO.AnnotationType, Instances.class);
704
705         Resource library = graph.getPossibleObject(targetModel, ANNO.HasAnnotationTypeRoot);
706         // HAXX:
707         if(library == null) {
708             library = graph.newResource();
709             graph.claim(library, L0.InstanceOf, null, ANNO.AnnotationTypeLibrary);
710             graph.claimLiteral(library, L0.HasName, L0.NameOf, L0.String, "Annotation types", Bindings.STRING);
711             graph.claim(library, L0.PartOf, L0.ConsistsOf, targetModel);
712             graph.claim(targetModel, ANNO.HasAnnotationTypeRoot, library);
713         }
714
715         for(Resource type : query.find(graph, sourceModel)) {
716             String name = graph.getRelatedValue(type, L0.HasName);
717             Resource existing = Layer0Utils.getPossibleChild(graph, library, name);
718             if(existing != null) {
719                 RemoverUtil.remove(graph, existing);
720             }
721             Layer0Utils.copyTo(graph, library, type);
722         }
723
724     }
725     
726         public static void deleteIndex(WriteGraph graph, Resource model) throws DatabaseException {
727                 Layer0X L0X = Layer0X.getInstance(graph);
728                 IndexedRelations ir = graph.getService(IndexedRelations.class);
729                 // Deletes index files
730                 ir.reset(null, graph, L0X.DependenciesRelation, model);
731         }
732     
733         public static void disableDependencies(WriteGraph graph, Resource dummy) {
734                 Layer0Utils.setDependenciesIndexingDisabled(graph, true);               
735         }
736
737     public static void releaseMemory(WriteGraph graph) {
738         
739                 QueryControl qc = graph.getService(QueryControl.class);
740                 ClusterControl cc = graph.getService(ClusterControl.class);
741                 cc.flushClusters();
742                 qc.flush(graph);
743         
744     }
745
746     public static List<Resource> filterByIndexRoot(ReadGraph graph, Resource indexRoot, List<Resource> resources) throws DatabaseException {
747         ArrayList<Resource> result =  new ArrayList<Resource>(resources.size());
748         for (Resource r : resources) {
749             Resource root = graph.syncRequest(new PossibleIndexRoot(r));
750             if (indexRoot.equals(root))
751                 result.add(r);
752         }
753         return result;
754     }
755
756     public static List<Resource> searchByTypeShallow(ReadGraph graph, Resource model, Resource type) throws DatabaseException {
757         return graph.syncRequest(new QueryIndex(model, type, ""), TransientCacheListener.<List<Resource>>instance());
758     }
759
760     public static List<Resource> searchByType(ReadGraph graph, Resource model, Resource type) throws DatabaseException {
761         Instances query = graph.adapt(type, Instances.class);
762         return Layer0Utils.sortByCluster(graph, query.find(graph, model));
763     }
764
765     public static List<Resource> searchByGUID(ReadGraph graph, Resource indexRoot, GUID guid) throws DatabaseException {
766         return searchByGUID(graph, indexRoot, guid.indexString());
767     }
768     
769     public static List<Resource> searchByGUID(ReadGraph graph, Resource indexRoot, String indexString) throws DatabaseException {
770         return searchByQueryShallow(graph, indexRoot, "GUID:" + indexString);
771     }
772
773     public static List<Resource> searchByQueryShallow(ReadGraph graph, Resource model, String query) throws DatabaseException {
774         return graph.syncRequest(new QueryIndex(model, Layer0.getInstance(graph).Entity, query), TransientCacheListener.<List<Resource>>instance());
775     }
776
777     public static List<Resource> searchByQuery(ReadGraph graph, Resource model, String query) throws DatabaseException {
778         Instances instances = graph.adapt(Layer0.getInstance(graph).Entity, Instances.class);
779         Collection<Resource> queryResult = instances.find(graph, model, query);
780         return Layer0Utils.sortByCluster(graph, queryResult);
781     }
782
783     public static List<Resource> searchByTypeAndFilter(ReadGraph graph, Resource model, Resource type, Function1<Resource,Boolean> filter) throws DatabaseException {
784         Instances query = graph.adapt(type, Instances.class);
785         ArrayList<Resource> result =  new ArrayList<Resource>();
786         for(Resource r : query.find(graph, model)) {
787                 if(filter.apply(r))
788                         result.add(r);
789         }
790         return result;
791     }
792
793     public static List<Triple<Resource, Resource, String>> getIndexEntries(ReadGraph graph, Resource model, String filter) throws DatabaseException {
794         Layer0 L0 = Layer0.getInstance(graph);
795         List<Resource> entries = searchByQuery(graph, model, filter);
796         List<Triple<Resource, Resource, String>> listOfTriples = new ArrayList<Triple<Resource,Resource,String>>();
797         for (Resource entry : entries) {
798                 Resource type = graph.getPossibleObject(entry, L0.InstanceOf);
799                 String name = NameUtils.getSafeName(graph, entry);
800                 listOfTriples.add(new Triple<Resource, Resource, String>(entry, type, name));
801         }
802                 return listOfTriples;
803     }
804     
805     public static String listIndexEntries(ReadGraph graph, Resource model, String filter) throws DatabaseException {
806         List<Triple<Resource, Resource, String>> listOfTriples = getIndexEntries(graph, model, filter);
807         StringBuilder sb = new StringBuilder();
808         sb.append("== LISTING INDEX ENTRIES OF INDEX: " + NameUtils.getSafeName(graph, model) + ". AMOUNT OF ENTRIES: " + listOfTriples.size() + " ==\n");
809         for (Triple<Resource, Resource, String> entry : listOfTriples) {
810                 String instanceOf = NameUtils.getSafeName(graph, entry.second);
811                 sb.append("Name: " + entry.third + " instanceOf: " + instanceOf + " Resource: " + entry.first.toString() + "\n");
812         }
813                 return sb.toString();
814     }
815
816     public static List<Resource> searchByTypeAndName(ReadGraph graph, Resource model, Resource type, String name) throws DatabaseException {
817         Instances query = graph.adapt(type, Instances.class);
818         ArrayList<Resource> result =  new ArrayList<Resource>();
819         for(Resource r : query.findByName(graph, model, name)) {
820                 if(graph.isInstanceOf(r, type))
821                         result.add(r);
822         }
823         return result;
824     }
825
826     public static List<Resource> searchByTypeAndNameShallow(ReadGraph graph, Resource model, Resource type, String name) throws DatabaseException {
827         return graph.syncRequest(new QueryIndex(model, type, name), TransientCacheListener.<List<Resource>>instance());
828     }
829
830         /**
831          * @param graph
832          *            database write access
833          * @param sourceContainer
834          *            the source container to look for annotationProperty from to be
835          *            used as the copy source
836          * @param targetContainer
837          *            the target container for the copied annotationProperty
838          *            annotation
839          * @param annotationProperty
840          *            the annotation property relation
841          * @return created copy of the original annotation or <code>null</code> if
842          *         there was nothing to copy
843          * @throws DatabaseException
844          */
845         public static Resource copyPossibleAnnotation(WriteGraph graph, Resource sourceContainer, Resource targetContainer, Resource annotationProperty) throws DatabaseException {
846                 return copyPossibleAnnotation2(graph, sourceContainer, targetContainer, annotationProperty, null);
847         }
848
849         public static List<String> getPossibleNamePath(ReadGraph graph, Resource resource) throws DatabaseException {
850                 return getPossibleNamePath(graph, resource, null);
851         }
852          
853         private static List<String> getPossibleNamePath(ReadGraph graph, Resource resource, List<String> result) throws DatabaseException {
854                 
855                 Layer0 L0 = Layer0.getInstance(graph);
856                 String name = graph.getPossibleRelatedValue(resource, L0.HasName, Bindings.STRING);
857                 if(name == null) return null;
858
859                 if(result == null) result = new ArrayList<String>();
860                 
861                 SimulationResource SIMU = SimulationResource.getInstance(graph);
862                 if(graph.isInstanceOf(resource, SIMU.Model)) return result;
863                 
864                 Resource parent = graph.getPossibleObject(resource, L0.PartOf);
865                 if(parent != null) {
866                         getPossibleNamePath(graph, parent, result);
867                 } else {
868                         return null;
869                 }
870
871                 result.add(name);
872                 
873                 return result;
874
875         }
876         
877         public static Resource claimLibraryPath(WriteGraph graph, Resource resource, List<String> path) throws DatabaseException {
878                 Layer0 L0 = Layer0.getInstance(graph);
879                 for(int i=0;i<path.size()-1;i++) {
880                         String p = path.get(i);
881                         Resource child = Layer0Utils.getPossibleChild(graph, resource, p);
882                         if(child == null) {
883                                 child = graph.newResource();
884                                 graph.claim(child, L0.InstanceOf, L0.Library);
885                                 graph.addLiteral(child, L0.HasName, L0.NameOf, L0.String, p, Bindings.STRING);
886                                 graph.claim(resource, L0.ConsistsOf, L0.PartOf, child);
887                         }
888                         resource = child;
889                 }
890                 return resource;
891         }
892         
893         /**
894          * @param graph
895          *            database write access
896          * @param sourceContainer
897          *            the source container to look for annotationProperty from to be
898          *            used as the copy source
899          * @param targetContainer
900          *            the target container for the copied annotationProperty
901          *            annotation
902          * @param annotationProperty
903          *            the annotation property relation
904          * @param annotationProperty
905          *            the 2nd level annotation property relation or
906          *            <code>null</code> if no 2nd level annotation exists
907          * @return created copy of the original annotation or <code>null</code> if
908          *         there was nothing to copy
909          * @throws DatabaseException
910          */
911         public static Resource copyPossibleAnnotation2(WriteGraph graph,
912                         Resource sourceContainer, Resource targetContainer,
913                         Resource annotationProperty, Resource entryType) throws DatabaseException {
914
915                 // Delete existing target value first
916                 Layer0 L0 = Layer0.getInstance(graph);
917                 Resource targetValue = graph.getPossibleObject(targetContainer, annotationProperty);
918                 if (targetValue != null) {
919                         if(!graph.hasStatement(targetValue, L0.PartOf))
920                                 RemoverUtil.remove(graph, targetValue);
921                         graph.deny(targetContainer, annotationProperty);
922                 }
923
924                 Resource sourceValue = graph.getPossibleObject(sourceContainer, annotationProperty);
925                 if (sourceValue == null)
926                         return null;
927                 
928                 List<String> sourceValuePath = getPossibleNamePath(graph, sourceValue);
929                 if(sourceValuePath != null) {
930                         Resource targetModel = graph.sync(new PossibleModel(targetContainer));
931                         if(targetModel == null) throw new DatabaseException("No target model found for " + targetContainer);
932                         Resource library = claimLibraryPath(graph, targetModel, sourceValuePath);
933                         Resource existing = Layer0Utils.getPossibleChild(graph, library, sourceValuePath.get(sourceValuePath.size()-1));
934                         if(existing == null) {
935                                 existing = doCopyPossibleAnnotation2(graph, sourceContainer, targetContainer, annotationProperty, entryType);
936                                 graph.claim(library, L0.ConsistsOf, L0.PartOf, existing);
937                         }
938                         graph.claim(targetContainer, annotationProperty, existing);
939                         return existing;
940                 } else {
941                         return doCopyPossibleAnnotation2(graph, sourceContainer, targetContainer, annotationProperty, entryType);
942                 }
943
944         }
945
946         private static Resource doCopyPossibleAnnotation2(WriteGraph graph,
947                         Resource sourceContainer, Resource targetContainer,
948                         Resource annotationProperty, Resource entryType) throws DatabaseException {
949
950                 Resource sourceValue = graph.getPossibleObject(sourceContainer, annotationProperty);
951                 if (sourceValue == null)
952                         return null;
953                 
954                 // Copy 1st level annotation
955                 Resource targetValue = createAnnotation(graph, targetContainer, annotationProperty, sourceValue);
956
957                 // Copy possible 2nd level annotations and attach to 1st if entry
958                 // property is defined.
959                 Layer0 L0 = Layer0.getInstance(graph);
960                 if (entryType != null) {
961                         
962                         AnnotationResource ANNO = AnnotationResource.getInstance(graph);
963                         for (Resource entry : graph.getObjects(sourceValue, ANNO.Annotation_HasEntry)) {
964
965                                 String name = graph.getRelatedValue(entry, L0.HasName, Bindings.STRING);
966
967                                 List<String> entryPath = getPossibleNamePath(graph, entry);
968                                 if(entryPath != null) {
969                                         Resource targetModel = graph.sync(new PossibleModel(targetContainer));
970                                         if(targetModel == null) throw new DatabaseException("No target model found for " + targetContainer);
971                                         Resource library = claimLibraryPath(graph, targetModel, entryPath);
972                                         Resource existing = Layer0Utils.getPossibleChild(graph, library, entryPath.get(entryPath.size()-1));
973                                         if(existing == null) {
974                                                 existing = createTypedAnnotation(graph, null, null, entry, entryType, name);
975                                                 graph.claim(library, L0.ConsistsOf, L0.PartOf, existing);
976                                         }
977                                         graph.claim(targetValue, ANNO.Annotation_HasEntry, existing);
978                                 } else {
979                                         Resource result = createTypedAnnotation(graph, null, null, entry, entryType, name);
980                                         graph.claim(targetValue, ANNO.Annotation_HasEntry, result);
981                                 }
982                                 
983                         }
984                 }
985
986                 return targetValue;
987
988         }
989
990         /**
991          * @param graph
992          *            database write access
993          * @param container
994          *            the container resource to attach the new annotation to
995          * @param property
996          *            the annotation property relation. The type of the created
997          *            annotation is decided from this property relation's range
998          * @param sourceAnnotation
999          *            the annotation to copy data from or <code>null</code> if
1000          *            nothing shall be copied
1001          * @return the newly created annotation resource or <code>null</code> if the
1002          *         annotation property relation didn't have a single range type
1003          * @throws DatabaseException
1004          */
1005         public static Resource createAnnotation(WriteGraph graph, Resource container, Resource property, Resource sourceAnnotation) throws DatabaseException {
1006                 return createAnnotation(graph, container, property, sourceAnnotation, null);
1007         }
1008
1009         /**
1010          * @param graph
1011          *            database write access
1012          * @param container
1013          *            the container resource to attach the new annotation to
1014          * @param property
1015          *            the annotation property relation. The type of the created
1016          *            annotation is decided from this property relation's range
1017          * @param sourceAnnotation
1018          *            the annotation to copy data from or <code>null</code> if
1019          *            nothing shall be copied
1020          * @param name
1021          *            name for newly created annotation or <code>null</code> to copy
1022          *            name from source if available
1023          * @return the newly created annotation resource or <code>null</code> if the
1024          *         annotation property relation didn't have a single range type
1025          * @throws DatabaseException
1026          */
1027         public static Resource createAnnotation(WriteGraph graph, Resource container, Resource property, Resource sourceAnnotation, String name) throws DatabaseException {
1028
1029                 Layer0 L0 = Layer0.getInstance(graph);
1030                 Resource annotationType = graph.getSingleObject(property, L0.HasRange);
1031                 if (annotationType == null)
1032                         return null;
1033
1034                 return createTypedAnnotation(graph, container, property, sourceAnnotation, annotationType, name);
1035
1036         }
1037
1038         /**
1039          * @param graph
1040          *            database write access
1041          * @param container
1042          *            the container resource to attach the new annotation to
1043          * @param property
1044          *            the annotation property relation
1045          * @param sourceAnnotation
1046          *            the annotation to copy data from or <code>null</code> if
1047          *            nothing shall be copied
1048          * @param annotationType
1049          *            the type of the new annotation
1050          * @return the newly created annotation resource
1051          * @throws DatabaseException
1052          */
1053         public static Resource createTypedAnnotation(WriteGraph graph, Resource container, Resource property, Resource sourceAnnotation, Resource annotationType) throws DatabaseException {
1054                 return createTypedAnnotation(graph, container, property, sourceAnnotation, annotationType, null);
1055         }
1056
1057         /**
1058          * @param graph
1059          *            database write access
1060          * @param container
1061          *            the container resource to attach the new annotation to
1062          * @param property
1063          *            the annotation property relation
1064          * @param sourceAnnotation
1065          *            the annotation to copy data from or <code>null</code> if
1066          *            nothing shall be copied
1067          * @param annotationType
1068          *            the type of the new annotation
1069          * @param name
1070          *            name for newly created annotation or <code>null</code> to copy
1071          *            name from source if available
1072          * @return the newly created annotation resource
1073          * @throws DatabaseException
1074          */
1075         public static Resource createTypedAnnotation(WriteGraph graph, Resource container, Resource property, Resource sourceAnnotation, Resource annotationType, String name) throws DatabaseException {
1076
1077                 Layer0 L0 = Layer0.getInstance(graph);
1078
1079                 Resource anno = graph.newResource();
1080
1081                 graph.claim(anno, L0.InstanceOf, null, annotationType);
1082
1083                 if (name != null)
1084                         graph.addLiteral(anno, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING);
1085
1086                 if (sourceAnnotation != null) {
1087
1088                         if (name == null) {
1089                                 String sourceName = graph.getPossibleRelatedValue(sourceAnnotation, L0.HasName, Bindings.STRING);
1090                                 if(sourceName != null) graph.addLiteral(anno, L0.HasName, L0.NameOf, L0.String, sourceName, Bindings.STRING);
1091                         }
1092
1093                         Resource sourceType = graph.getSingleType(sourceAnnotation);
1094                         List<AnnotationMap> am = getAnnotationMap(graph, annotationType, sourceType);
1095                         for (AnnotationMap a : am) {
1096                                 Resource object = graph.getSingleObject(sourceAnnotation, a.sourcePredicate);
1097                                 Collection<Resource> objectTypes = graph.getTypes(object);
1098                                 if (objectTypes.contains(L0.Literal)) {
1099                                         Object value = graph.getValue(object, a.defaultValueBinding);
1100                                         if (!ObjectUtils.objectEquals(value, a.defaultValue)) {
1101                                                 graph.addLiteral(anno, a.annotationPredicate, a.annotationPredicateInverse, a.defaultValueType, value, a.defaultValueBinding);
1102                                         }
1103                                 }
1104                         }
1105                 }
1106
1107                 if (container != null && property != null) {
1108                         graph.claim(container, property, anno);
1109                 }
1110
1111                 return anno;
1112
1113         }
1114
1115         private static class AnnotationMap {
1116
1117                 final public Resource sourcePredicate;
1118                 final public Resource sourcePredicateInverse;
1119
1120                 final public Resource annotationPredicate;
1121                 final public Resource annotationPredicateInverse;
1122
1123                 final public Resource defaultValueType;
1124                 final public Object defaultValue;
1125                 final public Binding defaultValueBinding;
1126
1127                 public AnnotationMap(Resource sp, Resource spi, Resource tp, Resource tpi, Resource defaultValueType, Object defaultValue, Binding defaultValueBinding) {
1128                         sourcePredicate = sp;
1129                         sourcePredicateInverse = spi;
1130                         annotationPredicate = tp;
1131                         annotationPredicateInverse = tpi;
1132                         this.defaultValueType = defaultValueType;
1133                         this.defaultValue = defaultValue;
1134                         this.defaultValueBinding = defaultValueBinding;
1135                 }
1136
1137         }
1138
1139         public static List<AnnotationMap> getAnnotationMap(ReadGraph graph, Resource annotationType, Resource sourceType) throws DatabaseException {
1140                 return graph.syncRequest(new AnnotationMapRequest(annotationType, sourceType), TransientCacheListener.<List<AnnotationMap>>instance());
1141         }
1142
1143         static class AnnotationMapRequest extends ResourceRead2<List<AnnotationMap>> {
1144
1145                 public AnnotationMapRequest(Resource annotationType, Resource sourceType) {
1146                         super(annotationType, sourceType);
1147                 }
1148
1149                 @Override
1150                 public List<AnnotationMap> perform(ReadGraph graph) throws DatabaseException {
1151
1152                         Layer0 L0 = Layer0.getInstance(graph);
1153
1154                         ArrayList<AnnotationMap> result = new ArrayList<AnnotationMap>(); 
1155
1156                         Map<String, Resource> annotationPredicates = new HashMap<String, Resource>();
1157                         for(Resource predicate : graph.getObjects(resource, L0.DomainOf)) {
1158                                 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
1159                                 annotationPredicates.put(name, predicate);
1160                         }
1161                         Map<String, Resource> sourcePredicates = new HashMap<String, Resource>();
1162                         for(Resource predicate : graph.getObjects(resource2, L0.DomainOf)) {
1163                                 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
1164                                 sourcePredicates.put(name, predicate);
1165                         }
1166
1167                         for(String key : sourcePredicates.keySet()) {
1168                                 Resource sourcePredicate = sourcePredicates.get(key);
1169                                 Resource anno = annotationPredicates.get(key);
1170                                 if(sourcePredicate != null && anno != null) {
1171                                         Resource defaultValueType = graph.getSingleObject(anno, L0.HasRange);
1172                                         Binding defaultValueBinding = null;
1173                                         Object defaultValue = null;
1174                                         Resource assertion = graph.getPossibleObject(anno, L0.HasPredicateInverse);
1175                                         if (assertion != null) {
1176                                                 Resource object = graph.getPossibleObject(assertion, L0.HasObject);
1177                                                 if (object != null) {
1178                                                         if(graph.isInstanceOf(object, L0.Literal)) {
1179                                                                 Datatype dt = graph.getDataType(object);
1180                                                                 defaultValueBinding = Bindings.getBeanBinding(dt);
1181                                                                 defaultValue = graph.getPossibleValue(object);
1182                                                         }
1183                                                 }
1184                                         }
1185                                         result.add(new AnnotationMap(
1186                                                         sourcePredicate, graph.getInverse(sourcePredicate),
1187                                                         anno, graph.getInverse(anno),
1188                                                         defaultValueType, defaultValue, defaultValueBinding));
1189                                 }
1190                         }
1191
1192                         return result;
1193
1194                 }
1195
1196         }
1197
1198         public static final String DRAWING_TEMPLATE_FORMAT    = "drawingTemplate";
1199     public static final String DRAWING_TEMPLATE_FORMAT_V1 = DRAWING_TEMPLATE_FORMAT + ":1";
1200     public static final String DRAWING_TEMPLATE_FORMAT_V2 = DRAWING_TEMPLATE_FORMAT + ":2";
1201
1202     public static Resource importDrawingTemplate(final Resource model, final File file) throws IOException, SerializationException, DatabaseException, TransferableGraphException {
1203
1204                 try {
1205
1206                         final Resource library = Simantics.sync(new WriteResultRequest<Resource>() {
1207
1208                                 @Override
1209                                 public Resource perform(WriteGraph graph) throws DatabaseException {
1210                                         
1211                                         Layer0 L0 = Layer0.getInstance(graph);
1212                                         Template2dResource TEMPLATE = Template2dResource.getInstance(graph);
1213                                         Resource root = graph.getPossibleObject(model, TEMPLATE.HasDrawingTemplateRoot);
1214                                         if(root == null) {
1215                                                 Template2dResource TEMPLATE2D = Template2dResource.getInstance(graph);
1216                                                 root = graph.newResource();
1217                                                 graph.claim(root, L0.InstanceOf, null, TEMPLATE2D.DrawingTemplateLibrary);
1218                                                 graph.claim(root, L0.InstanceOf, null, TEMPLATE2D.DrawingTemplateLibraryUI);
1219                                                 graph.claimLiteral(root, L0.HasName, L0.NameOf, L0.String, "Diagram Templates", Bindings.STRING);
1220                                                 graph.claim(root, L0.PartOf, L0.ConsistsOf, model);
1221                                                 graph.claim(model, TEMPLATE2D.HasDrawingTemplateRoot, root);
1222                                         }
1223                                         
1224                                         String name = new Path(file.getAbsolutePath()).removeFileExtension().lastSegment();
1225                                         if(name != null) {
1226                                                 Resource existing = Layer0Utils.getPossibleChild(graph, root, name);
1227                                                 if(existing != null)
1228                                                         graph.deny(root, L0.ConsistsOf, existing);
1229                                         }
1230                                         
1231                                         return root;
1232                                         
1233                                 }
1234
1235                         });
1236
1237                         final DefaultPasteImportAdvisor advisor = new DefaultPasteImportAdvisor(library);
1238
1239                         try {
1240                                 HashMap<String, FormatHandler<Object>> handlers = new HashMap<String, FormatHandler<Object>>();
1241                                 FormatHandler<Object> handler = new FormatHandler<Object>() {
1242                                         @Override
1243                                         public Binding getBinding() {
1244                                                 return TransferableGraph1.BINDING;
1245                                         }
1246
1247                                         @Override
1248                                         public Object process(DataContainer container) throws Exception {
1249                                                 TransferableGraphs.importGraph1(Simantics.getSession(), (TransferableGraph1)container.content.getValue(), 
1250                                                                 advisor, null);
1251                                                 return null;
1252                                         }
1253                                 };
1254                                 handlers.put(DRAWING_TEMPLATE_FORMAT_V1, handler);
1255                                 handlers.put(DRAWING_TEMPLATE_FORMAT_V2, handler);
1256                                 try {
1257                                         DataContainers.readFile(file, handlers);
1258                                 } catch(DataFormatException e) {
1259                                         throw new IOException(e);
1260                                 } catch(IOException e) {
1261                                         throw e;
1262                                 } catch(Exception e) {
1263                                         if(e instanceof RuntimeException)
1264                                                 throw (RuntimeException)e;
1265                                         else
1266                                                 throw new RuntimeException(e);
1267                                 }
1268
1269                         } catch(IOException e) {
1270                         }
1271
1272                         return advisor.getRoot();
1273
1274                 } catch (Throwable t) {
1275                         Logger.defaultLogError("Unexpected exception while importing diagram template.", t);
1276                 } finally {
1277                 }
1278
1279                 return null;
1280
1281         }
1282     
1283     public static Collection<Variable> getMappedVariables(ReadGraph graph, Variable source) throws DatabaseException {
1284         
1285         ArrayList<Variable> result = new ArrayList<Variable>();
1286         Resource represents = source.getPossibleRepresents(graph);
1287         if(represents == null) return Collections.emptyList();
1288         ModelingResources MOD = ModelingResources.getInstance(graph);
1289         for(Resource r : getElementCorrespondendences(graph, represents)) {
1290             result.add(Variables.getVariable(graph, r));
1291         }
1292         for(Resource r : graph.getObjects(represents, MOD.ComponentToElement)) {
1293             result.add(Variables.getVariable(graph, r));
1294         }
1295         for(Resource r : graph.getObjects(represents, MOD.DiagramToComposite)) {
1296             result.add(Variables.getVariable(graph, r));
1297         }
1298         for(Resource r : graph.getObjects(represents, MOD.CompositeToDiagram)) {
1299             result.add(Variables.getVariable(graph, r));
1300         }
1301         return result;
1302         
1303     }
1304     
1305     public static Resource getPossibleModel(ReadGraph graph, Resource resource) throws DatabaseException {
1306         
1307         PossibleModel pm = new PossibleModel(resource);
1308         Resource model = pm.perform(graph);
1309         return model;
1310     }
1311     
1312     public static Resource possibleIndexRoot(ReadGraph graph, Resource resource) throws DatabaseException {
1313         return graph.syncRequest(new PossibleIndexRoot(resource));
1314     }
1315
1316     public static Object getMonitorValue(StructuralComponent _variable, ReadGraph graph, String path) throws DatabaseException {
1317         Variable variable = ((VariableStructuralContext)_variable).variable;
1318         Variable var = variable.browse(graph, path);
1319         return var.getValue(graph);
1320     }
1321     
1322     public static void createSharedOntologyWithUI(ReadGraph graph, Variable variable, Resource baseType) throws DatabaseException {
1323         createSharedOntologyWithUI(graph, baseType);
1324     }
1325
1326     public static void createSharedOntologyWithUI(ReadGraph graph, Resource baseType) throws DatabaseException {
1327         
1328 //      Resource indexRoot_ = variable.getPossibleRepresents(graph);
1329 //      if(indexRoot_ == null) return;
1330
1331             final Map<Resource, Pair<String,ImageDescriptor>> map = new HashMap<Resource, Pair<String,ImageDescriptor>>();
1332
1333         Layer0 L0 = Layer0.getInstance(graph);
1334         SimulationResource SIMU = SimulationResource.getInstance(graph);
1335         Instances query = graph.adapt(L0.IndexRootType, Instances.class);
1336         for(Resource ontology : Layer0Utils.listOntologies(graph)) {
1337                 for(Resource type : query.find(graph, ontology)) {
1338                         if(graph.isInheritedFrom(type, SIMU.Model)) continue;
1339                         if(graph.hasStatement(type, L0.Abstract)) continue;
1340                         if(!graph.isInheritedFrom(type, baseType)) continue;
1341                         String name = graph.getPossibleRelatedValue(type, L0.HasLabel, Bindings.STRING);
1342                         if(name == null) name = graph.getRelatedValue(type, L0.HasName, Bindings.STRING);
1343                         map.put(type, new Pair<String,ImageDescriptor>(name, null));
1344                 }
1345         }
1346         
1347         Display.getDefault().asyncExec(new Runnable() {
1348                         @Override
1349                         public void run() {
1350                                 Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
1351                                 CreateSharedOntologyDialog page = new CreateSharedOntologyDialog(shell, map, "Select type and name of new shared library");
1352                                 if (page.open() == Window.OK) {
1353                                         Object[] result = page.getResult();
1354                                         if (result != null && result.length == 1) {
1355                                                 final Resource res = (Resource)result[0];
1356                                                 final String name = "http://" + page.getName();
1357                                                 Simantics.getSession().asyncRequest(new WriteRequest() {
1358
1359                                                         @Override
1360                                                         public void perform(WriteGraph graph) throws DatabaseException {
1361                                                                 graph.markUndoPoint();
1362                                                                 Resource target = Simantics.applySCL("Simantics/SharedOntologies", "createSharedOntology", graph, name+"@A", res);
1363                                                                 
1364                                                                 ProjectResource PROJ = ProjectResource.getInstance(graph);
1365                                                                 Layer0 L0 = Layer0.getInstance(graph);
1366                                                                 for(Resource dep : graph.getObjects(Simantics.getProjectResource(), L0.IsLinkedTo)) {
1367                                                                         if(graph.isInstanceOf(dep, PROJ.NamespaceRequirement)) {
1368                                                                                 for(Resource req : graph.getObjects(dep, PROJ.RequiresNamespace)) {
1369                                                                                         String uri = graph.getPossibleValue(req, Bindings.STRING);
1370                                                                                         if(uri != null) {
1371                                                                                                 Resource ns = graph.getResource(uri);
1372                                                                                                 if(ns != null) {
1373                                                                                                         graph.claim(target, L0.IsLinkedTo, null, ns);
1374                                                                                                 }
1375                                                                                         }
1376                                                                                 }
1377                                                                         }
1378                                                                 }
1379                                                                 
1380                                                         }
1381                                                         
1382                                                 });
1383                                         }
1384                                 }
1385                         }
1386                 });
1387         
1388     }
1389
1390     public static void unlinkSharedOntologyWithUI(ReadGraph graph, Variable variable, final List<Resource> libraries) throws DatabaseException {
1391         
1392         final Resource indexRoot = variable.getPossibleRepresents(graph);
1393         if(indexRoot == null) return;
1394         
1395         StructuralResource2 STR = StructuralResource2.getInstance(graph);
1396
1397         final List<String> instances = new ArrayList<String>();
1398         
1399         DiagramResource DIA = DiagramResource.getInstance(graph);
1400         
1401         for(Resource library : libraries) {
1402                 for(Resource type : ModelingUtils.searchByTypeShallow(graph, library, STR.ComponentType)) {
1403                         for(Resource instance : ModelingUtils.searchByTypeShallow(graph, indexRoot, type)) {
1404                                 // TODO: haxx
1405                                 if(graph.isInstanceOf(instance, DIA.Element)) continue;
1406                                 String name = Versions.getStandardPathNameString(graph, instance);
1407                                 instances.add(name);
1408                         }
1409                 }
1410         }
1411         
1412         if(instances.isEmpty()) {
1413                 graph.getSession().asyncRequest(new WriteRequest() {
1414                         
1415                                 @Override
1416                                 public void perform(WriteGraph graph) throws DatabaseException {
1417                                 Layer0 L0 = Layer0.getInstance(graph);
1418                                 for(Resource library : libraries)
1419                                         graph.deny(indexRoot, L0.IsLinkedTo, library);
1420                                 }
1421                         
1422                 });
1423                 return;
1424         }
1425         
1426         PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
1427             @Override
1428             public void run() {
1429                 
1430                 if (!PlatformUI.isWorkbenchRunning())
1431                     return;
1432
1433                 Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
1434                 ListDialog<String> dialog = new ListDialog<String>(
1435                         shell,
1436                         instances,
1437                         "Cannot unlink selected libraries",
1438                         "Libraries cannot be unlinked since the following instances are referring to them.") {
1439
1440                         protected void createButtonsForButtonBar(Composite parent) {
1441                                 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,true);
1442                         }
1443                         
1444                 };
1445                 int result = dialog.open();
1446                 if (result != Dialog.OK)
1447                     return;
1448
1449             }
1450         });
1451         
1452     }
1453     
1454     public static MigratedImportResult importSharedOntologyWithResult(String fileName) throws Exception {
1455         try {
1456                 DataContainer dc = DataContainers.readFile(new File(fileName));
1457                 TransferableGraph1 tg = (TransferableGraph1)dc.content.getValue(TransferableGraph1.BINDING);
1458                 Variant draftStatus = dc.metadata.get(DraftStatusBean.EXTENSION_KEY);
1459                 return MigrationUtils.importSharedOntology(Simantics.getSession(), tg, draftStatus == null);
1460         } catch (Exception e) {
1461                 Logger.defaultLogError(e);
1462                 throw e;
1463         }
1464     }
1465     
1466     public static void importSharedOntology(String fileName) throws Exception {
1467         importSharedOntologyWithResult(fileName);
1468     }
1469
1470     public static List<Resource> importSharedOntology2(String fileName) throws Exception {
1471         MigratedImportResult result = importSharedOntologyWithResult(fileName);
1472         return new ArrayList<Resource>(result.roots);
1473     }
1474     
1475     public static void importSharedOntologyWithUI(ReadGraph graph, final Variable variable) throws DatabaseException {
1476         
1477         Display.getDefault().asyncExec(new Runnable() {
1478
1479                         @Override
1480                         public void run() {
1481                                 IStructuredSelection sel = new StructuredSelection(variable);
1482                         openWizard(Display.getCurrent(), sel, "org.simantics.modeling.ui.sharedOntologyImportWizard");
1483                         }
1484                         
1485                 });
1486         
1487     }
1488     
1489         public static class LibraryInfo implements Comparable<LibraryInfo> {
1490                 public NamedResource library;
1491                 public DraftStatusBean draft;
1492                 public LibraryInfo(String name, Resource r, DraftStatusBean draft) {
1493                         library = new NamedResource(name, r);
1494                         this.draft = draft;
1495                 }
1496                 @Override
1497                 public int compareTo(LibraryInfo o) {
1498                         return library.compareTo(o.library);
1499                 }
1500                 @Override
1501                 public int hashCode() {
1502                         return library.hashCode();
1503                 }
1504                 @Override
1505                 public boolean equals(Object object) {
1506                 if (this == object)
1507                     return true;
1508                 else if (object == null)
1509                     return false;
1510                 else if (!(object instanceof LibraryInfo))
1511                     return false;
1512                 LibraryInfo info = (LibraryInfo)object;
1513                 return info.library.equals(library);
1514                 }
1515                 
1516         }
1517         
1518     public static void exportSharedOntologyWithUI(final Resource sharedOntology) {
1519
1520         Display.getDefault().asyncExec(new Runnable() {
1521
1522                 @Override
1523                 public void run() {
1524                         HintContext hc = new HintContext();
1525                         hc.setHint(SelectionHints.KEY_MAIN, sharedOntology);
1526                         IStructuredSelection sel = new StructuredSelection(hc);
1527                 openWizard(Display.getCurrent(), sel, "org.simantics.modeling.ui.sharedOntologyExportWizard");
1528                 }
1529                 
1530         });
1531         
1532     }
1533         
1534     public static TransferableGraph1 exportSharedOntology(IProgressMonitor monitor, RequestProcessor processor, File location, String format, int version, final LibraryInfo info) throws DatabaseException, IOException {
1535         
1536         if(monitor == null) monitor = new NullProgressMonitor();
1537         
1538         // TODO: figure out a way to make the TG go directly into a file
1539         // instead of having it all in memory at once.
1540
1541         monitor.beginTask("Exporting shared library...", 100);
1542         SimanticsClipboard clipboard = processor.syncRequest(new Read<SimanticsClipboard>() {
1543             @Override
1544             public SimanticsClipboard perform(ReadGraph graph) throws DatabaseException {
1545                 CopyHandler ch = graph.adapt(info.library.getResource(), CopyHandler.class);
1546                 SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
1547                 ch.copyToClipboard(graph, clipboard);
1548                 return clipboard;
1549             }
1550         });
1551         
1552         TreeMap<String,Variant> metadata = getExportMetadata();
1553         DraftStatusBean draft = info.draft;
1554         if(draft != null) {
1555                 metadata.put(DraftStatusBean.EXTENSION_KEY, new Variant(DraftStatusBean.BINDING ,draft));
1556         }
1557         
1558         for (Set<Representation> object : clipboard.getContents()) {
1559                 
1560             TransferableGraph1 tg = ClipboardUtils.accept(processor, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
1561             monitor.worked(95);
1562             
1563             Variant edb = tg.extensions.get(ExternalDownloadBean.EXTENSION_KEY);
1564             if(edb != null) {
1565                 metadata.put(ExternalDownloadBean.EXTENSION_KEY, edb);
1566             }
1567
1568             if(location != null) {
1569                     monitor.setTaskName("Writing transferable graph...");
1570                     DataContainers.writeFile(location, new DataContainer(
1571                             format, version,
1572                             metadata, new Variant(TransferableGraph1.BINDING, tg)));
1573                     monitor.worked(5);
1574             }
1575             
1576             return tg;
1577             
1578         }
1579         
1580         throw new DatabaseException("Failed to export");
1581         
1582     }
1583
1584     public static TreeMap<String, Variant> getExportMetadata() {
1585
1586         TreeMap<String,Variant> metadata = new TreeMap<String,Variant>();
1587         metadata.put("date", Variant.ofInstance(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date())));
1588         metadata.put("author", Variant.ofInstance(System.getProperty("user.name", "")));
1589
1590         return metadata;
1591         
1592     }
1593     
1594     public static void createNewVersionWithoutUI(WriteGraph graph, Resource resource) throws DatabaseException {
1595         VersionInfo info = graph.syncRequest(new VersionInfoRequest(resource));
1596         int currentVersion = Integer.parseInt(info.version);
1597         String result = Integer.toString(currentVersion + 1);
1598         createNewVersion(graph, resource, info, result);
1599     }
1600     
1601     public static void createNewVersionWithUI(ReadGraph graph, final Resource resource) throws DatabaseException {
1602         
1603         final VersionInfo info = graph.syncRequest(new VersionInfoRequest(resource));
1604         
1605         Display.getDefault().asyncExec(new Runnable() {
1606                         @Override
1607                         public void run() {
1608                                 Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
1609                                 CreateVersionDialog dialog = new CreateVersionDialog(shell, info);
1610                                 if (dialog.open() == Window.OK) {
1611                                         final String result = dialog.getResult();
1612                                         Simantics.getSession().asyncRequest(new WriteRequest() {
1613                                                 @Override
1614                                                 public void perform(WriteGraph graph) throws DatabaseException {
1615                                                     createNewVersion(graph, resource, info, result);
1616                                                 }
1617                                         });
1618                                 }
1619                         }
1620                 });
1621         
1622     }
1623     
1624     public static void createNewVersion(WriteGraph graph, Resource resource, final VersionInfo info, final String result) throws DatabaseException {
1625         graph.markUndoPoint();
1626         Layer0 L0 = Layer0.getInstance(graph);
1627         Resource parent = graph.getPossibleObject(resource, L0.PartOf);
1628         if(parent == null) return;
1629         final String parentURI = graph.getPossibleURI(parent);
1630         if(parentURI == null) return;
1631         Layer0Utils.copyTo(graph, parent, resource, new PasteEventHandler() {
1632
1633             @Override
1634             public void postProcess(WriteGraph graph, Resource root) throws DatabaseException {
1635                 Layer0 L0 = Layer0.getInstance(graph);
1636                 graph.deny(root, L0.Entity_published);
1637             }
1638             
1639             @Override
1640             public IImportAdvisor2 createAdvisor(ReadGraph graph, ImportAdvisorFactory factory, Resource target) throws DatabaseException {
1641                 Map<String,Object> context = new HashMap<String,Object>();
1642                 String base = parentURI + "/" + URIStringUtils.escape( info.baseName ) + "@";
1643                 Map<String,String> renameMap = new HashMap<String,String>();
1644                 renameMap.put(base + info.version, base + result);
1645                 renameMap.put(info.baseName + "@" + info.version, info.baseName + "@" + result);
1646                 context.put(ImportAdvisors.RENAME_MAP, renameMap);
1647                 return factory.create(graph, target, context);
1648             }
1649             
1650         });
1651         Layer0Utils.addCommentMetadata(graph, "Created new version of " + info.baseName);
1652     }
1653     
1654     public static boolean isUserComponent(ReadGraph graph, Resource type) throws DatabaseException {
1655         StructuralResource2 STR = StructuralResource2.getInstance(graph);
1656         if(graph.isInstanceOf(type, STR.ProceduralComponentType)) return true;
1657         else if (graph.hasStatement(type, STR.IsDefinedBy)) return true;
1658         return false;
1659     }
1660     
1661     public static void publishComponentTypeWithUI(WriteGraph graph, final Resource componentType) throws DatabaseException {
1662
1663         Layer0 L0 = Layer0.getInstance(graph);
1664         StructuralResource2 STR = StructuralResource2.getInstance(graph);
1665         Resource composite = graph.getPossibleObject(componentType, STR.IsDefinedBy);
1666         final List<String> instances = new ArrayList<String>();
1667         if(composite != null) {
1668                 for(Resource component : graph.syncRequest(new ObjectsWithType(composite, L0.ConsistsOf, STR.Component))) {
1669                 Resource type = graph.getPossibleType(component, STR.Component);
1670                         if(type != null && isUserComponent(graph, type)) {
1671                                 if(!Layer0Utils.isPublished(graph, type)) instances.add(Versions.getStandardPathNameString(graph, component));
1672                         }
1673                 }
1674         }
1675
1676         if(instances.isEmpty()) {
1677                 graph.getSession().asyncRequest(new WriteRequest() {
1678                         
1679                                 @Override
1680                                 public void perform(WriteGraph graph) throws DatabaseException {
1681                                 graph.markUndoPoint();
1682                                 publish(graph, componentType);
1683                                 }
1684                         
1685                 });
1686                 return;
1687         }
1688         
1689         PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
1690             @Override
1691             public void run() {
1692                 
1693                 if (!PlatformUI.isWorkbenchRunning())
1694                     return;
1695
1696                 Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
1697                 ListDialog<String> dialog = new ListDialog<String>(
1698                         shell,
1699                         instances,
1700                         "Cannot publish user component",
1701                         "The following instances are referring to unpublished user components.") {
1702
1703                         protected void createButtonsForButtonBar(Composite parent) {
1704                                 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,true);
1705                         }
1706                         
1707                 };
1708                 int result = dialog.open();
1709                 if (result != Dialog.OK)
1710                     return;
1711
1712             }
1713         });
1714         
1715     }
1716
1717     public static void publishSharedOntologyWithUI(WriteGraph graph, final Resource sharedOntology) throws DatabaseException {
1718         
1719         Layer0 L0 = Layer0.getInstance(graph);
1720         DiagramResource DIA = DiagramResource.getInstance(graph);
1721         StructuralResource2 STR = StructuralResource2.getInstance(graph);
1722         final List<String> instances = new ArrayList<String>();
1723         for(Resource type : searchByTypeShallow(graph, sharedOntology, STR.ComponentType)) {
1724                         // TODO: haxx
1725                         if(graph.isInheritedFrom(type, DIA.Element)) continue;
1726                 if(!Layer0Utils.isPublished(graph, type)) instances.add(Versions.getStandardPathNameString(graph, type));
1727         }
1728         for(Resource dep : graph.syncRequest(new ObjectsWithType(sharedOntology, L0.IsLinkedTo, L0.SharedOntology))) {
1729                 if(!Layer0Utils.isPublished(graph, dep)) instances.add(Versions.getStandardPathNameString(graph, dep));
1730         }
1731         
1732         if(instances.isEmpty()) {
1733                 graph.getSession().asyncRequest(new WriteRequest() {
1734                         
1735                                 @Override
1736                                 public void perform(WriteGraph graph) throws DatabaseException {
1737                                 graph.markUndoPoint();
1738                                 publish(graph, sharedOntology);
1739                                 }
1740                         
1741                 });
1742                 return;
1743         }
1744         
1745         PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
1746             @Override
1747             public void run() {
1748                 
1749                 if (!PlatformUI.isWorkbenchRunning())
1750                     return;
1751
1752                 Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
1753                 ListDialog<String> dialog = new ListDialog<String>(
1754                         shell,
1755                         instances,
1756                         "Cannot publish shared library",
1757                         "The following dependencies are unpublished.") {
1758
1759                         protected void createButtonsForButtonBar(Composite parent) {
1760                                 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,true);
1761                         }
1762                         
1763                 };
1764                 int result = dialog.open();
1765                 if (result != Dialog.OK)
1766                     return;
1767
1768             }
1769         });
1770         
1771     }
1772
1773     public static Resource createSCLModuleDefault(WriteGraph graph, Resource target) throws DatabaseException {
1774         String name = NameUtils.findFreshEscapedName(graph, "SCLModule", target);
1775         return createSCLModule(graph, target, name);
1776     }
1777
1778     public static Resource createSCLModule(WriteGraph graph, Resource target, String name) throws DatabaseException {
1779         graph.markUndoPoint();
1780         Layer0 L0 = Layer0.getInstance(graph);
1781         Resource sclModule = GraphUtils.create2(graph, L0.SCLModule,
1782                 L0.HasName, name,
1783                 L0.PartOf, target,
1784                 L0.SCLModule_definition, "");
1785         Layer0Utils.addCommentMetadata(graph, "Created SCL Module " + name + " " + sclModule.toString());
1786         return sclModule;
1787     }
1788
1789     public static Resource setSCLModuleDefinition(WriteGraph graph, Resource module, String definition) throws DatabaseException {
1790         graph.markUndoPoint();
1791         Layer0 L0 = Layer0.getInstance(graph);
1792         graph.claimLiteral(module, L0.SCLModule_definition, definition, Bindings.STRING);
1793         Layer0Utils.addCommentMetadata(graph, "Set SCL module " + module + " definition.");
1794         return module;
1795     }
1796
1797     public static Resource createSCLScriptDefault(WriteGraph graph, Resource target) throws DatabaseException {
1798         String name = NameUtils.findFreshEscapedName(graph, "SCLScript", target);
1799         return createSCLScript(graph, target, name);
1800     }
1801
1802     public static Resource createSCLScript(WriteGraph graph, Resource target, String name) throws DatabaseException {
1803         graph.markUndoPoint();
1804         Layer0 L0 = Layer0.getInstance(graph);
1805         Resource sclModule = GraphUtils.create2(graph, L0.SCLScript,
1806                 L0.HasName, name,
1807                 L0.PartOf, target,
1808                 L0.SCLScript_definition, "");
1809         Layer0Utils.addCommentMetadata(graph, "Created SCL Script " + name + " " + sclModule.toString());
1810         return sclModule;
1811     }
1812
1813     public static Resource setSCLScriptDefinition(WriteGraph graph, Resource script, String definition) throws DatabaseException {
1814         graph.markUndoPoint();
1815         Layer0 L0 = Layer0.getInstance(graph);
1816         graph.claimLiteral(script, L0.SCLScript_definition, definition, Bindings.STRING);
1817         Layer0Utils.addCommentMetadata(graph, "Set SCL script " + script + " definition.");
1818         return script;
1819     }
1820
1821     public static Resource createPGraphDefault(WriteGraph graph, Resource target) throws DatabaseException {
1822         String name = NameUtils.findFreshEscapedName(graph, "Ontology Definition File", target);
1823         return createPGraph(graph, target, name);
1824     }
1825
1826     public static Resource createPGraph(WriteGraph graph, Resource target, String name) throws DatabaseException {
1827         graph.markUndoPoint();
1828         Layer0 L0 = Layer0.getInstance(graph);
1829         Resource file = GraphUtils.create2(graph, L0.PGraph,
1830                 L0.HasName, name,
1831                 L0.PartOf, target,
1832                 L0.PGraph_definition, "");
1833         Layer0Utils.addCommentMetadata(graph, "Created Ontology Definition File " + name + " " + file.toString());
1834         return file;
1835     }
1836
1837     public static Resource setPGraphDefinition(WriteGraph graph, Resource pgraph, String definition) throws DatabaseException {
1838         graph.markUndoPoint();
1839         Layer0 L0 = Layer0.getInstance(graph);
1840         graph.claimLiteral(pgraph, L0.PGraph_definition, definition, Bindings.STRING);
1841         Layer0Utils.addCommentMetadata(graph, "Set PGraph " + pgraph + " definition.");
1842         return pgraph;
1843     }
1844
1845     public static void publish(WriteGraph graph, Resource target) throws DatabaseException {
1846         Layer0 L0 = Layer0.getInstance(graph);
1847         graph.claimLiteral(target, L0.Entity_published, true, Bindings.BOOLEAN);
1848         Layer0Utils.addCommentMetadata(graph, "Published " + graph.getPossibleRelatedValue2(target, L0.HasName, Bindings.STRING) + " " + target.toString());
1849     }
1850
1851     public static boolean isLinkedToDeep(ReadGraph graph, Resource r1, Resource r2) throws DatabaseException {
1852         return graph.syncRequest(new IsLinkedTo(r1, r2));
1853     }
1854     
1855     public static void openWizard(Display display, IStructuredSelection selection, String id) {
1856         // First see if this is a "new wizard".
1857         IWizardDescriptor descriptor = PlatformUI.getWorkbench()
1858                         .getNewWizardRegistry().findWizard(id);
1859         // If not check if it is an "import wizard".
1860         if  (descriptor == null) {
1861                 descriptor = PlatformUI.getWorkbench().getImportWizardRegistry()
1862                                 .findWizard(id);
1863         }
1864         // Or maybe an export wizard
1865         if  (descriptor == null) {
1866                 descriptor = PlatformUI.getWorkbench().getExportWizardRegistry()
1867                                 .findWizard(id);
1868         }
1869         try  {
1870                 // Then if we have a wizard, open it.
1871                 if  (descriptor != null) {
1872                         IWorkbenchWizard wizard = descriptor.createWizard();
1873                         wizard.init(PlatformUI.getWorkbench(), selection);
1874                         WizardDialog wd = new  WizardDialog(display.getActiveShell(), wizard);
1875                         wd.setTitle(wizard.getWindowTitle());
1876                         wd.open();
1877                 }
1878         } catch  (CoreException e) {
1879                 e.printStackTrace();
1880         }
1881     }
1882     
1883     public static String withinEpsilon(double value, double reference, double epsilon) {
1884         if(Math.abs(value-reference) < epsilon) return "True";
1885         else return "Not within epsilon value=" + value + ", reference=" + reference + " , epsilon=" + epsilon; 
1886     }
1887     
1888     public static boolean needsIdentifier(ReadGraph graph, Resource r) throws DatabaseException {
1889         Layer0 L0 = Layer0.getInstance(graph);
1890         Collection<Resource> types = graph.getPrincipalTypes(r);
1891         for(Resource type : types)
1892                 if(graph.syncRequest(new IsInstanceOf(type, L0.TypeWithIdentifier), TransientCacheAsyncListener.<Boolean>instance()))
1893                                 return true;
1894         return false;
1895     }
1896
1897     public static boolean needsModificationInfo(ReadGraph graph, Resource r) throws DatabaseException {
1898         ModelingResources MOD = ModelingResources.getInstance(graph);
1899         Collection<Resource> types = graph.getPrincipalTypes(r);
1900         for(Resource type : types)
1901                 if(graph.syncRequest(new IsInstanceOf(type, MOD.TypeWithChangeInformation), TransientCacheAsyncListener.<Boolean>instance()))
1902                                 return true;
1903         return false;
1904     }
1905
1906     public static void attachCreationInformation(IProgressMonitor monitor, WriteGraph graph, Resource model) throws DatabaseException {
1907         
1908         if(monitor == null) monitor = new NullProgressMonitor();
1909         
1910         final String author = System.getProperty("user.name", "");
1911         final long time = System.currentTimeMillis();
1912         
1913         monitor.setTaskName("Attach creation information");
1914
1915         ModelingResources MOD = ModelingResources.getInstance(graph);
1916         Collection<Resource> rs = ModelingUtils.searchByType(graph, model, MOD.TypeWithChangeInformation);
1917         Collection<Resource> supers = ModelingUtils.getMostUnspecificTypes(graph, rs);
1918         
1919         CollectionSupport cs = graph.getService(CollectionSupport.class);
1920         Collection<Resource> set = cs.createSet();
1921         for(Resource type : supers) {
1922                 set.addAll(ModelingUtils.searchByTypeShallow(graph, model, type));
1923         }
1924         Collection<Resource> instances = Layer0Utils.sortByCluster(graph, set);
1925
1926         int pc = instances.size() / 100;
1927         int done = 0;
1928         int stint = pc;
1929
1930         for(Resource instance : instances) {
1931                 ChangeInformation info = graph.getPossibleRelatedValue(instance, MOD.changeInformation, ChangeInformation.BINDING);
1932                 if(info == null) {
1933                         info = new ChangeInformation();
1934                         info.createdAt = time;
1935                         info.createdBy = author;
1936                         info.modifiedAt = time;
1937                         info.modifiedBy = author;
1938                         graph.claimLiteral(instance, MOD.changeInformation, MOD.changeInformation_Inverse, MOD.ChangeInformation, info, ChangeInformation.BINDING);
1939                 }
1940                 done++;
1941                 stint--;
1942                 if(stint == 0) {
1943                         Double d = (100.0*done)/instances.size();
1944                         monitor.setTaskName("Attach creation information " +  d.intValue() + "%");
1945                         stint = pc;
1946                 }
1947         }
1948         
1949                 monitor.setTaskName("Attach creation information - commit");
1950         
1951     }
1952
1953     public static class DiagramComponentInfo {
1954
1955         private static String CHILD_PREFIX             = "child:";
1956
1957                 final private String compositePathAndName;
1958                 final private String componentName;
1959                 final private GUID guid;
1960                 
1961                 public DiagramComponentInfo(String compositePathAndName, String componentName, GUID guid) {
1962                         this.compositePathAndName = compositePathAndName;
1963                         this.componentName = componentName;
1964                         this.guid = guid;
1965                 }
1966                 
1967                 public static boolean isDiagramComponent(String tgName) {
1968                         return tgName.startsWith(CHILD_PREFIX);
1969                 }
1970
1971                 public String getTGName(CompositeInfo info) {
1972                         return CHILD_PREFIX + info.getOriginalPath() + ModelingUtils.COMPOSITE_SEPARATOR_CHAR + info.getEscapedName() + ModelingUtils.COMPOSITE_SEPARATOR_CHAR + getEscapedComponentName() + ModelingUtils.COMPOSITE_SEPARATOR_CHAR + guid.indexString();
1973                 }
1974                 
1975                 public boolean existsGUID(ReadGraph graph, Resource indexRoot) throws DatabaseException {
1976                         Collection<Resource> res = ModelingUtils.searchByGUID(graph, indexRoot, guid);
1977                         return !res.isEmpty();
1978                 }
1979
1980                 public static DiagramComponentInfo fromResource(ReadGraph graph, CompositeInfo info, Resource resource) throws DatabaseException {
1981                         Layer0 L0 = Layer0.getInstance(graph);
1982                 GUID childId = graph.getRelatedValue(resource, L0.identifier, GUID.BINDING);
1983             String childName = graph.getRelatedValue(resource, L0.HasName, Bindings.STRING);
1984             return new DiagramComponentInfo(info.getStateKey(), URIStringUtils.escape(childName), childId);
1985                 }
1986                 
1987                 public GUID getGUID() {
1988                         return guid;
1989                 }
1990                 
1991                 public String getEscapedCompositePathAndName() {
1992                         return compositePathAndName;
1993                 }
1994                 
1995                 public String getEscapedComponentName() {
1996                         return componentName;
1997                 }
1998                 
1999                 public String getUnescapedComponentName() {
2000                         return URIStringUtils.unescape(getEscapedComponentName());
2001                 }
2002                 
2003                 // "child:path#compositeName#componentName#guid"
2004                 public static DiagramComponentInfo parse(String tgName) {
2005                         
2006             String name = tgName.substring(CHILD_PREFIX.length());
2007             String compositePathAndName = "";
2008             String moduleName = name;
2009             GUID guid = GUID.invalid();
2010             int lastHash = name.lastIndexOf(ModelingUtils.COMPOSITE_SEPARATOR_CHAR);
2011             if(lastHash >= 0) {
2012                 String first = name.substring(0, lastHash);
2013                 String second = name.substring(lastHash+1);
2014                 lastHash = first.lastIndexOf(ModelingUtils.COMPOSITE_SEPARATOR_CHAR);
2015                 if(lastHash >= 0) {
2016                         compositePathAndName = first.substring(0, lastHash);
2017                         moduleName = first.substring(lastHash+1);
2018                         guid = GUID.parseIndexString(second);
2019                 } else {
2020                         compositePathAndName = first;
2021                         moduleName = second;
2022                 }
2023             }
2024             return new DiagramComponentInfo(compositePathAndName, moduleName, guid); 
2025                         
2026                 }
2027
2028
2029         @Override
2030                 public int hashCode() {
2031                         final int prime = 31;
2032                         int result = 1;
2033                         result = prime * result + ((compositePathAndName == null) ? 0 : compositePathAndName.hashCode());
2034                         result = prime * result + ((componentName == null) ? 0 : componentName.hashCode());
2035                         return result;
2036                 }
2037
2038                 @Override
2039                 public boolean equals(Object obj) {
2040                         if (this == obj)
2041                                 return true;
2042                         if (obj == null)
2043                                 return false;
2044                         if (getClass() != obj.getClass())
2045                                 return false;
2046                         DiagramComponentInfo other = (DiagramComponentInfo) obj;
2047                         if (compositePathAndName == null) {
2048                                 if (other.compositePathAndName != null)
2049                                         return false;
2050                         } else if (!compositePathAndName.equals(other.compositePathAndName))
2051                                 return false;
2052                         if (componentName == null) {
2053                                 if (other.componentName != null)
2054                                         return false;
2055                         } else if (!componentName.equals(other.componentName))
2056                                 return false;
2057                         return true;
2058                 }
2059                 
2060     }
2061     
2062         public static class CompositeInfo {
2063
2064             public static String COMPOSITE_PREFIX         = "composite:";
2065
2066                 final private boolean useGuids;
2067                 final private boolean applyPaths;
2068                 final private String path;
2069                 final private String name;
2070                 final private GUID guid;
2071                 
2072                 private CompositeInfo(boolean useGuids, boolean applyPaths, String path, String name, GUID guid) {
2073                         this.useGuids = useGuids;
2074                         this.applyPaths = applyPaths;
2075                         this.path = path;
2076                         this.name = name;
2077                         this.guid = guid;
2078                 }
2079
2080                 @Override
2081                 public String toString() {
2082                         return "CompositeInfo[useGuids=" + useGuids + ", applyPaths=" + applyPaths + ", path=" + path + ", name=" + name + ", guid=" + guid.indexString() + "]";
2083                 }
2084
2085                 public static boolean isComposite(String tgName) {
2086                         return tgName.startsWith(COMPOSITE_PREFIX);
2087                 }
2088
2089                 public String getTGName() {
2090                         return COMPOSITE_PREFIX + getOriginalPath() + ModelingUtils.COMPOSITE_SEPARATOR_CHAR + getEscapedName() + ModelingUtils.COMPOSITE_SEPARATOR_CHAR + guid.indexString();
2091                 }
2092                 
2093                 public boolean existsGUID(ReadGraph graph, Resource indexRoot) throws DatabaseException {
2094                         Collection<Resource> res = ModelingUtils.searchByGUID(graph, indexRoot, guid);
2095                         return !res.isEmpty();
2096                 }
2097
2098                 public static CompositeInfo fromResource(ReadGraph graph, Resource resource) throws DatabaseException {
2099                         
2100                         Layer0 L0 = Layer0.getInstance(graph);
2101             GUID rootId = graph.getRelatedValue(resource, L0.identifier, GUID.BINDING);
2102             String rootName = graph.getRelatedValue(resource, L0.HasName, Bindings.STRING);
2103             String escapedRootName = URIStringUtils.escape(rootName);
2104             String escapedPath = ModelingUtils.getDiagramCompositePath(graph, resource);
2105             return new CompositeInfo(true, true, escapedPath, escapedRootName, rootId);
2106                         
2107                 }
2108
2109             public static CompositeInfo parse(String tgName) {
2110                 return parse(tgName, true, true);
2111             }
2112
2113             /*
2114              * Index 0 is root-relative folder path separated with '/' or null if target-relative positioning is used
2115              * Index 1 is diagram name
2116              */
2117             public static CompositeInfo parse(String tgName, boolean applyPaths, boolean useGuids) {
2118                 if(!tgName.startsWith(COMPOSITE_PREFIX)) return null;
2119                 tgName = tgName.substring(COMPOSITE_PREFIX.length());
2120                 if(!tgName.contains(COMPOSITE_SEPARATOR)) {
2121                         if(useGuids) throw new IllegalStateException("GUID identifiers were not found for diagrams.");
2122                         return new CompositeInfo(useGuids, applyPaths, null, tgName, null);
2123                 }
2124                 String[] parts = tgName.split(COMPOSITE_SEPARATOR);
2125                 if(parts.length == 2) {
2126                         String name = parts[1];
2127                         String path = applyPaths ? parts[0] : null;
2128                         if(useGuids) throw new IllegalStateException("GUID identifiers were not found for diagrams.");
2129                         return new CompositeInfo(useGuids, applyPaths, path, name, null);
2130                 } else if(parts.length == 3) {
2131                         String path = parts[0];
2132                         String name = parts[1];
2133                         GUID guid = GUID.parseIndexString(parts[2]);
2134                         return new CompositeInfo(useGuids, applyPaths, path, name, guid);
2135                 } else {
2136                         return null;
2137                 }
2138             }
2139
2140                 public GUID getGUID() {
2141                         return guid;
2142                 }
2143
2144                 public String getEscapedName() {
2145                         return name;
2146                 }
2147                 
2148                 public String getUnescapedName() {
2149                         return URIStringUtils.unescape(name);
2150                 }
2151                 
2152                 public String getOriginalPath() {
2153                         return path;
2154                 }
2155                 
2156                 public String getFinalPath() {
2157                         if(applyPaths) return path;
2158                         else return null;
2159                 }
2160                 
2161                 public CompositeInfo renamed(String newName) {
2162                         return new CompositeInfo(useGuids, applyPaths, path, newName, guid);
2163                 }
2164                 
2165                 public String getStateKey() {
2166                         return path + "#" + getEscapedName();
2167                 }
2168                 
2169                 private Resource getFromFolder(ReadGraph graph, Resource target) throws DatabaseException {
2170             Resource diagram = Layer0Utils.getPossibleChild(graph, target, URIStringUtils.unescape(name));
2171             if(diagram == null) return null;
2172             StructuralResource2 STR = StructuralResource2.getInstance(graph);
2173             return graph.isInstanceOf(diagram, STR.Composite) ? diagram : null;
2174                 }
2175                 
2176                 public Resource resolve(ReadGraph graph, Resource target) throws DatabaseException {
2177
2178                         if(useGuids && guid != null) {
2179                                 Resource indexRoot = graph.syncRequest(new IndexRoot(target));
2180                                 Collection<Resource> queryResult = searchByGUID(graph, indexRoot, guid);
2181                                 if(queryResult.size() == 1) {
2182                                         Resource composite = queryResult.iterator().next(); 
2183                             StructuralResource2 STR = StructuralResource2.getInstance(graph);
2184                             if(!graph.isInstanceOf(composite, STR.Composite)) return null;
2185                             return composite;
2186                                 }
2187                         }
2188                         
2189                         if(applyPaths) {
2190                                 Resource folder = resolveFolder(graph, target);
2191                                 if(folder == null) return null;
2192                         return getFromFolder(graph, folder);
2193                         } else {
2194                         return getFromFolder(graph, target);
2195                         }
2196                         
2197                 }
2198                 
2199                 public Resource resolveFolder(ReadGraph graph, Resource target) throws DatabaseException {
2200                         
2201                         String path = getFinalPath();
2202                         if(path == null) return target;
2203                         
2204                 Resource folder = graph.syncRequest(new Configuration(target));
2205                 String[] segments = path.split("/");
2206                 for(int i=0;i<segments.length;i++) {
2207                         if(segments[i].isEmpty()) continue;
2208                         folder = Layer0Utils.getPossibleChild(graph, folder, URIStringUtils.unescape(segments[i]));
2209                         if(folder == null) return null;
2210                 }
2211                 
2212                 return folder;
2213                         
2214                 }
2215                 
2216                 
2217                 @Override
2218                 public int hashCode() {
2219                         
2220                         if(useGuids) return guid.hashCode();
2221                         
2222                         final int prime = 31;
2223                         int result = name.hashCode();
2224                         result = prime * result + ((path == null) ? 0 : path.hashCode());
2225                         return result;
2226                         
2227                 }
2228
2229                 @Override
2230                 public boolean equals(Object obj) {
2231                         
2232                         if (this == obj)
2233                                 return true;
2234                         if (obj == null)
2235                                 return false;
2236                         if (getClass() != obj.getClass())
2237                                 return false;
2238                         
2239                         CompositeInfo other = (CompositeInfo) obj;
2240                         
2241                         if(useGuids) return guid.equals(other.guid);
2242                         
2243                         if (!name.equals(other.name))
2244                                 return false;
2245                         
2246                         if(applyPaths)
2247                                 if (!path.equals(other.path))
2248                                         return false;
2249                         
2250                         return true;
2251                         
2252                 }
2253                 
2254         }
2255         
2256     public static char   COMPOSITE_SEPARATOR_CHAR = '#';
2257     public static String COMPOSITE_SEPARATOR      = String.valueOf(COMPOSITE_SEPARATOR_CHAR);
2258     
2259     public static CompositeInfo parseCompositeNameFromRoot(Root root, boolean applyPaths, boolean useGuids) {
2260         return CompositeInfo.parse(root.name, applyPaths, useGuids);
2261     }
2262
2263     public static CompositeInfo parseCompositeNameFromRoot(Identity root, boolean applyPaths, boolean useGuids) {
2264         String coded = TransferableGraphUtils.getName(root);
2265         return CompositeInfo.parse(coded, applyPaths, useGuids);
2266     }
2267     
2268         private static StringBuilder getDiagramCompositePathInternal(ReadGraph graph, Resource folder, StringBuilder builder) throws DatabaseException {
2269                 SimulationResource SIMU = SimulationResource.getInstance(graph);
2270                 Resource model = graph.getPossibleObject(folder, SIMU.IsConfigurationOf);
2271                 if (model != null) return builder;
2272
2273                 Layer0 L0 = Layer0.getInstance(graph);
2274                 String name = graph.getPossibleRelatedValue(folder, L0.HasName, Bindings.STRING);
2275                 if (name == null) return null;
2276                 Resource parent = graph.getPossibleObject(folder, L0.PartOf);
2277                 if (parent == null) return null;
2278
2279                 StringBuilder sb = getDiagramCompositePathInternal(graph, parent, builder);
2280                 if (sb == null) return null;
2281                 if (sb.length() > 0)
2282                         sb.append(URIStringUtils.NAMESPACE_PATH_SEPARATOR);
2283                 sb.append( URIStringUtils.escape(name) );
2284                 return sb;
2285         }
2286
2287         /**
2288          * @param graph
2289          * @param diagram
2290          * @return diagram/folder path up until model configuration root with each
2291          *         segment escaped using {@link URIStringUtils#escape(String)} and
2292          *         {@value URIStringUtils#NAMESPACE_PATH_SEPARATOR} between each
2293          *         segment or <code>null</code> if the specified diagram composite
2294          *         is not part of any model configuration structure.
2295          * @throws DatabaseException
2296          */
2297         public static String getDiagramCompositePath(ReadGraph graph, Resource diagram) throws DatabaseException {
2298                 Layer0 L0 = Layer0.getInstance(graph);
2299                 Resource parent = graph.getPossibleObject(diagram, L0.PartOf);
2300                 if(parent == null) return null;
2301                 StringBuilder sb = getDiagramCompositePathInternal(graph, parent, new StringBuilder());
2302                 return sb != null ? sb.toString() : null;
2303         }
2304         
2305         public static void exportModel(ReadGraph graph, Resource model, String fileName, String format, int version) throws DatabaseException {
2306                 TransferableGraphConfiguration2 conf = new TransferableGraphConfiguration2(graph, model, true, false);
2307                 exportModel(graph, conf, fileName, format, version);
2308         }
2309         
2310         public static void exportModel(ReadGraph graph, TransferableGraphConfiguration2 conf, String fileName, String format, int version) throws DatabaseException {
2311                 
2312                 try {
2313                 TransferableGraphSource s = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf));
2314                         TransferableGraphs.writeTransferableGraph(graph, format, version, s, new File(fileName));
2315                 } catch (DatabaseException e) {
2316                         throw e;
2317                 } catch (Exception e) {
2318                         throw new DatabaseException(e);
2319                 }
2320
2321         }
2322
2323         public static TransferableGraph1 exportSharedOntology(ReadGraph graph, Resource library, String fileName, String format, int version) throws DatabaseException {
2324                 
2325         Layer0 L0 = Layer0.getInstance(graph);
2326         String name = graph.getRelatedValue(library, L0.HasName, Bindings.STRING);
2327
2328         DraftStatusBean draft = null;
2329         boolean published = Layer0Utils.isPublished(graph, library);
2330         if(!published) draft = new DraftStatusBean(new String[0]);
2331         
2332         LibraryInfo info = new LibraryInfo(name, library, draft);
2333                 
2334         try {
2335                         return exportSharedOntology(new NullProgressMonitor(), graph, fileName != null ? new File(fileName) : null, format, version, info);
2336                 } catch (IOException e) {
2337                         throw new DatabaseException(e);
2338                 }
2339
2340         }
2341
2342     public static DraftStatusBean getDependencyDraftStatus(ReadGraph graph, Resource library) throws DatabaseException {
2343         Layer0 L0 = Layer0.getInstance(graph);
2344         List<String> drafts = new ArrayList<>();
2345         for (Resource shared : graph.syncRequest(new ObjectsWithType(library, L0.IsLinkedTo, L0.SharedOntology))) {
2346             boolean published = Layer0Utils.isPublished(graph, shared);
2347             if (!published)
2348                 drafts.add(graph.getURI(shared));
2349         }
2350         return drafts.isEmpty() ? null : new DraftStatusBean(drafts);
2351     }
2352
2353         public static Set<Resource> getMostUnspecificTypes(final ReadGraph graph, Collection<Resource> types) throws DatabaseException {
2354                 
2355                 final Set<Resource> work = new HashSet<Resource>(types);
2356                 for(Resource type : types) {
2357                         Set<Resource> supers = graph.getSupertypes(type);
2358                         if(!Collections.disjoint(supers, work)) work.remove(type);
2359                 }
2360
2361                 return work;
2362                 
2363         }
2364         
2365         public static void rewriteGUIDS(WriteGraph graph, Resource root, boolean deep) throws DatabaseException {
2366                 List<Resource> todo = new ArrayList<Resource>();
2367                 todo.add(root);
2368                 Layer0 L0 = Layer0.getInstance(graph);
2369                 while(!todo.isEmpty()) {
2370                         Resource resource = todo.remove(todo.size()-1);
2371                         Layer0Utils.claimNewIdentifier(graph, resource, false);
2372             if(deep)
2373                 todo.addAll(graph.getObjects(resource, L0.ConsistsOf));
2374                 }
2375         }
2376         
2377         public static void createMissingGUIDs(IProgressMonitor monitor, WriteGraph graph, Collection<Resource> roots) throws DatabaseException {
2378                 
2379         if(monitor == null) monitor = new NullProgressMonitor();
2380         
2381                 Layer0 L0 = Layer0.getInstance(graph);
2382                 
2383         // Allow this process to make 50k queries
2384         QueryMemoryWatcher memory = new QueryMemoryWatcher(graph, 50000);
2385
2386                 for(Resource root : roots) {
2387                         
2388                         boolean madeChanges = false;
2389                         
2390                 monitor.setTaskName("Creating missing GUID identifiers " + NameUtils.getSafeName(graph, root));
2391                         Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(root));
2392                         for(Resource r : searchByType(graph, indexRoot, L0.Entity)) {
2393
2394                                 memory.maintain();
2395
2396                                 if(graph.isImmutable(r)) continue;
2397
2398                                 if(!ModelingUtils.needsIdentifier(graph, r)) continue;
2399                                 
2400                                 GUID existing = graph.getPossibleRelatedValue(r, L0.identifier, GUID.BINDING);
2401                                 if(existing == null) {
2402                                     Layer0Utils.claimNewIdentifier(graph, r, true);
2403                                         madeChanges = true;
2404                                 }
2405                                 
2406                         }
2407                         
2408                         if(madeChanges)
2409                                 ModelingUtils.deleteIndex(graph, root);
2410                         
2411                 }
2412                 
2413                 
2414         }
2415         
2416         public static boolean activateModel(WriteGraph graph, Resource model) throws DatabaseException {
2417                 return graph.syncRequest(new ActivateModel(Simantics.getProjectResource(), model));
2418         }
2419         
2420         public static File fileDialog(String title, List<Tuple> namesAndExtensions) {
2421                 
2422                 Display display = Display.getCurrent();
2423                 Shell shell = display.getActiveShell();
2424                 
2425         FileDialog dialog = new FileDialog(shell, SWT.OPEN);
2426         dialog.setText(title);
2427         
2428         String[] extensions = new String[namesAndExtensions.size()];
2429         String[] filterNames = new String[namesAndExtensions.size()];
2430         int index = 0;
2431         for(Tuple t : namesAndExtensions) {
2432                 String filterName = (String)t.get(0);
2433                 String extension = (String)t.get(1);
2434                 filterNames[index] = filterName;
2435                 extensions[index] = extension;
2436                 index++;
2437         }
2438         
2439         dialog.setFilterExtensions(extensions);
2440         dialog.setFilterNames(filterNames);
2441         final String fileName = dialog.open();
2442         if (fileName == null) return null;
2443         
2444         return new File(fileName);
2445
2446         }
2447         
2448         public static Resource createLibrary(WriteGraph graph, Resource parent) throws DatabaseException {
2449         Layer0 l0 = Layer0.getInstance(graph);
2450         return createLibrary(graph, parent, NameUtils.findFreshName(graph, "Library", parent, l0.ConsistsOf));
2451     }
2452     
2453     public static Resource createLibrary(WriteGraph graph, Resource parent, String name) throws DatabaseException {
2454         graph.markUndoPoint();
2455         Layer0 l0 = Layer0.getInstance(graph);
2456
2457         Resource library = graph.newResource();
2458         graph.claim(library, l0.InstanceOf, null, l0.Library);
2459         graph.addLiteral(library, l0.HasName, l0.NameOf, l0.String, name, Bindings.STRING);
2460         graph.claim(library, l0.PartOf, parent);
2461
2462         Layer0Utils.addCommentMetadata(graph, "Created new Library named " + name + ", resource " + library);
2463
2464         return library;
2465     }
2466
2467
2468 }