1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.ui.handlers.exports;
\r
14 import java.io.File;
\r
15 import java.io.IOException;
\r
16 import java.util.ArrayList;
\r
17 import java.util.Collection;
\r
19 import org.eclipse.core.commands.AbstractHandler;
\r
20 import org.eclipse.core.commands.ExecutionEvent;
\r
21 import org.eclipse.core.commands.ExecutionException;
\r
22 import org.eclipse.core.runtime.Platform;
\r
23 import org.eclipse.jface.viewers.ISelection;
\r
24 import org.eclipse.swt.SWT;
\r
25 import org.eclipse.swt.widgets.FileDialog;
\r
26 import org.eclipse.swt.widgets.MessageBox;
\r
27 import org.eclipse.swt.widgets.Shell;
\r
28 import org.eclipse.ui.handlers.HandlerUtil;
\r
29 import org.simantics.databoard.Bindings;
\r
30 import org.simantics.databoard.Files;
\r
31 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
\r
32 import org.simantics.db.ReadGraph;
\r
33 import org.simantics.db.Resource;
\r
34 import org.simantics.db.WriteGraph;
\r
35 import org.simantics.db.common.primitiverequest.PossibleRelatedValue;
\r
36 import org.simantics.db.common.request.ObjectsWithType;
\r
37 import org.simantics.db.common.request.ReadRequest;
\r
38 import org.simantics.db.common.request.WriteRequest;
\r
39 import org.simantics.db.common.utils.NameUtils;
\r
40 import org.simantics.db.exception.DatabaseException;
\r
41 import org.simantics.db.layer0.util.TransferableGraphRequest2;
\r
42 import org.simantics.db.request.Read;
\r
43 import org.simantics.graph.representation.TransferableGraph1;
\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.handlers.imports.ImportModuleHandler;
\r
50 import org.simantics.ui.SimanticsUI;
\r
51 import org.simantics.ui.utils.ResourceAdaptionUtils;
\r
52 import org.simantics.utils.datastructures.Pair;
\r
55 * Exports a selected module
\r
56 * @author Teemu Lempinen
\r
59 public class ExportModuleHandler extends AbstractHandler {
\r
62 * Temporary exception. At this phase, the system will not support exporting modules
\r
63 * that depend on other modules.
\r
65 * @author Teemu Lempinen
\r
68 class ContainsDependenciesException extends DatabaseException {
\r
69 private static final long serialVersionUID = -1533706136673146020L;
\r
71 private Collection<String> dependencies;
\r
73 ContainsDependenciesException(Collection<String> dependencies) {
\r
74 this.dependencies = dependencies;
\r
77 public Collection<String> getDependencies() {
\r
78 return this.dependencies;
\r
84 public Object execute(ExecutionEvent event) throws ExecutionException {
\r
86 ISelection sel = HandlerUtil.getCurrentSelection(event);
\r
87 final Resource modulesymbol = ResourceAdaptionUtils.toSingleResource(sel);
\r
88 if(modulesymbol == null) return null;
\r
92 name = SimanticsUI.getSession().syncRequest(new Read<String>() {
\r
95 public String perform(ReadGraph graph) throws DatabaseException {
\r
96 ModelingResources mr = ModelingResources.getInstance(graph);
\r
97 StructuralResource2 sr2 = StructuralResource2.getInstance(graph);
\r
98 SysdynResource sr = SysdynResource.getInstance(graph);
\r
99 Layer0 l0 = Layer0.getInstance(graph);
\r
101 // Start checking for module dependencies
\r
102 Resource component = graph.getPossibleObject(modulesymbol, mr.SymbolToComponentType);
\r
103 if (component == null || !graph.hasStatement(component, Layer0.getInstance(graph).PartOf))
\r
106 Resource configuration = graph.getPossibleObject(component, sr2.IsDefinedBy);
\r
107 if (configuration == null)
\r
110 ArrayList<String> dependencies = null;
\r
111 for(Resource r : graph.syncRequest(new ObjectsWithType(configuration, l0.ConsistsOf, sr.Module))) {
\r
112 if(dependencies == null)
\r
113 dependencies = new ArrayList<String>();
\r
114 String name = NameUtils.getSafeName(graph, r);
\r
115 String instanceOf = NameUtils.getSafeName(graph, graph.getSingleObject(r, l0.InstanceOf));
\r
116 dependencies.add(name + " : " + instanceOf);
\r
118 if(dependencies != null && !dependencies.isEmpty())
\r
119 throw new ContainsDependenciesException(dependencies);
\r
120 // End checking for module dependencies. If dependencies were found, an exception was thrown
\r
122 String name = graph.getPossibleRelatedValue(component, l0.HasName, Bindings.STRING);
\r
128 } catch (ContainsDependenciesException e1) {
\r
129 Shell shell = HandlerUtil.getActiveShellChecked(event);
\r
130 MessageBox mb = new MessageBox(shell, SWT.OK);
\r
131 StringBuilder sb = new StringBuilder();
\r
132 sb.append("This version does not support exporting modules with other module instances.\n\n");
\r
133 sb.append("Dependencies:\n");
\r
134 for(String s : e1.getDependencies())
\r
135 sb.append(" " + s + "\n");
\r
136 mb.setMessage(sb.toString());
\r
137 mb.setText("Module contains dependencies.");
\r
140 } catch (DatabaseException e1) {
\r
141 e1.printStackTrace();
\r
144 // Do not export if the resource has no name
\r
145 if(name == null) return null;
\r
147 // Find a location (and name) for the exported library using FileDialog
\r
148 Shell shell = HandlerUtil.getActiveShellChecked(event);
\r
149 FileDialog fd = new FileDialog(shell, SWT.SAVE);
\r
150 fd.setText("Export Module");
\r
151 fd.setFileName(name);
\r
152 String path = Activator.getDefault().getPreferenceStore().getString(ImportModuleHandler.IMPORTMODULETPATH);
\r
153 if(path.isEmpty() || !(new File(path).exists()))
\r
154 path = Platform.getLocation().toOSString();
\r
155 fd.setFilterPath(path);
\r
156 String[] filterExt = {"*.tg"};
\r
157 fd.setFilterExtensions(filterExt);
\r
158 final String selected = fd.open();
\r
159 if(selected == null) return null;
\r
161 // Save location to preference store
\r
162 Activator.getDefault().getPreferenceStore().setValue(ImportModuleHandler.IMPORTMODULETPATH, (new File(selected)).getParent());
\r
164 // Asynchronously create the file using transferable graph
\r
165 SimanticsUI.getSession().asyncRequest(new ReadRequest() {
\r
168 public void run(ReadGraph graph) throws DatabaseException {
\r
169 Layer0 l0 = Layer0.getInstance(graph);
\r
170 ModelingResources mr = ModelingResources.getInstance(graph);
\r
172 final Resource component = graph.getPossibleObject(modulesymbol, mr.SymbolToComponentType);
\r
173 if (component == null || !graph.hasStatement(component, Layer0.getInstance(graph).PartOf))
\r
175 String name = graph.syncRequest(new PossibleRelatedValue<String>(component, l0.HasName, Bindings.STRING ));
\r
176 final ArrayList<Pair<Resource, String>> roots = new ArrayList<Pair<Resource, String>>();
\r
177 roots.add(Pair.make(component, name));
\r
179 graph.asyncRequest(new WriteRequest() {
\r
182 public void perform(WriteGraph graph) throws DatabaseException {
\r
183 Layer0 l0 = Layer0.getInstance(graph);
\r
184 StructuralResource2 sr2 = StructuralResource2.getInstance(graph);
\r
186 Resource configuration = graph.getPossibleObject(component, sr2.IsDefinedBy);
\r
187 if (!graph.hasStatement(configuration, l0.PartOf, component)&&
\r
188 !graph.hasStatement(modulesymbol, l0.PartOf, component)) {
\r
189 // Make sure that configuration and symbol are included.
\r
190 // In old versions, they were attached to model, not to module.
\r
191 Resource previousPartof = graph.getSingleObject(configuration, l0.PartOf);
\r
193 graph.deny(configuration, l0.PartOf);
\r
194 graph.deny(modulesymbol, l0.PartOf);
\r
195 graph.claim(configuration, l0.PartOf, l0.ConsistsOf, component);
\r
196 graph.claim(modulesymbol, l0.PartOf, l0.ConsistsOf, component);
\r
198 export(graph, selected, roots, component);
\r
200 graph.deny(configuration, l0.PartOf);
\r
201 graph.deny(modulesymbol, l0.PartOf);
\r
202 graph.claim(configuration, l0.PartOf, l0.ConsistsOf, previousPartof);
\r
203 graph.claim(modulesymbol, l0.PartOf, l0.ConsistsOf, previousPartof);
\r
206 export(graph, selected, roots, component);
\r
218 * Export module (without dependencies to other modules) and write it to file.
\r
219 * Disable existing enumeration replacement for during export.
\r
221 * @param graph WriteGraph
\r
222 * @param path Path for the exported file
\r
224 * @param component Module
\r
226 private void export(WriteGraph graph, String path, ArrayList<Pair<Resource, String>> roots, Resource component) {
\r
228 // FIXME: Enumeration replacement handling like this is not suitable.
\r
230 Layer0 l0 = Layer0.getInstance(graph);
\r
231 SysdynResource sr = SysdynResource.getInstance(graph);
\r
232 StructuralResource2 sr2 = StructuralResource2.getInstance(graph);
\r
234 Resource configuration = graph.getPossibleObject(component, sr2.IsDefinedBy);
\r
235 ArrayList<Pair<Resource, Resource>> replacements = new ArrayList<Pair<Resource, Resource>>();
\r
237 for(Resource enumeration : graph.syncRequest(new ObjectsWithType(configuration, l0.ConsistsOf, sr.Enumeration))) {
\r
238 if(graph.hasStatement(enumeration, sr.Redeclaration_replacedEnumeration_Inverse)) {
\r
239 for(Resource replacement : graph.getObjects(enumeration, sr.Redeclaration_replacedEnumeration_Inverse)) {
\r
240 replacements.add(new Pair<Resource, Resource>(enumeration, replacement));
\r
245 for(Pair<Resource,Resource> replacement : replacements)
\r
246 graph.deny(replacement.first, sr.Redeclaration_replacedEnumeration_Inverse, replacement.second);
\r
248 TransferableGraph1 tg = graph.syncRequest(new TransferableGraphRequest2(roots, component));
\r
249 Files.createFile(new File(path), Bindings.getBindingUnchecked(TransferableGraph1.class), tg);
\r
251 for(Pair<Resource,Resource> replacement : replacements)
\r
252 graph.claim(replacement.first, sr.Redeclaration_replacedEnumeration_Inverse, replacement.second);
\r
254 } catch (RuntimeBindingConstructionException e) {
\r
255 e.printStackTrace();
\r
256 } catch (IOException e) {
\r
257 e.printStackTrace();
\r
258 } catch (DatabaseException e) {
\r
259 e.printStackTrace();
\r