/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser;
import gw.config.CommonServices;
import gw.internal.gosu.parser.java.classinfo.CompileTimeExpressionParser;
import gw.lang.GosuShop;
import gw.lang.annotation.Annotations;
import gw.lang.javadoc.IClassDocNode;
import gw.lang.javadoc.IDocRef;
import gw.lang.parser.IExpression;
import gw.lang.parser.ISymbol;
import gw.lang.parser.ISymbolTable;
import gw.lang.parser.Keyword;
import gw.lang.parser.TypeVarToTypeMap;
import gw.lang.reflect.ConstructorInfoBuilder;
import gw.lang.reflect.FeatureManager;
import gw.lang.reflect.IAnnotationInfo;
import gw.lang.reflect.IConstructorHandler;
import gw.lang.reflect.IConstructorInfo;
import gw.lang.reflect.IEventInfo;
import gw.lang.reflect.IMethodInfo;
import gw.lang.reflect.IPropertyInfo;
import gw.lang.reflect.IRelativeTypeInfo;
import gw.lang.reflect.IScriptabilityModifier;
import gw.lang.reflect.IType;
import gw.lang.reflect.MethodList;
import gw.lang.reflect.ParameterInfoBuilder;
import gw.lang.reflect.TypeInfoUtil;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.gs.IGosuClass;
import gw.lang.reflect.java.IJavaAnnotatedElement;
import gw.lang.reflect.java.IJavaClassConstructor;
import gw.lang.reflect.java.IJavaClassField;
import gw.lang.reflect.java.IJavaClassInfo;
import gw.lang.reflect.java.IJavaClassMethod;
import gw.lang.reflect.java.IJavaMethodDescriptor;
import gw.lang.reflect.java.IJavaMethodInfo;
import gw.lang.reflect.java.IJavaPropertyDescriptor;
import gw.lang.reflect.java.IJavaType;
import gw.lang.reflect.java.IJavaTypeInfo;
import gw.util.concurrent.LockingLazyVar;
import java.beans.IndexedPropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
/**
*/
public class JavaTypeInfo extends JavaBaseFeatureInfo implements IJavaTypeInfo
{
private final IType _type;
private final IJavaClassInfo _backingClass;
private WeakReference<IClassDocNode> _classDocumentation;
private LockingLazyVar<List<IPropertyInfo>> _declaredProperties;
private LockingLazyVar<List<IJavaMethodInfo>> _declaredMethods;
private LockingLazyVar<List<IConstructorInfo>> _allCtors;
private JavaFeatureManager _fm;
private final ReentrantLock _myLock = new ReentrantLock();
private static class JavaFeatureManager extends FeatureManager {
public JavaFeatureManager(IRelativeTypeInfo type) {
super(type, true, type.getOwnersType().isInterface() &&
type.getOwnersType().getSupertype() == null);
}
}
public JavaTypeInfo(IType intrType, IJavaClassInfo backingClass) {
super(intrType);
_type = intrType;
_backingClass = backingClass;
_fm = new JavaFeatureManager(this);
_declaredProperties = new LockingLazyVar<List<IPropertyInfo>>() {
@Override
protected List<IPropertyInfo> init() {
List<IPropertyInfo> ret;
IJavaPropertyDescriptor[] properties = _backingClass.getPropertyDescriptors();
if( properties == null ) {
ret = Collections.emptyList();
} else {
ret = new ArrayList<IPropertyInfo>();
for( IJavaPropertyDescriptor property : properties )
{
if( property instanceof IndexedPropertyDescriptor )
{
IndexedPropertyDescriptor indexedProp = (IndexedPropertyDescriptor)property;
if( indexedProp.getPropertyType() == null )
{
// Indexed properties must provide non-indexed access.
continue;
}
}
JavaPropertyInfo pi = new JavaPropertyInfo(JavaTypeInfo.this, property);
// We only want properties that are at least readable
if (pi.isReadable()) {
ret.add(pi);
}
}
addFieldProperties(ret);
addArrayProperties(ret);
ret = Collections.unmodifiableList(ret);
}
return ret;
}
private void addArrayProperties(List<IPropertyInfo> ret) {
if ( getOwnersType().isArray()) {
for (Iterator<IPropertyInfo> iterator = ret.iterator(); iterator.hasNext();) {
IPropertyInfo propertyInfo = iterator.next();
if (propertyInfo.getName().equals(Keyword.KW_length.toString())) {
iterator.remove();
}
}
IPropertyInfo lengthProperty = GosuShop.createPropertyDelegate(JavaTypeInfo.this, GosuShop.createLengthProperty(JavaTypeInfo.this));
ret.add(lengthProperty);
}
}
private void addFieldProperties( List<IPropertyInfo> properties )
{
TypeSystem.lock();
try
{
IJavaClassField[] fields = _backingClass.getDeclaredFields();
for( IJavaClassField field : fields )
{
if( field.isSynthetic() )
{
// E.g., $assertionsDisabled
continue;
}
if( Modifier.isStatic( field.getModifiers() ) )
{
TypeVarToTypeMap actualParamByVarName =
TypeLord.mapTypeByVarName( getOwnersType(), getOwnersType(), true );
JavaFieldPropertyInfo staticProp = new JavaFieldPropertyInfo( JavaTypeInfo.this, field.getGenericType().getActualType( actualParamByVarName, true ), field, true );
int pos = getPosition(properties, staticProp.getName());
// We favor non-static over static
if( pos == -1 || properties.get(pos).isStatic() )
{
if (pos == -1) {
properties.add(staticProp);
} else {
properties.set(pos, staticProp);
}
}
else
{
staticProp.changeNameForNonStaticCollision();
properties.add(staticProp);
}
}
else if( !_backingClass.hasCustomBeanInfo() )
{
TypeVarToTypeMap actualParamByVarName = TypeLord.mapTypeByVarName( getOwnersType(), getOwnersType(), true );
if (field == null) {
throw new IllegalStateException("A null field was found for " + _backingClass.getName() + " : " + Arrays.toString(fields));
}
if (field.getGenericType() == null) {
throw new IllegalStateException("The generic type for the field " + field.getName() + " on " + _backingClass.getName() + " was null");
}
JavaFieldPropertyInfo prop = new JavaFieldPropertyInfo( JavaTypeInfo.this, field.getGenericType().getActualType( actualParamByVarName, true ), field, false );
int pos = getPosition(properties, prop.getName());
// We favor non-static over static
if( pos == -1 || properties.get(pos) instanceof JavaFieldPropertyInfo )
{
//## todo: Really we should preserve the field name if it differs by case, and even if it's the same,
//## we should have two separate features to reflect the actual structure of the type. Essentially,
//## we don't want to lose type information.
if (pos == -1) {
properties.add(prop);
} else {
properties.set(pos, prop);
}
}
}
}
}
finally
{
TypeSystem.unlock();
}
}
private int getPosition(List<IPropertyInfo> properties, String name) {
for (int i = 0; i < properties.size(); i++) {
IPropertyInfo propertyInfo = properties.get(i);
// if( ILanguageLevel.Util.STANDARD_GOSU() ) {
if (propertyInfo.getName().equals(name)) {
return i;
}
// }
// else {
// if (propertyInfo.getName().equals(name)) {
// return i;
// }
// }
}
return -1;
}
};
_declaredMethods = new LockingLazyVar<List<IJavaMethodInfo>>() {
@Override
protected List<IJavaMethodInfo> init() {
List<IJavaMethodInfo> ret;
IJavaMethodDescriptor[] methods = _backingClass.getMethodDescriptors();
if (methods == null) {
ret = Collections.emptyList();
} else {
ret = new ArrayList<IJavaMethodInfo>(methods.length);
for (IJavaMethodDescriptor method : methods) {
ret.add(new JavaMethodInfo(JavaTypeInfo.this, method, !Modifier.isStatic( method.getMethod().getModifiers() ) && isPropertyMethod(method)));
}
((ArrayList)ret).trimToSize();
ret = Collections.unmodifiableList(ret);
}
return ret;
}
};
_allCtors = new LockingLazyVar<List<IConstructorInfo>>() {
@Override
protected List<IConstructorInfo> init() {
List<IConstructorInfo> constructors;
if( _backingClass.isAnnotation() )
{
return generateAnnotationConstructors( _backingClass );
}
IJavaClassConstructor[] ctors = _backingClass.getDeclaredConstructors();
if( ctors == null )
{
constructors = Collections.emptyList();
} else {
constructors = new ArrayList<IConstructorInfo>( ctors.length );
for (IJavaClassConstructor ctor : ctors) {
try {
constructors.add(new JavaConstructorInfo(JavaTypeInfo.this, ctor));
} catch (SecurityException ex) {
// ok, don't add. This happens for things like java.lang.Class
}
}
constructors = TypeInfoUtil.makeSortedUnmodifiableRandomAccessList( constructors );
}
return constructors;
}
};
}
private List<IConstructorInfo> generateAnnotationConstructors( IJavaClassInfo backingClass )
{
IJavaClassMethod[] methods = backingClass.getDeclaredMethods();
Arrays.sort( methods, new Comparator<IJavaClassMethod>()
{
@Override
public int compare( IJavaClassMethod o1, IJavaClassMethod o2 )
{
return o1.getName().compareTo( o2.getName() );
}
} );
ArrayList<IConstructorInfo> constructorInfoArrayList = new ArrayList<IConstructorInfo>();
if (CommonServices.getEntityAccess().getLanguageLevel().supportHistoricalJavaAnnotationConstructors()) {
addCtor( constructorInfoArrayList, makeLegacyAnnotationConstructor(methods) );
if( hasArrayArgs(methods) )
{
addCtor( constructorInfoArrayList, makeLegacyArrayAnnotationConstructor(methods) );
}
if( hasDefaultArgs( methods ) )
{
addCtor( constructorInfoArrayList, makeLegacyAllArgsAnnotationConstructor(methods) );
}
if( hasArrayArgs( methods ) && hasDefaultArgs( methods ) )
{
addCtor( constructorInfoArrayList, makeDefaultArrayAnnotationConstructor(methods) );
}
}
constructorInfoArrayList.add( makeStandardAnnotationConstructor(methods) );
return constructorInfoArrayList;
}
private void addCtor( ArrayList<IConstructorInfo> list, IConstructorInfo ci )
{
if( !list.contains( ci ) )
{
list.add( ci );
}
}
private boolean hasArrayArgs( IJavaClassMethod[] methods )
{
for( IJavaClassMethod method : methods )
{
if( method.getReturnType().isArray() )
{
return true;
}
}
return false;
}
private boolean hasDefaultArgs( IJavaClassMethod[] methods )
{
for( IJavaClassMethod method : methods )
{
if( method.getDefaultValue() != null )
{
return true;
}
}
return false;
}
private IConstructorInfo makeStandardAnnotationConstructor(final IJavaClassMethod[] methods)
{
ArrayList<ParameterInfoBuilder> params = new ArrayList<ParameterInfoBuilder>();
ArrayList<ParameterInfoBuilder> paramsWDefaultValues = new ArrayList<ParameterInfoBuilder>();
for( IJavaClassMethod method : methods )
{
ParameterInfoBuilder pib = new ParameterInfoBuilder().withName(method.getName()).withType(method.getReturnType());
if (method.getDefaultValue() != null) {
pib.withDefValue( makeDefaultValueExpression( method ) );
paramsWDefaultValues.add(pib);
} else {
params.add(pib);
}
}
params.addAll(paramsWDefaultValues);
return new ConstructorInfoBuilder()
.withParameters( params.toArray( new ParameterInfoBuilder[params.size()] ) )
.withConstructorHandler(new StandardJavaAnnotationConstructor(this, methods)).build( this );
}
private IConstructorInfo makeLegacyArrayAnnotationConstructor(final IJavaClassMethod[] methods)
{
ArrayList<ParameterInfoBuilder> params = new ArrayList<ParameterInfoBuilder>();
for( IJavaClassMethod method : methods )
{
if( method.getReturnType().isArray() )
{
params.add( new ParameterInfoBuilder().withName( method.getName() ).withType( method.getReturnType().getComponentType() ) );
}
else
{
params.add( new ParameterInfoBuilder().withName( method.getName() ).withType( method.getReturnType() ) );
}
}
return new ConstructorInfoBuilder()
.withParameters( params.toArray( new ParameterInfoBuilder[params.size()] ) )
.withConstructorHandler( new IConstructorHandler()
{
@Override
public Object newInstance( Object... args )
{
Annotations.Builder<? extends Annotation> builder = Annotations.builder( ((ClassJavaClassInfo)_backingClass).getJavaClass() );
for( int i = 0; i < args.length; i++ )
{
IJavaClassMethod method = methods[i];
Object value = args[i];
if( method.getReturnType().isArray() )
{
Object[] arr = (Object[])Array.newInstance( ((IJavaType)method.getReturnType().getComponentType()).getBackingClass(), 1 );
arr[0] = value;
value = arr;
}
builder.withElement( method.getName(), value );
}
return builder.create();
}
} ).build( this );
}
private IConstructorInfo makeLegacyAnnotationConstructor(final IJavaClassMethod[] methods)
{
ArrayList<ParameterInfoBuilder> params = new ArrayList<ParameterInfoBuilder>();
for( IJavaClassMethod method : methods )
{
if( method.getDefaultValue() == null )
{
params.add( new ParameterInfoBuilder().withName( method.getName() ).withType( method.getReturnType() ) );
}
}
return new ConstructorInfoBuilder()
.withParameters( params.toArray( new ParameterInfoBuilder[params.size()] ) )
.withConstructorHandler( new IConstructorHandler()
{
@Override
public Object newInstance( Object... args )
{
Annotations.Builder<? extends Annotation> builder = Annotations.builder( _backingClass.getBackingClass() );
Iterator argIter = Arrays.asList( args ).iterator();
for( IJavaClassMethod method : methods )
{
Object value = method.getDefaultValue() != null ? method.getDefaultValue() : argIter.next();
builder.withElement( method.getName(), value );
}
return builder.create();
}
} ).build( this );
}
private IConstructorInfo makeLegacyAllArgsAnnotationConstructor(final IJavaClassMethod[] methods)
{
ArrayList<ParameterInfoBuilder> params = new ArrayList<ParameterInfoBuilder>();
for( IJavaClassMethod method : methods )
{
if( method.getDefaultValue() != null ) {
params.add( new ParameterInfoBuilder()
.withName( method.getName() )
.withType( method.getReturnType() )
.withDefValue( makeDefaultValueExpression( method ) ) );
}
else {
params.add( new ParameterInfoBuilder().withName( method.getName() ).withType( method.getReturnType() ) );
}
}
return new ConstructorInfoBuilder()
.withParameters( params.toArray( new ParameterInfoBuilder[params.size()] ) )
.withConstructorHandler( new IConstructorHandler()
{
@Override
public Object newInstance( Object... args )
{
Annotations.Builder<? extends Annotation> builder = Annotations.builder( ((ClassJavaClassInfo)_backingClass).getJavaClass() );
Iterator argIter = Arrays.asList( args ).iterator();
for( IJavaClassMethod method : methods )
{
Object value = argIter.next();
builder.withElement( method.getName(), value );
}
return builder.create();
}
} ).build( this );
}
private IExpression makeDefaultValueExpression( IJavaClassMethod method ) {
String exprString = GosuClassProxyFactory.makeValueString( method.getDefaultValue(), method.getReturnType() );
return CompileTimeExpressionParser.parse( exprString, ((IJavaType)getOwnersType()).getBackingClassInfo(), method.getReturnType() );
}
private IConstructorInfo makeDefaultArrayAnnotationConstructor( final IJavaClassMethod[] methods )
{
ArrayList<ParameterInfoBuilder> params = new ArrayList<ParameterInfoBuilder>();
for( IJavaClassMethod method : methods )
{
if( method.getDefaultValue() == null )
{
if( method.getReturnType().isArray() )
{
params.add( new ParameterInfoBuilder().withName( method.getName() ).withType( method.getReturnType().getComponentType() ) );
}
else
{
params.add( new ParameterInfoBuilder().withName( method.getName() ).withType( method.getReturnType() ) );
}
}
}
return new ConstructorInfoBuilder()
.withParameters( params.toArray( new ParameterInfoBuilder[params.size()] ) )
.withConstructorHandler( new IConstructorHandler()
{
@Override
public Object newInstance( Object... args )
{
Annotations.Builder<? extends Annotation> builder = Annotations.builder( ((ClassJavaClassInfo)_backingClass).getJavaClass() );
Iterator argIter = Arrays.asList( args ).iterator();
for( IJavaClassMethod method : methods )
{
Object value;
if( method.getDefaultValue() != null )
{
value = method.getDefaultValue();
}
else
{
value = argIter.next();
if( method.getReturnType().isArray() )
{
Object[] arr = (Object[])Array.newInstance( ((IJavaType)method.getReturnType().getComponentType()).getBackingClass(), 1 );
arr[0] = value;
value = arr;
}
}
builder.withElement( method.getName(), value );
}
return builder.create();
}
} ).build( this );
}
private boolean isPropertyMethod( IJavaMethodDescriptor md )
{
String name = md.getName();
if( md.getMethod().getParameterTypes().length == 0 )
{
String propName = null;
if( name.startsWith( "get" ) || name.startsWith( "set" ) )
{
propName = name.substring( 3 );
}
else if( name.startsWith( "is" ) )
{
propName = name.substring( 2 );
}
if( propName != null )
{
for( IPropertyInfo propertyInfo : _declaredProperties.get() )
{
if( propertyInfo.getName().equals( propName ) &&
(!(propertyInfo instanceof JavaPropertyInfo) ||
((JavaPropertyInfo)propertyInfo).getPropertyDescriptor().getReadMethod().equals(md.getMethod())) )
{
return true;
}
}
}
}
return false;
}
@Override
public void unload()
{
TypeSystem.lock();
try
{
_declaredMethods.clear();
_declaredProperties.clear();
_fm = new JavaFeatureManager(this);
}
finally
{
TypeSystem.unlock();
}
}
@Override
protected IJavaAnnotatedElement getAnnotatedElement()
{
return _backingClass;
}
@Override
protected boolean isVisibleViaFeatureDescriptor(IScriptabilityModifier constraint) {
return _backingClass.isVisibleViaFeatureDescriptor(constraint);
}
@Override
protected boolean isHiddenViaFeatureDescriptor() {
return _backingClass.isHiddenViaFeatureDescriptor();
}
@Override
public Accessibility getAccessibilityForType( IType whosaskin )
{
return getAccessibilityForClass( _type, whosaskin == null ? getCompilingClass( _type ) : whosaskin );
}
@Override
public List<? extends IPropertyInfo> getProperties()
{
return getProperties( null );
}
@Override
public List<IPropertyInfo> getProperties( IType whosAskin )
{
return _fm.getProperties(getAccessibilityForType(whosAskin));
}
@Override
public IPropertyInfo getProperty( CharSequence propName )
{
return getProperty( null, propName );
}
@Override
public IPropertyInfo getProperty( IType whosAskin, CharSequence propName )
{
return _fm.getProperty(getAccessibilityForType(whosAskin), propName);
}
@Override
public MethodList getMethods()
{
return getMethods(null);
}
@Override
public MethodList getMethods(IType whosAskin)
{
return _fm.getMethods(getAccessibilityForType(whosAskin));
}
@Override
public List<? extends IConstructorInfo> getConstructors()
{
return getConstructors( null );
}
@Override
public List<? extends IConstructorInfo> getConstructors( IType whosAskin )
{
return _fm.getConstructors(getAccessibilityForType(whosAskin));
}
@Override
public IMethodInfo getMethod( CharSequence methodName, IType... params )
{
return FIND.method( getMethods(), methodName, params );
}
@Override
public IMethodInfo getMethod( IType whosaskin, CharSequence methodName, IType... params )
{
MethodList methods = getMethods( whosaskin );
return FIND.method( methods, methodName, params );
}
@Override
public IConstructorInfo getConstructor( IType... params )
{
return FIND.constructor( getConstructors(), params );
}
@Override
public IConstructorInfo getConstructor( IType whosAskin, IType[] params )
{
List<? extends IConstructorInfo> ctors = getConstructors( whosAskin );
return FIND.constructor( ctors, params );
}
@Override
public List<? extends IPropertyInfo> getDeclaredProperties() {
return _declaredProperties.get();
}
@Override
public List<? extends IMethodInfo> getDeclaredMethods() {
return _declaredMethods.get();
}
@Override
public List<? extends IConstructorInfo> getDeclaredConstructors() {
return _allCtors.get();
}
@Override
public IMethodInfo getCallableMethod( CharSequence strMethod, IType... params )
{
return FIND.callableMethod( getMethods(), strMethod, params );
}
@Override
public IConstructorInfo getCallableConstructor( IType... params )
{
return FIND.callableConstructor( getConstructors(), params );
}
@Override
public List<IEventInfo> getEvents()
{
return Collections.emptyList();
}
@Override
public IEventInfo getEvent( CharSequence strEvent )
{
return null;
}
@Override
public String getName()
{
return _backingClass.getRelativeName();
}
@Override
public String getDisplayName()
{
return _backingClass.getDisplayName();
}
@Override
public String getDescription() {
if (getDocNode().get() != null && getDocNode().get().getDescription() != null) {
return getDocNode().get().getDescription();
}
return null;
}
@Override
public boolean isDeprecated()
{
return super.isDeprecated() || _backingClass.isAnnotationPresent( java.lang.Deprecated.class );
}
@Override
@SuppressWarnings({"unchecked"})
public List<IAnnotationInfo> getDeclaredAnnotations() {
List<IAnnotationInfo> annotations = super.getDeclaredAnnotations();
String deprecatedWarningToAdd = null;
if (getDocNode().get() != null && getDocNode().get().isDeprecated()) {
deprecatedWarningToAdd = getDocNode().get().getDeprecated();
} else {
//## todo: Diamond: re-enable this and provide some means to escape it in the language e.g., provide an internal modifier for the uses-statement: internal uses com.abc.Foo
// IJavaType typeToCheck = (IJavaType) getOwnersIntrinsicType();
// if (!typeToCheck.isArray() &&
// !typeToCheck.isPrimitive() &&
// isFilteredType(typeToCheck) &&
// typeToCheck.getIntrinsicClass().getAnnotation(PublishInGosu.class) == null) {
// deprecatedWarningToAdd = CommonServices.getGosuLocalizationService().localize(Res.USING_INTERNAL_CLASS);
// }
}
if (deprecatedWarningToAdd != null) {
annotations.add(GosuShop.getAnnotationInfoFactory().createJavaAnnotation(makeDeprecated(deprecatedWarningToAdd), this));
}
return annotations;
}
@Override
public boolean isHidden() {
return false;
}
@Override
protected boolean isDefaultEnumFeature()
{
return false;
}
@Override
public boolean isStatic()
{
return Modifier.isStatic( _type.getModifiers() );
}
public boolean isPrivate()
{
return Modifier.isPrivate( _type.getModifiers() );
}
@Override
public boolean isInternal()
{
return !isPublic() && !isProtected() && !isPrivate();
}
public boolean isProtected()
{
return Modifier.isProtected( _type.getModifiers() );
}
public boolean isPublic()
{
return Modifier.isPublic( _type.getModifiers() );
}
private Accessibility getAccessibilityForClass( IType ownersClass, IType whosAskin )
{
if( GosuClassTypeInfo.isIncludeAll() )
{
return Accessibility.PRIVATE;
}
if( ownersClass == null || whosAskin == null )
{
return Accessibility.PUBLIC;
}
if (whosAskin instanceof IGosuClassInternal && ((IGosuClassInternal)whosAskin).isProxy()) {
IJavaType javaType = ((IGosuClassInternal)whosAskin).getJavaType();
if( javaType != null )
{
whosAskin = javaType;
}
}
if( ownersClass == whosAskin )
{
return Accessibility.PRIVATE;
}
if( FeatureManager.isInSameNamespace(ownersClass, whosAskin))
{
return Accessibility.INTERNAL;
}
if( IGosuClass.ProxyUtil.isProxyStart( whosAskin.getNamespace() ) )
{
IType genOwnerType = TypeLord.getPureGenericType( ownersClass );
String strGenericOwnerClass = genOwnerType.getName();
if( IGosuClass.ProxyUtil.getNameSansProxy( whosAskin ).equals( strGenericOwnerClass ) )
{
return Accessibility.INTERNAL;
}
if( genOwnerType.getRelativeName().startsWith( IGosuClass.SUPER_PROXY_CLASS_PREFIX ) )
{
return Accessibility.INTERNAL;
}
}
if (FeatureManager.isInEnclosingClassHierarchy(ownersClass, whosAskin))
{
return Accessibility.PROTECTED;
}
return Accessibility.PUBLIC;
}
public static IType getCompilingClass( IType type )
{
if( GosuClassTypeInfo.isIncludeAll() )
{
return type;
}
IType compilingClass = GosuClassCompilingStack.getCurrentCompilingType();
if( compilingClass == null )
{
ISymbolTable symTableCtx = CompiledGosuClassSymbolTable.getSymTableCtx();
ISymbol thisSymbol = symTableCtx.getThisSymbolFromStackOrMap();
if( thisSymbol != null )
{
IType thisSymbolType = thisSymbol.getType();
if( thisSymbolType instanceof IGosuClassInternal )
{
compilingClass = thisSymbolType;
}
}
}
if( IGosuClass.ProxyUtil.isProxy( compilingClass ) )
{
return compilingClass;
}
return null;
}
private IDocRef<IClassDocNode> _docRef = new IDocRef<IClassDocNode>() {
@Override
public IClassDocNode get() {
_myLock.lock();
try {
IClassDocNode classDoc = _classDocumentation == null ? null : _classDocumentation.get();
if (classDoc == null) {
classDoc = _backingClass.createClassDocNode();
if( classDoc == null )
{
classDoc = GosuShop.getJavaDocFactory().create();//so we do not reenter this
}
_classDocumentation = new WeakReference<IClassDocNode>(classDoc);
}
return classDoc;
} finally {
_myLock.unlock();
}
}
};
IDocRef<IClassDocNode> getDocNode() {
return _docRef;
}
}