/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser;
import gw.lang.reflect.IPropertyInfo;
import gw.lang.reflect.IRelativeTypeInfo;
import gw.lang.reflect.IScriptabilityModifier;
import gw.lang.reflect.IType;
import gw.lang.reflect.ITypeInfo;
import gw.lang.reflect.gs.IGosuProgram;
import gw.lang.reflect.java.JavaTypes;
import gw.util.IFeatureFilter;
/**
* BeanAccess is a helper class to facilitate JavaBean introspection esp. Descriptor
* hierarchy navigation. Its primary function is to aid in Property and Method type
* discovery as well as Property and Method evaluation and invocation, respectively.
*/
public class SimpleBeanAccess
{
/**
* private to enforce singleton access.
*/
private SimpleBeanAccess()
{
}
/**
* Resolves the property directly, as if the type were requesting it, giving access to all properties
*/
public static IPropertyInfo getPropertyInfoDirectly( IType classBean, String strProperty )
{
return getPropertyInfo( classBean, classBean, strProperty, null, null, null );
}
public static IPropertyInfo getPropertyInfo( IType classBean, String strProperty, IFeatureFilter filter, ParserBase parser, IScriptabilityModifier scriptabilityConstraint)
{
IType whosaskin = classBean;
if( parser != null )
{
whosaskin = parser.getGosuClass();
// Hack to ensure that we adhere to visibility rules when parsing
whosaskin = whosaskin != null || GosuClassTypeInfo.isIncludeAll() ? whosaskin : JavaTypes.OBJECT();
if( GosuClassTypeInfo.isIncludeAll() && whosaskin instanceof IGosuProgram &&
// Well... downstream we check for null on whosaskin and ignore TypeSystem.isIncludeAll(), that can't happen for CompileTimeExpressionParser
!whosaskin.getName().startsWith( IGosuProgram.PACKAGE ) )
{
whosaskin = null;
}
}
return getPropertyInfo( classBean, whosaskin, strProperty, filter, parser, scriptabilityConstraint );
}
public static IPropertyInfo getPropertyInfo( IType classBean, IType whosAskin, String strProperty, IFeatureFilter filter, ParserBase parser, IScriptabilityModifier scriptabilityConstraint)
{
if( classBean == null )
{
return null;
}
ITypeInfo beanInfo = classBean.getTypeInfo();
if( beanInfo == null )
{
return null;
}
int iArrayBracket = strProperty.indexOf( '[' );
if( iArrayBracket > 0 )
{
strProperty = strProperty.substring( 0, iArrayBracket );
}
IPropertyInfo property = getProperty( beanInfo, whosAskin, strProperty );
if( property != null )
{
if( !BeanAccess.isDescriptorHidden(property) &&
(filter == null || filter.acceptFeature(classBean, property )) )
{
if( !property.isVisible(scriptabilityConstraint) )
{
return null;
}
return property;
}
}
else
{
IType componentType = TypeLord.getExpandableComponentType( classBean );
if( componentType != null )
{
// Allow expressions of the form: <array-of-foo>.<property-of-foo>. The
// result of evaluating such an expression is of type array-of-property-type.
IPropertyInfo propertyInfo = getPropertyInfo(componentType, strProperty, filter, parser, scriptabilityConstraint);
if (propertyInfo != null) {
return new ArrayExpansionPropertyInfo(propertyInfo);
}
}
}
return null;
}
public static IPropertyInfo getProperty( ITypeInfo beanInfo, IType classBean, String strMember )
{
IPropertyInfo property;
if( beanInfo instanceof IRelativeTypeInfo)
{
property = ((IRelativeTypeInfo)beanInfo).getProperty( classBean, strMember );
}
else
{
property = beanInfo.getProperty( strMember );
}
return property;
}
}