Skip to content

Package: ViewMigrationHandler

ViewMigrationHandler

nameinstructionbranchcomplexitylinemethod
ViewMigrationHandler(String, String)
M: 9 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
checkView(IFile)
M: 44 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 10 C: 0
0%
M: 1 C: 0
0%
execute(IFile)
M: 160 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 43 C: 0
0%
M: 1 C: 0
0%
execute(Set, SubMonitor)
M: 41 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 10 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 4 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) 2017 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: * Edgar Mueller - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emf.ecp.ide.internal.migration;
15:
16: import java.io.IOException;
17: import java.io.PipedInputStream;
18: import java.io.PipedOutputStream;
19: import java.util.LinkedHashMap;
20: import java.util.LinkedHashSet;
21: import java.util.Map;
22: import java.util.Set;
23: import java.util.concurrent.Callable;
24: import java.util.concurrent.ExecutionException;
25: import java.util.concurrent.ExecutorService;
26: import java.util.concurrent.Executors;
27: import java.util.concurrent.Future;
28:
29: import javax.xml.parsers.DocumentBuilder;
30: import javax.xml.parsers.DocumentBuilderFactory;
31: import javax.xml.parsers.ParserConfigurationException;
32: import javax.xml.transform.Transformer;
33: import javax.xml.transform.TransformerConfigurationException;
34: import javax.xml.transform.TransformerException;
35: import javax.xml.transform.TransformerFactory;
36: import javax.xml.transform.dom.DOMSource;
37: import javax.xml.transform.stream.StreamResult;
38: import javax.xml.xpath.XPath;
39: import javax.xml.xpath.XPathConstants;
40: import javax.xml.xpath.XPathExpression;
41: import javax.xml.xpath.XPathExpressionException;
42: import javax.xml.xpath.XPathFactory;
43:
44: import org.eclipse.core.resources.IFile;
45: import org.eclipse.core.runtime.CoreException;
46: import org.eclipse.core.runtime.NullProgressMonitor;
47: import org.eclipse.core.runtime.SubMonitor;
48: import org.eclipse.emf.common.util.Diagnostic;
49: import org.eclipse.emf.ecp.ide.spi.util.EcoreHelper;
50: import org.eclipse.emf.ecp.ide.spi.util.ViewModelHelper;
51: import org.eclipse.emf.ecp.view.spi.model.VView;
52: import org.eclipse.emf.ecp.view.spi.model.VViewModelProperties;
53: import org.eclipse.emf.ecp.view.spi.model.util.ViewModelPropertiesHelper;
54: import org.eclipse.emfforms.common.Optional;
55: import org.eclipse.emfforms.common.internal.validation.ValidationServiceImpl;
56: import org.w3c.dom.Document;
57: import org.w3c.dom.Node;
58: import org.w3c.dom.NodeList;
59: import org.xml.sax.SAXException;
60:
61: /**
62: * Executes a simple XPath-based transformation for migrating the namespace
63: * fragments of a given view model file.
64: *
65: */
66: public class ViewMigrationHandler {
67:
68:         private static ExecutorService executorService = Executors.newFixedThreadPool(1);
69:
70:         private final String oldNamespaceFragment;
71:         private final String newNamespaceFragment;
72:
73:         /**
74:          * Default constructor.
75:          *
76:          * @param oldNamespaceFragment the value of the namespace fragment to be replaced
77:          * @param newNamespaceFragment the new namespace fragment to replace the old with
78:          */
79:         public ViewMigrationHandler(String oldNamespaceFragment, String newNamespaceFragment) {
80:                 this.oldNamespaceFragment = oldNamespaceFragment;
81:                 this.newNamespaceFragment = newNamespaceFragment;
82:         }
83:
84:         /**
85:          * Execute the migration for all given files.
86:          *
87:          * @param files the set of files to be migrated
88:          * @param monitor a {@link SubMonitor} that allows for reporting progress
89:          * @return a map of file names containing the view models to be migrated
90:          * to the respective {@link Diagnostic}s which have been produced
91:          * while loading the views
92:          *
93:          * @throws ViewMigrationException in case the migration of the view fails
94:          */
95:         public Map<String, Optional<Diagnostic>> execute(Set<IFile> files, SubMonitor monitor)
96:                 throws ViewMigrationException {
97:                 final SubMonitor subMonitor = SubMonitor.convert(monitor, files.size());
98:                 final Map<String, Optional<Diagnostic>> diagnostics = new LinkedHashMap<String, Optional<Diagnostic>>();
99:
100:•                for (final IFile file : files) {
101:                         try {
102:                                 final Optional<Diagnostic> diagnostic = execute(file);
103:                                 diagnostics.put(file.getName(), diagnostic);
104:                                 // BEGIN SUPRESS CATCH EXCEPTION
105:                         } catch (final Exception throwable) {
106:                                 Activator.log(throwable);
107:                                 // END SUPRESS CATCH EXCEPTION
108:                                 continue;
109:                         }
110:                         subMonitor.worked(1);
111:                 }
112:
113:                 return diagnostics;
114:         }
115:
116:         /**
117:          * Execute the migration for a single file and validate it.
118:          *
119:          * @param file the file to be migrated
120:          * @return the validation result after the file has been migrated, or {@link Optional#empty}
121:          * if the view could not be resolved
122:          *
123:          * @throws ViewMigrationException in case the migration of the view fails
124:          */
125:         public Optional<Diagnostic> execute(final IFile file) throws ViewMigrationException {
126:
127:                 try {
128:                         file.refreshLocal(0, new NullProgressMonitor());
129:                         final TransformerFactory transformerFactory = TransformerFactory.newInstance();
130:                         final Transformer transformer = transformerFactory.newTransformer();
131:                         final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
132:                         final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
133:                         final Document doc = docBuilder.parse(file.getContents());
134:
135:                         final XPathFactory xPathfactory = XPathFactory.newInstance();
136:                         final XPath xpath = xPathfactory.newXPath();
137:
138:                         // select all elements with a href attribute
139:                         final XPathExpression expr = xpath.compile("//*[@href]"); //$NON-NLS-1$
140:                         final NodeList elements = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
141:
142:•                        for (int i = 0; i < elements.getLength(); i++) {
143:                                 final Node item = elements.item(i);
144:                                 final Node href = item.getAttributes().getNamedItem("href"); //$NON-NLS-1$
145:                                 href.setNodeValue(href.getNodeValue().replace(oldNamespaceFragment, newNamespaceFragment));
146:                         }
147:
148:                         final DOMSource source = new DOMSource(doc);
149:
150:                         final PipedInputStream pis = new PipedInputStream();
151:                         final PipedOutputStream pos = new PipedOutputStream();
152:                         pos.connect(pis);
153:                         final StreamResult result = new StreamResult(pos);
154:                         final Future<Void> future = executorService.submit(new Callable<Void>() {
155:                                 @Override
156:                                 public Void call() throws Exception {
157:                                         try {
158:                                                 file.setContents(pis, true, true, new NullProgressMonitor());
159:                                         } finally {
160:                                                 pis.close();
161:                                         }
162:                                         return null;
163:                                 }
164:                         });
165:                         try {
166:                                 transformer.transform(source, result);
167:                         } finally {
168:                                 pos.close();
169:                         }
170:
171:                         // block per file, could be optimized
172:                         future.get();
173:
174:                         return checkView(file);
175:                 } catch (final SAXException ex) {
176:                         throw new ViewMigrationException(ex);
177:                 } catch (final TransformerConfigurationException ex) {
178:                         throw new ViewMigrationException(ex);
179:                 } catch (final ParserConfigurationException ex) {
180:                         throw new ViewMigrationException(ex);
181:                 } catch (final IOException ex) {
182:                         throw new ViewMigrationException(ex);
183:                 } catch (final XPathExpressionException ex) {
184:                         throw new ViewMigrationException(ex);
185:                 } catch (final TransformerException ex) {
186:                         throw new ViewMigrationException(ex);
187:                 } catch (final CoreException ex) {
188:                         throw new ViewMigrationException(ex);
189:                 } catch (final InterruptedException ex) {
190:                         throw new ViewMigrationException(ex);
191:                 } catch (final ExecutionException ex) {
192:                         throw new ViewMigrationException(ex);
193:                 }
194:         }
195:
196:         private Optional<Diagnostic> checkView(IFile file) throws IOException {
197:                 final LinkedHashSet<String> ecores = new LinkedHashSet<String>();
198:                 final VView view = ViewModelHelper.loadView(file, ecores);
199:                 try {
200:•                        if (view != null) {
201:                                 final VViewModelProperties properties = ViewModelPropertiesHelper.getInhertitedPropertiesOrEmpty(view);
202:                                 view.setLoadingProperties(properties);
203:                                 final ValidationServiceImpl validationService = new ValidationServiceImpl();
204:                                 return Optional.of(validationService.validate(view));
205:                         }
206:                         return Optional.empty();
207:                 } finally {
208:•                        for (final String registeredEcore : ecores) {
209:                                 EcoreHelper.unregisterEcore(registeredEcore);
210:                         }
211:                 }
212:         }
213: }