Skip to content

Package: ViewModelHelper$ViewLoader

ViewModelHelper$ViewLoader

nameinstructionbranchcomplexitylinemethod
ViewModelHelper.ViewLoader()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
ecoreExistsInWorkspace(String)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getPath(IFile)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getReportService()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getViewName(VView)
M: 21 C: 15
42%
M: 8 C: 4
33%
M: 6 C: 1
14%
M: 3 C: 4
57%
M: 0 C: 1
100%
getViewNameAndLocation(VView, String)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
lambda$0(String, String)
M: 13 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
loadView(IFile, Collection)
M: 2 C: 20
91%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 1 C: 5
83%
M: 0 C: 1
100%
loadView(String)
M: 2 C: 20
91%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 5
83%
M: 0 C: 1
100%
registerEcore(String)
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
registerReferencedEcores(VView, String, Collection)
M: 1 C: 54
98%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 1 C: 11
92%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2014 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: * Alexandra Buzila - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emf.ecp.ide.spi.util;
15:
16: import java.io.IOException;
17: import java.text.MessageFormat;
18: import java.util.Arrays;
19: import java.util.Collection;
20: import java.util.Collections;
21: import java.util.LinkedList;
22: import java.util.List;
23: import java.util.Optional;
24:
25: import org.eclipse.core.resources.IFile;
26: import org.eclipse.core.resources.ResourcesPlugin;
27: import org.eclipse.core.runtime.IStatus;
28: import org.eclipse.emf.common.command.BasicCommandStack;
29: import org.eclipse.emf.common.notify.AdapterFactory;
30: import org.eclipse.emf.common.util.URI;
31: import org.eclipse.emf.ecore.EClass;
32: import org.eclipse.emf.ecore.EObject;
33: import org.eclipse.emf.ecore.EPackage;
34: import org.eclipse.emf.ecore.EPackage.Descriptor;
35: import org.eclipse.emf.ecore.EPackage.Registry;
36: import org.eclipse.emf.ecore.EStructuralFeature;
37: import org.eclipse.emf.ecore.resource.Resource;
38: import org.eclipse.emf.ecore.resource.ResourceSet;
39: import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
40: import org.eclipse.emf.ecore.util.EcoreUtil;
41: import org.eclipse.emf.ecore.util.FeatureMap;
42: import org.eclipse.emf.ecore.util.FeatureMap.ValueListIterator;
43: import org.eclipse.emf.ecore.xmi.XMLResource;
44: import org.eclipse.emf.ecore.xml.type.AnyType;
45: import org.eclipse.emf.ecp.ide.internal.Activator;
46: import org.eclipse.emf.ecp.internal.ide.util.messages.Messages;
47: import org.eclipse.emf.ecp.view.spi.model.VView;
48: import org.eclipse.emf.ecp.view.spi.model.VViewPackage;
49: import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
50: import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
51: import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
52: import org.eclipse.emfforms.spi.common.report.AbstractReport;
53: import org.eclipse.emfforms.spi.common.report.ReportService;
54:
55: /**
56: * Helper class for view model objects.
57: *
58: * @author Alexandra Buzila
59: *
60: * @since 1.13
61: */
62: public final class ViewModelHelper {
63:
64:         private ViewModelHelper() {
65:         }
66:
67:         /**
68:          * Creates a new view model file.
69:          *
70:          * @param modelFile the file in which the view should be saved
71:          * @param selectedEClass the <em>Root EClass</em> for the new {@link VView}
72:          * @param selectedEcore the ecore containing the <em>selectedEClass</em>. If the <em>selectedEcore</em> is null,
73:          * then the <em>selectedEClass</em> must come from an EPackage which is registered by default in
74:          * the
75:          * package registry.
76:          *
77:          * @return the newly created {@link VView}
78:          *
79:          * @throws IOException when something goes wrong while loading or saving the resource
80:          *
81:          */
82:         public static VView createViewModel(IFile modelFile, EClass selectedEClass, IFile selectedEcore)
83:                 throws IOException {
84:
85:                 AdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
86:                 adapterFactory = new ComposedAdapterFactory(new AdapterFactory[] { adapterFactory,
87:                         new ReflectiveItemProviderAdapterFactory() });
88:                 final AdapterFactoryEditingDomain domain = new AdapterFactoryEditingDomain(adapterFactory,
89:                         new BasicCommandStack());
90:
91:                 // create resource for the view
92:                 final URI fileURI = URI.createPlatformResourceURI(modelFile.getFullPath().toString(), true);
93:                 final Resource resource = domain.createResource(fileURI.toString());
94:
95:                 // Add the initial model object to the contents.
96:                 final VView view = VViewPackage.eINSTANCE.getViewFactory().createView();
97:                 if (view == null) {
98:                         return null;
99:                 }
100:                 resource.getContents().add(view);
101:
102:                 // Add the selected EClass as the VView's RootEClass
103:                 //
104:                 // get the EClass from the registry, to ensure it has the correct href
105:                 final EPackage ePackage = selectedEClass.getEPackage();
106:
107:                 final Registry instance = org.eclipse.emf.ecore.EPackage.Registry.INSTANCE;
108:                 final Object ePackageObject = instance.get(ePackage.getNsURI());
109:                 EPackage ep;
110:                 if (EPackage.Descriptor.class.isInstance(ePackageObject)) {
111:                         final Descriptor descriptor = EPackage.Descriptor.class.cast(ePackageObject);
112:                         ep = descriptor.getEPackage();
113:                 } else if (EPackage.class.isInstance(ePackageObject)) {
114:                         ep = (EPackage) ePackageObject;
115:                 } else {
116:                         ep = null;
117:                 }
118:                 if (ep == null && selectedEcore != null) {
119:                         EcoreHelper.registerEcore(selectedEcore.getFullPath().toString());
120:                         ep = (EPackage) instance.get(ePackage.getNsURI());
121:                 }
122:
123:                 final EClass ec = (EClass) ep.getEClassifier(selectedEClass.getName());
124:
125:                 view.setRootEClass(ec);
126:                 view.setName(selectedEClass.getName());
127:                 // Update the VView-EClass mapping
128:                 if (selectedEcore != null
129:                         && !view.getEcorePaths().contains(selectedEcore.getFullPath().toString())) {
130:                         view.getEcorePaths().add(selectedEcore.getFullPath().toString());
131:                 }
132:
133:                 // Save the contents of the resource to the file system.
134:                 resource.save(Collections.singletonMap(XMLResource.OPTION_ENCODING, "UTF-8")); //$NON-NLS-1$
135:
136:                 return view;
137:         }
138:
139:         /**
140:          * Tries to load a view from the given file.
141:          *
142:          * @param file the {@link IFile} that contains the view model to be loaded
143:          * @param registeredEcores a {@link Collection} that will contain the paths of all
144:          * Ecores that are necessary to load the view. call
145:          * @return the {@link VView}. Note that view resolution may fail, so callers should check
146:          * whether the view has been resolved successfully
147:          * @throws IOException in case an error occurs while loading the view
148:          */
149:         public static VView loadView(IFile file, Collection<String> registeredEcores) throws IOException {
150:                 return new ViewLoader().loadView(file, registeredEcores);
151:         }
152:
153:         /**
154:          * Check whether the given view has been resolved, i.e. whether it is a proxy or not
155:          *
156:          * @param view the {@link VView} to be checked
157:          * @return {@code true}, if the view is not a proxy, {@code false} otherwise
158:          */
159:         public static boolean viewIsResolved(VView view) {
160:                 return !view.getRootEClass().eIsProxy();
161:         }
162:
163:         /**
164:          * Extract the list of Ecore paths from a view model resource.
165:          *
166:          * @param resource the resource to extract the paths from
167:          * @return list of Ecore paths
168:          *
169:          * @since 1.17
170:          */
171:         public static List<String> getEcorePaths(Resource resource) {
172:                 if (resource == null || resource.getContents().isEmpty()) {
173:                         return Collections.emptyList();
174:                 }
175:                 final EObject eObject = resource.getContents().get(0);
176:                 if (VView.class.isInstance(eObject)) {
177:                         return VView.class.cast(eObject).getEcorePaths();
178:                 }
179:                 if (AnyType.class.isInstance(eObject)) {
180:                         /* view model has older ns uri */
181:                         // up to 1.16.0
182:                         final FeatureMap anyAttribute = AnyType.class.cast(eObject).getAnyAttribute();
183:                         for (int i = 0; i < anyAttribute.size(); i++) {
184:                                 final EStructuralFeature feature = anyAttribute.getEStructuralFeature(i);
185:                                 if ("ecorePath".equals(feature.getName())) { //$NON-NLS-1$
186:                                         return Arrays.asList(new String[] { (String) anyAttribute.getValue(i) });
187:                                 }
188:                         }
189:
190:                         // from 1.17.0
191:                         final FeatureMap any = AnyType.class.cast(eObject).getAny();
192:                         final List<String> ecorePaths = new LinkedList<String>();
193:                         for (int i = 0; i < any.size(); i++) {
194:                                 final EStructuralFeature feature = any.getEStructuralFeature(i);
195:                                 if ("ecorePaths".equals(feature.getName())) { //$NON-NLS-1$
196:                                         final AnyType listType = (AnyType) any.getValue(i);
197:                                         final FeatureMap mixed = listType.getMixed();
198:
199:                                         // Use iterator to avoid IndexOutOfBounce exceptions for empty ecore paths
200:                                         final ValueListIterator<Object> iterator = mixed.valueListIterator();
201:                                         if (iterator.hasNext()) {
202:                                                 ecorePaths.add((String) iterator.next());
203:                                         }
204:                                 }
205:                         }
206:                         return ecorePaths;
207:                 }
208:                 return Collections.emptyList();
209:         }
210:
211:         /**
212:          * Helper class for encapsulating view loading functionality.
213:          */
214:         public static class ViewLoader {
215:                 /**
216:                  * Loads the view denoted by the given file. Also tries to register referenced Ecores.
217:                  *
218:                  * @param file the view to load
219:                  * @param registeredEcores a collection to which all Ecores which are successfully registered are added.
220:                  * @return the {@link VView} denoted by the given file.
221:                  * @throws IOException if something goes wrong during loading or registering
222:                  */
223:                 public VView loadView(IFile file, Collection<String> registeredEcores) throws IOException {
224:                         final String path = getPath(file);
225:                         final VView view = loadView(path);
226:                         registerReferencedEcores(view, path, registeredEcores);
227:•                        if (view != null && !viewIsResolved(view)) {
228:                                 EcoreUtil.resolveAll(view);
229:                         }
230:                         return view;
231:                 }
232:
233:                 /**
234:                  * Returns the path string of the given file.
235:                  *
236:                  * @param file the {@link IFile} for which the path string shall be determined.
237:                  * @return The determined string path.
238:                  */
239:                 protected String getPath(IFile file) {
240:                         return file.getLocation().toString();
241:                 }
242:
243:                 /**
244:                  * Loads the view denoted by the given path.
245:                  *
246:                  * @param path the path denoting the {@link VView}
247:                  * @return the loaded {@link VView}
248:                  */
249:                 protected VView loadView(String path) {
250:                         final ResourceSet resourceSet = new ResourceSetImpl();
251:                         final URI fileURI = URI.createFileURI(path);
252:                         final Resource resource = resourceSet.getResource(fileURI, true);
253:•                        if (resource != null) {
254:                                 return (VView) resource.getContents().get(0);
255:                         }
256:                         return null;
257:                 }
258:
259:                 /**
260:                  * Registers the referenced Ecores of the given view.
261:                  *
262:                  * @param view the {@link VView} which possibly references Ecores.
263:                  * @param viewLocation the location of the given view. Used for error reporting.
264:                  * @param registeredEcores a collection to which all Ecores which are successfully registered are added.
265:                  * @throws IOException if something goes wrong during loading or registering
266:                  */
267:                 protected void registerReferencedEcores(VView view, String viewLocation, Collection<String> registeredEcores)
268:                         throws IOException {
269:•                        if (view == null || view.getEcorePaths() == null) {
270:                                 return;
271:                         }
272:•                        for (final String ecorePath : view.getEcorePaths()) {
273:•                                if (!ecoreExistsInWorkspace(ecorePath)) {
274:                                         final String message = MessageFormat.format(Messages.ViewModelHelper_couldNotFindEcorePath_message,
275:                                                 ecorePath, getViewNameAndLocation(view, viewLocation));
276:                                         getReportService()
277:                                                 .report(new AbstractReport(message, IStatus.WARNING));
278:                                         continue;
279:                                 }
280:                                 registerEcore(ecorePath);
281:                                 registeredEcores.add(ecorePath);
282:                         }
283:                 }
284:
285:                 /**
286:                  * Returns a string representation of the view and its location.
287:                  *
288:                  * @param view the {@link VView}.
289:                  * @param viewLocation the location.
290:                  * @return a string representation of the view and its location
291:                  */
292:                 protected String getViewNameAndLocation(VView view, String viewLocation) {
293:                         return getViewName(view)
294:                                 .map(viewName -> MessageFormat.format(Messages.ViewModelHelper_couldNotFindEcorePath_nameAndLocation,
295:                                         viewName, viewLocation))
296:                                 .orElse(viewLocation);
297:                 }
298:
299:                 /**
300:                  * Determines a name for the given view.
301:                  *
302:                  * @param view the [@link VView}.
303:                  * @return an optional possibly containing a determined name, empty otherwise.
304:                  */
305:                 protected Optional<String> getViewName(VView view) {
306:•                        if (view.getLabel() != null && !view.getLabel().isEmpty()) {
307:                                 return Optional.of(view.getLabel());
308:                         }
309:•                        if (view.getName() != null && !view.getName().isEmpty()) {
310:                                 return Optional.of(view.getName());
311:                         }
312:•                        if (view.getRootEClass() != null && view.getRootEClass().getName() != null) {
313:                                 return Optional.of(view.getRootEClass().getName());
314:                         }
315:                         return Optional.empty();
316:                 }
317:
318:                 /**
319:                  * Indicates whether the Ecore denoted by the path exists in the workspace.
320:                  *
321:                  * @param ecorePath the potential path to an Ecore
322:                  * @return {@code true} if an Ecore exists at the path in the workspace, {@code false} otherwise.
323:                  */
324:                 protected boolean ecoreExistsInWorkspace(String ecorePath) {
325:•                        return ResourcesPlugin.getWorkspace().getRoot().findMember(ecorePath) != null;
326:                 }
327:
328:                 /**
329:                  * Returns the service used for error reporting.
330:                  *
331:                  * @return the {@link ReportService}
332:                  */
333:                 protected ReportService getReportService() {
334:                         return Activator.getDefault().getReportService();
335:                 }
336:
337:                 /**
338:                  * Try to register the Ecore denoted by the path.
339:                  *
340:                  * @param ecorePath the path to the Ecore in the workspace which shall be registered.
341:                  * @throws IOException if something goes wrong during registering.
342:                  */
343:                 protected void registerEcore(String ecorePath) throws IOException {
344:                         EcoreHelper.registerEcore(ecorePath);
345:                 }
346:         }
347: }