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

spoon.support.DefaultCoreFactory Maven / Gradle / Ivy

/* 
 * Spoon - http://spoon.gforge.inria.fr/
 * Copyright (C) 2006 INRIA Futurs 
 * 
 * This software is governed by the CeCILL-C License under French law and
 * abiding by the rules of distribution of free software. You can use, modify 
 * and/or redistribute the software under the terms of the CeCILL-C license as 
 * circulated by CEA, CNRS and INRIA at http://www.cecill.info. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
 *  
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C license and that you accept its terms.
 */

package spoon.support;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;

import spoon.Launcher;
import spoon.reflect.code.CtAnnotationFieldAccess;
import spoon.reflect.code.CtArrayAccess;
import spoon.reflect.code.CtAssert;
import spoon.reflect.code.CtAssignment;
import spoon.reflect.code.CtBinaryOperator;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtBreak;
import spoon.reflect.code.CtCase;
import spoon.reflect.code.CtCatch;
import spoon.reflect.code.CtCodeSnippetExpression;
import spoon.reflect.code.CtCodeSnippetStatement;
import spoon.reflect.code.CtConditional;
import spoon.reflect.code.CtContinue;
import spoon.reflect.code.CtDo;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtFieldAccess;
import spoon.reflect.code.CtFor;
import spoon.reflect.code.CtForEach;
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtNewArray;
import spoon.reflect.code.CtNewClass;
import spoon.reflect.code.CtOperatorAssignment;
import spoon.reflect.code.CtReturn;
import spoon.reflect.code.CtStatementList;
import spoon.reflect.code.CtSuperAccess;
import spoon.reflect.code.CtSwitch;
import spoon.reflect.code.CtSynchronized;
import spoon.reflect.code.CtThisAccess;
import spoon.reflect.code.CtThrow;
import spoon.reflect.code.CtTry;
import spoon.reflect.code.CtUnaryOperator;
import spoon.reflect.code.CtVariableAccess;
import spoon.reflect.code.CtWhile;
import spoon.reflect.cu.CompilationUnit;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtAnnotationType;
import spoon.reflect.declaration.CtAnonymousExecutable;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtEnum;
import spoon.reflect.declaration.CtField;
import spoon.reflect.declaration.CtInterface;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtPackage;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.declaration.CtTypeParameter;
import spoon.reflect.factory.CoreFactory;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtArrayTypeReference;
import spoon.reflect.reference.CtExecutableReference;
import spoon.reflect.reference.CtFieldReference;
import spoon.reflect.reference.CtLocalVariableReference;
import spoon.reflect.reference.CtPackageReference;
import spoon.reflect.reference.CtParameterReference;
import spoon.reflect.reference.CtReference;
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.support.reflect.code.CtAnnotationFieldAccesImpl;
import spoon.support.reflect.code.CtArrayAccessImpl;
import spoon.support.reflect.code.CtAssertImpl;
import spoon.support.reflect.code.CtAssignmentImpl;
import spoon.support.reflect.code.CtBinaryOperatorImpl;
import spoon.support.reflect.code.CtBlockImpl;
import spoon.support.reflect.code.CtBreakImpl;
import spoon.support.reflect.code.CtCaseImpl;
import spoon.support.reflect.code.CtCatchImpl;
import spoon.support.reflect.code.CtCodeSnippetExpressionImpl;
import spoon.support.reflect.code.CtCodeSnippetStatementImpl;
import spoon.support.reflect.code.CtConditionalImpl;
import spoon.support.reflect.code.CtContinueImpl;
import spoon.support.reflect.code.CtDoImpl;
import spoon.support.reflect.code.CtFieldAccessImpl;
import spoon.support.reflect.code.CtForEachImpl;
import spoon.support.reflect.code.CtForImpl;
import spoon.support.reflect.code.CtIfImpl;
import spoon.support.reflect.code.CtInvocationImpl;
import spoon.support.reflect.code.CtLiteralImpl;
import spoon.support.reflect.code.CtLocalVariableImpl;
import spoon.support.reflect.code.CtNewArrayImpl;
import spoon.support.reflect.code.CtNewClassImpl;
import spoon.support.reflect.code.CtOperatorAssignmentImpl;
import spoon.support.reflect.code.CtReturnImpl;
import spoon.support.reflect.code.CtStatementListImpl;
import spoon.support.reflect.code.CtSuperAccessImpl;
import spoon.support.reflect.code.CtSwitchImpl;
import spoon.support.reflect.code.CtSynchronizedImpl;
import spoon.support.reflect.code.CtThisAccessImpl;
import spoon.support.reflect.code.CtThrowImpl;
import spoon.support.reflect.code.CtTryImpl;
import spoon.support.reflect.code.CtUnaryOperatorImpl;
import spoon.support.reflect.code.CtVariableAccessImpl;
import spoon.support.reflect.code.CtWhileImpl;
import spoon.support.reflect.cu.CompilationUnitImpl;
import spoon.support.reflect.cu.SourcePositionImpl;
import spoon.support.reflect.declaration.CompilationUnitVirtualImpl;
import spoon.support.reflect.declaration.CtAnnotationImpl;
import spoon.support.reflect.declaration.CtAnnotationTypeImpl;
import spoon.support.reflect.declaration.CtAnonymousExecutableImpl;
import spoon.support.reflect.declaration.CtClassImpl;
import spoon.support.reflect.declaration.CtConstructorImpl;
import spoon.support.reflect.declaration.CtElementImpl;
import spoon.support.reflect.declaration.CtEnumImpl;
import spoon.support.reflect.declaration.CtFieldImpl;
import spoon.support.reflect.declaration.CtInterfaceImpl;
import spoon.support.reflect.declaration.CtMethodImpl;
import spoon.support.reflect.declaration.CtPackageImpl;
import spoon.support.reflect.declaration.CtParameterImpl;
import spoon.support.reflect.declaration.CtTypeParameterImpl;
import spoon.support.reflect.reference.CtArrayTypeReferenceImpl;
import spoon.support.reflect.reference.CtExecutableReferenceImpl;
import spoon.support.reflect.reference.CtFieldReferenceImpl;
import spoon.support.reflect.reference.CtLocalVariableReferenceImpl;
import spoon.support.reflect.reference.CtPackageReferenceImpl;
import spoon.support.reflect.reference.CtParameterReferenceImpl;
import spoon.support.reflect.reference.CtTypeParameterReferenceImpl;
import spoon.support.reflect.reference.CtTypeReferenceImpl;
import spoon.support.util.RtHelper;

