]> git.uio.no Git - ifi-stolz-refaktor.git/blobdiff - case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/constraints/SuperTypeConstraintsModel.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / core refactoring / org / eclipse / jdt / internal / corext / refactoring / structure / constraints / SuperTypeConstraintsModel.java
diff --git a/case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/constraints/SuperTypeConstraintsModel.java b/case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/constraints/SuperTypeConstraintsModel.java
new file mode 100644 (file)
index 0000000..af92158
--- /dev/null
@@ -0,0 +1,604 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.corext.refactoring.structure.constraints;
+
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jdt.core.dom.CastExpression;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.Type;
+
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeEnvironment;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraint2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ImmutableTypeVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.IndependentTypeVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterTypeVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ReturnTypeVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.SubTypeConstraint2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.VariableVariable2;
+import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
+
+
+/**
+ * Type constraints model to hold all type constraints to replace type occurrences by a given supertype.
+ *
+ * @since 3.1
+ */
+public final class SuperTypeConstraintsModel {
+
+       /** Customized implementation of a hash set 
+        * @param <E> the element type */
+       private static class HashedSet<E> extends AbstractSet<E> {
+
+               /** The backing hash map */
+               private final Map<E, E> fImplementation= new HashMap<E, E>();
+
+               /*
+                * @see java.util.AbstractCollection#add(java.lang.Object)
+                */
+               @Override
+               public final boolean add(final E object) {
+                       return fImplementation.put(object, object) == null;
+               }
+
+               /**
+                * Attempts to add the specified object to this set.
+                *
+                * @param object the object to add
+                * @return An already existing object considered equal to the specified one, or the newly added object
+                */
+               public final E addExisting(final E object) {
+                       final E result= fImplementation.get(object);
+                       if (result != null)
+                               return result;
+                       fImplementation.put(object, object);
+                       return object;
+               }
+
+               /*
+                * @see java.util.AbstractCollection#clear()
+                */
+               @Override
+               public final void clear() {
+                       fImplementation.clear();
+               }
+
+               /*
+                * @see java.util.AbstractCollection#contains(java.lang.Object)
+                */
+               @Override
+               public final boolean contains(final Object object) {
+                       return fImplementation.containsKey(object);
+               }
+
+               /*
+                * @see java.util.AbstractCollection#isEmpty()
+                */
+               @Override
+               public final boolean isEmpty() {
+                       return fImplementation.isEmpty();
+               }
+
+               /*
+                * @see java.util.AbstractCollection#iterator()
+                */
+               @Override
+               public final Iterator<E> iterator() {
+                       return fImplementation.keySet().iterator();
+               }
+
+               /*
+                * @see java.util.AbstractCollection#remove(java.lang.Object)
+                */
+               @Override
+               public final boolean remove(final Object object) {
+                       return fImplementation.remove(object) == object;
+               }
+
+               /*
+                * @see java.util.AbstractCollection#size()
+                */
+               @Override
+               public final int size() {
+                       return fImplementation.size();
+               }
+       }
+
+       /** The usage data */
+       private static final String DATA_USAGE= "us"; //$NON-NLS-1$
+
+       /** Maximal number of TTypes */
+       private static final int MAX_CACHE= 64;
+
+       /**
+        * Returns the usage of the specified constraint variable.
+        *
+        * @param variable the constraint variable
+        * @return the usage of the constraint variable (element type: <code>ITypeConstraint2</code>)
+        */
+       public static Collection<ITypeConstraint2> getVariableUsage(final ConstraintVariable2 variable) {
+               final Object data= variable.getData(DATA_USAGE);
+               if (data == null) {
+                       return Collections.emptyList();
+               } else if (data instanceof Collection) {
+                       @SuppressWarnings("unchecked")
+                       Collection<ITypeConstraint2> collection= (Collection<ITypeConstraint2>) data;
+                       return Collections.unmodifiableCollection(collection);
+               } else {
+                       return Collections.singletonList((ITypeConstraint2) data);
+               }
+       }
+
+       /**
+        * Is the type represented by the specified binding a constrained type?
+        *
+        * @param binding the binding to check, or <code>null</code>
+        * @return <code>true</code> if it is constrained, <code>false</code> otherwise
+        */
+       public static boolean isConstrainedType(final ITypeBinding binding) {
+               return binding != null && !binding.isSynthetic() && !binding.isPrimitive();
+       }
+
+       /**
+        * Sets the usage of the specified constraint variable.
+        *
+        * @param variable the constraint variable
+        * @param constraint the type constraint
+        */
+       public static void setVariableUsage(final ConstraintVariable2 variable, ITypeConstraint2 constraint) {
+               final Object data= variable.getData(DATA_USAGE);
+               if (data == null) {
+                       variable.setData(DATA_USAGE, constraint);
+               } else if (data instanceof Collection) {
+                       @SuppressWarnings("unchecked")
+                       Collection<ITypeConstraint2> collection= (Collection<ITypeConstraint2>) data;
+                       collection.add(constraint);
+               } else {
+                       final Collection<Object> usage= new ArrayList<Object>(2);
+                       usage.add(data);
+                       usage.add(constraint);
+                       variable.setData(DATA_USAGE, usage);
+               }
+       }
+
+       /** The cast variables (element type: <code>CastVariable2</code>) */
+       private final Collection<CastVariable2> fCastVariables= new ArrayList<CastVariable2>();
+
+       /** The compliance level */
+       private int fCompliance= 3;
+
+       /** The set of constraint variables (element type: <code>ConstraintVariable2</code>) */
+       private final HashedSet<ConstraintVariable2> fConstraintVariables= new HashedSet<ConstraintVariable2>();
+
+       /** The covariant type constraints (element type: <code>CovariantTypeConstraint</code>) */
+       private final Collection<ITypeConstraint2> fCovariantTypeConstraints= new ArrayList<ITypeConstraint2>();
+
+       /** The type environment to use */
+       private TypeEnvironment fEnvironment;
+
+       /** The subtype to replace */
+       private final TType fSubType;
+
+       /** The supertype as replacement */
+       private final TType fSuperType;
+
+       /** The TType cache */
+       private Map<String, TType> fTTypeCache= new LinkedHashMap<String, TType>(MAX_CACHE, 0.75f, true) {
+
+               private static final long serialVersionUID= 1L;
+
+               @Override
+               protected final boolean removeEldestEntry(Map.Entry<String, TType> entry) {
+                       return size() > MAX_CACHE;
+               }
+       };
+
+       /** The set of type constraints (element type: <code>ITypeConstraint2</code>) */
+       private final Set<ITypeConstraint2> fTypeConstraints= new HashSet<ITypeConstraint2>();
+
+       /**
+        * Creates a new super type constraints model.
+        *
+        * @param environment the type environment
+        * @param subType the subtype to replace
+        * @param superType the supertype replacement
+        */
+       public SuperTypeConstraintsModel(final TypeEnvironment environment, TType subType, TType superType) {
+               fEnvironment= environment;
+               fSubType= subType;
+               fSuperType= superType;
+       }
+
+       /**
+        * Gets called when the creation of the model begins.
+        */
+       public final void beginCreation() {
+               // Do nothing right now
+       }
+
+       /**
+        * Creates a cast variable.
+        *
+        * @param expression the cast expression
+        * @param variable the associated constraint variable
+        * @return the created cast variable
+        */
+       public final ConstraintVariable2 createCastVariable(final CastExpression expression, final ConstraintVariable2 variable) {
+               ITypeBinding binding= expression.resolveTypeBinding();
+               if (binding.isArray())
+                       binding= binding.getElementType();
+               if (isConstrainedType(binding)) {
+                       final CastVariable2 result= new CastVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(expression), expression), variable);
+                       fCastVariables.add(result);
+                       return result;
+               }
+               return null;
+       }
+
+       /**
+        * Creates a conditional type constraint.
+        *
+        * @param expressionVariable the expression type constraint variable
+        * @param thenVariable the then type constraint variable
+        * @param elseVariable the else type constraint variable
+        */
+       public final void createConditionalTypeConstraint(final ConstraintVariable2 expressionVariable, final ConstraintVariable2 thenVariable, final ConstraintVariable2 elseVariable) {
+               final ITypeConstraint2 constraint= new ConditionalTypeConstraint(expressionVariable, thenVariable, elseVariable);
+               if (!fTypeConstraints.contains(constraint)) {
+                       fTypeConstraints.add(constraint);
+                       setVariableUsage(expressionVariable, constraint);
+                       setVariableUsage(thenVariable, constraint);
+                       setVariableUsage(elseVariable, constraint);
+               }
+       }
+
+       /**
+        * Creates a subtype constraint.
+        *
+        * @param descendant the descendant type constraint variable
+        * @param ancestor the ancestor type constraint variable
+        */
+       public final void createCovariantTypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) {
+               final ITypeConstraint2 constraint= new CovariantTypeConstraint(descendant, ancestor);
+               if (!fTypeConstraints.contains(constraint)) {
+                       fTypeConstraints.add(constraint);
+                       fCovariantTypeConstraints.add(constraint);
+                       setVariableUsage(descendant, constraint);
+                       setVariableUsage(ancestor, constraint);
+               }
+       }
+
+       /**
+        * Creates a declaring type variable.
+        * <p>
+        * A declaring type variable stands for a type where something has been declared.
+        * </p>
+        *
+        * @param type the type binding
+        * @return the created declaring type variable
+        */
+       public final ConstraintVariable2 createDeclaringTypeVariable(ITypeBinding type) {
+               if (type.isArray())
+                       type= type.getElementType();
+               type= type.getTypeDeclaration();
+               return fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type)));
+       }
+
+       /**
+        * Creates an equality constraint.
+        *
+        * @param left the left typeconstraint variable
+        * @param right the right typeconstraint variable
+        */
+       public final void createEqualityConstraint(final ConstraintVariable2 left, final ConstraintVariable2 right) {
+               if (left != null && right != null) {
+                       final TypeEquivalenceSet first= left.getTypeEquivalenceSet();
+                       final TypeEquivalenceSet second= right.getTypeEquivalenceSet();
+                       if (first == null) {
+                               if (second == null) {
+                                       final TypeEquivalenceSet set= new TypeEquivalenceSet(left, right);
+                                       left.setTypeEquivalenceSet(set);
+                                       right.setTypeEquivalenceSet(set);
+                               } else {
+                                       second.add(left);
+                                       left.setTypeEquivalenceSet(second);
+                               }
+                       } else {
+                               if (second == null) {
+                                       first.add(right);
+                                       right.setTypeEquivalenceSet(first);
+                               } else if (first == second)
+                                       return;
+                               else {
+                                       final ConstraintVariable2[] variables= second.getContributingVariables();
+                                       first.addAll(variables);
+                                       for (int index= 0; index < variables.length; index++)
+                                               variables[index].setTypeEquivalenceSet(first);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Creates an exception variable.
+        *
+        * @param name the name of the thrown exception
+        * @return the created exception variable
+        */
+       public final ConstraintVariable2 createExceptionVariable(final Name name) {
+               final ITypeBinding binding= name.resolveTypeBinding();
+               if (isConstrainedType(binding))
+                       return fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(name), name)));
+               return null;
+       }
+
+       /**
+        * Creates an immutable type variable.
+        *
+        * @param type the type binding
+        * @return the created plain type variable
+        */
+       public final ConstraintVariable2 createImmutableTypeVariable(ITypeBinding type) {
+               if (type.isArray())
+                       type= type.getElementType();
+               if (isConstrainedType(type))
+                       return fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type)));
+               return null;
+       }
+
+       /**
+        * Creates an independent type variable.
+        * <p>
+        * An independant type variable stands for an arbitrary type.
+        * </p>
+        *
+        * @param type the type binding
+        * @return the created independant type variable
+        */
+       public final ConstraintVariable2 createIndependentTypeVariable(ITypeBinding type) {
+               if (type.isArray())
+                       type= type.getElementType();
+               if (isConstrainedType(type))
+                       return fConstraintVariables.addExisting(new IndependentTypeVariable2(createTType(type)));
+               return null;
+       }
+
+       /**
+        * Creates a new method parameter variable.
+        *
+        * @param method the method binding
+        * @param index the index of the parameter
+        * @return the created method parameter variable
+        */
+       public final ConstraintVariable2 createMethodParameterVariable(final IMethodBinding method, final int index) {
+               final ITypeBinding[] parameters= method.getParameterTypes();
+               if (parameters.length < 1)
+                       return null;
+               ITypeBinding binding= parameters[Math.min(index, parameters.length - 1)];
+               if (binding.isArray())
+                       binding= binding.getElementType();
+               if (isConstrainedType(binding)) {
+                       ConstraintVariable2 variable= null;
+                       final TType type= createTType(binding);
+                       if (method.getDeclaringClass().isFromSource())
+                               variable= new ParameterTypeVariable2(type, index, method.getMethodDeclaration());
+                       else
+                               variable= new ImmutableTypeVariable2(type);
+                       return fConstraintVariables.addExisting(variable);
+               }
+               return null;
+       }
+
+       /**
+        * Creates a new return type variable.
+        *
+        * @param method the method binding
+        * @return the created return type variable
+        */
+       public final ConstraintVariable2 createReturnTypeVariable(final IMethodBinding method) {
+               if (!method.isConstructor()) {
+                       ITypeBinding binding= method.getReturnType();
+                       if (binding != null && binding.isArray())
+                               binding= binding.getElementType();
+                       if (binding != null && isConstrainedType(binding)) {
+                               ConstraintVariable2 variable= null;
+                               final TType type= createTType(binding);
+                               if (method.getDeclaringClass().isFromSource())
+                                       variable= new ReturnTypeVariable2(type, method);
+                               else
+                                       variable= new ImmutableTypeVariable2(type);
+                               return fConstraintVariables.addExisting(variable);
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Creates a subtype constraint.
+        *
+        * @param descendant the descendant type constraint variable
+        * @param ancestor the ancestor type constraint variable
+        */
+       public final void createSubtypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) {
+               final ITypeConstraint2 constraint= new SubTypeConstraint2(descendant, ancestor);
+               if (!fTypeConstraints.contains(constraint)) {
+                       fTypeConstraints.add(constraint);
+                       setVariableUsage(descendant, constraint);
+                       setVariableUsage(ancestor, constraint);
+               }
+       }
+
+       /**
+        * Creates a new TType for the corresponding binding.
+        *
+        * @param binding The type binding
+        * @return The corresponding TType
+        */
+       public final TType createTType(final ITypeBinding binding) {
+               final String key= binding.getKey();
+               final TType cached= fTTypeCache.get(key);
+               if (cached != null)
+                       return cached;
+               final TType type= fEnvironment.create(binding);
+               fTTypeCache.put(key, type);
+               return type;
+       }
+
+       /**
+        * Creates a type variable.
+        *
+        * @param type the type binding
+        * @param range the compilation unit range
+        * @return the created type variable
+        */
+       public final ConstraintVariable2 createTypeVariable(ITypeBinding type, final CompilationUnitRange range) {
+               if (type.isArray())
+                       type= type.getElementType();
+               if (isConstrainedType(type))
+                       return fConstraintVariables.addExisting(new TypeVariable2(createTType(type), range));
+               return null;
+       }
+
+       /**
+        * Creates a type variable.
+        *
+        * @param type the type
+        * @return the created type variable
+        */
+       public final ConstraintVariable2 createTypeVariable(final Type type) {
+               ITypeBinding binding= type.resolveBinding();
+               if (binding != null) {
+                       if (binding.isArray())
+                               binding= binding.getElementType();
+                       if (isConstrainedType(binding))
+                               return fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(type), type)));
+               }
+               return null;
+       }
+
+       /**
+        * Creates a variable type variable.
+        *
+        * @param binding the variable binding
+        * @return the created variable variable
+        */
+       public final ConstraintVariable2 createVariableVariable(final IVariableBinding binding) {
+               ITypeBinding type= binding.getType();
+               if (type.isArray())
+                       type= type.getElementType();
+               if (isConstrainedType(type)) {
+                       ConstraintVariable2 variable= null;
+                       final IVariableBinding declaration= binding.getVariableDeclaration();
+                       if (declaration.isField()) {
+                               final ITypeBinding declaring= declaration.getDeclaringClass();
+                               if (!declaring.isFromSource())
+                                       variable= new ImmutableTypeVariable2(createTType(type));
+                       } else {
+                               final IMethodBinding declaring= declaration.getDeclaringMethod();
+                               if (declaring != null && !declaring.getDeclaringClass().isFromSource())
+                                       variable= new ImmutableTypeVariable2(createTType(type));
+                       }
+                       if (variable == null)
+                               variable= new VariableVariable2(createTType(type), declaration);
+                       return fConstraintVariables.addExisting(variable);
+               }
+               return null;
+       }
+
+       /**
+        * Gets called when the creation of the model ends.
+        */
+       public final void endCreation() {
+               fEnvironment= null;
+               fTTypeCache= null;
+       }
+
+       /**
+        * Returns the cast variables of this model.
+        *
+        * @return the cast variables (element type: <code>CastVariable2</code>)
+        */
+       public final Collection<CastVariable2> getCastVariables() {
+               return Collections.unmodifiableCollection(fCastVariables);
+       }
+
+       /**
+        * Returns the compliance level to use.
+        *
+        * @return the compliance level
+        */
+       public final int getCompliance() {
+               return fCompliance;
+       }
+
+       /**
+        * Returns the constraint variables of this model.
+        *
+        * @return the constraint variables (element type: <code>ConstraintVariable2</code>)
+        */
+       public final Collection<ConstraintVariable2> getConstraintVariables() {
+               return Collections.unmodifiableCollection(fConstraintVariables);
+       }
+
+       /**
+        * Returns the subtype to be replaced.
+        *
+        * @return the subtype to be replaced
+        */
+       public final TType getSubType() {
+               return fSubType;
+       }
+
+       /**
+        * Returns the supertype as replacement.
+        *
+        * @return the supertype as replacement
+        */
+       public final TType getSuperType() {
+               return fSuperType;
+       }
+
+       /**
+        * Returns the type constraints of this model.
+        *
+        * @return the type constraints (element type: <code>ITypeConstraint2</code>)
+        */
+       public final Collection<ITypeConstraint2> getTypeConstraints() {
+               return Collections.unmodifiableCollection(fTypeConstraints);
+       }
+
+       /**
+        * Sets the compliance level to use.
+        *
+        * @param level the compliance level to use. The argument must be one of the <code>AST.JLSx</code> constants.
+        */
+       public final void setCompliance(final int level) {
+               fCompliance= level;
+       }
+}
\ No newline at end of file