/*******************************************************************************
* Copyright (c) 2010, 2015 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* C.Damus, K.Hussey, E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.internal.delegate;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.BasicSettingDelegate;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.evaluation.EvaluationException;
import org.eclipse.ocl.pivot.internal.messages.PivotMessagesInternal;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.MetamodelManager;
import org.eclipse.ocl.pivot.utilities.OCL;
import org.eclipse.ocl.pivot.utilities.Query;
import org.eclipse.ocl.pivot.utilities.SemanticException;
/**
* An implementation of a setting delegate that computes OCL derived features.
*/
public class OCLSettingDelegate extends BasicSettingDelegate.Stateless
{
/**
* An implementation of a setting delegate that computes OCL derived features
* and caches explicitly changed values.
*
* @since 3.5
*/
public static class Changeable extends OCLSettingDelegate
{
private Map<InternalEObject, Object> valueMap = null;
public Changeable(@NonNull OCLDelegateDomain delegateDomain, @NonNull EStructuralFeature structuralFeature) {
super(delegateDomain, structuralFeature);
}
@Override
protected Object get(InternalEObject owner, boolean resolve, boolean coreType) {
if ((valueMap != null) && valueMap.containsKey(owner)) {
return valueMap.get(owner);
}
return super.get(owner, resolve, coreType);
}
@Override
protected boolean isSet(InternalEObject owner) {
return (valueMap != null) && valueMap.containsKey(owner);
}
@Override
protected void set(InternalEObject owner, Object newValue) {
if (owner != null) {
if (valueMap == null) {
valueMap = new HashMap<InternalEObject, Object>();
}
valueMap.put(owner, newValue);
}
}
@Override
protected void unset(InternalEObject owner) {
if (valueMap != null) {
valueMap.remove(owner);
}
}
}
protected final @NonNull OCLDelegateDomain delegateDomain;
private Property property;
private ExpressionInOCL query;
/**
* Initializes me with my structural feature.
*
* @param structuralFeature
* the structural feature that I handle
*/
public OCLSettingDelegate(@NonNull OCLDelegateDomain delegateDomain, @NonNull EStructuralFeature structuralFeature) {
super(structuralFeature);
this.delegateDomain = delegateDomain;
}
protected @Nullable Object evaluateEcore(@NonNull OCL ocl, @NonNull ExpressionInOCL query, @Nullable Object target) {
Query query2 = ocl.createQuery(query);
return query2.evaluateEcore(eStructuralFeature.getEType().getInstanceClass(), target);
}
@Override
protected Object get(InternalEObject owner, boolean resolve, boolean coreType) {
try {
OCL ocl = delegateDomain.getOCL();
MetamodelManager metamodelManager = ocl.getMetamodelManager();
ExpressionInOCL query2 = query;
if (query2 == null) {
Property property2 = getProperty();
query2 = query = SettingBehavior.INSTANCE.getQueryOrThrow(metamodelManager, property2);
SettingBehavior.INSTANCE.validate(property2);
}
Object ecoreResult = evaluateEcore(ocl, query2, owner);
return ecoreResult;
}
catch (EvaluationException e) {
throw new OCLDelegateException(new EvaluationException(e, PivotMessagesInternal.EvaluationResultIsInvalid_ERROR_, property));
}
}
public @NonNull Property getProperty() {
Property property2 = property;
if (property2 == null) {
property2 = property = delegateDomain.getPivot(Property.class, ClassUtil.nonNullEMF(eStructuralFeature));
if (property2 == null) {
throw new OCLDelegateException(new SemanticException("No pivot property for " + eStructuralFeature)) ;
}
}
return property2;
}
@Override
protected boolean isSet(InternalEObject owner) {
return false; // derived features are, implicitly, never set
}
@Override
public String toString() {
if (property != null) {
return "<" + delegateDomain.getURI() + ":setting> " + property; //$NON-NLS-1$ //$NON-NLS-2$
}
else {
String name = eStructuralFeature.getEContainingClass().getEPackage().getName()
+ "::" + eStructuralFeature.getEContainingClass().getName()
+ "." + eStructuralFeature.getName();
return "<" + delegateDomain.getURI() + ":setting> " + name; //$NON-NLS-1$ //$NON-NLS-2$
}
}
}