Skip to content

Package: RuleConditionDmrUtil

RuleConditionDmrUtil

nameinstructionbranchcomplexitylinemethod
getDmrRootEClass(EMFFormsDatabindingEMF, ReportService, EObject)
M: 0 C: 90
100%
M: 0 C: 12
100%
M: 0 C: 7
100%
M: 0 C: 22
100%
M: 0 C: 1
100%
getDmrRootObject(EMFFormsDatabindingEMF, ReportService, EObject, EObject)
M: 0 C: 126
100%
M: 0 C: 14
100%
M: 0 C: 8
100%
M: 0 C: 29
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.emf.ecp.view.spi.rule;
15:
16: import java.util.Collection;
17: import java.util.Collections;
18: import java.util.LinkedList;
19: import java.util.List;
20: import java.util.Optional;
21:
22: import org.eclipse.core.databinding.property.value.IValueProperty;
23: import org.eclipse.emf.ecore.EClass;
24: import org.eclipse.emf.ecore.EObject;
25: import org.eclipse.emf.ecore.EReference;
26: import org.eclipse.emf.ecore.EStructuralFeature.Setting;
27: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
28: import org.eclipse.emf.ecp.view.spi.model.VView;
29: import org.eclipse.emf.ecp.view.spi.rule.model.Condition;
30: import org.eclipse.emf.ecp.view.spi.rule.model.IterateCondition;
31: import org.eclipse.emfforms.spi.common.report.AbstractReport;
32: import org.eclipse.emfforms.spi.common.report.ReportService;
33: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
34: import org.eclipse.emfforms.spi.core.services.databinding.emf.EMFFormsDatabindingEMF;
35:
36: /**
37: * Utility class for common functionality needed for rule condition DMR tooling.
38: *
39: * @author Lucas Koehler
40: * @since 1.21
41: *
42: */
43: public final class RuleConditionDmrUtil {
44:
45:         private RuleConditionDmrUtil() {
46:                 // do not instantiate utility class
47:         }
48:
49:         /**
50:          * Get the root EClass for the {@link VDomainModelReference} to create. If the rule {@link Condition} is contained
51:          * in another Condition with a DMR, the root EClass is determined by resolving the container Condition(s) down from
52:          * the domain root.
53:          * Otherwise, the root EClass is the EClass of the domain root.
54:          *
55:          * @param databinding The {@link EMFFormsDatabindingEMF} used to resolve DMRs
56:          * @param reportService The {@link ReportService} used to report databinding failures
57:          * @param owner The condition containing the the DMR whose root EClass is needed
58:          * @return The root EClass or nothing if it could not be determined
59:          */
60:         public static Optional<EClass> getDmrRootEClass(EMFFormsDatabindingEMF databinding, ReportService reportService,
61:                 EObject owner) {
62:                 // We do not need to check the owner because the owner's dmr is the one we want to create
63:                 EObject testObject = owner.eContainer();
64:                 final List<IterateCondition> iterateConditions = new LinkedList<>();
65:
66:                 // Walk up the containment hierarchy up to the VView. Remember IterateConditions on the way
67:•                while (!VView.class.isInstance(testObject) && testObject != null) {
68:•                        if (testObject instanceof IterateCondition) {
69:                                 iterateConditions.add((IterateCondition) testObject);
70:                         }
71:                         testObject = testObject.eContainer();
72:                 }
73:
74:•                if (testObject instanceof VView) {
75:                         // Reverse because we need to resolve top to bottom but added the elements bottom to top
76:                         Collections.reverse(iterateConditions);
77:                         EClass currentRoot = VView.class.cast(testObject).getRootEClass();
78:                         // Resolve the nested iterate conditions from top (= view root EClass) to bottom
79:•                        for (final IterateCondition condition : iterateConditions) {
80:                                 final VDomainModelReference iterateDmr = condition.getItemReference();
81:                                 try {
82:                                         final IValueProperty<?, ?> valueProperty = databinding.getValueProperty(iterateDmr, currentRoot);
83:•                                        if (valueProperty.getValueType() instanceof EReference) {
84:                                                 currentRoot = EReference.class.cast(valueProperty.getValueType()).getEReferenceType();
85:                                         } else {
86:                                                 return Optional.empty();
87:                                         }
88:                                 } catch (final DatabindingFailedException ex) {
89:                                         reportService.report(
90:                                                 new AbstractReport(ex, "Could not determine root EClass for the DMR of Condition {0}.", owner)); //$NON-NLS-1$
91:                                         return Optional.empty();
92:                                 }
93:                         }
94:                         return Optional.of(currentRoot);
95:                 }
96:                 return Optional.empty();
97:         }
98:
99:         /**
100:          * Get the root EObjects for the owner's domain model reference. IF the owner is not nested in another Condition,
101:          * the result list simply contains the given <code>domainRoot</code>. IF the owner is nested in one or more
102:          * {@link IterateCondition IterateConditions}, the iterate conditions' dmrs are resolved and all possible root
103:          * objects collected and returned.
104:          *
105:          * @param databinding The {@link EMFFormsDatabindingEMF} used to resolve dmrs
106:          * @param reportService The {@link ReportService} to report databinding errors
107:          * @param domainRoot The domain root (usually the view model context's domain model)
108:          * @param owner The eObject containing the dmr (usually a {@link Condition})
109:          * @return the roots of the owner's dmr. If the owner condition is not nested, the result list contains only the
110:          * given domain root. May return an empty list if no root could be determined but never returns
111:          * <code>null</code>
112:          */
113:         @SuppressWarnings("unchecked")
114:         public static List<EObject> getDmrRootObject(EMFFormsDatabindingEMF databinding,
115:                 ReportService reportService, EObject domainRoot, EObject owner) {
116:
117:                 // We do not need to check the owner because the owner's dmr is the one we want to create
118:                 EObject testObject = owner.eContainer();
119:                 final List<IterateCondition> iterateConditions = new LinkedList<>();
120:
121:                 // Walk up the containment hierarchy up to the VView. Remember IterateConditions on the way
122:•                while (!VView.class.isInstance(testObject) && testObject != null) {
123:•                        if (testObject instanceof IterateCondition) {
124:                                 iterateConditions.add((IterateCondition) testObject);
125:                         }
126:                         testObject = testObject.eContainer();
127:                 }
128:
129:                 Collections.reverse(iterateConditions);
130:                 List<EObject> currentRoots = Collections.singletonList(domainRoot);
131:
132:                 // Resolve the nested iterate conditions from top to bottom
133:                 // Thereby, an iterate condition usually points to a multi reference. The next dmr is resolved against each of
134:                 // the reference's objects.
135:•                for (final IterateCondition condition : iterateConditions) {
136:                         final List<EObject> newRoots = new LinkedList<EObject>();
137:•                        for (final EObject currentRoot : currentRoots) {
138:                                 final VDomainModelReference iterateDmr = condition.getItemReference();
139:                                 try {
140:                                         final Setting setting = databinding.getSetting(iterateDmr, currentRoot);
141:•                                        if (setting.getEStructuralFeature() instanceof EReference) {
142:•                                                if (setting.getEStructuralFeature().isMany()) {
143:                                                         newRoots.addAll((Collection<EObject>) setting.get(true));
144:                                                 } else {
145:                                                         newRoots.add((EObject) setting.get(true));
146:                                                 }
147:                                         } else {
148:                                                 reportService.report(new AbstractReport(
149:                                                         "Could not determine root EObjects for the DMR of Condition {0} because the DMR {1} of a parent condition does not end in an EReference", //$NON-NLS-1$
150:                                                         owner, iterateDmr));
151:                                                 return Collections.emptyList();
152:                                         }
153:                                 } catch (final DatabindingFailedException ex) {
154:                                         reportService.report(new AbstractReport(ex,
155:                                                 "Could not determine root EObjects for the DMR of Condition {0}.", owner)); //$NON-NLS-1$
156:                                         return Collections.emptyList();
157:                                 }
158:                         }
159:                         currentRoots = newRoots;
160:                 }
161:
162:                 return currentRoots;
163:
164:         }
165: }