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