Skip to content

Package: MergeWithViewHandler$5

MergeWithViewHandler$5

nameinstructionbranchcomplexitylinemethod
execute(IProgressMonitor)
M: 45 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
{...}
M: 15 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2018 EclipseSource Muenchen GmbH and others.
3: *
4: * All rights reserved. This program and the accompanying materials
5: * are made available under the terms of the Eclipse Public License 2.0
6: * which accompanies this distribution, and is available at
7: * https://www.eclipse.org/legal/epl-2.0/
8: *
9: * SPDX-License-Identifier: EPL-2.0
10: *
11: * Contributors:
12: * Eugen Neufeld - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emfforms.internal.rulerepository.tooling.merge;
15:
16: import java.io.IOException;
17: import java.lang.reflect.InvocationTargetException;
18: import java.util.Collections;
19:
20: import org.eclipse.core.commands.AbstractHandler;
21: import org.eclipse.core.commands.ExecutionEvent;
22: import org.eclipse.core.commands.ExecutionException;
23: import org.eclipse.core.resources.IFile;
24: import org.eclipse.core.resources.IWorkspace;
25: import org.eclipse.core.resources.ResourcesPlugin;
26: import org.eclipse.core.runtime.IProgressMonitor;
27: import org.eclipse.core.runtime.IStatus;
28: import org.eclipse.core.runtime.Path;
29: import org.eclipse.core.runtime.Status;
30: import org.eclipse.emf.common.command.BasicCommandStack;
31: import org.eclipse.emf.common.util.URI;
32: import org.eclipse.emf.ecore.EObject;
33: import org.eclipse.emf.ecore.resource.Resource;
34: import org.eclipse.emf.ecore.resource.ResourceSet;
35: import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
36: import org.eclipse.emf.ecore.util.EcoreUtil;
37: import org.eclipse.emf.ecore.xmi.XMLResource;
38: import org.eclipse.emf.ecp.view.spi.model.VView;
39: import org.eclipse.emfforms.spi.editor.helpers.ResourceSetHelpers;
40: import org.eclipse.emfforms.spi.rulerepository.model.VRuleRepository;
41: import org.eclipse.jface.dialogs.ErrorDialog;
42: import org.eclipse.jface.viewers.ISelection;
43: import org.eclipse.jface.viewers.TreeSelection;
44: import org.eclipse.jface.window.Window;
45: import org.eclipse.swt.widgets.Shell;
46: import org.eclipse.ui.actions.WorkspaceModifyOperation;
47: import org.eclipse.ui.dialogs.SaveAsDialog;
48: import org.eclipse.ui.handlers.HandlerUtil;
49:
50: /**
51: * The Handler that gets triggered when the merge of rule repository and view is triggered.
52: *
53: * @author Eugen Neufeld
54: *
55: */
56: public class MergeWithViewHandler extends AbstractHandler {
57:
58:         private static final String ORG_ECLIPSE_EMFFORMS_RULEREPOSITORY_TOOLING = "org.eclipse.emfforms.rulerepository.tooling"; //$NON-NLS-1$
59:
60:         @Override
61:         public Object execute(final ExecutionEvent event) throws ExecutionException {
62:                 final ISelection currentSelection = HandlerUtil.getCurrentSelection(event);
63:                 final Shell activeShell = HandlerUtil.getActiveShell(event);
64:                 final IFile selectedFile = (IFile) TreeSelection.class.cast(currentSelection).getFirstElement();
65:                 final WorkspaceModifyOperation operation = mergeRuleRepoWithView(activeShell, selectedFile);
66:                 try {
67:                         if (operation != null) {
68:                                 HandlerUtil.getActiveWorkbenchWindow(event).run(false, false, operation);
69:                         }
70:                 } catch (final InvocationTargetException | InterruptedException ex) {
71:                         ErrorDialog.openError(activeShell, "Error", //$NON-NLS-1$
72:                                 ex.getMessage(),
73:                                 new Status(IStatus.ERROR, ORG_ECLIPSE_EMFFORMS_RULEREPOSITORY_TOOLING, ex.getMessage(), ex));
74:                 }
75:                 return null;
76:         }
77:
78:         private WorkspaceModifyOperation mergeRuleRepoWithView(final Shell activeShell, final IFile selectedFile) {
79:                 ResourceSet resourceSet;
80:                 try {
81:                         resourceSet = ResourceSetHelpers.loadResourceSetWithProxies(
82:                                 URI.createPlatformResourceURI(selectedFile.getFullPath().toOSString(), false),
83:                                 new BasicCommandStack(), null);
84:                 } catch (final IOException ex) {
85:                         ErrorDialog.openError(activeShell, "Error", //$NON-NLS-1$
86:                                 ex.getMessage(),
87:                                 new Status(IStatus.ERROR, ORG_ECLIPSE_EMFFORMS_RULEREPOSITORY_TOOLING, ex.getMessage(), ex));
88:                         return null;
89:                 }
90:
91:                 // FIXME Improve with Java8: Use method pointers
92:                 return this.mergeRuleRepoWithView(activeShell, resourceSet,
93:                         new ViewAndRepositoryProvider() {
94:                                 @Override
95:                                 public ViewAndRepository getViewAndRepository(ResourceSet resourceSet) {
96:                                         return extractViewAndRepository(resourceSet);
97:                                 }
98:                         },
99:                         new MergedViewPathProvider() {
100:                                 @Override
101:                                 public String getPath(Shell activeShell, VView view) {
102:                                         return getMergedViewPath(activeShell, view);
103:                                 }
104:                         },
105:                         new OperationProvider() {
106:                                 @Override
107:                                 public WorkspaceModifyOperation getOperation(Shell activeShell, String mergedViewPath,
108:                                         VView mergedView) {
109:                                         return getWorkspaceOperation(activeShell, mergedViewPath, mergedView);
110:                                 }
111:                         },
112:                         new MergeProvider() {
113:                                 @Override
114:                                 public VView merge(VRuleRepository repository, VView view) {
115:                                         return mergeRuleRepository(repository, view);
116:                                 }
117:
118:                         });
119:         }
120:
121:         /** Provides a method to get the save path of the merged view. */
122:         public interface MergedViewPathProvider {
123:                 /**
124:                  *
125:                  * @param activeShell The Shell
126:                  * @param view The base view
127:                  * @return The save path of the merged view
128:                  */
129:                 String getPath(Shell activeShell, VView view);
130:         }
131:
132:         /** Provides a method to create the {@link WorkspaceModifyOperation}. */
133:         public interface OperationProvider {
134:                 /**
135:                  * Get the {@link WorkspaceModifyOperation} that saved the merged view.
136:                  *
137:                  * @param activeShell The Shell
138:                  * @param mergedViewPath The save path
139:                  * @param mergedView The merged view
140:                  * @return The {@link WorkspaceModifyOperation}
141:                  */
142:                 WorkspaceModifyOperation getOperation(Shell activeShell, String mergedViewPath, VView mergedView);
143:         }
144:
145:         /** Provides a method to get the {@link VView} and {@link VRuleRepository} from a {@link ResourceSet}. */
146:         public interface ViewAndRepositoryProvider {
147:                 /**
148:                  *
149:                  * @param resourceSet The ResourceSet
150:                  * @return The RuleRepository and View
151:                  */
152:                 ViewAndRepository getViewAndRepository(ResourceSet resourceSet);
153:         }
154:
155:         /** Provides a method to merge the RuleRepository. */
156:         public interface MergeProvider {
157:                 /**
158:                  * Merges the RuleRepository in the View.
159:                  *
160:                  * @param repository The {@link VRuleRepository}
161:                  * @param view The {@link VView}
162:                  * @return The merged View
163:                  */
164:                 VView merge(VRuleRepository repository, VView view);
165:         }
166:
167:         /**
168:          * Merges a RuleRepository into its associated VView. Thereby, multiple providers are used to execute each step of
169:          * the algorithm.
170:          *
171:          * @param activeShell The {@link Shell}
172:          * @param resourceSet The {@link ResourceSet} containing the Rule Repository and the View
173:          * @param viewAndRepositoryProvider The {@link ViewAndRepositoryProvider}
174:          * @param pathProvider The {@link MergedViewPathProvider}
175:          * @param operationProvider The {@link OperationProvider}
176:          * @param mergeProvider The {@link MergeProvider}
177:          * @return The {@link WorkspaceModifyOperation} saving the merged View
178:          */
179:         WorkspaceModifyOperation mergeRuleRepoWithView(final Shell activeShell, final ResourceSet resourceSet,
180:                 ViewAndRepositoryProvider viewAndRepositoryProvider, MergedViewPathProvider pathProvider,
181:                 OperationProvider operationProvider, MergeProvider mergeProvider) {
182:
183:                 final ViewAndRepository vur = viewAndRepositoryProvider.getViewAndRepository(resourceSet);
184:
185:                 if (vur.getRuleRepository() == null) {
186:                         ErrorDialog.openError(activeShell, "Missing Rule Repository", //$NON-NLS-1$
187:                                 "The file doesn't contain a rule repository!", //$NON-NLS-1$
188:                                 new Status(IStatus.ERROR, ORG_ECLIPSE_EMFFORMS_RULEREPOSITORY_TOOLING, "No Rule Repository!")); //$NON-NLS-1$
189:                         return null;
190:                 }
191:                 if (vur.getView() == null) {
192:                         ErrorDialog.openError(activeShell, "Missing View", //$NON-NLS-1$
193:                                 "You must link a view model first!", //$NON-NLS-1$
194:                                 new Status(IStatus.ERROR, ORG_ECLIPSE_EMFFORMS_RULEREPOSITORY_TOOLING, "No View model linked!")); //$NON-NLS-1$
195:                         return null;
196:                 }
197:
198:                 final String mergedViewPath = pathProvider.getPath(activeShell, vur.getView());
199:
200:                 final VView mergedView = mergeProvider.merge(vur.getRuleRepository(), vur.getView());
201:
202:                 // Do the work within an operation.
203:                 return operationProvider.getOperation(activeShell, mergedViewPath, mergedView);
204:         }
205:
206:         /**
207:          * Merges the given rule repository into its linked VView.
208:          *
209:          * @param repository The {@link VRuleRepository}
210:          * @param view The VView linked in the {@link VRuleRepository}
211:          * @return The merged {@link VView}
212:          */
213:         VView mergeRuleRepository(VRuleRepository repository, VView view) {
214:                 MergeHelper.merge(repository);
215:                 return EcoreUtil.copy(view);
216:         }
217:
218:         /**
219:          * Opens a file save dialog to determine the save path of the merged view.
220:          *
221:          * @param activeShell The active Shell
222:          * @param view The View object
223:          * @return The save path
224:          */
225:         String getMergedViewPath(final Shell activeShell, VView view) {
226:                 final SaveAsDialog sad = new SaveAsDialog(activeShell);
227:                 final URI viewURI = view.eResource().getURI();
228:                 final IWorkspace workspace = ResourcesPlugin.getWorkspace();
229:                 final String mergedViewPath = viewURI.trimFileExtension().toPlatformString(false).substring(1) + "_merged." //$NON-NLS-1$
230:                         + viewURI.fileExtension();
231:
232:                 final IFile file = workspace.getRoot().getFile(new Path(mergedViewPath));
233:
234:                 sad.setOriginalFile(file);
235:                 final int result = sad.open();
236:                 if (result == Window.CANCEL) {
237:                         return null;
238:                 }
239:                 return sad.getResult().toString();
240:         }
241:
242:         /**
243:          * Creates a {@link WorkspaceModifyOperation} to save the merged view model to the specified file.
244:          *
245:          * @param activeShell The active Shell
246:          * @param mergedViewPath The path where the merged view is saved
247:          * @param mergedView The merged view
248:          * @return The {@link WorkspaceModifyOperation}
249:          */
250:         WorkspaceModifyOperation getWorkspaceOperation(final Shell activeShell, final String mergedViewPath,
251:                 final VView mergedView) {
252:                 return new WorkspaceModifyOperation() {
253:                         @Override
254:                         protected void execute(IProgressMonitor progressMonitor) {
255:                                 // Create a resource set
256:                                 final ResourceSet resourceSet = new ResourceSetImpl();
257:
258:                                 // Get the URI of the model file.
259:                                 final URI fileURI = URI.createPlatformResourceURI(mergedViewPath, true);
260:
261:                                 // Create a resource for this file.
262:                                 final Resource resource = resourceSet.createResource(fileURI);
263:
264:                                 resource.getContents().add(mergedView);
265:
266:                                 // Save the contents of the resource to the file system.
267:                                 try {
268:                                         resource.save(Collections.singletonMap(XMLResource.OPTION_ENCODING, "UTF-8")); //$NON-NLS-1$
269:                                 } catch (final IOException ex) {
270:                                         ErrorDialog.openError(activeShell, "Error", //$NON-NLS-1$
271:                                                 ex.getMessage(),
272:                                                 new Status(IStatus.ERROR, ORG_ECLIPSE_EMFFORMS_RULEREPOSITORY_TOOLING, ex.getMessage(), ex));
273:                                         return;
274:                                 } finally {
275:                                         progressMonitor.done();
276:                                 }
277:                         }
278:                 };
279:         }
280:
281:         /**
282:          * Gets the VView and VRuleRepository from the given {@link ResourceSet}.
283:          *
284:          * @param resourceSet The resource set containing the view and rule repository
285:          * @return The {@link ViewAndRepository} container
286:          */
287:         ViewAndRepository extractViewAndRepository(ResourceSet resourceSet) {
288:                 final ViewAndRepository result = new ViewAndRepository();
289:                 for (final Resource resource : resourceSet.getResources()) {
290:                         if (resource.getContents().isEmpty()) {
291:                                 continue;
292:                         }
293:                         final EObject eObject = resource.getContents().get(0);
294:                         if (VView.class.isInstance(eObject)) {
295:                                 result.setView(VView.class.cast(eObject));
296:                         }
297:                         if (VRuleRepository.class.isInstance(eObject)) {
298:                                 result.setRuleRepository(VRuleRepository.class.cast(eObject));
299:                         }
300:                 }
301:                 return result;
302:         }
303:
304:         /** Wrapper class containing a VView and a VRuleRepository. */
305:         public static class ViewAndRepository {
306:                 private VView view;
307:                 private VRuleRepository ruleRepository;
308:
309:                 /**
310:                  * @return the view
311:                  */
312:                 public VView getView() {
313:                         return view;
314:                 }
315:
316:                 /**
317:                  * @param view the view to set
318:                  */
319:                 public void setView(VView view) {
320:                         this.view = view;
321:                 }
322:
323:                 /**
324:                  * @return the ruleRepository
325:                  */
326:                 public VRuleRepository getRuleRepository() {
327:                         return ruleRepository;
328:                 }
329:
330:                 /**
331:                  * @param ruleRepository the ruleRepository to set
332:                  */
333:                 public void setRuleRepository(VRuleRepository ruleRepository) {
334:                         this.ruleRepository = ruleRepository;
335:                 }
336:         }
337: }