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