]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphs.java
c13f3cb430f8bdefd525c93f9b3329338a61308a
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / actions / CompilePGraphs.java
1 package org.simantics.modeling.ui.actions;
2
3 import static org.simantics.db.common.utils.Transaction.endTransaction;
4
5 import java.io.ByteArrayInputStream;
6 import java.io.Closeable;
7 import java.io.File;
8 import java.io.FileNotFoundException;
9 import java.io.FileOutputStream;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.UnsupportedEncodingException;
13 import java.net.URL;
14 import java.net.URLDecoder;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Set;
21
22 import org.eclipse.core.runtime.FileLocator;
23 import org.eclipse.jface.dialogs.MessageDialog;
24 import org.eclipse.jface.layout.GridDataFactory;
25 import org.eclipse.jface.layout.GridLayoutFactory;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.widgets.Composite;
28 import org.eclipse.swt.widgets.Control;
29 import org.eclipse.swt.widgets.Display;
30 import org.eclipse.swt.widgets.Shell;
31 import org.osgi.framework.Bundle;
32 import org.simantics.PlatformException;
33 import org.simantics.Simantics;
34 import org.simantics.databoard.Bindings;
35 import org.simantics.db.ReadGraph;
36 import org.simantics.db.Resource;
37 import org.simantics.db.WriteGraph;
38 import org.simantics.db.common.request.ObjectsWithType;
39 import org.simantics.db.common.request.ReadRequest;
40 import org.simantics.db.common.request.UniqueRead;
41 import org.simantics.db.common.request.WriteRequest;
42 import org.simantics.db.common.utils.Logger;
43 import org.simantics.db.exception.DatabaseException;
44 import org.simantics.db.layer0.adapter.ActionFactory;
45 import org.simantics.db.layer0.adapter.CopyHandler;
46 import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
47 import org.simantics.db.layer0.adapter.impl.DefaultCopyHandler;
48 import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler;
49 import org.simantics.db.layer0.adapter.impl.DefaultPasteImportAdvisor;
50 import org.simantics.db.layer0.util.ClipboardUtils;
51 import org.simantics.db.layer0.util.DomainProcessorState;
52 import org.simantics.db.layer0.util.Layer0Utils;
53 import org.simantics.db.layer0.util.ModelTransferableGraphSource;
54 import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest;
55 import org.simantics.db.layer0.util.SimanticsClipboard.Representation;
56 import org.simantics.db.layer0.util.SimanticsClipboardImpl;
57 import org.simantics.db.layer0.util.SimanticsKeys;
58 import org.simantics.db.layer0.util.TransferableGraphConfiguration2;
59 import org.simantics.db.service.SerialisationSupport;
60 import org.simantics.graph.compiler.CompilationResult;
61 import org.simantics.graph.compiler.GraphCompiler;
62 import org.simantics.graph.compiler.GraphCompilerPreferences;
63 import org.simantics.graph.compiler.ValidationMode;
64 import org.simantics.graph.db.TransferableGraphSource;
65 import org.simantics.graph.db.TransferableGraphs;
66 import org.simantics.graph.diff.Diff;
67 import org.simantics.graph.diff.TransferableGraphDelta1;
68 import org.simantics.graph.representation.Identity;
69 import org.simantics.graph.representation.Root;
70 import org.simantics.graph.representation.TransferableGraph1;
71 import org.simantics.layer0.Layer0;
72 import org.simantics.ltk.ISource;
73 import org.simantics.ltk.Problem;
74 import org.simantics.modeling.ui.Activator;
75 import org.simantics.utils.datastructures.Pair;
76
77 /**
78  * @author Antti Villberg
79  */
80 public class CompilePGraphs implements ActionFactory {
81
82     @Override
83     public Runnable create(Object target) {
84         
85         if (!(target instanceof Resource))
86             return null;
87         
88         final Resource r = (Resource)target;
89
90         return new Runnable() {
91                 
92             private void uncheckedClose(Closeable closeable) {
93                 try {
94                     if (closeable != null)
95                         closeable.close();
96                 } catch (IOException e) {
97                     //ignore
98                 }
99             }
100                 
101             private File copyResource(URL url, File targetFile) throws IOException, FileNotFoundException {
102                 FileOutputStream os = null;
103                 InputStream is = null;
104                 try {
105                     if (targetFile.exists())
106                         targetFile.delete();
107
108                     is = url.openStream();
109                     int read;
110                     byte [] buffer = new byte [16384];
111                     os = new FileOutputStream (targetFile);
112                     while ((read = is.read (buffer)) != -1) {
113                         os.write(buffer, 0, read);
114                     }
115                     os.close ();
116                     is.close ();
117
118                     return targetFile;
119                 } finally {
120                     uncheckedClose(os);
121                     uncheckedClose(is);
122                 }
123             }
124                 
125             private File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException {
126                 String tmpDirStr = System.getProperty("java.io.tmpdir");
127                 if (tmpDirStr == null)
128                     throw new NullPointerException("java.io.tmpdir property is null");
129                 File tmpDir = new File(tmpDirStr);
130                 File libFile = new File(tmpDir, libName);
131                 return copyResource(libURL, libFile);
132             }
133                 
134                 private File url2file(URL url, String fileName) {
135                         if ("file".equals(url.getProtocol())) {
136                                 try {
137                                         File path = new File(URLDecoder.decode(url.getPath(), "UTF-8"));
138                                         return path;
139                                 } catch (UnsupportedEncodingException e) {
140                                         Logger.defaultLogError(e);
141                                 }
142                         } else if ("jar".equals(url.getProtocol())) {
143                                 try {
144                                         File libFile = extractLib(url, fileName);
145                                         return libFile;
146                                 } catch (FileNotFoundException e) {
147                                         Logger.defaultLogError(e);
148                                 } catch (IOException e) {
149                                         Logger.defaultLogError(e);
150                                 }
151                         } else {
152                                 System.err.println("Unsupported URL protocol '" + url + "' for FastLZ native library file '" + fileName);
153                         }       
154                         return null;
155                 }
156                         @Override
157                         public void run() {
158                                 
159                                 try {
160                                         
161                                 final Collection<ISource> sources = new ArrayList<ISource>();
162                                 Collection<TransferableGraph1> dependencies = new ArrayList<TransferableGraph1>();
163
164                                 for(Bundle b : Activator.getContext().getBundles()) {
165                                         URL tg = b.getEntry("/graph.tg");
166                                         if(tg == null) continue;
167                                         File f = url2file(FileLocator.resolve(tg), b.getSymbolicName());
168                                         dependencies.add(GraphCompiler.read(f));
169                                 }
170
171                                 final TransferableGraph1 thisOntology = Simantics.sync(new UniqueRead<TransferableGraph1>() {
172
173                                                 @Override
174                                                 public TransferableGraph1 perform(ReadGraph graph) throws DatabaseException {
175                                                         
176                                                         Layer0 L0 = Layer0.getInstance(graph);
177                                                         Resource parent = graph.getSingleObject(r, L0.PartOf);
178                                                         
179                                     CopyHandler ch = new DefaultCopyHandler(r) {
180                                         
181                                         protected TransferableGraphConfiguration2 createConfiguration(ReadGraph graph, boolean cut) throws DatabaseException {
182
183                                                 Map<Resource, ExtentStatus> preStatus = new HashMap<Resource, ExtentStatus>();
184                                                 preStatus.put(r, ExtentStatus.EXTERNAL);
185                                                 if(!parent.equals(graph.getRootLibrary()))
186                                                         preStatus.put(parent, ExtentStatus.EXTERNAL);
187                                                 
188                                                 return new TransferableGraphConfiguration2(null, Collections.emptyList(), preStatus, true, true);
189                                                 
190                                         }
191
192                                         protected TransferableGraphSource computeSource(ReadGraph graph, TransferableGraphConfiguration2 conf) throws DatabaseException {
193                                                 return graph.syncRequest(new ModelTransferableGraphSourceRequest(conf) {
194
195                                                         protected ModelTransferableGraphSource getSource(ReadGraph graph, TransferableGraphConfiguration2 configuration, DomainProcessorState state, File otherStatementsFile, File valueFile) throws DatabaseException {
196                                                         return new ModelTransferableGraphSource(graph, configuration, state, otherStatementsFile, valueFile) {
197
198                                                                         @Override
199                                                                         protected Identity getRootIdentity(DomainProcessorState state, SerialisationSupport support, Resource rootLibrary) throws DatabaseException {
200                                                                                 return new Identity(state.ids.get(support.getTransientId(rootLibrary)), new Root("", ""));
201                                                                         }
202
203                                                         };
204                                                         }
205
206                                                 });
207                                         }
208                                         
209                                     };
210                                     SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
211                                     ch.copyToClipboard(graph, clipboard);
212                                     for (Set<Representation> object : clipboard.getContents()) {
213                                         TransferableGraph1 tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
214                                         if(tg != null) return tg;
215                                     }
216                                                         return null;
217                                                 }
218                                         
219                                 });
220
221                                 dependencies.add(thisOntology);
222                                 
223                                         Simantics.sync(new ReadRequest() {
224
225                                                 @Override
226                                                 public void run(ReadGraph graph) throws DatabaseException {
227                                                         Layer0 L0 = Layer0.getInstance(graph);
228                                                         for(Resource file : graph.syncRequest(new ObjectsWithType(r, L0.ConsistsOf, L0.PGraph))) {
229                                                                 
230                                                                 final String src = graph.getRelatedValue(file, L0.PGraph_definition, Bindings.STRING);
231
232                                                                 final ByteArrayInputStream baos = new ByteArrayInputStream(src.getBytes()); 
233                                                         
234                                                         sources.add(new ISource() {
235                                                                         
236                                                                         @Override
237                                                                         public int startPos() {
238                                                                                 return 0;
239                                                                         }
240                                                                         
241                                                                         @Override
242                                                                         public int startLine() {
243                                                                                 return 0;
244                                                                         }
245                                                                         
246                                                                         @Override
247                                                                         public InputStream open() throws IOException {
248                                                                                 return baos;
249                                                                         }
250                                                                         
251                                                                         @Override
252                                                                         public int length() throws IOException {
253                                                                                 return src.length();
254                                                                         }
255                                                                         
256                                                                         @Override
257                                                                         public String getName() {
258                                                                                 return "Source";
259                                                                         }
260                                                                         
261                                                                 });
262                                                                 
263                                                         }
264                                                 }
265                                                 
266                                         });
267                                 
268                                 final StringBuilder errorStringBuilder = new StringBuilder();
269                                 GraphCompilerPreferences prefs = new GraphCompilerPreferences();
270                                 prefs.validate = true;
271                                 prefs.validateRelationRestrictions = ValidationMode.ERROR;
272                                 prefs.validateResourceHasType = ValidationMode.IGNORE;
273                                 final CompilationResult result = GraphCompiler.compile("1.1", sources, dependencies, null, prefs);
274                                 
275                                 for(Problem problem : result.getErrors())
276                                         errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n");
277                                 for(Problem problem : result.getWarnings())
278                                         errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n");
279                                 
280                                 if(!result.getErrors().isEmpty() || !result.getWarnings().isEmpty()) {
281
282                                         class ErrorMessageDialog extends MessageDialog {
283
284                                                 public ErrorMessageDialog(Shell shell) {
285                                                         super(shell, 
286                                                                         "Unsatisfied dependencies", null, 
287                                                                         "The following dependencies were missing. Please import the dependencies and try again.", 
288                                                                         MessageDialog.ERROR, new String[] { "Continue" }, 0);
289                                                 }
290
291                                                 @Override
292                                                 protected Control createCustomArea(Composite composite) {
293                                                         
294                                                         GridLayoutFactory.fillDefaults().applyTo(composite);
295                                                         
296                                                         org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(composite, SWT.BORDER | SWT.READ_ONLY);
297                                                         GridDataFactory.fillDefaults().grab(true, true).applyTo(list);
298                                                 for(Problem problem : result.getErrors())
299                                                         list.add(problem.getLocation() + ": " + problem.getDescription() + "\n");
300                                                 for(Problem problem : result.getWarnings())
301                                                         list.add(problem.getLocation() + ": " + problem.getDescription() + "\n");
302
303                                                         return composite;
304                                                         
305                                                 }
306
307                                         }
308
309                                         ErrorMessageDialog md = new ErrorMessageDialog(Display.getCurrent().getActiveShell());
310                                         md.open();
311
312                                         return;
313                                 }
314                                 
315                                 
316                                 final Pair<TransferableGraph1, long[]> existing = Simantics.sync(new UniqueRead<Pair<TransferableGraph1, long[]>>() {
317
318                                                 @Override
319                                                 public Pair<TransferableGraph1, long[]> perform(ReadGraph graph) throws DatabaseException {
320                                                         Layer0 L0 = Layer0.getInstance(graph);
321                                                         TransferableGraph1 tg = graph.getPossibleRelatedValue(r, L0.SharedOntology_tg, Bindings.getBindingUnchecked( TransferableGraph1.class ));
322                                                         if(tg == null) return null;
323                                                         long[] tgResources = graph.getPossibleRelatedValue(r, L0.SharedOntology_tgResources, Bindings.LONG_ARRAY);
324                                                         if(tgResources == null) return null;
325                                                         return Pair.make(tg,  tgResources);
326                                                 }
327                                         
328                                 });
329                                 
330                                 if(existing != null) {
331                                         
332                             try {
333                                 
334                                                         Simantics.sync(new WriteRequest() {
335                                                                 
336                                                                 @Override
337                                                                 public void perform(WriteGraph graph) throws DatabaseException {
338
339                                                     TransferableGraphDelta1 delta = new Diff(existing.first, result.getGraph()).diff();
340                                                 long[] resourceArray = TransferableGraphs.applyDelta(graph, existing.second, delta);
341
342                                                                         Layer0 L0 = Layer0.getInstance(graph);
343                                                                         graph.claimLiteral(r, L0.SharedOntology_tg, result.getGraph(), Bindings.getBindingUnchecked( TransferableGraph1.class ));
344                                                                         graph.claimLiteral(r, L0.SharedOntology_tgResources, L0.ResourceIdArray, resourceArray, Bindings.LONG_ARRAY);
345                                                                         
346                                                         Layer0Utils.addCommentMetadata(graph, "Compiled ontology " + graph.getURI(r));
347
348                                                                 }
349                                                                 
350                                                         });
351
352                             } catch (Throwable t) {
353                                 throw new PlatformException(t);
354                             } finally {
355                                 endTransaction();
356                             }
357                                         
358                                 } else {
359                                 
360                                         final DefaultPasteImportAdvisor advisor = new DefaultPasteImportAdvisor(r);
361                                         
362                                         DefaultPasteHandler.defaultExecute(result.getGraph(), r, advisor);
363                                         
364                                                 Simantics.sync(new WriteRequest() {
365         
366                                                         @Override
367                                                         public void perform(WriteGraph graph) throws DatabaseException {
368         
369                                                                 Layer0 L0 = Layer0.getInstance(graph);
370                                                                 graph.claimLiteral(r, L0.SharedOntology_tg, result.getGraph(), Bindings.getBindingUnchecked( TransferableGraph1.class ));
371                                                                 graph.claimLiteral(r, L0.SharedOntology_tgResources, L0.ResourceIdArray, advisor.getResourceIds(), Bindings.LONG_ARRAY);
372
373                                                 Layer0Utils.addCommentMetadata(graph, "Compiled ontology " + graph.getURI(r));
374
375                                                         }
376                                                         
377                                                 });
378                                                 
379                                 }
380                                         
381                                 } catch (Exception e) {
382                                         Logger.defaultLogError(e);
383                                 }
384                                 
385                         }
386                 
387         };
388         
389     }
390
391 }