Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
gw.lang.reflect.FeatureManager Maven / Gradle / Ivy
/*
* Copyright 2014 Guidewire Software, Inc.
*/
package gw.lang.reflect;
import gw.config.CommonServices;
import gw.lang.parser.CICS;
import gw.lang.reflect.gs.IGenericTypeVariable;
import gw.lang.reflect.gs.IGosuClass;
import gw.lang.reflect.gs.IGosuEnhancement;
import gw.lang.reflect.java.IJavaType;
import gw.lang.reflect.java.JavaTypes;
import gw.lang.reflect.module.IModule;
import gw.util.DynamicArray;
import gw.util.GosuExceptionUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings({"unchecked"})
public class FeatureManager {
private final boolean _caseSensitive;
private final boolean _addObjectMethods;
private IRelativeTypeInfo _typeInfo;
private volatile Map _methodsInitialized = new HashMap();
private volatile Map _propertiesInitialized = new HashMap();
private volatile InitState _ctorsInitialized = InitState.NotInitialized;
private Map[]> _properties = new HashMap[]>();
private Map _methods = new HashMap();
private List[] _constructors = new List[IRelativeTypeInfo.Accessibility_Size];
private String _superPropertyPrefix;
private IType _supertypeToCopyPropertiesFrom;
public FeatureManager(IRelativeTypeInfo typeInfo, boolean caseSensitive) {
this(typeInfo, caseSensitive, false);
}
public FeatureManager(IRelativeTypeInfo typeInfo, boolean caseSensitive, boolean addObjectMethods) {
_typeInfo = typeInfo;
_caseSensitive = caseSensitive;// && !ILanguageLevel.Util.STANDARD_GOSU();
_addObjectMethods = addObjectMethods;
}
public static IRelativeTypeInfo.Accessibility getAccessibilityForClass( IType ownersClass, IType whosAskin )
{
if( TypeSystem.isIncludeAll() )
{
return IRelativeTypeInfo.Accessibility.PRIVATE;
}
if( ownersClass == null || whosAskin == null )
{
return IRelativeTypeInfo.Accessibility.PUBLIC;
}
if( getTopLevelTypeName( whosAskin ).equals( getTopLevelTypeName( ownersClass ) ) )
{
// Implies private members, which means everything.
return IRelativeTypeInfo.Accessibility.PRIVATE;
}
else if( Modifier.isPrivate( ownersClass.getModifiers() ) )
{
return IRelativeTypeInfo.Accessibility.NONE;
}
else if( isInSameNamespace( ownersClass, whosAskin ) )
{
return IRelativeTypeInfo.Accessibility.INTERNAL;
}
else if( Modifier.isInternal( ownersClass.getModifiers() ) )
{
return IRelativeTypeInfo.Accessibility.NONE;
}
else if( isInEnclosingClassHierarchy( ownersClass, whosAskin ) )
{
return IRelativeTypeInfo.Accessibility.PROTECTED;
}
return IRelativeTypeInfo.Accessibility.PUBLIC;
}
public static boolean isInSameNamespace(IType ownersClass, IType whosAskin) {
ownersClass = IGosuClass.ProxyUtil.getProxiedType( ownersClass );
whosAskin = IGosuClass.ProxyUtil.getProxiedType( whosAskin );
String whosAskinNamespace = getTopLevelEnclosingClassNamespace(whosAskin);
return whosAskinNamespace != null &&
whosAskinNamespace.equals( getTopLevelEnclosingClassNamespace( ownersClass ) );
}
private static String getTopLevelEnclosingClassNamespace(IType type) {
IType topLevelClass = type;
while (topLevelClass.getEnclosingType() != null) {
topLevelClass = topLevelClass.getEnclosingType();
}
return topLevelClass.getNamespace();
}
public static boolean isInEnclosingClassHierarchy(IType ownersClass, IType whosAskin) {
return whosAskin != null && ownersClass != null &&
(isInHierarchy(ownersClass, whosAskin) ||
isInEnhancedTypesHierarchy(ownersClass, whosAskin) ||
isInEnclosingClassHierarchy(ownersClass, whosAskin.getEnclosingType()));
}
protected static boolean isInEnhancedTypesHierarchy(IType ownersClass, IType whosAskin) {
return (whosAskin instanceof IGosuEnhancement &&
((IGosuEnhancement)whosAskin).getEnhancedType() != null &&
ownersClass.isAssignableFrom(((IGosuEnhancement) whosAskin).getEnhancedType()));
}
protected static boolean isInHierarchy(IType ownersClass, IType whosAskin) {
return ownersClass.isAssignableFrom(whosAskin) ||
ownersClass.getEnclosingType() != null && isInHierarchy( ownersClass.getEnclosingType(), whosAskin ) ||
(ownersClass instanceof IGosuClass && ((IGosuClass) ownersClass).isSubClass( whosAskin ));
}
private static String getTopLevelTypeName( IType type )
{
while( type.getEnclosingType() != null )
{
type = TypeSystem.getPureGenericType( type.getEnclosingType() );
}
return TypeSystem.getPureGenericType( type ).getName();
}
public static boolean isFeatureAccessible(IAttributedFeatureInfo property, IRelativeTypeInfo.Accessibility accessibility) {
boolean isAccessible = false;
switch (accessibility) {
case NONE:
break;
case PUBLIC:
if (property.isPublic()) {
isAccessible = true;
}
break;
case PROTECTED:
if (property.isPublic() || property.isProtected()) {
isAccessible = true;
}
break;
case INTERNAL:
if (property.isPublic() || property.isInternal() || property.isProtected()) {
isAccessible = true;
}
break;
case PRIVATE:
if (property.isPublic() || property.isInternal() || property.isProtected() || property.isPrivate()) {
isAccessible = true;
}
break;
}
return isAccessible;
}
public void clear() {
_methodsInitialized = new HashMap();
_propertiesInitialized = new HashMap();
_ctorsInitialized = InitState.NotInitialized;
clearMaps();
}
private void clearMaps() {
for(PropertyNameMap[] properties : _properties.values()) {
for (int i = 0; i < properties.length; i++) {
properties[i] = null;
}
}
for (int i = 0; i < _constructors.length; i++) {
_constructors[i] = null;
}
for(MethodList[] methods : _methods.values()) {
for (int i = 0; i < methods.length; i++) {
methods[i] = null;
}
}
}
private void clearProperties(IModule module) {
PropertyNameMap[] properties = _properties.get(module);
if(properties != null) {
for (int i = 0; i < properties.length; i++) {
properties[i] = null;
}
}
}
private void clearMethods(IModule module) {
MethodList[] methods = _methods.get(module);
if(methods != null) {
for (int i = 0; i < methods.length; i++) {
methods[i] = null;
}
}
}
private void clearCtors() {
for (int i = 0; i < _constructors.length; i++) {
_constructors[i] = null;
}
}
public List getProperties( IRelativeTypeInfo.Accessibility accessibility ) {
maybeInitProperties();
PropertyNameMap[] arr = _properties.get( TypeSystem.getCurrentModule() );
if( arr == null )
{
return Collections.emptyList();
}
PropertyNameMap props = arr[accessibility.ordinal()];
return (List) (props == null ? Collections.emptyList() : props.values());
}
public IPropertyInfo getProperty( IRelativeTypeInfo.Accessibility accessibility, CharSequence propName ) {
maybeInitProperties();
PropertyNameMap[] arr = _properties.get( TypeSystem.getCurrentModule() );
if( arr == null )
{
return null;
}
PropertyNameMap accessMap = arr[accessibility.ordinal()];
return accessMap == null ? null : accessMap.get(convertCharSequenceToCorrectSensitivity(propName));
}
private T convertCharSequenceToCorrectSensitivity(CharSequence propName) {
return (T) (_caseSensitive ? propName == null ? "": propName.toString() : CICS.get( propName ));
}
@SuppressWarnings({"unchecked"})
public MethodList getMethods( IRelativeTypeInfo.Accessibility accessibility) {
maybeInitMethods();
MethodList[] arr = _methods.get( TypeSystem.getCurrentModule() );
if( arr == null )
{
return MethodList.EMPTY;
}
MethodList iMethodInfos = arr[accessibility.ordinal()];
return iMethodInfos == null ? MethodList.EMPTY : iMethodInfos;
}
public IMethodInfo getMethod( IRelativeTypeInfo.Accessibility accessibility, CharSequence methodName, IType... params ) {
maybeInitMethods();
return ITypeInfo.FIND.method( getMethods( accessibility ), methodName, params );
}
@SuppressWarnings({"unchecked"})
public List extends IConstructorInfo> getConstructors( IRelativeTypeInfo.Accessibility accessibility ) {
maybeInitConstructors();
List list = _constructors[accessibility.ordinal()];
return (List) (list == null ? Collections.emptyList() : list);
}
public IConstructorInfo getConstructor( IRelativeTypeInfo.Accessibility accessibility, IType[] params ) {
maybeInitConstructors();
return ITypeInfo.FIND.constructor( getConstructors(accessibility), params );
}
@SuppressWarnings({"ConstantConditions"})
protected void maybeInitMethods() {
IModule module = TypeSystem.getCurrentModule();
if (module == null) {
throw new NullPointerException("Cannot init the FeatureManager with no current module.");
}
if (_methodsInitialized.get(module) != InitState.Initialized && _methodsInitialized.get(module) != InitState.ERROR) {
TypeSystem.lock();
try {
if (_methodsInitialized.get(module) != InitState.Initialized) {
if (_methodsInitialized.get(module) == InitState.Initializing) {
throw new IllegalStateException("Methods for " + _typeInfo.getOwnersType() + " are cyclic.");
}
_methodsInitialized.put(module, InitState.Initializing);
clearMethods( module );
try {
MethodList[] methods = new MethodList[IRelativeTypeInfo.Accessibility_Size];
{
MethodList privateMethods = new MethodList();
if( _addObjectMethods ) {
mergeMethods( privateMethods, convertType( JavaTypes.OBJECT() ), false );
}
if( _typeInfo == null ) {
throw new IllegalStateException( "Null TypeInfo" );
}
if( _typeInfo.getOwnersType() == null ) {
throw new IllegalStateException( "null owner" );
}
if( _typeInfo.getOwnersType().getInterfaces() == null ) {
throw new IllegalStateException( "null interfaces for " + _typeInfo.getOwnersType().getName() );
}
for (IType type : _typeInfo.getOwnersType().getInterfaces()) {
mergeMethods( privateMethods, convertType( type ), false );
}
if ( getSuperType() != null) {
mergeMethods(privateMethods, convertType( getSuperType() ), true);
}
List extends IMethodInfo> declaredMethods = _typeInfo.getDeclaredMethods();
for (IMethodInfo methodInfo : declaredMethods) {
mergeMethod(privateMethods, methodInfo, true);
}
addEnhancementMethods(privateMethods);
privateMethods.trimToSize();
// privateMethods = Collections.unmodifiableList(privateMethods);
// The size checking madness is to save memory. If the lists/maps are the same then reuse.
methods[IRelativeTypeInfo.Accessibility.PRIVATE.ordinal()] = privateMethods;
methods[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()] = privateMethods.filterMethods( IRelativeTypeInfo.Accessibility.PROTECTED );
if (methods[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()].size() == privateMethods.size()) {
methods[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()] = privateMethods;
}
methods[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()] = privateMethods.filterMethods( IRelativeTypeInfo.Accessibility.INTERNAL );
if (methods[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()].size() == methods[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()].size()) {
methods[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()] = methods[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()];
}
methods[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()] = privateMethods.filterMethods( IRelativeTypeInfo.Accessibility.PUBLIC );
if (methods[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()].size() == methods[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()].size()) {
methods[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()] = methods[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()];
}
methods[IRelativeTypeInfo.Accessibility.NONE.ordinal()] = MethodList.EMPTY;
}
_methods.put(module, methods);
_methodsInitialized.put(module, InitState.Initialized);
} finally {
if (_methodsInitialized.get(module) != InitState.Initialized) {
_methodsInitialized.put(module, InitState.ERROR);
}
}
}
} catch ( Exception ex ) {
ex.printStackTrace(); // exception is swallowed by source diff handler? print it again here
throw GosuExceptionUtil.forceThrow( ex, _typeInfo.getOwnersType().getName() );
} finally {
TypeSystem.unlock();
}
}
}
@SuppressWarnings({"ConstantConditions"})
protected void maybeInitProperties() {
maybeInitMethods(); // because properties depend on methods for their getter or setter method !
IModule module = TypeSystem.getCurrentModule();
if (module == null) {
throw new NullPointerException("Cannot init the FeatureManager with no current module.");
}
if (_propertiesInitialized.get(module) != InitState.Initialized && _propertiesInitialized.get(module) != InitState.ERROR) {
TypeSystem.lock();
try {
if (_propertiesInitialized.get(module) != InitState.Initialized) {
if (_propertiesInitialized.get(module) == InitState.Initializing) {
throw new IllegalStateException("Properties for " + _typeInfo.getOwnersType() + " are cyclic.");
}
_propertiesInitialized.put(module, InitState.Initializing);
clearProperties(module);
try {
PropertyNameMap[] properties = new PropertyNameMap[IRelativeTypeInfo.Accessibility_Size];
{
PropertyNameMap privateProps = new PropertyNameMap();
for (IType type : _typeInfo.getOwnersType().getInterfaces()) {
mergeProperties(privateProps, convertType(type), false);
}
IType supertype = getSuperType();
if ( supertype != null ) {
mergeProperties( privateProps, convertType( supertype ), true );
}
List declaredProperties = (List) _typeInfo.getDeclaredProperties();
for (IPropertyInfo property : declaredProperties) {
mergeProperty(privateProps, property, true);
}
addEnhancementProperties(privateProps, _caseSensitive);
privateProps.freeze();
// The size checking madness is to save memory. If the lists/maps are the same then reuse.
properties[IRelativeTypeInfo.Accessibility.PRIVATE.ordinal()] = privateProps;
properties[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()] = convertToMap(filterFeatures(privateProps.values(), IRelativeTypeInfo.Accessibility.PROTECTED));
if (properties[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()].size() == privateProps.size()) {
properties[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()] = privateProps;
}
properties[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()] = convertToMap(filterFeatures(privateProps.values(), IRelativeTypeInfo.Accessibility.INTERNAL));
if (properties[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()].size() == properties[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()].size()) {
properties[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()] = properties[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()];
}
properties[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()] = convertToMap(filterFeatures(privateProps.values(), IRelativeTypeInfo.Accessibility.PUBLIC));
if (properties[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()].size() == properties[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()].size()) {
properties[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()] = properties[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()];
}
properties[IRelativeTypeInfo.Accessibility.NONE.ordinal()] = new PropertyNameMap();
}
_properties.put(module, properties);
_propertiesInitialized.put(module, InitState.Initialized);
} finally {
if (_propertiesInitialized.get(module) != InitState.Initialized) {
_propertiesInitialized.put(module, InitState.ERROR);
}
}
}
} catch ( Exception ex ) {
ex.printStackTrace(); // exception is swallowed by source diff handler? print it again here
throw GosuExceptionUtil.forceThrow( ex, _typeInfo.getOwnersType().getName() );
} finally {
TypeSystem.unlock();
}
}
}
private IType getSuperType() {
IType ownersType = _typeInfo.getOwnersType();
IType supertype = ownersType.getSupertype();
if( supertype == null && ownersType instanceof IJavaType && !_typeInfo.getOwnersType().equals( JavaTypes.OBJECT() ) ) {
supertype = JavaTypes.OBJECT();
}
return supertype;
}
@SuppressWarnings({"ConstantConditions"})
protected void maybeInitConstructors() {
if (_ctorsInitialized != InitState.Initialized && _ctorsInitialized != InitState.ERROR) {
TypeSystem.lock();
try {
if (_ctorsInitialized != InitState.Initialized) {
if (_ctorsInitialized == InitState.Initializing) {
throw new IllegalStateException("Constructors for " + _typeInfo.getOwnersType() + " are cyclic.");
}
_ctorsInitialized = InitState.Initializing;
clearCtors();
try {
if(_ctorsInitialized != InitState.Initialized && _ctorsInitialized != InitState.ERROR) {
clearCtors();
try {
List[] constructors = new List[IRelativeTypeInfo.Accessibility_Size];
{
List privateConstructors = new ArrayList( _typeInfo.getDeclaredConstructors());
((ArrayList) privateConstructors).trimToSize();
privateConstructors = Collections.unmodifiableList(privateConstructors);
constructors[IRelativeTypeInfo.Accessibility.PRIVATE.ordinal()] = Collections.unmodifiableList(privateConstructors);
constructors[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()] = Collections.unmodifiableList((List) filterFeatures(privateConstructors, IRelativeTypeInfo.Accessibility.PROTECTED));
if (constructors[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()].size() == privateConstructors.size()) {
constructors[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()] = privateConstructors;
}
constructors[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()] = Collections.unmodifiableList((List) filterFeatures(privateConstructors, IRelativeTypeInfo.Accessibility.INTERNAL));
if (constructors[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()].size() == constructors[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()].size()) {
constructors[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()] = constructors[IRelativeTypeInfo.Accessibility.PROTECTED.ordinal()];
}
constructors[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()] = Collections.unmodifiableList((List) filterFeatures(privateConstructors, IRelativeTypeInfo.Accessibility.PUBLIC));
if (constructors[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()].size() == constructors[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()].size()) {
constructors[IRelativeTypeInfo.Accessibility.PUBLIC.ordinal()] = constructors[IRelativeTypeInfo.Accessibility.INTERNAL.ordinal()];
}
constructors[IRelativeTypeInfo.Accessibility.NONE.ordinal()] = Collections.emptyList();
}
_constructors = constructors;
_ctorsInitialized = InitState.Initialized;
} finally {
if(_ctorsInitialized != InitState.Initialized) {
_ctorsInitialized = InitState.ERROR;
}
}
}
_ctorsInitialized = InitState.Initialized;
} finally {
if (_ctorsInitialized != InitState.Initialized) {
_ctorsInitialized = InitState.ERROR;
}
}
}
} catch ( Exception ex ) {
// ex.printStackTrace(); // exception is swallowed by source diff handler? print it again here
throw GosuExceptionUtil.forceThrow( ex, _typeInfo.getOwnersType().getName() );
} finally {
TypeSystem.unlock();
}
}
}
protected IType convertType(IType type) {
return type;
}
protected void addEnhancementMethods(List privateMethods) {
CommonServices.getEntityAccess().addEnhancementMethods( _typeInfo.getOwnersType(), privateMethods );
}
protected void addEnhancementProperties(PropertyNameMap privateProps, boolean caseSensitive) {
CommonServices.getEntityAccess().addEnhancementProperties(_typeInfo.getOwnersType(), privateProps, caseSensitive );
}
public void setSuperPropertyPrefix( String superPropertyPrefix ) {
_superPropertyPrefix = superPropertyPrefix;
}
public void setSupertypeToCopyPropertiesFrom( IType supertypeToCopyPropertiesFrom ) {
_supertypeToCopyPropertiesFrom = supertypeToCopyPropertiesFrom;
}
private PropertyNameMap convertToMap(List features) {
PropertyNameMap ret = new PropertyNameMap();
for (IPropertyInfo feature : features) {
ret.put(convertCharSequenceToCorrectSensitivity(feature.getName()), feature);
}
ret.freeze();
return ret;
}
private List filterFeatures(List props, IRelativeTypeInfo.Accessibility accessibility) {
ArrayList ret = new ArrayList();
for (Object o : props) {
IAttributedFeatureInfo property = (IAttributedFeatureInfo) o;
if (isFeatureAccessible(property, accessibility)) {
ret.add(property);
}
}
ret.trimToSize();
return ret;
}
protected void mergeProperties(PropertyNameMap props, IType type, boolean replace) {
if( type != null )
{
List extends IPropertyInfo> propertyInfos;
if (type.getTypeInfo() instanceof IRelativeTypeInfo) {
propertyInfos = ((IRelativeTypeInfo) type.getTypeInfo()).getProperties( _typeInfo.getOwnersType());
} else {
propertyInfos = type.getTypeInfo().getProperties();
}
for (IPropertyInfo propertyInfo : propertyInfos) {
IType ownersType = propertyInfo.getOwnersType();
if ( _supertypeToCopyPropertiesFrom == null || ownersType.isAssignableFrom( _supertypeToCopyPropertiesFrom ) || ownersType instanceof IGosuEnhancement ) {
mergeProperty( props, propertyInfo, replace );
}
}
}
}
protected void mergeProperty(PropertyNameMap props, IPropertyInfo propertyInfo, boolean replace) {
boolean prependPrefix = _superPropertyPrefix != null && ! propertyInfo.getOwnersType().equals( _typeInfo.getOwnersType() );
T cs = convertCharSequenceToCorrectSensitivity( prependPrefix ? ( _superPropertyPrefix + propertyInfo.getName() ) : propertyInfo.getName() );
if ( replace || shouldReplace( props, cs, propertyInfo ) ) {
if ( prependPrefix ) {
props.put( cs, new PropertyInfoDelegate( propertyInfo.getContainer(), propertyInfo, cs.toString() ) );
}
else {
props.put(cs, propertyInfo);
}
}
}
private boolean shouldReplace( PropertyNameMap props, T cs, IPropertyInfo propertyInfo )
{
IPropertyInfo pi = props.get( cs );
if( pi == null )
{
return true;
}
if( propertyInfo.isReadable() && propertyInfo.isWritable( _typeInfo.getOwnersType() ) )
{
return !pi.isReadable() || !pi.isWritable();
}
return false;
}
protected void mergeMethods(MethodList methods, IType type, boolean replace) {
List extends IMethodInfo> methodInfos;
if (type != null && !TypeSystem.isDeleted(type)) {
if (type.getTypeInfo() instanceof IRelativeTypeInfo) {
methodInfos = ((IRelativeTypeInfo) type.getTypeInfo()).getMethods( _typeInfo.getOwnersType());
} else {
methodInfos = type.getTypeInfo().getMethods();
}
for (IMethodInfo methodInfo : methodInfos) {
if( !type.isInterface() || !methodInfo.isStatic() ) { // static interface methods are not inherited
mergeMethod(methods, methodInfo, replace);
}
}
}
}
protected void mergeMethod(MethodList methods, IMethodInfo thisMethodInfo, boolean replace) {
IType[] paramTypes = null;
DynamicArray extends IMethodInfo> matches = methods.getMethods( thisMethodInfo.getDisplayName() );
for( int i = 0; i < matches.size(); i++ )
{
IMethodInfo superMethodInfo = matches.get( i );
if( superMethodInfo.getParameters().length == thisMethodInfo.getParameters().length )
{
paramTypes = paramTypes == null ? removeGenericMethodParameters( thisMethodInfo ) : paramTypes;
IType[] superParamTypes = removeGenericMethodParameters( superMethodInfo );
if( argsEqual( superParamTypes, paramTypes ) )
{
if( replace )
{
methods.set( methods.indexOf( superMethodInfo ), thisMethodInfo );
}
return;
}
}
}
methods.add(thisMethodInfo);
}
private IType[] removeGenericMethodParameters(IMethodInfo thisMethodInfo) {
IParameterInfo[] parameters = thisMethodInfo.getParameters();
IType[] paramTypes = new IType[parameters.length];
List methodTypeVars = null;
if (thisMethodInfo instanceof IGenericMethodInfo) {
IGenericTypeVariable[] typeVariables = ((IGenericMethodInfo) thisMethodInfo).getTypeVariables();
if (typeVariables != null && typeVariables.length > 0) {
methodTypeVars = new ArrayList();
for (IGenericTypeVariable typeVariable : typeVariables) {
ITypeVariableType typeVarType = typeVariable.getTypeVariableDefinition().getType();
methodTypeVars.add(typeVarType);
}
}
}
for (int i = 0; i < parameters.length; i++) {
IParameterInfo parameter = parameters[i];
IType featureType = parameter.getFeatureType();
if (methodTypeVars != null) {
featureType = TypeSystem.boundTypes(featureType, methodTypeVars);
}
paramTypes[i] = featureType;
}
return paramTypes;
}
protected boolean areMethodParamsEqual(IType thisMethodParamType, IType superMethodParamType) {
return thisMethodParamType.equals(superMethodParamType);
}
private boolean argsEqual(IType[] parameters, IType[] parameters1) {
if (parameters.length == parameters1.length) {
for (int i = 0; i < parameters.length; i++) {
IType parameter = parameters[i];
if ( !areMethodParamsEqual(parameter, parameters1[i]) ) {
return false;
}
}
return true;
}
return false;
}
public String toString() {
return _typeInfo.getOwnersType().getName();
}
private enum InitState {
NotInitialized,
Initializing,
ERROR, Initialized
}
}