/**
 * This class implements a default core factory for Spoon's meta-model. This
 * implementation is done with regular Java classes (POJOs).
 */
public class DefaultCoreFactory implements CoreFactory, Serializable {

	private static final long serialVersionUID = 1L;

	// transient Stack cloningContext = new Stack();

	Factory mainFactory;

	/**
	 * Default constructor.
	 */
	public DefaultCoreFactory() {
	}

	public  T clone(T object) {
		return clone(object, new Stack());
	}

	@SuppressWarnings("unchecked")
	private  T clone(T object, Stack cloningContext) {
		if (object == null)
			return null;
		T result = null;
		try {
			if (!(object instanceof CtElement || object instanceof CtReference)) {
				return object;
			}
			// RP: this should be done first or removed?
			if (object instanceof Cloneable) {
				return (T) object.getClass().getMethod("clone").invoke(object);
			}
			// RP: never called?
			if (object.getClass().isEnum()) {
				return object;
			}
			// System.out.println("cloning " + object + "["
			// + object.getClass().getSimpleName() + "]");
			result = (T) object.getClass().newInstance();
			if (result instanceof CtElement) {
				// if (cloningContext.isEmpty()) {
				// //CtElement e = (CtElement)object;
				// //if(e.isParentInitialized()) {
				// // cloningContext.push(e.getParent());
				// //} else {
				// cloningContext.push(null);
				// //}
				// }
				cloningContext.push((CtElement) result);
			}
			for (Field f : RtHelper.getAllFields(object.getClass())) {
				// if (!clonedFields.contains(f)) {
				// clonedFields.push(f);
				f.setAccessible(true);
				// if (f.getName().equals("parent")) {
				// // if (!cloningContext.isEmpty()) {
				// ((CtElement) result).setParent(cloningContext
				// .get(cloningContext.size() - 2));
				// // }
				// } else {
				if (!f.getName().equals("parent")) {
					Object fieldValue = f.get(object);
					if (!Modifier.isFinal(f.getModifiers())
							&& !Modifier.isStatic(f.getModifiers())) {
						if (fieldValue instanceof Collection) {
							Collection c;
							if (fieldValue == CtElementImpl.EMPTY_COLLECTION()
									|| fieldValue == CtElementImpl.EMPTY_SET()) {
								c = (Collection) fieldValue;
							} else {
								c = (Collection) fieldValue.getClass()
										.getMethod("clone").invoke(fieldValue);
								c.clear();
								for (Object o : (Collection) fieldValue) {
									c.add(clone(o, cloningContext));
								}
							}
							f.set(result, c);

						} else if (fieldValue instanceof Map) {
							// TODO: ARE THERE REALLY MAP FIELDS IN THE MODEL?
							// System.err.println(" cloning collection " + f+" :
							// "+cloningContext.peek().getClass().getSimpleName());
							Map m = (Map) fieldValue
									.getClass().getMethod("clone")
									.invoke(fieldValue);
							// m.clear();
							f.set(result, m);
							for (Entry e : ((Map) fieldValue)
									.entrySet()) {
								m.put(e.getKey(),
										clone(e.getValue(), cloningContext));
							}
						} else if ((object instanceof CtReference)
								&& (fieldValue instanceof CtElement)) {

							f.set(result, fieldValue);
						} else {
							// System.err.println(" cloning field " + f+" :
							// "+cloningContext.peek().getClass().getSimpleName());
							f.set(result, clone(f.get(object), cloningContext));
						}
					}
				}
				// clonedFields.pop();
			}
			// }
			if (result instanceof CtElement) {
				cloningContext.pop();
				if (cloningContext.isEmpty()) {
					((CtElement) result).setParent(null);
				} else {
					((CtElement) result).setParent(cloningContext.peek());
				}
				// if (cloningContext.size() == 1)
				// cloningContext.pop();
			}
		} catch (Exception e) {
			Launcher.logger.error(e.getMessage(), e);
		}
		return result;

	}

