All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.epsilon.emc.emf.EmfPropertySetter Maven / Gradle / Ivy

/*******************************************************************************
 * 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;

import java.util.Collection;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.ETypedElement;
import org.eclipse.epsilon.common.util.CollectionUtil;
import org.eclipse.epsilon.eol.exceptions.EolIllegalPropertyAssignmentException;
import org.eclipse.epsilon.eol.exceptions.EolIllegalPropertyException;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.introspection.AbstractPropertySetter;
import org.eclipse.epsilon.eol.execute.introspection.IReflectivePropertySetter;

public class EmfPropertySetter extends AbstractPropertySetter implements IReflectivePropertySetter {

	@Override
	public Object coerce(Object target, String property, Object value, IEolContext context) throws EolIllegalPropertyException {
		EStructuralFeature sf = getEStructuralFeature(target, property, value, context);
		if (sf.isMany() && !(value instanceof Collection)) {
			return CollectionUtil.asList(value);
		}
		return value;
	}
	
	@Override
	public boolean conforms(Object target, String property, Object value, IEolContext context) throws EolIllegalPropertyException {
		EStructuralFeature sf = getEStructuralFeature(target, property, value, context);
		if (!sf.isChangeable()) {
			return false;
		}
		if (value instanceof Collection) {
			final Collection collection = ((Collection)value);
			return sf.isMany() &&
			       isConformantSizeForProperty(collection, sf) && 
			       allAreConformantTypeForProperty(collection, sf);
		}
		else {
			return sf.getEType().isInstance(value);
		}
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public void invoke(Object target, String property, Object value, IEolContext context) throws EolRuntimeException {
		EStructuralFeature sf = getEStructuralFeature(target, property, value, context);
		if (sf.isMany()) {
			if (value != null) {
				Collection sourceValues = (Collection) getEObject(target, property, value, context).eGet(sf);
				if (value instanceof Collection) {	
					copyCollectionValues(((Collection)value), sourceValues);
				}
				else {
					throw new EolIllegalPropertyAssignmentException(property, context);
				}
			}
		}
		else {
			getEObject(target, property, value, context).eSet(sf, value);
		}
	}
	
	protected void copyCollectionValues(Collection source, Collection target) {
		target.clear();
		target.addAll(source);
	}
	
	protected EObject getEObject(Object object, String property, Object value, IEolContext context) throws EolIllegalPropertyException {
		if (object instanceof EObject)
			return (EObject) object;
		else
			throw new EolIllegalPropertyException(object, property, context);
	}
	
	private EStructuralFeature getEStructuralFeature(Object object, String property, Object value, IEolContext context) throws EolIllegalPropertyException {
		final EStructuralFeature sf = EmfUtil.getEStructuralFeature(getEObject(object, property, value, context).eClass(), property);	
		if (sf == null) {
			throw new EolIllegalPropertyException(object, property, context);
		}
		return sf;
	}
	
	private boolean isConformantSizeForProperty(Collection values, EStructuralFeature sf) throws EolIllegalPropertyException {
		int size = values.size();
		int lowerbound = sf.getLowerBound();
		int upperbound = sf.getUpperBound();
		if (upperbound == ETypedElement.UNBOUNDED_MULTIPLICITY) {
			upperbound = Integer.MAX_VALUE;
		}
		return lowerbound <= size && size <= upperbound;
	}
	
	private boolean allAreConformantTypeForProperty(Collection values, EStructuralFeature sf) throws EolIllegalPropertyException {
		EClassifier eType = sf.getEType();
		for (Object value : values) {
			if (!eType.isInstance(value))
				return false;
		}		
		return true;
	}
}