| /******************************************************************************* |
| * Copyright (c) 2000, 2005 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.typeconstraints; |
| |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.IBinding; |
| 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.ReturnStatement; |
| import org.eclipse.jdt.core.dom.Type; |
| import org.eclipse.jdt.internal.corext.Assert; |
| import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| |
| /** |
| * Abstract Factory for the creation of ConstraintVariables. This default factory |
| * ensures that no duplicate ConstraintVariables are created, so that Object.equals() |
| * can be used to compare ConstraintVariables. |
| */ |
| public class ConstraintVariableFactory implements IConstraintVariableFactory { |
| |
| private Map/*<IBinding,IBinding>*/ fBindingMap= new HashMap(); |
| |
| private Map/*<IBinding + CompilationUnitRange,ExpressionVariable>*/ fExpressionMap= new Hashtable(); |
| private Map/*<Integer,ExpressionVariable>*/ fLiteralMap= new HashMap(); |
| private Map/*<CompilationUnitRange,TypeVariable>*/ fTypeVariableMap= new HashMap(); |
| private Map/*<String,DeclaringTypeVariable>*/ fDeclaringTypeVariableMap= new HashMap(); |
| private Map/*<String,ParameterTypeVariable>*/ fParameterMap= new HashMap(); |
| private Map/*<String,RawBindingVariable>*/ fRawBindingMap= new HashMap(); |
| private Map/*<String,ReturnTypeVariable>*/ fReturnVariableMap= new HashMap(); |
| |
| public static final boolean REPORT= false; |
| protected int nrCreated=0; |
| protected int nrRetrieved=0; |
| |
| public int getNumCreated(){ |
| return nrCreated; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeExpressionVariable(org.eclipse.jdt.core.dom.Expression, org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IContext) |
| */ |
| public ConstraintVariable makeExpressionOrTypeVariable(Expression expression, |
| IContext context) { |
| IBinding binding= ExpressionVariable.resolveBinding(expression); |
| |
| if (binding instanceof ITypeBinding){ |
| ICompilationUnit cu= ASTCreator.getCu(expression); |
| Assert.isNotNull(cu); |
| CompilationUnitRange range= new CompilationUnitRange(cu, expression); |
| return makeTypeVariable((ITypeBinding)getKey(binding), expression.toString(), range); |
| } |
| |
| if (ASTNodes.isLiteral(expression)){ |
| Integer nodeType= new Integer(expression.getNodeType()); |
| if (! fLiteralMap.containsKey(nodeType)){ |
| fLiteralMap.put(nodeType, new ExpressionVariable(expression)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (ExpressionVariable) fLiteralMap.get(nodeType); |
| } |
| |
| // For ExpressionVariables, there are two cases. If the expression has a binding |
| // we use that as the key. Otherwise, we use the CompilationUnitRange. See |
| // also ExpressionVariable.equals() |
| ExpressionVariable ev; |
| Object key; |
| if (binding != null){ |
| key= getKey(binding); |
| } else { |
| key= new CompilationUnitRange(ASTCreator.getCu(expression), expression); |
| } |
| ev= (ExpressionVariable)fExpressionMap.get(key); |
| |
| if (ev != null){ |
| if (REPORT) nrRetrieved++; |
| } else { |
| ev= new ExpressionVariable(expression); |
| fExpressionMap.put(key, ev); |
| if (REPORT) nrCreated++; |
| if (REPORT) dumpConstraintStats(); |
| } |
| return ev; |
| } |
| |
| |
| // |
| // The method IBinding.equals() does not have the desired behavior, and Bindings.equals() |
| // must be used to compare bindings. We use an additional layer of Hashing. |
| // |
| private IBinding getKey(IBinding binding) { |
| if (fBindingMap.containsKey(binding)){ |
| return (IBinding)fBindingMap.get(binding); |
| } else { |
| for (Iterator it= fBindingMap.keySet().iterator(); it.hasNext(); ){ |
| IBinding b2= (IBinding)it.next(); |
| if (Bindings.equals(binding, b2)){ |
| fBindingMap.put(binding, b2); |
| return b2; |
| } |
| } |
| fBindingMap.put(binding, binding); |
| return binding; |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeDeclaringTypeVariable(org.eclipse.jdt.core.dom.ITypeBinding) |
| */ |
| public DeclaringTypeVariable makeDeclaringTypeVariable(ITypeBinding memberTypeBinding) { |
| String key = memberTypeBinding.getKey(); |
| if (! fDeclaringTypeVariableMap.containsKey(key)){ |
| fDeclaringTypeVariableMap.put(key, new DeclaringTypeVariable(memberTypeBinding)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (DeclaringTypeVariable)fDeclaringTypeVariableMap.get(key); |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeDeclaringTypeVariable(org.eclipse.jdt.core.dom.IVariableBinding) |
| */ |
| public DeclaringTypeVariable makeDeclaringTypeVariable(IVariableBinding fieldBinding) { |
| String key= fieldBinding.getKey(); |
| if (! fDeclaringTypeVariableMap.containsKey(key)){ |
| fDeclaringTypeVariableMap.put(key, new DeclaringTypeVariable(fieldBinding)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (DeclaringTypeVariable)fDeclaringTypeVariableMap.get(key); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeDeclaringTypeVariable(org.eclipse.jdt.core.dom.IMethodBinding) |
| */ |
| public DeclaringTypeVariable makeDeclaringTypeVariable(IMethodBinding methodBinding) { |
| String key= methodBinding.getKey(); |
| if (! fDeclaringTypeVariableMap.containsKey(key)){ |
| fDeclaringTypeVariableMap.put(key, new DeclaringTypeVariable(methodBinding)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (DeclaringTypeVariable)fDeclaringTypeVariableMap.get(key); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeParameterTypeVariable(org.eclipse.jdt.core.dom.IMethodBinding, int) |
| */ |
| public ParameterTypeVariable makeParameterTypeVariable(IMethodBinding methodBinding, |
| int parameterIndex) { |
| String key= methodBinding.getKey() + parameterIndex; |
| if (! fParameterMap.containsKey(key)){ |
| fParameterMap.put(key, new ParameterTypeVariable(methodBinding, parameterIndex)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (ParameterTypeVariable)fParameterMap.get(key); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeRawBindingVariable(org.eclipse.jdt.core.dom.ITypeBinding) |
| */ |
| public RawBindingVariable makeRawBindingVariable(ITypeBinding binding) { |
| String key = binding.getKey(); |
| if (! fRawBindingMap.containsKey(key)){ |
| fRawBindingMap.put(key, new RawBindingVariable(binding)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (RawBindingVariable)fRawBindingMap.get(key); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeReturnTypeVariable(org.eclipse.jdt.core.dom.ReturnStatement) |
| */ |
| public ReturnTypeVariable makeReturnTypeVariable(ReturnStatement returnStatement) { |
| return makeReturnTypeVariable(ReturnTypeVariable.getMethod(returnStatement).resolveBinding()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeReturnTypeVariable(org.eclipse.jdt.core.dom.IMethodBinding) |
| */ |
| public ReturnTypeVariable makeReturnTypeVariable(IMethodBinding methodBinding) { |
| String key= methodBinding.getKey(); |
| if (!fReturnVariableMap.containsKey(key)){ |
| fReturnVariableMap.put(key, new ReturnTypeVariable(methodBinding)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (ReturnTypeVariable)fReturnVariableMap.get(key); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeTypeVariable(org.eclipse.jdt.core.dom.Type) |
| */ |
| public TypeVariable makeTypeVariable(Type type) { |
| ICompilationUnit cu= ASTCreator.getCu(type); |
| Assert.isNotNull(cu); |
| CompilationUnitRange range= new CompilationUnitRange(cu, type); |
| if (! fTypeVariableMap.containsKey(range)){ |
| fTypeVariableMap.put(range, new TypeVariable(type)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (TypeVariable) fTypeVariableMap.get(range); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.IConstraintVariableFactory#makeTypeVariable(org.eclipse.jdt.core.dom.ITypeBinding, java.lang.String, org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange) |
| */ |
| public TypeVariable makeTypeVariable(ITypeBinding binding, String source, CompilationUnitRange range) { |
| if (! fTypeVariableMap.containsKey(range)){ |
| fTypeVariableMap.put(range, new TypeVariable(binding, source, range)); |
| if (REPORT) nrCreated++; |
| } else { |
| if (REPORT) nrRetrieved++; |
| } |
| if (REPORT) dumpConstraintStats(); |
| return (TypeVariable) fTypeVariableMap.get(range); |
| } |
| |
| protected void dumpConstraintStats() { |
| System.out.println("created: " + nrCreated + ", retrieved: " + nrRetrieved); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| } |