/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser.fragments;
import gw.internal.gosu.compiler.GosuClassLoader;
import gw.internal.gosu.parser.ClassJavaClassInfo;
import gw.internal.gosu.parser.DynamicFunctionSymbol;
import gw.internal.gosu.parser.DynamicPropertySymbol;
import gw.internal.gosu.parser.GosuClassParseInfo;
import gw.internal.gosu.parser.GosuParser;
import gw.internal.gosu.parser.ICompilableTypeInternal;
import gw.internal.gosu.parser.IGosuAnnotation;
import gw.internal.gosu.parser.IGosuClassInternal;
import gw.internal.gosu.parser.statements.ClassStatement;
import gw.internal.gosu.parser.statements.StatementList;
import gw.internal.gosu.parser.statements.VarStatement;
import gw.lang.parser.IBlockClass;
import gw.lang.parser.ICapturedSymbol;
import gw.lang.parser.IExpression;
import gw.lang.parser.IGosuParser;
import gw.lang.parser.ISymbol;
import gw.lang.parser.ISymbolTable;
import gw.lang.parser.ITypeUsesMap;
import gw.lang.parser.expressions.IVarStatement;
import gw.lang.parser.statements.IClassStatement;
import gw.lang.reflect.AbstractType;
import gw.lang.reflect.DefaultArrayType;
import gw.lang.reflect.IRelativeTypeInfo;
import gw.lang.reflect.IType;
import gw.lang.reflect.Modifier;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.gs.ClassType;
import gw.lang.reflect.gs.FragmentInstance;
import gw.lang.reflect.gs.GosuClassTypeLoader;
import gw.lang.reflect.gs.IExternalSymbolMap;
import gw.lang.reflect.gs.IGenericTypeVariable;
import gw.lang.reflect.gs.IGosuClass;
import gw.lang.reflect.gs.IGosuFragment;
import gw.lang.reflect.gs.ISourceFileHandle;
import gw.lang.reflect.java.IJavaClassInfo;
import gw.lang.reflect.java.JavaTypes;
import gw.util.GosuExceptionUtil;
import gw.util.concurrent.LockingLazyVar;
import java.io.ObjectStreamException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @deprecated DO NOT USE THIS CLASS! This is here exclusively for PCF types.
*/
public class GosuFragment extends AbstractType implements IGosuFragment, ICompilableTypeInternal {
public static final String FRAGMENT_NAME_PREFIX = "__Fragment__";
private static final IGenericTypeVariable[] EMTPY_TYPE_VARIABLE_ARRAY = new IGenericTypeVariable[0];
private static final IType[] EMTPY_TYPE_ARRAY = new IType[0];
private List<IGosuClass> _blocks;
private GosuFragmentTypeInfo _typeInfo;
private boolean _discarded = false;
private ITypeUsesMap _typeUsesMap;
private LockingLazyVar<IType> _arrayType = new LockingLazyVar<IType>() {
@Override
protected IType init() {
return new DefaultArrayType(GosuFragment.this, getBackingClassInfo(), getTypeLoader());
}
};
private IExpression _expression;
private String _name;
private HashMap<String, ISymbol> _externalSymbols;
private IType _supertype;
private Set<IType> _allTypesInHierarchy;
private LockingLazyVar<IJavaClassInfo> _javaClass = new LockingLazyVar<IJavaClassInfo>() {
@Override
protected IJavaClassInfo init() {
return defineClass();
}
};
private LockingLazyVar<FragmentInstance> _sharedInstance = new LockingLazyVar<FragmentInstance>() {
@Override
protected FragmentInstance init() {
return createNewInstance();
}
};
public GosuFragment(String name, HashMap<String, ISymbol> externalSymbols, ITypeUsesMap typeUsesMap) {
_typeInfo = createTypeInfo();
_typeUsesMap = typeUsesMap;
_name = name;
_externalSymbols = externalSymbols;
_supertype = JavaTypes.FRAGMENT_INSTANCE();
_allTypesInHierarchy = new HashSet<IType>();
_allTypesInHierarchy.addAll(_supertype.getAllTypesInHierarchy());
_allTypesInHierarchy.add(this);
}
// ==========================================================================
// Methods with interesting implementations
// ==========================================================================
@Override
public int getBlockCount() {
return _blocks == null ? 0 : _blocks.size();
}
@Override
public void addBlock(IBlockClass block) {
if (_blocks == null) {
_blocks = new ArrayList<IGosuClass>();
}
_blocks.add(block);
}
@Override
public IGosuClass getBlock(int i) {
return _blocks.get(i);
}
@Override
public IRelativeTypeInfo getTypeInfo() {
return _typeInfo;
}
@Override
public boolean isFinal() {
return true;
}
@Override
public GosuClassTypeLoader getTypeLoader() {
return GosuClassTypeLoader.getDefaultClassLoader();
}
@Override
public ITypeUsesMap getTypeUsesMap() {
return _typeUsesMap;
}
@Override
public void assignTypeUsesMap(GosuParser parser) {
if (_typeUsesMap != null) {
parser.setTypeUsesMap(_typeUsesMap);
}
}
@Override
public boolean isValid() {
// Assume that these synthetic classes don't get created/get thrown away if they're invalid,
// so the existence of the class implies that it's valid
return true;
}
@Override
public IType getArrayType() {
return _arrayType.get();
}
// ==========================================================================
// Methods to double-check
// ==========================================================================
@Override
public ISourceFileHandle getSourceFileHandle() {
// TODO
return null;
}
@Override
public IClassStatement getClassStatement() {
return new ClassStatement(null);
}
// ==========================================================================
// No-op methods
// ==========================================================================
@Override
public List<DynamicFunctionSymbol> getMemberFunctions( String names) {
return Collections.emptyList();
}
@Override
public IType resolveRelativeInnerClass( String strRelativeInnerClassName, boolean bForce ) {
return null;
}
@Override
public IGosuClassInternal getEnclosingType() {
return null;
}
@Override
public IType getEnclosingNonBlockType() {
return null;
}
@Override
public DynamicPropertySymbol getStaticProperty( String name) {
return null;
}
@Override
public DynamicPropertySymbol getMemberProperty( String name) {
return null;
}
@Override
public Map<String, ICapturedSymbol> getCapturedSymbols() {
return Collections.emptyMap();
}
@Override
public ICapturedSymbol getCapturedSymbol( String strName) {
return null;
}
@Override
public VarStatement getMemberField( String charSequence) {
return null;
}
@Override
public boolean isStatic() {
return false;
}
@Override
public boolean isAnonymous() {
return false;
}
@Override
public IType getGenericType() {
return null;
}
@Override
public boolean isInterface() {
return false;
}
@Override
public boolean isEnum() {
return false;
}
@Override
public IType[] getInterfaces() {
return EMPTY_TYPE_ARRAY;
}
@Override
public boolean isParameterizedType() {
return false;
}
@Override
public boolean isGenericType() {
return false;
}
@Override
public IGosuParser getParser() {
return null;
}
@Override
public void addCapturedSymbol(ICapturedSymbol sym) {
// Do nothing
}
@Override
public IGenericTypeVariable[] getGenericTypeVariables() {
return EMTPY_TYPE_VARIABLE_ARRAY;
}
@Override
public IType getParameterizedType(IType... ofType) {
return null;
}
@Override
public IType[] getTypeParameters() {
return EMTPY_TYPE_ARRAY;
}
@Override
public boolean isArray() {
return false;
}
@Override
public boolean isPrimitive() {
return false;
}
@Override
public Object makeArrayInstance(int iLength) {
return Array.newInstance( getBackingClassInfo().getBackingClass(), iLength );
}
@Override
public Object getArrayComponent(Object array, int iIndex) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
return Array.get( array, iIndex );
}
@Override
public void setArrayComponent(Object array, int iIndex, Object value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
Array.set( array, iIndex, value );
}
@Override
public int getArrayLength(Object array) throws IllegalArgumentException {
return Array.getLength( array );
}
@Override
public IType getComponentType() {
return null;
}
@Override
public boolean isAssignableFrom(IType type) {
// Synthetic types are final singletons
return type == this;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public void unloadTypeInfo() {
// Do nothing
}
@Override
public Object readResolve() throws ObjectStreamException {
return TypeSystem.getByFullName( getName() );
}
@Override
public int getModifiers() {
return Modifier.STATIC | Modifier.PUBLIC;
}
@Override
public boolean isAbstract() {
return false;
}
@Override
public boolean isDiscarded() {
return _discarded;
}
@Override
public void setDiscarded(boolean bDiscarded) {
_discarded = bDiscarded;
}
@Override
public boolean isCompoundType() {
return false;
}
@Override
public Set<IType> getCompoundTypeComponents() {
return Collections.emptySet();
}
@Override
public IType getInnerClass(CharSequence strTypeName) {
return null;
}
@Override
public int getDepth() {
return 0;
}
@Override
public void compileDeclarationsIfNeeded() {
// Do nothing
}
@Override
public void compileDefinitionsIfNeeded( boolean bForce ) {
// Do nothing
}
@Override
public void compileHeaderIfNeeded() {
// Do nothing
}
@Override
public void putClassMembers(GosuParser owner, ISymbolTable table, IGosuClassInternal gsContextClass, boolean bStatic) {
// Do nothing
}
public void putClassMembers(GosuClassTypeLoader loader, GosuParser owner, ISymbolTable table, IGosuClassInternal gsContextClass, boolean bStatic) {
// Do nothing
}
@Override
public boolean isCreateEditorParser() {
return false;
}
@Override
public String getInterfaceMethodsClassName()
{
return null;
}
@Override
public int getAnonymousInnerClassCount() {
return 0;
}
@Override
public List<? extends IGosuAnnotation> getGosuAnnotations() {
return Collections.emptyList();
}
@Override
public List<StatementList> getAnnotationInitialization()
{
return Collections.emptyList();
}
@Override
public boolean shouldFullyCompileAnnotations()
{
return true;
}
@Override
public List<? extends IVarStatement> getMemberFields()
{
return Collections.emptyList();
}
@Override
public List<IVarStatement> getStaticFields()
{
return Collections.emptyList();
}
public void setExpression(IExpression expression) {
_expression = expression;
}
protected GosuFragmentTypeInfo createTypeInfo() {
return new GosuFragmentTypeInfo(this);
}
@Override
public IExpression getExpression() {
return _expression;
}
public boolean isExternalSymbol( String name ) {
return _externalSymbols.containsKey( name );
}
@Override
public Object evaluate(IExternalSymbolMap externalSymbols) {
try
{
return _sharedInstance.get().evaluate(externalSymbols);
}
catch( Exception e )
{
String s = null;
try
{
s = _expression.toString();
}
catch( Exception e1 )
{
//ignore
}
throw GosuExceptionUtil.forceThrow( e, s );
}
}
@Override
public Object evaluateRoot(IExternalSymbolMap externalSymbols) {
return _sharedInstance.get().evaluateRootExpression(externalSymbols);
}
@Override
public Class getBackingClass() {
return getBackingClassInfo().getBackingClass();
}
public IJavaClassInfo getBackingClassInfo() {
return _javaClass.get();
}
public String getRelativeName() {
if (_name.startsWith("pcf.")) {
return _name.substring(4);
}
return _name;
}
public String getName() {
if (_name.startsWith("pcf.")) {
return _name;
}
return FRAGMENT_PACKAGE + "." + _name;
}
public String getNamespace() {
if (_name.startsWith("pcf.")) {
return "pcf";
}
return FRAGMENT_PACKAGE;
}
@Override
public String getDisplayName() {
return _name;
}
@Override
public IType getSupertype() {
return _supertype;
}
@Override
public Set<? extends IType> getAllTypesInHierarchy() {
return _allTypesInHierarchy;
}
@Override
public ISymbol getExternalSymbol(String strName) {
return _externalSymbols.get( strName );
}
// -------------------- Private helper methods
private FragmentInstance createNewInstance() {
try {
return (FragmentInstance) getBackingClass().newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private IJavaClassInfo defineClass() {
try {
Class aClass = GosuClassLoader.instance().defineClass(this, true); //getRelativeName().startsWith( FRAGMENT_NAME_PREFIX ) );
return new ClassJavaClassInfo(aClass, getTypeLoader().getModule());
} catch (ClassNotFoundException e) {
throw new RuntimeException( e );
}
}
@Override
public String getSource()
{
return null;
}
@Override
public GosuClassParseInfo getParseInfo() {
throw new RuntimeException();
}
@Override
public boolean hasAssertions()
{
return false;
}
@Override
public ClassType getClassType() {
return ClassType.Class;
}
@Override
public List<? extends IType> getInnerClasses() {
return null;
}
@Override
public List<? extends IType> getLoadedInnerClasses() {
return Collections.emptyList();
}
@Override
public String toString() {
return getName();
}
@Override
public boolean isCompilable() {
return false;
}
@Override
public byte[] compile() {
throw new UnsupportedOperationException();
}
}