/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.ir.nodes; import gw.internal.gosu.parser.*; import gw.lang.parser.IReducedDynamicPropertySymbol; import gw.lang.reflect.IPropertyInfo; import gw.lang.reflect.IPropertyInfoDelegate; import gw.lang.reflect.IRelativeTypeInfo; import gw.lang.reflect.IType; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.IMetaType; import gw.lang.reflect.gs.IGosuPropertyInfo; import gw.lang.reflect.gs.IGosuVarPropertyInfo; import gw.lang.reflect.gs.IGosuEnhancement; import gw.lang.reflect.gs.IGosuClass; import gw.lang.reflect.java.*; import gw.lang.ir.IRType; import gw.internal.gosu.ir.transform.util.IRTypeResolver; import gw.internal.gosu.ir.transform.util.AccessibilityUtil; public class IRPropertyFromPropertyInfo implements IRProperty { private IPropertyInfo _terminalProperty; public IRPropertyFromPropertyInfo(IPropertyInfo originalProperty) { _terminalProperty = originalProperty; while (_terminalProperty instanceof IPropertyInfoDelegate) { _terminalProperty = ((IPropertyInfoDelegate) _terminalProperty).getSource(); } } public IPropertyInfo getTerminalProperty() { return _terminalProperty; } @Override public IRType getType() { return getPropertyIRType( _terminalProperty ); } @Override public String getName() { if( _terminalProperty.getClass() == JavaFieldPropertyInfo.class ) { return ((JavaFieldPropertyInfo)_terminalProperty).getField().getName(); } else { return _terminalProperty.getName(); } } @Override public boolean isField() { return _terminalProperty instanceof IGosuVarPropertyInfo || _terminalProperty instanceof IJavaFieldPropertyInfo; } @Override public boolean isCaptured() { return false; } @Override public IRMethod getGetterMethod() { return new IRMethodForPropertyGetter( this ); } @Override public IRMethod getSetterMethod() { return new IRMethodForPropertySetter( this ); } @Override public IRType getOwningIRType() { if( _terminalProperty instanceof IJavaPropertyInfo ) { // We have to get the owner type from the method because it may be different from the owning type e.g., entity aspects see ContactGosuAspect.AllAdresses IJavaPropertyDescriptor descriptor = ((IJavaPropertyInfo)_terminalProperty).getPropertyDescriptor(); IJavaClassMethod m = descriptor.getReadMethod(); if( m != null ) { return IRTypeResolver.getDescriptor( m.getEnclosingClass() ); } else { m = descriptor.getWriteMethod(); if( m != null ) { return IRTypeResolver.getDescriptor( m.getEnclosingClass() ); } } } else if (_terminalProperty instanceof IJavaFieldPropertyInfo) { IJavaClassField field = ((IJavaFieldPropertyInfo) _terminalProperty).getField(); if (field != null) { return IRTypeResolver.getDescriptor(field.getEnclosingClass()); } } return IRTypeResolver.getDescriptor( _terminalProperty.getOwnersType() ); } @Override public IType getOwningIType() { IType owningType; if( _terminalProperty instanceof IJavaPropertyInfo ) { // We have to get the owner type from the method because it may be different from the owning type e.g., entity aspects see ContactGosuAspect.AllAdresses IJavaPropertyDescriptor descriptor = ((IJavaPropertyInfo)_terminalProperty).getPropertyDescriptor(); IJavaClassMethod m = descriptor.getReadMethod(); if( m != null ) { owningType = TypeSystem.get( m.getEnclosingClass() ); } else { m = descriptor.getWriteMethod(); if( m != null ) { owningType = TypeSystem.get( m.getEnclosingClass() ); } else { owningType = _terminalProperty.getOwnersType(); } } } else if (_terminalProperty instanceof IJavaFieldPropertyInfo) { IJavaClassField field = ((IJavaFieldPropertyInfo) _terminalProperty).getField(); if (field != null) { owningType = TypeSystem.get(field.getEnclosingClass()); } else { owningType = _terminalProperty.getOwnersType(); } } else { owningType = _terminalProperty.getOwnersType(); } if( owningType instanceof IMetaType) { owningType = ((IMetaType)owningType).getType(); } return owningType; } @Override public IRelativeTypeInfo.Accessibility getAccessibility() { return AccessibilityUtil.forFeatureInfo( _terminalProperty ); } @Override public boolean isStatic() { return _terminalProperty.isStatic(); } @Override public IRType getTargetRootIRType() { IRType owner = getOwningIRType(); if( owner instanceof GosuClassIRType && ((GosuClassIRType)owner).getType() instanceof IGosuEnhancement) { return IRTypeResolver.getDescriptor( ((IGosuEnhancement)((GosuClassIRType)owner).getType()).getEnhancedType() ); } else { return owner; } } @Override public boolean isBytecodeProperty() { return (_terminalProperty instanceof IJavaPropertyInfo || _terminalProperty instanceof IGosuPropertyInfo || _terminalProperty instanceof IJavaFieldPropertyInfo || _terminalProperty instanceof IGosuVarPropertyInfo) && !IRFeatureBase.isExternalEntityJavaType( _terminalProperty ); } public IRType getPropertyIRType( IPropertyInfo pi ) { if( pi instanceof IJavaPropertyInfo) { // We have to get the owner type from the method because it may be different from the owning type e.g., entity aspects see ContactGosuAspect.AllAdresses IJavaPropertyDescriptor descriptor = ((IJavaPropertyInfo)pi).getPropertyDescriptor(); IJavaClassMethod m = descriptor.getReadMethod(); if( m != null ) { return IRTypeResolver.getDescriptor( m.getReturnClassInfo() ); } else { m = descriptor.getWriteMethod(); if( m != null ) { return IRTypeResolver.getDescriptor( m.getParameterTypes()[0] ); } } } else if ( pi instanceof IJavaFieldPropertyInfo) { return IRTypeResolver.getDescriptor( ((IJavaFieldPropertyInfo) pi).getField().getType()); } else if (pi instanceof IGosuPropertyInfo) { IReducedDynamicPropertySymbol dps = ((IGosuPropertyInfo)pi).getDps(); return getBoundedPropertyType( dps ); } else if (pi instanceof IGosuVarPropertyInfo) { IType declaredVarType = ((IGosuVarPropertyInfo)pi).getScopedSymbolType(); return IRTypeResolver.getDescriptor( TypeLord.getDefaultParameterizedTypeWithTypeVars( declaredVarType ) ); } return IRTypeResolver.getDescriptor( pi.getFeatureType() ); } public IRType getBoundedPropertyType( IReducedDynamicPropertySymbol dps ) { while( dps instanceof ReducedParameterizedDynamicPropertySymbol) { ReducedParameterizedDynamicPropertySymbol pdfs = (ReducedParameterizedDynamicPropertySymbol)dps; dps = pdfs.getDelegate(); } if( dps.getGosuClass() != null && IGosuClass.ProxyUtil.isProxy( dps.getGosuClass() ) ) { return getBoundedReturnTypeFromProxiedClass( dps ); } return IRTypeResolver.getDescriptor( TypeLord.getDefaultParameterizedTypeWithTypeVars( dps.getType() ) ); } private IRType getBoundedReturnTypeFromProxiedClass( IReducedDynamicPropertySymbol dps ) { IJavaPropertyDescriptor pd = getJavaPropertyFromProxy( dps ); IJavaClassInfo type = pd.getReadMethod() != null ? pd.getReadMethod().getReturnClassInfo() : pd.getPropertyClassInfo(); return JavaClassIRType.get( type ); } private IJavaPropertyDescriptor getJavaPropertyFromProxy( IReducedDynamicPropertySymbol dps ) { IType proxyType = dps.getGosuClass(); IJavaType javaType = (IJavaType) IGosuClass.ProxyUtil.getProxiedType( proxyType ); javaType = (IJavaType)TypeLord.getDefaultParameterizedType( javaType ); IJavaPropertyInfo jpi = (IJavaPropertyInfo)((IRelativeTypeInfo)javaType.getTypeInfo()).getProperty( javaType, dps.getName() ); return jpi.getPropertyDescriptor(); } }