Skip to content

Package: DmrToSegmentsMigratorImpl

DmrToSegmentsMigratorImpl

nameinstructionbranchcomplexitylinemethod
DmrToSegmentsMigratorImpl()
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%
isLegacyDmr(EObject)
M: 0 C: 13
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
lambda$0(List, TreeIterator, EObject)
M: 0 C: 12
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
lambda$3(Map, EObject, Collection)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
lambda$4(Map, EObject, EStructuralFeature.Setting)
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%
loadResource(URI)
M: 0 C: 22
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
needsMigration(Resource)
M: 0 C: 19
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
needsMigration(URI)
M: 17 C: 9
35%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 5 C: 3
38%
M: 0 C: 1
100%
performMigration(Resource, DmrToSegmentsMigrator.PreReplaceProcessor[])
M: 11 C: 120
92%
M: 1 C: 9
90%
M: 1 C: 5
83%
M: 3 C: 25
89%
M: 0 C: 1
100%
performMigration(URI, DmrToSegmentsMigrator.PreReplaceProcessor[])
M: 26 C: 16
38%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 2 C: 6
75%
M: 0 C: 1
100%
setEMFFormsSegmentGenerator(EMFFormsSegmentGenerator)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setReportService(ReportService)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2019 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: * Lucas Koehler - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emfforms.internal.ide.view.segments;
15:
16: import java.io.IOException;
17: import java.util.Collection;
18: import java.util.Collections;
19: import java.util.HashMap;
20: import java.util.LinkedList;
21: import java.util.List;
22: import java.util.Map;
23:
24: import org.eclipse.emf.common.util.BasicEList;
25: import org.eclipse.emf.common.util.EList;
26: import org.eclipse.emf.common.util.TreeIterator;
27: import org.eclipse.emf.common.util.URI;
28: import org.eclipse.emf.ecore.EObject;
29: import org.eclipse.emf.ecore.EStructuralFeature.Setting;
30: import org.eclipse.emf.ecore.resource.Resource;
31: import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
32: import org.eclipse.emf.ecore.util.EcoreUtil;
33: import org.eclipse.emf.ecore.xmi.XMLResource;
34: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
35: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReferenceSegment;
36: import org.eclipse.emf.ecp.view.spi.model.VViewFactory;
37: import org.eclipse.emf.ecp.view.spi.model.VViewPackage;
38: import org.eclipse.emf.ecp.view.spi.model.util.VViewResourceFactoryImpl;
39: import org.eclipse.emf.ecp.view.spi.table.model.VTableDomainModelReference;
40: import org.eclipse.emfforms.spi.common.report.AbstractReport;
41: import org.eclipse.emfforms.spi.common.report.ReportService;
42: import org.eclipse.emfforms.spi.core.services.segments.EMFFormsSegmentGenerator;
43: import org.eclipse.emfforms.spi.ide.view.segments.DmrToSegmentsMigrationException;
44: import org.eclipse.emfforms.spi.ide.view.segments.DmrToSegmentsMigrator;
45: import org.eclipse.emfforms.view.spi.multisegment.model.MultiSegmentUtil;
46: import org.eclipse.emfforms.view.spi.multisegment.model.VMultiDomainModelReferenceSegment;
47: import org.osgi.service.component.annotations.Component;
48: import org.osgi.service.component.annotations.Reference;
49:
50: /**
51: * Implementation of {@link DmrToSegmentsMigrator}.
52: *
53: * @author Lucas Koehler
54: *
55: */
56: @Component
57: public class DmrToSegmentsMigratorImpl implements DmrToSegmentsMigrator {
58:
59:         private EMFFormsSegmentGenerator segmentGenerator;
60:         private ReportService reportService;
61:
62:         /**
63:          * Sets the {@link EMFFormsSegmentGenerator}.
64:          *
65:          * @param segmentGenerator The {@link EMFFormsSegmentGenerator}
66:          */
67:         @Reference(unbind = "-")
68:         void setEMFFormsSegmentGenerator(EMFFormsSegmentGenerator segmentGenerator) {
69:                 this.segmentGenerator = segmentGenerator;
70:         }
71:
72:         /**
73:          * Sets the {@link ReportService}.
74:          *
75:          * @param reportService The {@link ReportService}
76:          */
77:         @Reference(unbind = "-")
78:         void setReportService(ReportService reportService) {
79:                 this.reportService = reportService;
80:
81:         }
82:
83:         @Override
84:         public boolean needsMigration(URI resourceUri) {
85:                 Resource resource;
86:                 try {
87:                         resource = loadResource(resourceUri);
88:                 } catch (final IOException ex) {
89:                         reportService.report(
90:                                 new AbstractReport(ex,
91:                                         "Could not check whether resource ''{0}'' still uses legacy DMRs because it could not be loaded.", //$NON-NLS-1$
92:                                         resourceUri));
93:                         return false;
94:                 }
95:
96:                 return needsMigration(resource);
97:         }
98:
99:         /**
100:          * Checks whether a view model still contains legacy domain model references that need to be migrated to segments.
101:          * The resource must be {@link Resource#load(java.util.Map) loaded} before handing it into this method.
102:          *
103:          * @param resource The loaded resource
104:          * @return true, if the view model requires a migration, false otherwise.
105:          */
106:         protected boolean needsMigration(Resource resource) {
107:                 final TreeIterator<EObject> allContents = resource.getAllContents();
108:•                while (allContents.hasNext()) {
109:                         final EObject next = allContents.next();
110:•                        if (isLegacyDmr(next)) {
111:                                 return true;
112:                         }
113:                 }
114:
115:                 return false;
116:         }
117:
118:         @Override
119:         public void performMigration(URI resourceUri, PreReplaceProcessor... preReplaceProcessors)
120:                 throws DmrToSegmentsMigrationException {
121:                 final Resource resource;
122:                 try {
123:                         resource = loadResource(resourceUri);
124:                 } catch (final IOException ex) {
125:                         throw new DmrToSegmentsMigrationException(ex, "The resource {0} could not be loaded", resourceUri); //$NON-NLS-1$
126:                 }
127:
128:                 performMigration(resource, preReplaceProcessors);
129:
130:                 try {
131:                         resource.save(Collections.singletonMap(XMLResource.OPTION_ENCODING, "UTF-8")); //$NON-NLS-1$
132:                 } catch (final IOException ex) {
133:                         throw new DmrToSegmentsMigrationException(ex, "Migrated resource could not be saved to {0}.", resourceUri); //$NON-NLS-1$
134:                 }
135:         }
136:
137:         /**
138:          * Migrates all legacy domain model references in the given resource. The resource must be
139:          * {@link Resource#load(java.util.Map) loaded} before handing it into this method.
140:          *
141:          * @param resource The loaded resource
142:          * @param preReplaceProcessors The {@link PreReplaceProcessor PreReplaceProcessors}
143:          * @throws DmrToSegmentsMigrationException if the migration fails
144:          */
145:         protected void performMigration(final Resource resource, PreReplaceProcessor... preReplaceProcessors)
146:                 throws DmrToSegmentsMigrationException {
147:                 // Collect all legacy DMRs
148:                 final List<VDomainModelReference> legacyDmrs = new LinkedList<>();
149:                 final TreeIterator<EObject> allContents = resource.getAllContents();
150:                 allContents.forEachRemaining(eObject -> {
151:•                        if (isLegacyDmr(eObject)) {
152:                                 legacyDmrs.add((VDomainModelReference) eObject);
153:                                 // Skip contents of legacy DMRs because we do not need to explicitly convert DMRs contained in other
154:                                 // DMRs. The contained DMRs will be considered when generating the segments for their parents.
155:                                 allContents.prune();
156:                         }
157:                 });
158:
159:                 // Generate new DMRs, replace the legacy ones in place, and adjust cross references
160:•                for (final VDomainModelReference legacyDmr : legacyDmrs) {
161:                         final List<VDomainModelReferenceSegment> segments = segmentGenerator.generateSegments(legacyDmr);
162:                         final VDomainModelReference newDmr = VViewFactory.eINSTANCE.createDomainModelReference();
163:                         newDmr.getSegments().addAll(segments);
164:
165:                         final Map<VDomainModelReference, VDomainModelReference> crossRefReplacements = new HashMap<>();
166:                         crossRefReplacements.put(legacyDmr, newDmr);
167:
168:                         // If the legacy dmr is a table dmr, we need to make sure references to columns (e.g. in read only configs)
169:                         // are migrated. This is not automatically done because we need to skip DMRs contained in other DMRs in the
170:                         // initial legacy DMR collection.
171:•                        if (legacyDmr instanceof VTableDomainModelReference) {
172:                                 final EList<VDomainModelReference> columnDmrs = VTableDomainModelReference.class.cast(legacyDmr)
173:                                         .getColumnDomainModelReferences();
174:                                 final EList<VDomainModelReference> childDmrs = MultiSegmentUtil.getMultiSegment(newDmr)
175:                                         .map(VMultiDomainModelReferenceSegment::getChildDomainModelReferences)
176:                                         .orElseGet(BasicEList::new);
177:•                                if (columnDmrs.size() != childDmrs.size()) {
178:                                         throw new DmrToSegmentsMigrationException(
179:                                                 "There was a different number of legacy column DMRs and generated child DMRs for table DMR {0}.", //$NON-NLS-1$
180:                                                 legacyDmr);
181:                                 }
182:•                                for (int i = 0; i < columnDmrs.size(); i++) {
183:                                         crossRefReplacements.put(columnDmrs.get(i), childDmrs.get(i));
184:                                 }
185:                         }
186:
187:•                        for (final PreReplaceProcessor processor : preReplaceProcessors) {
188:                                 processor.process(legacyDmr, newDmr);
189:                         }
190:
191:                         // Replace legacy dmr with new dmr and then update all cross references to the legacy dmr or its child dmrs
192:                         // (in case of a table dmr)
193:                         EcoreUtil.replace(legacyDmr, newDmr);
194:                         final Map<EObject, Collection<Setting>> usageMap = EcoreUtil.UsageCrossReferencer
195:                                 .findAll(crossRefReplacements.keySet(), resource);
196:                         usageMap.forEach((old, usages) -> {
197:                                 usages.forEach(setting -> {
198:                                         final VDomainModelReference replacement = crossRefReplacements.get(old);
199:                                         EcoreUtil.replace(setting, old, replacement);
200:                                 });
201:                         });
202:
203:                 }
204:         }
205:
206:         /**
207:          * Checks whether the given EObject is a legacy domain model reference. Legacy DMRs are all EObjects that are of a
208:          * subtype of DomainModelReference but are not of type DomainModelReference itself
209:          *
210:          * @param eObject The {@link EObject} to check
211:          * @return true if the given EObject is a legacy DMR
212:          */
213:         private boolean isLegacyDmr(final EObject eObject) {
214:•                return VViewPackage.Literals.DOMAIN_MODEL_REFERENCE.isSuperTypeOf(eObject.eClass())
215:•                        && !(VViewPackage.Literals.DOMAIN_MODEL_REFERENCE == eObject.eClass());
216:         }
217:
218:         private Resource loadResource(URI resourceUri) throws IOException {
219:                 final ResourceSetImpl resourceSet = new ResourceSetImpl();
220:                 resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
221:                         Resource.Factory.Registry.DEFAULT_EXTENSION, new VViewResourceFactoryImpl());
222:                 final Resource resource = resourceSet.createResource(resourceUri);
223:                 resource.load(null);
224:                 return resource;
225:         }
226: }