Skip to content

Package: RuleService

RuleService

nameinstructionbranchcomplexitylinemethod
RuleService()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
canOverrideParent(boolean, boolean)
M: 0 C: 12
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
checkDryRun(Map)
M: 12 C: 91
88%
M: 6 C: 14
70%
M: 5 C: 6
55%
M: 3 C: 23
88%
M: 0 C: 1
100%
childContextAdded(VElement, EMFFormsViewContext)
M: 0 C: 1
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
childContextDisposed(EMFFormsViewContext)
M: 0 C: 1
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
contextDispose()
M: 0 C: 1
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
contextInitialised()
M: 5 C: 87
95%
M: 1 C: 7
88%
M: 1 C: 4
80%
M: 1 C: 16
94%
M: 0 C: 1
100%
dispose()
M: 0 C: 21
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
evalAffectedRenderables(RuleRegistry, Class, UniqueSetting)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
evalAffectedRenderables(RuleRegistry, Class, UniqueSetting, Map)
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
evalAffectedRenderables(RuleRegistry, Class, UniqueSetting, boolean, Map)
M: 4 C: 102
96%
M: 2 C: 18
90%
M: 2 C: 9
82%
M: 2 C: 24
92%
M: 0 C: 1
100%
evalEnable(UniqueSetting)
M: 0 C: 28
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
evalShow(UniqueSetting)
M: 0 C: 76
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 16
100%
M: 0 C: 1
100%
getDisabledRenderables(Map, UniqueSetting)
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getHiddenRenderables(Map, UniqueSetting)
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getPriority()
M: 0 C: 2
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getRule(Class, VElement)
M: 0 C: 25
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
getRules(VElement)
M: 0 C: 37
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 7
100%
M: 0 C: 1
100%
init(RuleRegistry, Class, EObject, EObject)
M: 0 C: 35
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
instantiate(ViewModelContext)
M: 0 C: 25
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
isDisableRule(Rule)
M: 0 C: 11
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
isEnableRule(Rule)
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%
isHideRule(Rule)
M: 0 C: 11
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
isOpposite(Rule)
M: 0 C: 10
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
isShowRule(Rule)
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%
propagateChanges(boolean, boolean, Rule, VElement)
M: 0 C: 50
100%
M: 1 C: 27
96%
M: 1 C: 14
93%
M: 0 C: 12
100%
M: 0 C: 1
100%
register(RuleRegistry, Class, EObject, EObject)
M: 0 C: 28
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
resetToEnabled(VElement)
M: 0 C: 34
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
resetToVisible(VElement)
M: 0 C: 34
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
ruleApplies(Rule, Class)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
updateStateMap(Map, VElement, boolean, boolean, Class)
M: 6 C: 119
95%
M: 4 C: 28
88%
M: 3 C: 14
82%
M: 0 C: 20
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2013 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: * Johannes Faltermeier - registry setting based instead of feature based
14: ******************************************************************************/
15: package org.eclipse.emf.ecp.view.internal.rule;
16:
17: import java.util.Arrays;
18: import java.util.Collection;
19: import java.util.Collections;
20: import java.util.HashMap;
21: import java.util.HashSet;
22: import java.util.LinkedHashMap;
23: import java.util.LinkedHashSet;
24: import java.util.List;
25: import java.util.Map;
26: import java.util.Set;
27:
28: import org.eclipse.emf.common.notify.Notifier;
29: import org.eclipse.emf.common.util.TreeIterator;
30: import org.eclipse.emf.ecore.EClass;
31: import org.eclipse.emf.ecore.EObject;
32: import org.eclipse.emf.ecore.EStructuralFeature;
33: import org.eclipse.emf.ecore.EStructuralFeature.Setting;
34: import org.eclipse.emf.ecore.InternalEObject;
35: import org.eclipse.emf.ecp.common.spi.UniqueSetting;
36: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
37: import org.eclipse.emf.ecp.view.spi.context.ViewModelService;
38: import org.eclipse.emf.ecp.view.spi.model.ModelChangeAddRemoveListener;
39: import org.eclipse.emf.ecp.view.spi.model.ModelChangeListener;
40: import org.eclipse.emf.ecp.view.spi.model.ModelChangeNotification;
41: import org.eclipse.emf.ecp.view.spi.model.VAttachment;
42: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
43: import org.eclipse.emf.ecp.view.spi.model.VElement;
44: import org.eclipse.emf.ecp.view.spi.model.VFeaturePathDomainModelReference;
45: import org.eclipse.emf.ecp.view.spi.model.VViewPackage;
46: import org.eclipse.emf.ecp.view.spi.rule.model.Condition;
47: import org.eclipse.emf.ecp.view.spi.rule.model.EnableRule;
48: import org.eclipse.emf.ecp.view.spi.rule.model.LeafCondition;
49: import org.eclipse.emf.ecp.view.spi.rule.model.Rule;
50: import org.eclipse.emf.ecp.view.spi.rule.model.ShowRule;
51: import org.eclipse.emfforms.spi.core.services.view.EMFFormsContextListener;
52: import org.eclipse.emfforms.spi.core.services.view.EMFFormsViewContext;
53:
54: /**
55: * Rule service that, once instantiated, maintains and synchronizes
56: * the state of a rule with its {@link VElement}.
57: *
58: * @author emueller
59: * @author jfaltermeier
60: */
61: public class RuleService implements ViewModelService, EMFFormsContextListener {
62:
63:         private static final String DOMAIN_MODEL_NULL_EXCEPTION = "Domain model must not be null."; //$NON-NLS-1$
64:         private static final String VIEW_MODEL_NULL_EXCEPTION = "View model must not be null."; //$NON-NLS-1$
65:         private ViewModelContext context;
66:         private ModelChangeListener domainChangeListener;
67:         private ModelChangeAddRemoveListener viewChangeListener;
68:
69:         private RuleRegistry<EnableRule> enableRuleRegistry;
70:         private RuleRegistry<ShowRule> showRuleRegistry;
71:         private ConditionServiceManager conditionServiceManager;
72:
73:         /**
74:          * Instantiates the rule service.
75:          */
76:         public RuleService() {
77:         }
78:
79:         /**
80:          * {@inheritDoc}
81:          *
82:          * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#instantiate(org.eclipse.emf.ecp.view.spi.context.ViewModelContext)
83:          */
84:         @Override
85:         public void instantiate(final ViewModelContext context) {
86:                 this.context = context;
87:                 enableRuleRegistry = new RuleRegistry<EnableRule>(context);
88:                 showRuleRegistry = new RuleRegistry<ShowRule>(context);
89:                 context.registerEMFFormsContextListener(this);
90:                 conditionServiceManager = context.getService(ConditionServiceManager.class);
91:         }
92:
93:         private void resetToVisible(VElement renderable) {
94:•                if (renderable == null) {
95:                         return;
96:                 }
97:                 final Map<VElement, Boolean> maps = new LinkedHashMap<VElement, Boolean>();
98:                 updateStateMap(maps, renderable, false, true, ShowRule.class);
99:•                for (final VElement vElement : maps.keySet()) {
100:                         vElement.setVisible(maps.get(vElement));
101:                 }
102:         }
103:
104:         private void resetToEnabled(VElement renderable) {
105:•                if (renderable == null) {
106:                         return;
107:                 }
108:                 final Map<VElement, Boolean> maps = new LinkedHashMap<VElement, Boolean>();
109:                 updateStateMap(maps, renderable, false, true, EnableRule.class);
110:•                for (final VElement vElement : maps.keySet()) {
111:                         vElement.setEnabled(maps.get(vElement));
112:                 }
113:         }
114:
115:         private static Collection<Rule> getRules(VElement renderable) {
116:                 final Map<Class<? extends Rule>, Rule> rules = new HashMap<Class<? extends Rule>, Rule>();
117:•                for (final VAttachment attachment : renderable.getAttachments()) {
118:•                        if (Rule.class.isInstance(attachment)) {
119:                                 final Rule rule = (Rule) attachment;
120:•                                if (!rules.containsKey(rule.getClass())) {
121:                                         rules.put(rule.getClass(), rule);
122:                                 }
123:                         }
124:                 }
125:                 return rules.values();
126:         }
127:
128:         private static <T extends Rule> T getRule(Class<T> ruleType, VElement renderable) {
129:                 final Collection<Rule> rules = getRules(renderable);
130:•                for (final Rule rule : rules) {
131:•                        if (ruleType.isInstance(rule)) {
132:                                 return ruleType.cast(rule);
133:                         }
134:                 }
135:                 return null;
136:         }
137:
138:         private <T extends Rule> void updateStateMap(Map<VElement, Boolean> stateMap, VElement renderable,
139:                 boolean isOpposite, boolean evalResult, Class<T> ruleType) {
140:
141:•                if (!stateMap.containsKey(renderable)) {
142:                         final Collection<Rule> rules = getRules(renderable);
143:                         boolean didUpdate = false;
144:•                        for (final Rule rule : rules) {
145:•                                if (rule != null && ruleApplies(rule, ruleType)) {
146:                                         final Condition condition = rule.getCondition();
147:•                                        if (condition != null && canOverrideParent(evalResult, isOpposite)) {
148:                                                 final boolean evaluate = conditionServiceManager.evaluate(condition, context.getDomainModel());
149:•                                                stateMap.put(renderable, isOpposite(rule) ? !evaluate : evaluate);
150:                                                 didUpdate = true;
151:                                         }
152:                                 }
153:                         }
154:                         // use result of parent
155:•                        if (!didUpdate) {
156:•                                stateMap.put(renderable, isOpposite ? !evalResult : evalResult);
157:                         }
158:                 } else {
159:                         final Boolean currentState = stateMap.get(renderable).booleanValue();
160:•                        if (currentState) {
161:•                                stateMap.put(renderable, isOpposite ? !evalResult : evalResult);
162:                         }
163:                 }
164:
165:•                for (final EObject childContent : renderable.eContents()) {
166:•                        if (childContent instanceof VElement) {
167:                                 updateStateMap(stateMap, (VElement) childContent, isOpposite, evalResult, ruleType);
168:                         }
169:                 }
170:         }
171:
172:         private static boolean canOverrideParent(boolean evalResult, boolean isOpposite) {
173:•                return evalResult && !isOpposite || !evalResult && isOpposite;
174:         }
175:
176:         private static <T extends Rule> boolean ruleApplies(Rule rule, Class<T> ruleType) {
177:                 return Arrays.asList(rule.getClass().getInterfaces()).contains(ruleType);
178:         }
179:
180:         private static boolean isOpposite(Rule rule) {
181:•                return isHideRule(rule) || isDisableRule(rule);
182:         }
183:
184:         private <T extends Rule> Map<VElement, Boolean> evalAffectedRenderables(RuleRegistry<T> registry,
185:                 Class<T> ruleType, UniqueSetting setting, boolean isDryRun, Map<Setting, Object> possibleValues) {
186:
187:                 final Map<VElement, Boolean> map = new LinkedHashMap<VElement, Boolean>();
188:
189:•                for (final Map.Entry<T, VElement> ruleAndRenderable : registry.getAffectedRenderables(
190:                         setting).entrySet()) {
191:
192:                         final Rule rule = ruleAndRenderable.getKey();
193:
194:                         final VElement renderable = ruleAndRenderable.getValue();
195:                         // whether the value changed at all, if newValue has been provided
196:                         boolean hasChanged = true;
197:
198:•                        if (!ruleType.isInstance(rule)) {
199:                                 continue;
200:                         }
201:
202:•                        if (isDryRun) {
203:
204:                                 hasChanged = checkDryRun(possibleValues);
205:
206:                         }
207:
208:                         boolean result = false;
209:                         boolean updateMap = true;
210:•                        if (rule.getCondition() == null) {
211:                                 result = true;
212:•                        } else if (isDryRun && hasChanged) {
213:                                 result = conditionServiceManager.evaluateChangedValues(rule.getCondition(), context.getDomainModel(),
214:                                         possibleValues);
215:•                        } else if (!isDryRun) {
216:                                 result = conditionServiceManager.evaluate(rule.getCondition(), context.getDomainModel());
217:                         } else {
218:                                 updateMap = false;
219:                         }
220:•                        final boolean isOposite = isDisableRule(rule) || isHideRule(rule);
221:                         updateMap &= propagateChanges(result, isOposite, rule, renderable);
222:•                        if (updateMap) {
223:                                 updateStateMap(map, renderable, isOposite, result, ruleType);
224:                         }
225:                 }
226:
227:                 return map;
228:         }
229:
230:         private static boolean propagateChanges(boolean result, boolean isOposite, Rule rule, VElement renderable) {
231:•                if (result && !isOposite || isOposite && !result) {
232:•                        if (ShowRule.class.isInstance(rule)) {
233:•                                if (isOposite && result != renderable.isVisible()) {
234:                                         return false;
235:•                                } else if (!isOposite && result == renderable.isVisible()) {
236:                                         return false;
237:                                 }
238:•                        } else if (EnableRule.class.isInstance(rule)) {
239:•                                if (isOposite && result != renderable.isEnabled()) {
240:                                         return false;
241:•                                } else if (!isOposite && result == renderable.isEnabled()) {
242:                                         return false;
243:                                 }
244:                         }
245:                 }
246:                 return true;
247:         }
248:
249:         private static boolean checkDryRun(Map<Setting, Object> possibleValues) {
250:                 boolean hasChanged = true;
251:•                for (final Setting setting : possibleValues.keySet()) {
252:                         final EObject parent = setting.getEObject();
253:                         final EStructuralFeature feature = setting.getEStructuralFeature();
254:                         final EClass attributeClass = feature.getEContainingClass();
255:•                        if (!attributeClass.isInstance(parent)) {
256:                                 continue;
257:                         }
258:                         final Object actualValue = parent.eGet(feature);
259:                         final Object newValue = possibleValues.get(setting);
260:•                        if (!feature.isMany()) {
261:•                                if (newValue == null) {
262:•                                        hasChanged &= actualValue == null;
263:                                 } else {
264:•                                        hasChanged &= !newValue.equals(actualValue);
265:                                 }
266:                         } else {
267:                                 // EMF API
268:                                 @SuppressWarnings("unchecked")
269:                                 final List<Object> objects = (List<Object>) actualValue;
270:                                 @SuppressWarnings("unchecked")
271:                                 final List<Object> newValues = (List<Object>) newValue;
272:•                                if (objects.size() == newValues.size()) {
273:                                         boolean sameEntries = true;
274:•                                        for (final Object newValueListEntry : newValues) {
275:•                                                if (!objects.contains(newValueListEntry)) {
276:                                                         sameEntries = false;
277:                                                 }
278:                                         }
279:•                                        hasChanged &= !sameEntries;
280:                                 } else {
281:                                         hasChanged = true;
282:                                 }
283:                         }
284:                 }
285:                 return hasChanged;
286:         }
287:
288:         private <T extends Rule> Map<VElement, Boolean> evalAffectedRenderables(RuleRegistry<T> registry,
289:                 Class<T> ruleType, UniqueSetting setting, Map<Setting, Object> possibleValues) {
290:                 return evalAffectedRenderables(registry, ruleType, setting, true, possibleValues);
291:         }
292:
293:         private <T extends Rule> Map<VElement, Boolean> evalAffectedRenderables(RuleRegistry<T> registry,
294:                 Class<T> ruleType, UniqueSetting setting) {
295:                 final Map<Setting, Object> changedValues = Collections.emptyMap();
296:                 return evalAffectedRenderables(registry, ruleType, setting, false, changedValues);
297:         }
298:
299:         private static boolean isDisableRule(Rule rule) {
300:•                if (isEnableRule(rule)) {
301:                         final EnableRule enableRule = (EnableRule) rule;
302:                         return enableRule.isDisable();
303:                 }
304:
305:                 return false;
306:         }
307:
308:         private static boolean isHideRule(Rule rule) {
309:•                if (isShowRule(rule)) {
310:                         final ShowRule showRule = (ShowRule) rule;
311:                         return showRule.isHide();
312:                 }
313:
314:                 return false;
315:         }
316:
317:         private static boolean isShowRule(Rule rule) {
318:                 return rule instanceof ShowRule;
319:         }
320:
321:         private <T extends Rule> void evalShow(UniqueSetting setting) {
322:
323:                 final Map<VElement, Boolean> visibleMap = evalAffectedRenderables(showRuleRegistry, ShowRule.class,
324:                         setting);
325:                 final Set<VElement> toBeVisible = new LinkedHashSet<VElement>();
326:                 final Set<VElement> toBeInvisible = new LinkedHashSet<VElement>();
327:•                for (final Map.Entry<VElement, Boolean> e : visibleMap.entrySet()) {
328:                         final Boolean isVisible = e.getValue();
329:                         final VElement renderable = e.getKey();
330:•                        if (isVisible) {
331:                                 toBeVisible.add(renderable);
332:                         } else {
333:                                 toBeInvisible.add(renderable);
334:                         }
335:                 }
336:
337:•                for (final VElement vElement : toBeInvisible) {
338:                         vElement.setVisible(false);
339:                 }
340:•                for (final VElement vElement : toBeVisible) {
341:                         vElement.setVisible(true);
342:                 }
343:         }
344:
345:         private <T extends Rule> void evalEnable(UniqueSetting setting) {
346:
347:                 final Map<VElement, Boolean> enabledMap = evalAffectedRenderables(enableRuleRegistry, EnableRule.class,
348:                         setting);
349:
350:•                for (final Map.Entry<VElement, Boolean> e : enabledMap.entrySet()) {
351:                         e.getKey().setEnabled(e.getValue());
352:                 }
353:         }
354:
355:         private <T extends Rule> Set<UniqueSetting> init(RuleRegistry<T> registry, Class<T> ruleType,
356:                 EObject viewModel,
357:                 EObject domainObject) {
358:                 final TreeIterator<EObject> iterator = viewModel.eAllContents();
359:                 final Set<UniqueSetting> relevantSettings = new LinkedHashSet<UniqueSetting>();
360:                 relevantSettings.addAll(register(registry, ruleType, domainObject, viewModel));
361:
362:•                while (iterator.hasNext()) {
363:                         final EObject content = iterator.next();
364:                         relevantSettings.addAll(register(registry, ruleType, domainObject, content));
365:                 }
366:                 return relevantSettings;
367:         }
368:
369:         private <T extends Rule> Set<UniqueSetting> register(RuleRegistry<T> registry, Class<T> ruleType,
370:                 EObject domainObject, final EObject viewModel) {
371:                 final Set<UniqueSetting> result = new HashSet<UniqueSetting>();
372:•                if (viewModel instanceof VElement) {
373:                         final VElement renderable = (VElement) viewModel;
374:                         final T rule = getRule(ruleType, renderable);
375:•                        if (rule != null) {
376:                                 result.addAll(registry.register(renderable, rule, rule.getCondition(), domainObject));
377:                         }
378:                 }
379:                 return result;
380:         }
381:
382:         /**
383:          * Returns all {@link VElement}s, that would we disabled if {@code possibleValues} would be set for the given
384:          * {@code setting}s.
385:          *
386:          * @param possibleValues
387:          * a mapping of settings to their would-be new value
388:          * @param setting the changed setting
389:          * @return the hidden {@link VElement}s and their new state if {@code possibleValues} would be set
390:          */
391:         public Map<VElement, Boolean> getDisabledRenderables(Map<Setting, Object> possibleValues,
392:                 UniqueSetting setting) {
393:
394:                 return evalAffectedRenderables(enableRuleRegistry,
395:                         EnableRule.class, setting, possibleValues);
396:         }
397:
398:         /**
399:          * Returns all {@link VElement}s, that would we hidden if {@code possibleValues} would be set for the given
400:          * {@code setting}s.
401:          *
402:          * @param possibleValues
403:          * a mapping of settings to their would-be new value
404:          * @param setting the setting that was changed
405:          * @return the hidden {@link VElement}s and their new state if {@code possibleValues} would be set
406:          */
407:         public Map<VElement, Boolean> getHiddenRenderables(Map<Setting, Object> possibleValues, UniqueSetting setting) {
408:
409:                 return evalAffectedRenderables(showRuleRegistry,
410:                         ShowRule.class, setting, possibleValues);
411:         }
412:
413:         /**
414:          * Dispose.
415:          */
416:         @Override
417:         public void dispose() {
418:                 // dispose stuff
419:                 context.unregisterEMFFormsContextListener(this);
420:                 context.unregisterDomainChangeListener(domainChangeListener);
421:                 context.unregisterViewChangeListener(viewChangeListener);
422:                 enableRuleRegistry.dispose();
423:                 showRuleRegistry.dispose();
424:         }
425:
426:         private static boolean isEnableRule(Rule rule) {
427:                 return EnableRule.class.isInstance(rule);
428:         }
429:
430:         /**
431:          * {@inheritDoc}
432:          *
433:          * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#getPriority()
434:          */
435:         @Override
436:         public int getPriority() {
437:                 return 1;
438:         }
439:
440:         /**
441:          * Lister of the rule service reacting to view model changes.
442:          */
443:         private final class RuleServiceViewChangeListener implements ModelChangeAddRemoveListener {
444:                 private final ViewModelContext context;
445:
446:                 /**
447:                  * @param context
448:                  */
449:                 private RuleServiceViewChangeListener(ViewModelContext context) {
450:                         this.context = context;
451:                 }
452:
453:                 @Override
454:                 public void notifyChange(ModelChangeNotification notification) {
455:                         if (VFeaturePathDomainModelReference.class.isInstance(notification.getNotifier())) {
456:                                 if (notification.getStructuralFeature() == VViewPackage.eINSTANCE
457:                                         .getDomainModelReference_ChangeListener()) {
458:                                         return;
459:                                 }
460:                                 final VDomainModelReference domainModelReference = VDomainModelReference.class.cast(notification
461:                                         .getNotifier());
462:                                 final EObject eContainer = domainModelReference.eContainer();
463:                                 if (!LeafCondition.class.isInstance(eContainer)) {
464:                                         return;
465:                                 }
466:                                 final Condition condition = Condition.class.cast(eContainer);
467:                                 enableRuleRegistry.removeCondition(condition);
468:                                 showRuleRegistry.removeCondition(condition);
469:                                 EObject parent = condition.eContainer();
470:                                 while (parent != null && !Rule.class.isInstance(parent)) {
471:                                         parent = parent.eContainer();
472:                                 }
473:                                 if (parent == null) {
474:                                         return;
475:                                 }
476:                                 if (!Rule.class.isInstance(parent)) {
477:                                         return;
478:                                 }
479:                                 final Rule rule = Rule.class.cast(parent);
480:                                 final VElement renderable = VElement.class.isInstance(rule.eContainer())
481:                                         ? VElement.class.cast(rule.eContainer())
482:                                         : null;
483:
484:                                 if (renderable == null) {
485:                                         return;
486:                                 }
487:                                 reevaluateRule(condition, rule, renderable);
488:                         }
489:                 }
490:
491:                 private void reevaluateRule(final Condition condition, final Rule rule, final VElement renderable) {
492:                         if (isEnableRule(rule)) {
493:                                 if (enableRuleRegistry.register(renderable, (EnableRule) rule, condition,
494:                                         context.getDomainModel()).isEmpty()) {
495:                                         renderable.setEnabled(true);
496:                                 } else {
497:                                         resetToEnabled(renderable);
498:                                 }
499:                         }
500:                         if (isShowRule(rule)) {
501:                                 if (showRuleRegistry.register(renderable, (ShowRule) rule, condition, context.getDomainModel())
502:                                         .isEmpty()) {
503:                                         renderable.setVisible(true);
504:                                 } else {
505:                                         resetToVisible(renderable);
506:                                 }
507:                         }
508:                 }
509:
510:                 @Override
511:                 public void notifyAdd(Notifier notifier) {
512:                         if (VElement.class.isInstance(notifier)) {
513:                                 register(enableRuleRegistry, EnableRule.class, context.getDomainModel(),
514:                                         VElement.class.cast(notifier));
515:                                 register(showRuleRegistry, ShowRule.class, context.getDomainModel(), VElement.class.cast(notifier));
516:
517:                                 final Collection<Rule> rules = getRules(VElement.class.cast(notifier));
518:                                 if (rules.isEmpty()) {
519:                                         return;
520:                                 }
521:                                 for (final Rule rule : rules) {
522:                                         final Set<UniqueSetting> settings = conditionServiceManager.getConditionSettings(
523:                                                 rule.getCondition(),
524:                                                 context.getDomainModel());
525:                                         for (final UniqueSetting setting : settings) {
526:                                                 evalEnable(setting);
527:                                                 evalShow(setting);
528:                                         }
529:                                 }
530:
531:                         } else if (EnableRule.class.isInstance(notifier)) {
532:                                 final Set<UniqueSetting> register = register(enableRuleRegistry, EnableRule.class,
533:                                         context.getDomainModel(),
534:                                         EnableRule.class.cast(notifier).eContainer());
535:
536:                                 for (final UniqueSetting setting : register) {
537:                                         evalEnable(setting);
538:                                 }
539:
540:                         } else if (ShowRule.class.isInstance(notifier)) {
541:                                 final Set<UniqueSetting> register = register(showRuleRegistry, ShowRule.class,
542:                                         context.getDomainModel(), ShowRule.class.cast(notifier)
543:                                                 .eContainer());
544:
545:                                 for (final UniqueSetting setting : register) {
546:                                         evalShow(setting);
547:                                 }
548:
549:                         }
550:                 }
551:
552:                 @Override
553:                 public void notifyRemove(Notifier notifier) {
554:                         if (VElement.class.isInstance(notifier)) {
555:                                 final VElement renderable = VElement.class.cast(notifier);
556:                                 showRuleRegistry.removeRenderable(renderable);
557:                                 enableRuleRegistry.removeRenderable(renderable);
558:                         } else if (Condition.class.isInstance(notifier)) {
559:                                 final Condition condition = Condition.class.cast(notifier);
560:                                 resetToVisible(showRuleRegistry.removeCondition(condition));
561:
562:                                 resetToEnabled(enableRuleRegistry
563:                                         .removeCondition(condition));
564:
565:                         } else if (ShowRule.class.isInstance(notifier)) {
566:                                 final ShowRule showRule = ShowRule.class.cast(notifier);
567:                                 resetToVisible(showRuleRegistry.removeRule(showRule));
568:
569:                         } else if (EnableRule.class.isInstance(notifier)) {
570:                                 final EnableRule enableRule = EnableRule.class.cast(notifier);
571:                                 final VElement removeRule = enableRuleRegistry.removeRule(enableRule);
572:                                 resetToEnabled(removeRule);
573:
574:                         }
575:                 }
576:         }
577:
578:         /**
579:          * {@inheritDoc}
580:          *
581:          * @see org.eclipse.emfforms.spi.core.services.view.EMFFormsContextListener#childContextAdded(org.eclipse.emf.ecp.view.spi.model.VElement,
582:          * org.eclipse.emfforms.spi.core.services.view.EMFFormsViewContext)
583:          */
584:         @Override
585:         public void childContextAdded(VElement parentElement, EMFFormsViewContext childContext) {
586:                 // do nothing
587:         }
588:
589:         /**
590:          * {@inheritDoc}
591:          *
592:          * @see org.eclipse.emfforms.spi.core.services.view.EMFFormsContextListener#childContextDisposed(org.eclipse.emfforms.spi.core.services.view.EMFFormsViewContext)
593:          */
594:         @Override
595:         public void childContextDisposed(EMFFormsViewContext childContext) {
596:                 // do nothing
597:         }
598:
599:         /**
600:          * {@inheritDoc}
601:          *
602:          * @see org.eclipse.emfforms.spi.core.services.view.EMFFormsContextListener#contextInitialised()
603:          */
604:         @Override
605:         public void contextInitialised() {
606:                 final VElement view = context.getViewModel();
607:                 domainChangeListener = new ModelChangeListener() {
608:
609:                         @Override
610:                         public void notifyChange(ModelChangeNotification notification) {
611:                                 if (notification.getStructuralFeature() == null) {
612:                                         return;
613:                                 }
614:                                 // add && reference && !containment
615:                                 final Setting setting = ((InternalEObject) notification.getNotifier()).eSetting(notification
616:                                         .getStructuralFeature());
617:                                 evalShow(UniqueSetting.createSetting(setting));
618:                                 evalEnable(UniqueSetting.createSetting(setting));
619:                         }
620:                 };
621:                 context.registerDomainChangeListener(domainChangeListener);
622:                 viewChangeListener = new RuleServiceViewChangeListener(context);
623:                 context.registerViewChangeListener(viewChangeListener);
624:
625:•                if (view == null) {
626:                         throw new IllegalStateException(VIEW_MODEL_NULL_EXCEPTION);
627:                 }
628:
629:                 final EObject domainModel = context.getDomainModel();
630:
631:•                if (domainModel == null) {
632:                         throw new IllegalStateException(DOMAIN_MODEL_NULL_EXCEPTION);
633:                 }
634:
635:                 final Set<UniqueSetting> enableSettings = init(enableRuleRegistry, EnableRule.class, view, domainModel);
636:                 final Set<UniqueSetting> showSettings = init(showRuleRegistry, ShowRule.class, view, domainModel);
637:•                for (final UniqueSetting setting : enableSettings) {
638:                         evalEnable(setting);
639:                 }
640:•                for (final UniqueSetting setting : showSettings) {
641:                         evalShow(setting);
642:                 }
643:         }
644:
645:         /**
646:          * {@inheritDoc}
647:          *
648:          * @see org.eclipse.emfforms.spi.core.services.view.EMFFormsContextListener#contextDispose()
649:          */
650:         @Override
651:         public void contextDispose() {
652:                 // do nothing
653:         }
654: }