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