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