]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
7d7e7fcf62c91827dc197eae6db360ca33615958
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2013 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.sysdyn.ui.handlers.exports;\r
13 \r
14 import java.io.File;\r
15 import java.util.ArrayList;\r
16 import java.util.Collection;\r
17 \r
18 import org.eclipse.core.commands.AbstractHandler;\r
19 import org.eclipse.core.commands.ExecutionEvent;\r
20 import org.eclipse.core.commands.ExecutionException;\r
21 import org.eclipse.core.runtime.Platform;\r
22 import org.eclipse.jface.viewers.ISelection;\r
23 import org.eclipse.swt.SWT;\r
24 import org.eclipse.swt.widgets.FileDialog;\r
25 import org.eclipse.swt.widgets.MessageBox;\r
26 import org.eclipse.swt.widgets.Shell;\r
27 import org.eclipse.ui.handlers.HandlerUtil;\r
28 import org.simantics.databoard.Bindings;\r
29 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;\r
30 import org.simantics.db.ReadGraph;\r
31 import org.simantics.db.Resource;\r
32 import org.simantics.db.WriteGraph;\r
33 import org.simantics.db.common.primitiverequest.PossibleRelatedValue;\r
34 import org.simantics.db.common.request.ObjectsWithType;\r
35 import org.simantics.db.common.request.ReadRequest;\r
36 import org.simantics.db.common.request.WriteRequest;\r
37 import org.simantics.db.common.utils.NameUtils;\r
38 import org.simantics.db.exception.DatabaseException;\r
39 import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest;\r
40 import org.simantics.db.layer0.util.TransferableGraphConfiguration2;\r
41 import org.simantics.db.request.Read;\r
42 import org.simantics.graph.db.TransferableGraphSource;\r
43 import org.simantics.graph.db.TransferableGraphs;\r
44 import org.simantics.layer0.Layer0;\r
45 import org.simantics.modeling.ModelingResources;\r
46 import org.simantics.structural.stubs.StructuralResource2;\r
47 import org.simantics.sysdyn.SysdynResource;\r
48 import org.simantics.sysdyn.ui.Activator;\r
49 import org.simantics.sysdyn.ui.utils.imports.ImportUtilsUI;\r
50 import org.simantics.ui.SimanticsUI;\r
51 import org.simantics.ui.utils.ResourceAdaptionUtils;\r
52 import org.simantics.utils.datastructures.Pair;\r
53 \r
54 /**\r
55  * Exports a selected module\r
56  * @author Teemu Lempinen\r
57  * @author Tuomas Miettinen\r
58  *\r
59  */\r
60 public class ExportModuleHandler extends AbstractHandler {\r
61 \r
62         /**\r
63          * Temporary exception. At this phase, the system will not support exporting modules\r
64          * that depend on other modules. \r
65          * \r
66          * @author Teemu Lempinen\r
67          *\r
68          */\r
69         class ContainsDependenciesException extends DatabaseException {\r
70                 private static final long serialVersionUID = -1533706136673146020L;\r
71                 \r
72                 private final Collection<String> dependencies;\r
73                 \r
74                 ContainsDependenciesException(Collection<String> dependencies) {\r
75                         this.dependencies = dependencies;\r
76                 }\r
77                 \r
78                 public Collection<String> getDependencies() {\r
79                         return this.dependencies;\r
80                 }\r
81                 \r
82         }\r
83         \r
84         @Override\r
85         public Object execute(ExecutionEvent event) throws ExecutionException {\r
86 \r
87         ISelection sel = HandlerUtil.getCurrentSelection(event);\r
88         final Resource modulesymbol = ResourceAdaptionUtils.toSingleResource(sel);\r
89         if(modulesymbol == null) return null;\r
90                 \r
91                 String name = null;\r
92                 try {\r
93                         name = SimanticsUI.getSession().syncRequest(new Read<String>() {\r
94 \r
95                                 @Override\r
96                                 public String perform(ReadGraph graph) throws DatabaseException {\r
97                                         ModelingResources mr = ModelingResources.getInstance(graph);\r
98                                         StructuralResource2 sr2 = StructuralResource2.getInstance(graph);\r
99                                         SysdynResource sr = SysdynResource.getInstance(graph);\r
100                                         Layer0 l0 = Layer0.getInstance(graph);\r
101                                         \r
102                                         // Start checking for module dependencies\r
103                                         Resource component = graph.getPossibleObject(modulesymbol, mr.SymbolToComponentType);\r
104                                         if (component == null || !graph.hasStatement(component, Layer0.getInstance(graph).PartOf))\r
105                                                 return null;\r
106                                         \r
107                                         Resource configuration = graph.getPossibleObject(component, sr2.IsDefinedBy);\r
108                                         if (configuration == null)\r
109                                                 return null;\r
110                                         \r
111                                         ArrayList<String> dependencies = null;\r
112                                         for(Resource r : graph.syncRequest(new ObjectsWithType(configuration, l0.ConsistsOf, sr.Module))) {\r
113                                                 if(dependencies == null)\r
114                                                         dependencies = new ArrayList<String>();\r
115                                                 String name = NameUtils.getSafeName(graph, r);\r
116                                                 String instanceOf = NameUtils.getSafeName(graph, graph.getSingleObject(r, l0.InstanceOf));\r
117                                                 dependencies.add(name + " : " + instanceOf);\r
118                                         }\r
119                                         if(dependencies != null && !dependencies.isEmpty())\r
120                                                 throw new ContainsDependenciesException(dependencies);\r
121                                         // End checking for module dependencies. If dependencies were found, an exception was thrown\r
122                                         \r
123                                         String name = graph.getPossibleRelatedValue(component, l0.HasName, Bindings.STRING);\r
124                                         return name;\r
125                                         \r
126                                 }\r
127                                 \r
128                         });\r
129                 } catch (ContainsDependenciesException e1) {\r
130                         Shell shell = HandlerUtil.getActiveShellChecked(event);\r
131                         MessageBox mb = new MessageBox(shell, SWT.OK);\r
132                         StringBuilder sb = new StringBuilder();\r
133                         sb.append("This version does not support exporting modules with other module instances.\n\n");\r
134                         sb.append("Dependencies:\n");\r
135                         for(String s : e1.getDependencies())\r
136                                 sb.append("    " + s + "\n");\r
137                         mb.setMessage(sb.toString());\r
138                         mb.setText("Module contains dependencies.");\r
139                         mb.open();\r
140                         return null;\r
141                 } catch (DatabaseException e1) {\r
142                         e1.printStackTrace();\r
143                 }\r
144                 \r
145         // Do not export if the resource has no name\r
146                 if(name == null) return null;\r
147                 \r
148         // Find a location (and name) for the exported library using FileDialog\r
149                 Shell shell = HandlerUtil.getActiveShellChecked(event);\r
150                 FileDialog fd = new FileDialog(shell, SWT.SAVE);\r
151                 fd.setText("Export Module");\r
152                 fd.setFileName(name);\r
153                 String path = Activator.getDefault().getPreferenceStore().getString(ImportUtilsUI.IMPORTMODULETPATH);\r
154                 if(path.isEmpty() || !(new File(path).exists()))\r
155                         path = Platform.getLocation().toOSString();\r
156                 fd.setFilterPath(path);\r
157                 String[] filterExt = {"*.tg"};\r
158                 fd.setFilterExtensions(filterExt);\r
159                 fd.setOverwrite(true);\r
160                 final String selected = fd.open();\r
161                 if(selected == null) return null;\r
162                 \r
163         // Save location to preference store\r
164                 Activator.getDefault().getPreferenceStore().setValue(ImportUtilsUI.IMPORTMODULETPATH, (new File(selected)).getParent());\r
165                 \r
166         // Asynchronously create the file using transferable graph\r
167                 SimanticsUI.getSession().asyncRequest(new ReadRequest() {\r
168                         \r
169                         @Override\r
170                         public void run(ReadGraph graph) throws DatabaseException {\r
171                                 Layer0 l0 = Layer0.getInstance(graph);\r
172                                 ModelingResources mr = ModelingResources.getInstance(graph);\r
173 \r
174                                 final Resource component = graph.getPossibleObject(modulesymbol, mr.SymbolToComponentType);\r
175                                 if (component == null || !graph.hasStatement(component, Layer0.getInstance(graph).PartOf))\r
176                                         return;\r
177                                 String name = graph.syncRequest(new PossibleRelatedValue<String>(component, l0.HasName, Bindings.STRING ));\r
178                                 final ArrayList<Pair<Resource, String>> roots = new ArrayList<Pair<Resource, String>>();\r
179                                 roots.add(Pair.make(component, name));\r
180 \r
181                                 graph.asyncRequest(new WriteRequest() {\r
182 \r
183                                         @Override\r
184                                         public void perform(WriteGraph graph) throws DatabaseException {\r
185                                                 Layer0 l0 = Layer0.getInstance(graph);\r
186                                                 StructuralResource2 sr2 = StructuralResource2.getInstance(graph);\r
187 \r
188                                                 Resource configuration = graph.getPossibleObject(component, sr2.IsDefinedBy);\r
189                                                 if (!graph.hasStatement(configuration, l0.PartOf, component)&& \r
190                                                                 !graph.hasStatement(modulesymbol, l0.PartOf, component)) {\r
191                                                         // Make sure that configuration and symbol are included.\r
192                                                         // In old versions, they were attached to model, not to module.\r
193                                                         Resource previousPartof = graph.getSingleObject(configuration, l0.PartOf);\r
194 \r
195                                                         graph.deny(configuration, l0.PartOf);\r
196                                                         graph.deny(modulesymbol, l0.PartOf);\r
197                                                         graph.claim(configuration, l0.PartOf, l0.ConsistsOf, component);\r
198                                                         graph.claim(modulesymbol, l0.PartOf, l0.ConsistsOf, component);\r
199 \r
200                                                         export(graph, selected, roots, component);\r
201 \r
202                                                         graph.deny(configuration, l0.PartOf);\r
203                                                         graph.deny(modulesymbol, l0.PartOf);\r
204                                                         graph.claim(configuration, l0.PartOf, l0.ConsistsOf, previousPartof);\r
205                                                         graph.claim(modulesymbol, l0.PartOf, l0.ConsistsOf, previousPartof);\r
206                                                 } else {\r
207                                                         // Normal export\r
208                                                         export(graph, selected, roots, component);\r
209                                                 }\r
210                                         }\r
211                                 });\r
212 \r
213                         }\r
214                 });\r
215 \r
216                 return null;\r
217         }\r
218         \r
219         /**\r
220          * Export module (without dependencies to other modules) and write it to file. \r
221          * Disable existing enumeration replacement for during export.  \r
222          *  \r
223          * @param graph WriteGraph\r
224          * @param path Path for the exported file\r
225          * @param roots\r
226          * @param component Module\r
227          */\r
228         private void export(WriteGraph graph, final String path, ArrayList<Pair<Resource, String>> roots, final Resource component) {\r
229                 \r
230                 // FIXME: Enumeration replacement handling like this is not suitable.\r
231                 try {\r
232                         Layer0 l0 = Layer0.getInstance(graph);\r
233                         SysdynResource sr = SysdynResource.getInstance(graph);\r
234                         StructuralResource2 sr2 = StructuralResource2.getInstance(graph);\r
235 \r
236                         Resource configuration = graph.getPossibleObject(component, sr2.IsDefinedBy);\r
237                         ArrayList<Pair<Resource, Resource>> replacements = new ArrayList<Pair<Resource, Resource>>();\r
238 \r
239                         for(Resource enumeration : graph.syncRequest(new ObjectsWithType(configuration, l0.ConsistsOf, sr.Enumeration))) {\r
240                                 if(graph.hasStatement(enumeration, sr.Redeclaration_replacedEnumeration_Inverse)) {\r
241                                         for(Resource replacement : graph.getObjects(enumeration, sr.Redeclaration_replacedEnumeration_Inverse)) {\r
242                                                 replacements.add(new Pair<Resource, Resource>(enumeration, replacement));\r
243                                         }\r
244                                 }\r
245                         }\r
246                         \r
247                         for(Pair<Resource,Resource> replacement : replacements)\r
248                                 graph.deny(replacement.first, sr.Redeclaration_replacedEnumeration_Inverse, replacement.second);\r
249                         \r
250                         SimanticsUI.getSession().asyncRequest(new ReadRequest() {\r
251 \r
252                             @Override\r
253                             public void run(ReadGraph graph) throws DatabaseException {\r
254                                 TransferableGraphConfiguration2 conf = new TransferableGraphConfiguration2(graph, component);\r
255                                 TransferableGraphSource s = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf));\r
256                                 try {\r
257                                     TransferableGraphs.writeTransferableGraph(graph, "sysdynModule", 1, s,new File(path));\r
258                                 } catch (Exception e) {\r
259                                     e.printStackTrace();\r
260                                 }\r
261                             }\r
262                         });\r
263 \r
264                         \r
265                         for(Pair<Resource,Resource> replacement : replacements)\r
266                                 graph.claim(replacement.first, sr.Redeclaration_replacedEnumeration_Inverse, replacement.second);\r
267 \r
268                 } catch (RuntimeBindingConstructionException e) {\r
269                         e.printStackTrace();\r
270 //              } catch (IOException e) {\r
271 //                      e.printStackTrace();\r
272                 } catch (DatabaseException e) {\r
273                         e.printStackTrace();\r
274                 }\r
275         }\r
276 }