gt: 			return (EObject) object;
context: /**
   * 
   */
  package it.xsemantics.runtime;
  
  import java.lang.reflect.Method;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Set;
  
  import org.eclipse.emf.common.util.WrappedException;
  import org.eclipse.emf.ecore.EObject;
  import org.eclipse.emf.ecore.EStructuralFeature;
  import org.eclipse.emf.ecore.util.EcoreUtil;
  import org.eclipse.xtext.util.PolymorphicDispatcher;
  
  import com.google.common.base.Predicate;
  import com.google.common.collect.Lists;
  import com.google.inject.Inject;
  import com.google.inject.Provider;
  
  /**
   * All generated systems will inherit from this class.
   * 
   * @author Lorenzo Bettini
   * 
   */
  public class XsemanticsRuntimeSystem {
  
  	// The first two params are RuleEnvironment and RuleApplicationTrace
  	protected static final int INDEX_OF_RULE_PARAMETERS = 2;
  
  	// The first param is the RuleApplicationTrace
  	protected static final int INDEX_OF_AUX_PARAMETERS = 1;
  
  	@Inject
  	protected StringRepresentation stringRepresentation;
  
  	@Inject
  	private Provider<XsemanticsCache> cacheProvider;
  
  	private XsemanticsCache cache = null;
  
  	/**
  	 * @since 1.6
  	 */
  	public XsemanticsCache getCache() {
  		if (cache == null) {
  			cache = cacheProvider.get();
  		}
  		return cache;
  	}
  
  	/**
  	 * @since 1.6
  	 */
  	protected <T> T getFromCache(String methodName, RuleEnvironment environment,
  			RuleApplicationTrace trace, XsemanticsProvider<T> provider,
  			Object... elements) {
  		return getCache().get(methodName, environment, trace, provider, elements);
  	}
  
  	protected Predicate<Method> getPredicate(String methodName, int numOfArgs) {
  		return PolymorphicDispatcher.Predicates.forName(methodName, numOfArgs);
  	}
  
  	protected <T> PolymorphicDispatcher<T> buildPolymorphicDispatcher(
  			final String methodName, int numOfArgs) {
  		return new PolymorphicDispatcher<T>(
  				Collections.singletonList(this), getPredicate(methodName,
  						numOfArgs)) {
  			@Override
  			protected T handleNoSuchMethod(Object... params) {
  				throw noSuchMethodException(methodName, params);
  			}
  		};
  	}
  
  	protected <T> PolymorphicDispatcher<Result<T>> buildPolymorphicDispatcher1(
  			String methodName, int numOfArgs, final String judgmentSymbol,
  			final String... relationSymbols) {
  		return new PolymorphicDispatcher<Result<T>>(
  				Collections.singletonList(this), getPredicate(methodName,
  						numOfArgs)) {
  			@Override
  			protected Result<T> handleNoSuchMethod(Object... params) {
  				throw noSuchMethodException(
  						judgmentSymbol, Arrays.asList(relationSymbols),
  						params);
  			}
  		};
  	}
  
  	protected <F, S> PolymorphicDispatcher<Result2<F, S>> buildPolymorphicDispatcher2(
  			String methodName, int numOfArgs, final String judgmentSymbol,
  			final String... relationSymbols) {
  		return new PolymorphicDispatcher<Result2<F, S>>(
  				Collections.singletonList(this), getPredicate(methodName,
  						numOfArgs)) {
  			@Override
  			protected Result2<F, S> handleNoSuchMethod(
  					Object... params) {
  				throw noSuchMethodException(
  						judgmentSymbol, Arrays.asList(relationSymbols),
  						params);
  			}
  		};
  	}
  
  	protected <F, S, T> PolymorphicDispatcher<Result3<F, S, T>> buildPolymorphicDispatcher3(
  			String methodName, int numOfArgs, final String judgmentSymbol,
  			final String... relationSymbols) {
  		return new PolymorphicDispatcher<Result3<F, S, T>>(
  				Collections.singletonList(this), getPredicate(methodName,
  						numOfArgs)) {
  			@Override
  			protected Result3<F, S, T> handleNoSuchMethod(
  					Object... params) {
  				throw noSuchMethodException(
  						judgmentSymbol, Arrays.asList(relationSymbols),
  						params);
  			}
  		};
  	}
  
  	public boolean isResultAssignableTo(Object result, Class<?> destinationClass) {
  		// null is always assignable
  		if (result == null) {
  			return true;
  		}
  		return destinationClass.isAssignableFrom(result.getClass());
  	}
  
  	/**
  	 * Checks whether the result is assignable to the specified
  	 * destinationClass; if not it throws a {@link RuleFailedException}.
  	 * 
  	 * @param result
  	 * @param destinationClass
  	 */
  	public void checkAssignableTo(Object result, Class<?> destinationClass) {
  		if (!isResultAssignableTo(result, destinationClass)) {
  			throw newRuleFailedException(stringRep(result)
  					+ " cannot be assigned to " + stringRep(destinationClass));
  		}
  	}
  
  	public void checkParamsNotNull(Object... objects) {
  		for (int i = 0; i < objects.length; i++) {
  			Object object = objects[i];
  			checkNotNull(object);
  		}
  	}
  
  	/**
  	 * Checks that the passed object is not null; if it is null it throws a
  	 * {@link RuleFailedException}.
  	 * 
  	 * @param object
  	 */
  	public void checkNotNull(Object object) {
  		if (object == null) {
  			throw newRuleFailedException("passed null object to system");
  		}
  	}
  
  	public String stringRep(Object object) {
  		return stringRepresentation.string(object);
  	}
  
  	protected String stringRepForEnv(RuleEnvironment ruleEnvironment) {
  		if (ruleEnvironment == null) {
  			return "[]";
  		}
  		return stringRepresentation.string(ruleEnvironment);
  	}
  
  	protected String stringRepForParams(Object[] params,
  			Iterable<String> relationSymbols) {
  		StringBuilder builder = new StringBuilder();
  		Iterator<String> it = relationSymbols.iterator();
  		for (int i = INDEX_OF_RULE_PARAMETERS; i < params.length; i++) {
  			builder.append(stringRep(params[i]));
  			if (it.hasNext()) {
  				builder.append(" " + it.next() + " ");
  			}
  		}
  		return builder.toString();
  	}
  
  	protected String stringRepForParams(Object[] params) {
  		StringBuilder builder = new StringBuilder();
  		for (int i = INDEX_OF_AUX_PARAMETERS; i < params.length; i++) {
  			if (builder.length() > 0) {
  				builder.append(", ");
  			}
  			builder.append(stringRep(params[i]));
  		}
  		return builder.toString();
  	}
  
  	protected RuleFailedException noSuchMethodException(
  			final String judgmentSymbol,
  			final Iterable<String> relationSymbols, Object... params) {
  		return newRuleFailedException("cannot find a rule for "
  				+ judgmentSymbol + " "
  				+ stringRepForParams(params, relationSymbols));
  	}
  
  	protected RuleFailedException noSuchMethodException(final String name,
  			Object... params) {
  		return newRuleFailedException("cannot find an implementation for "
  				+ name + "(" + stringRepForParams(params) + ")");
  	}
  
  	public void sneakyThrowRuleFailedException(Exception e) {
  		throw extractRuleFailedException(e);
  	}
  
  	public void sneakyThrowRuleFailedException(String message) {
  		throw newRuleFailedException(message, null);
  	}
  
  	public void throwForExplicitFail() {
  		throw newRuleFailedException();
  	}
  
  	public void throwForExplicitFail(String message,
  			ErrorInformation errorInformation) {
  		final RuleFailedException ex = newRuleFailedException(message);
  		ex.addErrorInformation(errorInformation);
  		throw ex;
  	}
  
  	public void throwRuleFailedException(String message, String issue,
  			Throwable t, ErrorInformation... errorInformations) {
  		throw newRuleFailedException(message, issue, t, errorInformations);
  	}
  
  	/**
  	 * @since 1.5
  	 */
  	public RuleFailedException newRuleFailedException() {
  		return createRuleFailedException(null, null, null);
  	}
  
  	/**
  	 * @since 1.5
  	 */
  	public RuleFailedException newRuleFailedException(Throwable t) {
  		return createRuleFailedException(t.toString(), null, t);
  	}
  
  	/**
  	 * @since 1.5
  	 */
  	public RuleFailedException newRuleFailedException(String message) {
  		return createRuleFailedException(message, null, null);
  	}
  
  	public RuleFailedException newRuleFailedException(String message,
  			String issue, ErrorInformation... errorInformations) {
  		return newRuleFailedException(message, issue, null, errorInformations);
  	}
  
  	public RuleFailedException newRuleFailedException(String message,
  			String issue, Throwable t, ErrorInformation... errorInformations) {
  		final RuleFailedException ruleFailedException = createRuleFailedException(
  				failed(message), issue, t);
  		ruleFailedException.addErrorInformations(errorInformations);
  		return ruleFailedException;
  	}
  
  	/**
  	 * This factory method can be overridden if one needs to provide a custom implementation
  	 * of {@link RuleFailedException}.
  	 * 
  	 * @param message
  	 * @param issue
  	 * @param t
  	 * @return
  	 * 
  	 * @since 1.5
  	 */
  	protected RuleFailedException createRuleFailedException(String message,
  			String issue, Throwable t) {
  		return new RuleFailedException(message, issue, t);
  	}
  
  	public RuleFailedException extractRuleFailedException(Exception e) {
  		if (e instanceof WrappedException) {
  			WrappedException wrappedException = (WrappedException) e;
  			Exception exception = wrappedException.exception();
  			if (exception instanceof RuleFailedException) {
  				return (RuleFailedException) exception;
  			}
  		} else if (e instanceof RuleFailedException) {
  			return (RuleFailedException) e;
  		}
  		return newRuleFailedException(e);
  	}
  
  	protected <T> Result<T> resultForFailure(Exception e) {
  		return new Result<T>(extractRuleFailedException(e));
  	}
  
  	protected <F, S> Result2<F, S> resultForFailure2(
  			Exception e) {
  		return new Result2<F, S>(extractRuleFailedException(e));
  	}
  
  	protected <F, S, T> Result3<F, S, T> resultForFailure3(
  			Exception e) {
  		return new Result3<F, S, T>(extractRuleFailedException(e));
  	}
  
  	protected String failed(String message) {
  		return "failed: " + trimIfNotNull(message);
  	}
  
  	protected String trimIfNotNull(String message) {
  		return message != null ? message.trim() : message;
  	}
  
  	protected String ruleName(String ruleName) {
  		return trimIfNotNull(ruleName) + ": ";
  	}
  	
  	protected String auxFunName(String ruleName) {
  		return trimIfNotNull(ruleName);
  	}
  
  	/**
  	 * If the passed ruleApplicationTrace is not null, then uses the
  	 * traceElementProvider to create an element to add to the trace.
  	 * 
  	 * Using a provider instead of the actual element avoids the creation of
  	 * such element in case the ruleApplicationTrace is null, heavily reducing
  	 * overhead and increasing performance.
  	 * 
  	 * See also <a
  	 * href="https://github.com/LorenzoBettini/xsemantics/pull/27">https
  	 * ://github.com/LorenzoBettini/xsemantics/pull/27</a>
  	 * 
  	 * @param ruleApplicationTrace
  	 * @param traceElementProvider
  	 * 
  	 * @since 1.6
  	 */
  	public void addToTrace(RuleApplicationTrace ruleApplicationTrace,
  			Provider<? extends Object> traceElementProvider) {
  		if (ruleApplicationTrace != null) {
  			ruleApplicationTrace.addToTrace(traceElementProvider.get());
  		}
  	}
  
  	public RuleApplicationTrace newTrace(
  			RuleApplicationTrace ruleApplicationTrace) {
  		if (ruleApplicationTrace != null) {
  			return new RuleApplicationTrace();
  		}
  		return null;
  	}
  
  	public void addAsSubtrace(RuleApplicationTrace ruleApplicationTrace,
  			RuleApplicationTrace subTrace) {
  		if (ruleApplicationTrace != null) {
  			ruleApplicationTrace.addAsSubtrace(subTrace);
  		}
  	}
  
  	/**
  	 * This method replaces the previous keyword 'env' in Xsemantics grammar
  	 * (before version 1.5.0).
  	 * 
  	 * It is useless to have such element in the grammar, since it has
  	 * exactly the same syntax of this Java method invocation.
  	 * 
  	 * @param environment
  	 * @param key
  	 * @param clazz
  	 * @return
  	 * @throws RuleFailedException
  	 * @since 1.5
  	 */
  	public <T> T env(RuleEnvironment environment, Object key,
  			Class<? extends T> clazz) throws RuleFailedException {
  		return environmentAccess(environment, key, clazz);
  	}
  
  	@SuppressWarnings("unchecked")
  	public <T> T environmentAccess(RuleEnvironment environment, Object key,
  			Class<? extends T> clazz) throws RuleFailedException {
  		if (environment == null) {
  			throw newRuleFailedException("access to null environment");
  		}
  		Object value = environment.get(key);
  		if (value == null) {
  			throw newRuleFailedException("no mapping in the environment for: "
  					+ stringRep(key));
  		}
  		if (clazz.isAssignableFrom(value.getClass())) {
  			return (T) value;
  		}
  		throw newRuleFailedException("mapped value " + stringRep(value)
  				+ " cannot be assigned to " + stringRep(clazz));
  	}
  
  	public <T extends EObject> T clone(T eObject) {
  		return EcoreUtil.copy(eObject);
  	}
  
  	public RuleEnvironment emptyEnvironment() {
  		return new RuleEnvironment();
  	}
  
  	public RuleEnvironment environmentEntry(Object key, Object value) {
  		return new RuleEnvironment(new RuleEnvironmentEntry(key, value));
  	}
  
  	public RuleEnvironment environmentComposition(RuleEnvironment environment,
  			RuleEnvironment environment2) {
  		if (environment == null) {
  			return new RuleEnvironment(environment2);
  		}
  		return new RuleEnvironment(environment, environment2);
  	}
  
  	public <T> List<T> getAll(EObject eObject, EStructuralFeature mainFeature,
  			EStructuralFeature extendFeature, Class<? extends T> clazz) {
  		List<T> list = new LinkedList<T>();
  
  		if (eObject != null) {
  			// get all the stuff from the main object
  			addToList(list, eObject.eGet(mainFeature), clazz);
  
  			// follow the extend feature performing the closure
  			List<EObject> nodesInRelation = getAllNodesInRelation(eObject,
  					extendFeature);
  			for (EObject object : nodesInRelation) {
  				addToList(list, object.eGet(mainFeature), clazz);
  			}
  		}
  
  		return list;
  	}
  
  	public List<EObject> getAllNodesInRelation(EObject eObject,
  			EStructuralFeature extendFeature) {
  		List<EObject> nodes = new LinkedList<EObject>();
  		Set<EObject> seen = new HashSet<EObject>();
  
  		getAllNodesInRelation(eObject, extendFeature, nodes, seen);
  
  		return nodes;
  	}
  
  	protected void getAllNodesInRelation(EObject eObject,
  			EStructuralFeature extendFeature, List<EObject> nodes,
  			Set<EObject> seen) {
  		if (eObject != null) {
  			// follow the extend feature performing the closure
  			List<Object> objectsToFollow = getList(eObject.eGet(extendFeature));
  
  			for (Object object : objectsToFollow) {
  				EObject toFollow = getEObject(object);
  				if (toFollow != null && !seen.contains(toFollow)) {
  					seen.add(toFollow);
  					nodes.add(toFollow);
  					getAllNodesInRelation(toFollow, extendFeature, nodes, seen);
  				}
  			}
  		}
  	}
  
  	/**
  	 * If the object is a list returns the list itself, otherwise returns a list
  	 * with only the passed object as element.
  	 * 
  	 * @param object
  	 * @return
  	 */
  	@SuppressWarnings("unchecked")
  	public List<Object> getList(Object object) {
  		if (object == null) {
  			return Lists.newArrayList();
  		}
  
  		if (object instanceof List) {
  			return (List<Object>) object;
  		}
  
  		return Lists.newArrayList(object);
  	}
  
  	public EObject getEObject(Object object) {
  		if (object instanceof EObject) {
  