blob: 9d3b60c7a3b27a693a08c620fb9ec6cd28acbe76 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 The University of York.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Dimitrios Kolovos - initial API and implementation
******************************************************************************/
package org.eclipse.epsilon.emc.emf.decorator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.epsilon.emc.emf.EmfModel;
import org.eclipse.epsilon.emc.emf.EmfPropertyGetter;
import org.eclipse.epsilon.emc.emf.EmfPropertySetter;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.introspection.IReflectivePropertySetter;
public class DecoratorEmfModel extends EmfModel {
EObject decorator = null;
DecoratorDescriptor decoratorDescriptor = null;
List<DecoratorDescriptor> decoratorDescriptors;
public DecoratorEmfModel() {
propertyGetter = new DecoratorPropertyGetter();
}
protected List<EClass> getDecoratorEClasses(Collection<EPackage> ePackages) {
List<EClass> decoratorEClasses = new ArrayList<>();
for (EPackage ePackage :ePackages) {
for (EClassifier eClassifier : ePackage.getEClassifiers()) {
if (eClassifier instanceof EClass) {
EClass eClass = (EClass) eClassifier;
if (isDecorator(eClass)) {
decoratorEClasses.add(eClass);
}
}
}
decoratorEClasses.addAll(getDecoratorEClasses(ePackage.getESubpackages()));
}
return decoratorEClasses;
}
protected List<DecoratorDescriptor> getDecoratorDescriptors() {
if (decoratorDescriptors == null) {
decoratorDescriptors = new ArrayList<>();
List<EClass> decoratorEClasses = getDecoratorEClasses(packages);
for (EClass decoratorEClass : decoratorEClasses) {
for (EReference hook : decoratorEClass.getEAllReferences()) {
if (isHook(hook)) {
DecoratorDescriptor decoratorDescriptor = new DecoratorDescriptor();
decoratorDescriptor.setEClass(decoratorEClass);
decoratorDescriptor.setEReference(hook);
decoratorDescriptors.add(decoratorDescriptor);
}
}
}
}
return decoratorDescriptors;
}
@Override
public boolean knowsAboutProperty(Object instance, String property) {
//If it is not an EObject don't look any further
if (!(instance instanceof EObject)) return false;
//If it is a model element of the decorator model return true
if (super.owns(instance)) {
decorator = (EObject) instance;
return true;
}
// Look for a suitable decorator descriptor
this.decoratorDescriptor = null;
for (DecoratorDescriptor decoratorDescriptor : getDecoratorDescriptors()) {
if (decoratorDescriptor.decorates((EObject) instance, property)) {
this.decoratorDescriptor = decoratorDescriptor;
break;
}
}
if (this.decoratorDescriptor == null) return false;
// If we find the descriptor,
// also cache the
// actual decorator
Collection<EObject> candidateDecorators = new ArrayList<>();
try {
candidateDecorators = getAllOfKind(getFullyQualifiedName(decoratorDescriptor.getEClass()));
}
catch (Exception ex) {
}
for (EObject candidateDecorator : candidateDecorators) {
if (isDecoratorFor(candidateDecorator, instance, decoratorDescriptor.getEReference())) {
decorator = candidateDecorator;
return true;
}
}
// No decorator found but if we have reached here
// it means that we have found a decorator descriptor
// at least
decorator = null;
return true;
}
protected boolean isDecorator(EClass e) {
if (e.getEAnnotation("decorator") != null) {
return true;
}
else {
for (EClass supertype : e.getESuperTypes()) {
if (isDecorator(supertype)) {
return true;
}
}
}
return false;
}
protected boolean isHook(EReference e) {
return e.getEAnnotation("decorator.hook") != null;
}
@SuppressWarnings("unchecked")
protected boolean isDecoratorFor(EObject candidateDecorator, Object target, EReference eReference) {
if (eReference.isMany()) {
if (((Collection<Object>)candidateDecorator.eGet(eReference)).contains(target)) {
return true;
}
}
else {
if (candidateDecorator.eGet(eReference) == target) {
return true;
}
}
return false;
}
@Override
public IReflectivePropertySetter getPropertySetter() {
return new DecoratorPropertySetter();
}
class DecoratorPropertyGetter extends EmfPropertyGetter {
@Override
public Object invoke(Object object, String property, IEolContext context) throws EolRuntimeException {
if (decorator == null) {
if (decoratorDescriptor.getLastValueFeature().isMany()) {
return new ArrayList<>();
}
else {
return decoratorDescriptor.getLastValueFeature().getDefaultValue();
}
}
else {
return super.invoke(decorator, property, context);
}
}
}
class DecoratorPropertySetter extends EmfPropertySetter {
@Override
public void invoke(Object object, String property, Object value, IEolContext context) throws EolRuntimeException {
if (decorator != null) {
super.invoke(decorator, property, value, context);
}
else {
throw new EolRuntimeException("Cannot set the value of feature " + property + " as the decorator object does not exist");
}
}
}
}