Skip to content

Package: EMFFormsStructuralChangeTesterImpl

EMFFormsStructuralChangeTesterImpl

nameinstructionbranchcomplexitylinemethod
EMFFormsStructuralChangeTesterImpl()
M: 0 C: 13
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
addStructuralChangeSegmentTester(StructuralChangeSegmentTester)
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%
addStructuralChangeTesterInternal(StructuralChangeTesterInternal)
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%
isStructureChanged(VDomainModelReference, EObject, ModelChangeNotification)
M: 0 C: 31
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
lambda$0(VDomainModelReferenceSegment, StructuralChangeSegmentTester)
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%
lambda$1(VDomainModelReference, StructuralChangeTesterInternal)
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%
removeStructuralChangeSegmentTester(StructuralChangeSegmentTester)
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%
removeStructuralChangeTesterInternal(StructuralChangeTesterInternal)
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%
setEMFFormsSegmentResolver(EMFFormsSegmentResolver)
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%
static {...}
M: 0 C: 17
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 9
100%
M: 0 C: 1
100%
testOnDmr(VDomainModelReference, EObject, ModelChangeNotification)
M: 0 C: 34
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
testOnSegments(VDomainModelReference, EObject, ModelChangeNotification)
M: 21 C: 78
79%
M: 3 C: 7
70%
M: 3 C: 3
50%
M: 4 C: 20
83%
M: 0 C: 1
100%

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: * Lucas Koehler - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emfforms.internal.core.services.structuralchange;
15:
16: import java.util.LinkedHashSet;
17: import java.util.Set;
18:
19: import org.eclipse.core.runtime.IStatus;
20: import org.eclipse.emf.common.util.EList;
21: import org.eclipse.emf.ecore.EAttribute;
22: import org.eclipse.emf.ecore.EObject;
23: import org.eclipse.emf.ecore.EReference;
24: import org.eclipse.emf.ecore.EStructuralFeature.Setting;
25: import org.eclipse.emf.ecp.view.spi.model.ModelChangeNotification;
26: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
27: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReferenceSegment;
28: import org.eclipse.emfforms.common.RankingHelper;
29: import org.eclipse.emfforms.spi.common.report.AbstractReport;
30: import org.eclipse.emfforms.spi.common.report.ReportService;
31: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
32: import org.eclipse.emfforms.spi.core.services.databinding.emf.EMFFormsSegmentResolver;
33: import org.eclipse.emfforms.spi.core.services.structuralchange.EMFFormsStructuralChangeTester;
34: import org.eclipse.emfforms.spi.core.services.structuralchange.StructuralChangeSegmentTester;
35: import org.eclipse.emfforms.spi.core.services.structuralchange.StructuralChangeTesterInternal;
36: import org.osgi.service.component.annotations.Component;
37: import org.osgi.service.component.annotations.Reference;
38: import org.osgi.service.component.annotations.ReferenceCardinality;
39: import org.osgi.service.component.annotations.ReferencePolicy;
40:
41: /**
42: * Implementation of {@link EMFFormsStructuralChangeTester}.
43: *
44: * @author Lucas Koehler
45: *
46: */
47: @Component(name = "EMFFormsStructuralChangeTesterImpl")
48: public class EMFFormsStructuralChangeTesterImpl implements EMFFormsStructuralChangeTester {
49:
50:         private ReportService reportService;
51:         private final Set<StructuralChangeTesterInternal> dmrChangeTesters = new LinkedHashSet<StructuralChangeTesterInternal>();
52:         private final Set<StructuralChangeSegmentTester> segmentChangeTesters = new LinkedHashSet<>();
53:         private EMFFormsSegmentResolver segmentResolver;
54:
55:         private static final RankingHelper<StructuralChangeTesterInternal> DMR_RANKING_HELPER = //
56:                 new RankingHelper<StructuralChangeTesterInternal>(
57:                         StructuralChangeTesterInternal.class,
58:                         StructuralChangeTesterInternal.NOT_APPLICABLE,
59:                         StructuralChangeTesterInternal.NOT_APPLICABLE);
60:
61:         private static final RankingHelper<StructuralChangeSegmentTester> SEGMENTS_RANKING_HELPER = //
62:                 new RankingHelper<>(
63:                         StructuralChangeSegmentTester.class, StructuralChangeSegmentTester.NOT_APPLICABLE,
64:                         StructuralChangeSegmentTester.NOT_APPLICABLE);
65:
66:         /**
67:          * Sets the {@link ReportService}.
68:          *
69:          * @param reportService The {@link ReportService}
70:          */
71:         @Reference(unbind = "-")
72:         protected void setReportService(ReportService reportService) {
73:                 this.reportService = reportService;
74:         }
75:
76:         /**
77:          * Called by the framework to add a {@link StructuralChangeTesterInternal}.
78:          *
79:          * @param structuralChangeTester The {@link StructuralChangeTesterInternal} to add
80:          */
81:         @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
82:         protected void addStructuralChangeTesterInternal(StructuralChangeTesterInternal structuralChangeTester) {
83:                 dmrChangeTesters.add(structuralChangeTester);
84:         }
85:
86:         /**
87:          * Called by the framework to remove a {@link StructuralChangeTesterInternal}.
88:          *
89:          * @param structuralChangeTester The {@link StructuralChangeTesterInternal} to remove
90:          */
91:         protected void removeStructuralChangeTesterInternal(StructuralChangeTesterInternal structuralChangeTester) {
92:                 dmrChangeTesters.remove(structuralChangeTester);
93:         }
94:
95:         /**
96:          * Called by the framework to add a {@link StructuralChangeSegmentTester}.
97:          *
98:          * @param segmentChangeTester The {@link StructuralChangeSegmentTester} to add
99:          */
100:         @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
101:         protected void addStructuralChangeSegmentTester(StructuralChangeSegmentTester segmentChangeTester) {
102:                 segmentChangeTesters.add(segmentChangeTester);
103:         }
104:
105:         /**
106:          * Called by the framework to remove a {@link StructuralChangeSegmentTester}.
107:          *
108:          * @param segmentChangeTester The {@link StructuralChangeSegmentTester} to remove
109:          */
110:         protected void removeStructuralChangeSegmentTester(StructuralChangeSegmentTester segmentChangeTester) {
111:                 segmentChangeTesters.remove(segmentChangeTester);
112:         }
113:
114:         /**
115:          * Sets the {@link EMFFormsSegmentResolver}.
116:          *
117:          * @param segmentResolver The {@link EMFFormsSegmentResolver}
118:          */
119:         @Reference(unbind = "-")
120:         protected void setEMFFormsSegmentResolver(EMFFormsSegmentResolver segmentResolver) {
121:                 this.segmentResolver = segmentResolver;
122:         }
123:
124:         @Override
125:         public boolean isStructureChanged(final VDomainModelReference reference, final EObject domainRootObject,
126:                 ModelChangeNotification notification) {
127:
128:                 // Changed EAttributes or only touched EReferences do not constitute structural changes
129:•                if (EAttribute.class.isInstance(notification.getStructuralFeature())) {
130:                         return false;
131:                 }
132:•                if (notification.getRawNotification().isTouch()) {
133:                         return false;
134:                 }
135:
136:                 final EList<VDomainModelReferenceSegment> segments = reference.getSegments();
137:•                if (segments.isEmpty()) {
138:                         // fall back to DMR based structural change testing
139:                         return testOnDmr(reference, domainRootObject, notification);
140:                 }
141:
142:                 return testOnSegments(reference, domainRootObject, notification);
143:         }
144:
145:         /**
146:          * Test for structural changes based on the {@link VDomainModelReference VDomainModelReference's} segments.
147:          *
148:          * @param reference The {@link VDomainModelReference} whose segments are tested
149:          * @param domainRootObject The root domain object to resolve and test the segments against
150:          * @param notification The {@link ModelChangeNotification} triggering the structural change test
151:          * @return <code>true</code> if the structure has changed, <code>false</code> otherwise
152:          */
153:         private boolean testOnSegments(final VDomainModelReference reference, final EObject domainRootObject,
154:                 ModelChangeNotification notification) {
155:                 final EList<VDomainModelReferenceSegment> segments = reference.getSegments();
156:                 boolean relevantChange = false;
157:                 EObject currentDomainObject = domainRootObject;
158:•                for (int i = 0; i < segments.size(); i++) {
159:                         final VDomainModelReferenceSegment segment = segments.get(i);
160:                         final StructuralChangeSegmentTester segmentTester = SEGMENTS_RANKING_HELPER
161:                                 .getHighestRankingElement(segmentChangeTesters, tester -> tester.isApplicable(segment));
162:•                        if (segmentTester == null) {
163:                                 reportService.report(new AbstractReport(String.format(
164:                                         "Structural changes of the DMR: %1$s could not be analyzed because no suitable StructuralChangeSegmentTester was available for segment %2$s.", //$NON-NLS-1$
165:                                         reference, segment), IStatus.WARNING));
166:                                 return false;
167:                         }
168:
169:                         final Setting setting;
170:                         try {
171:                                 setting = segmentResolver.resolveSegment(segment, currentDomainObject);
172:                         } catch (final DatabindingFailedException ex) {
173:                                 reportService.report(new AbstractReport(ex,
174:                                         "Could not finish structural change calculation.")); //$NON-NLS-1$
175:                                 break;
176:                         }
177:
178:                         relevantChange |= segmentTester.isStructureChanged(segment, currentDomainObject, notification);
179:
180:•                        if (relevantChange || !EReference.class.isInstance(setting.getEStructuralFeature())) {
181:                                 return relevantChange;
182:                         }
183:
184:                         // Do not resolve the last setting and convert its value because the last value is not needed and might be
185:                         // an EList because the last segment may represent a multi reference
186:•                        if (i == segments.size() - 1) {
187:                                 break;
188:                         }
189:                         // The value of the Setting is an EObject because its EStructuralFeature is an EReference.
190:                         currentDomainObject = (EObject) setting.get(true);
191:                 }
192:
193:                 return relevantChange;
194:         }
195:
196:         /**
197:          * Test for structural changes based on the whole {@link VDomainModelReference}.
198:          *
199:          * @param reference The {@link VDomainModelReference} to test
200:          * @param domainRootObject The root domain object to resolve and test the DMR against
201:          * @param notification The {@link ModelChangeNotification} triggering the structural change test
202:          * @return <code>true</code> if the structure has changed, <code>false</code> otherwise
203:          */
204:         private boolean testOnDmr(final VDomainModelReference reference, final EObject domainRootObject,
205:                 ModelChangeNotification notification) {
206:                 final StructuralChangeTesterInternal bestTester = DMR_RANKING_HELPER.getHighestRankingElement(
207:                         dmrChangeTesters, tester -> tester.isApplicable(reference));
208:
209:•                if (bestTester == null) {
210:                         reportService.report(new AbstractReport("Structural changes of the DMR: " + reference //$NON-NLS-1$
211:                                 + "could not be analyzed because no suitable StructuralChangeTesterInternal was available.", //$NON-NLS-1$
212:                                 IStatus.WARNING));
213:                         return false;
214:                 }
215:                 return bestTester.isStructureChanged(reference, domainRootObject, notification);
216:         }
217:
218: }