blob: 8065e44491c8d83e759aacf560d03bace6b114c7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Christian W. Damus and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christian W. Damus - initial API and implementation
******************************************************************************/
package org.eclipse.emf.ecp.view.internal.rule;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecp.common.spi.UniqueSetting;
import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
import org.eclipse.emf.ecp.view.spi.rule.ConditionService;
import org.eclipse.emf.ecp.view.spi.rule.model.Condition;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Deactivate;
/**
* Partial implementation of a condition service for composite conditions.
*
* @param <C> the type of condition for which I provide service
*
* @author Christian W. Damus
*/
abstract class CompositeConditionService<C extends Condition> implements ConditionService<C> {
private ServiceReference<ConditionServiceManager> conditionServiceManagerReference;
private ConditionServiceManager conditionServiceManager;
/**
* Initializes me.
*/
protected CompositeConditionService() {
super();
}
/**
* Deactivates me.
*/
@Deactivate
void deactivate() {
conditionServiceManager = null;
if (conditionServiceManagerReference != null) {
getBundleContext().ungetService(conditionServiceManagerReference);
}
}
private BundleContext getBundleContext() {
return FrameworkUtil.getBundle(getClass()).getBundleContext();
}
@Override
public Set<UniqueSetting> getConditionSettings(C condition, EObject domainModel) {
final Set<UniqueSetting> result = new LinkedHashSet<UniqueSetting>();
final ConditionServiceManager manager = getConditionServiceManager();
final Iterable<? extends EObject> targets = getTargets(condition, domainModel);
for (final Condition component : components(condition)) {
for (final EObject next : targets) {
result.addAll(manager.getConditionSettings(component, next));
}
}
return result;
}
/**
* Obtains the objects on which a {@code condition} is evaluated.
*
* @param condition a composite condition of my type
* @param domainModel the source from which to navigate to obtain the targets for evaluation
* of the {@code condition}
* @return the evaluation targets
*/
protected List<? extends EObject> getTargets(C condition, EObject domainModel) {
return Collections.singletonList(domainModel);
}
/**
* Obtains the nested conditions in a composite {@code condition} of my type.
*
* @param condition the composite condition from which to get components
* @return the {@code condition}'s zero or more nested conditions that are its components
*/
protected abstract Iterable<? extends Condition> components(C condition);
@Override
public Set<VDomainModelReference> getDomainModelReferences(C condition) {
final Set<VDomainModelReference> result = new LinkedHashSet<VDomainModelReference>();
final ConditionServiceManager manager = getConditionServiceManager();
for (final Condition next : components(condition)) {
result.addAll(manager.getDomainModelReferences(next));
}
return result;
}
@Override
public boolean evaluate(C condition, EObject domainModel) {
return condition.evaluate(domainModel);
}
@Override
public boolean evaluateChangedValues(C condition, EObject domainModel, Map<Setting, Object> possibleNewValues) {
return condition.evaluateChangedValues(domainModel, possibleNewValues);
}
private ConditionServiceManager getConditionServiceManager() {
if (conditionServiceManager == null) {
final BundleContext context = getBundleContext();
conditionServiceManagerReference = context.getServiceReference(ConditionServiceManager.class);
if (conditionServiceManagerReference == null) {
throw new IllegalStateException("No ConditionServiceManager"); //$NON-NLS-1$
}
conditionServiceManager = context.getService(conditionServiceManagerReference);
}
return conditionServiceManager;
}
}