	public  CtAnnotation createAnnotation() {
		CtAnnotation e = new CtAnnotationImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtAnnotationType createAnnotationType() {
		CtAnnotationType e = new CtAnnotationTypeImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtAnonymousExecutable createAnonymousExecutable() {
		CtAnonymousExecutable e = new CtAnonymousExecutableImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public > CtArrayAccess createArrayAccess() {
		CtArrayAccess e = new CtArrayAccessImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtArrayTypeReference createArrayTypeReference() {
		CtArrayTypeReference e = new CtArrayTypeReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtAssert createAssert() {
		CtAssert e = new CtAssertImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtAssignment createAssignment() {
		CtAssignment e = new CtAssignmentImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtBinaryOperator createBinaryOperator() {
		CtBinaryOperator e = new CtBinaryOperatorImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtBlock createBlock() {
		CtBlock e = new CtBlockImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtBreak createBreak() {
		CtBreak e = new CtBreakImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtCase createCase() {
		CtCase e = new CtCaseImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtCatch createCatch() {
		CtCatch e = new CtCatchImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtClass createClass() {
		CtClass e = new CtClassImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtConditional createConditional() {
		CtConditional e = new CtConditionalImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtConstructor createConstructor() {
		CtConstructor e = new CtConstructorImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtContinue createContinue() {
		CtContinue e = new CtContinueImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtDo createDo() {
		CtDo e = new CtDoImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public > CtEnum createEnum() {
		CtEnum e = new CtEnumImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtExecutableReference createExecutableReference() {
		CtExecutableReference e = new CtExecutableReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtField createField() {
		CtField e = new CtFieldImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtFieldAccess createFieldAccess() {
		CtFieldAccess e = new CtFieldAccessImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtAnnotationFieldAccess createAnnotationFieldAccess() {
		CtAnnotationFieldAccess e = new CtAnnotationFieldAccesImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtFieldReference createFieldReference() {
		CtFieldReference e = new CtFieldReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtFor createFor() {
		CtFor e = new CtForImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtForEach createForEach() {
		CtForEach e = new CtForEachImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtIf createIf() {
		CtIf e = new CtIfImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtInterface createInterface() {
		CtInterface e = new CtInterfaceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtInvocation createInvocation() {
		CtInvocation e = new CtInvocationImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtLiteral createLiteral() {
		CtLiteral e = new CtLiteralImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtLocalVariable createLocalVariable() {
		CtLocalVariable e = new CtLocalVariableImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtLocalVariableReference createLocalVariableReference() {
		CtLocalVariableReference e = new CtLocalVariableReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtMethod createMethod() {
		CtMethod e = new CtMethodImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtNewArray createNewArray() {
		CtNewArray e = new CtNewArrayImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtNewClass createNewClass() {
		CtNewClass e = new CtNewClassImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtOperatorAssignment createOperatorAssignment() {
		CtOperatorAssignment e = new CtOperatorAssignmentImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtPackage createPackage() {
		CtPackage e = new CtPackageImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtPackageReference createPackageReference() {
		CtPackageReference e = new CtPackageReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtParameter createParameter() {
		CtParameter e = new CtParameterImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtParameterReference createParameterReference() {
		CtParameterReference e = new CtParameterReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtReturn createReturn() {
		CtReturn e = new CtReturnImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtStatementList createStatementList() {
		CtStatementList e = new CtStatementListImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtSwitch createSwitch() {
		CtSwitch e = new CtSwitchImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtSynchronized createSynchronized() {
		CtSynchronized e = new CtSynchronizedImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtThrow createThrow() {
		CtThrow e = new CtThrowImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtTry createTry() {
		CtTry e = new CtTryImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtTypeParameter createTypeParameter() {
		CtTypeParameter e = new CtTypeParameterImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtTypeParameterReference createTypeParameterReference() {
		CtTypeParameterReference e = new CtTypeParameterReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtTypeReference createTypeReference() {
		CtTypeReference e = new CtTypeReferenceImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtUnaryOperator createUnaryOperator() {
		CtUnaryOperator e = new CtUnaryOperatorImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtVariableAccess createVariableAccess() {
		CtVariableAccess e = new CtVariableAccessImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtCodeSnippetExpression createCodeSnippetExpression() {
		CtCodeSnippetExpression e = new CtCodeSnippetExpressionImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtCodeSnippetStatement createCodeSnippetStatement() {
		CtCodeSnippetStatement e = new CtCodeSnippetStatementImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public CtWhile createWhile() {
		CtWhile e = new CtWhileImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public Factory getMainFactory() {
		return mainFactory;
	}

	public void setMainFactory(Factory mainFactory) {
		this.mainFactory = mainFactory;
	}

	public SourcePosition createSourcePosition(CompilationUnit compilationUnit,
			int start, int end, int[] lineSeparatorPositions) {
		return new SourcePositionImpl(compilationUnit, start, end,
				lineSeparatorPositions);
	}

	public CompilationUnit createCompilationUnit() {
		CompilationUnit cu = new CompilationUnitImpl();
		cu.setFactory(getMainFactory());
		return cu;
	}

	public CompilationUnit createVirtualCompilationUnit() {
		CompilationUnit cu = new CompilationUnitVirtualImpl();
		cu.setFactory(getMainFactory());
		return cu;
	}

	public  CtThisAccess createThisAccess() {
		CtThisAccess e = new CtThisAccessImpl();
		e.setFactory(getMainFactory());
		return e;
	}

	public  CtSuperAccess createSuperAccess() {
		CtSuperAccess e = new CtSuperAccessImpl();
		e.setFactory(getMainFactory());
		return e;
	}

}