/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser; import gw.config.BaseService; import gw.config.CommonServices; import gw.fs.IDirectory; import gw.lang.parser.GlobalScope; import gw.lang.parser.IAttributeSource; import gw.lang.parser.IParseIssue; import gw.lang.parser.ITypeUsesMap; import gw.lang.parser.ILanguageLevel; import gw.lang.parser.exceptions.IncompatibleTypeException; import gw.lang.parser.exceptions.ParseIssue; import gw.lang.parser.expressions.IQueryExpression; import gw.lang.parser.expressions.IQueryExpressionEvaluator; import gw.lang.reflect.IEntityAccess; import gw.lang.reflect.IFeatureInfo; import gw.lang.reflect.IGosuClassLoadingObserver; import gw.lang.reflect.IPropertyInfo; import gw.lang.reflect.IType; import gw.lang.reflect.ITypeLoader; import gw.lang.reflect.AbstractTypeSystemListener; import gw.lang.reflect.RefreshRequest; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.gs.GosuClassTypeLoader; import gw.lang.reflect.gs.ICompilableType; import gw.lang.reflect.module.IModule; import gw.util.GosuExceptionUtil; import gw.util.IFeatureFilter; import gw.util.ILogger; import gw.util.SystemOutLogger; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; /** */ public class DefaultEntityAccess extends BaseService implements IEntityAccess { public static final SystemOutLogger DEFAULT_LOGGER = new SystemOutLogger(SystemOutLogger.LoggingLevel.WARN); private static DefaultEntityAccess g_instance; private static final ITypeUsesMap EMPTY_TYPE_USES = new TypeUsesMap( Collections.<String>emptyList() ).lock(); private List<IGosuClassLoadingObserver> _classLoadingObservers; public static DefaultEntityAccess instance() { return g_instance == null ? g_instance = new DefaultEntityAccess() : g_instance; } private Map _scopes = new HashMap(); /** */ public DefaultEntityAccess() { _classLoadingObservers = Collections.synchronizedList(new ArrayList<IGosuClassLoadingObserver>()); } public ITypeLoader getDefaultTypeLoader() { return DefaultTypeLoader.instance(); } @Override public ITypeUsesMap getDefaultTypeUses() { return EMPTY_TYPE_USES; } /** * @return x */ @Override public boolean isDomainInstance( Object value ) { return false; } /** * @return x */ @Override public boolean isEntityClass( IType cls ) { return false; } @Override public boolean isViewEntityClass( IType type ) { return false; } @Override public IType getPrimaryEntityClass( IType type ) { return null; } /** * @return x */ @Override public boolean isKeyableEntityClass( IType cls ) { return false; } /** * @return x */ @Override public boolean isDomainClass( IType cls ) { return false; } @Override public boolean isTypekey( IType cls ) { return false; } /** * @return x */ @Override public Object getEntityInstanceFrom( Object entity, IType classEntity ) { return null; } /** * @return x */ @Override public boolean areBeansEqual( Object bean1, Object bean2 ) { return bean1.equals( bean2 ); } /** * @param type * @param value * @return * @throws RuntimeException */ @Override public boolean verifyValueForType( IType type, Object value ) throws RuntimeException { try { IType valueType = TypeLoaderAccess.instance().getIntrinsicTypeFromObject(value); CommonServices.getCoercionManager().verifyTypesComparable( type, valueType, false ); } catch( ParseIssue pe ) { throw new IncompatibleTypeException( "Value of type: " + TypeLoaderAccess.instance().getIntrinsicTypeFromObject( value ).getName() + " is not compatible with symbol type: " + type.getName() ); } return true; } @Override public String makeStringFrom( Object obj ) { if( obj == null ) { return null; } return obj.toString(); } /** * @return x */ @Override public long getHashedEntityId( String strId, IType classEntity ) { return -1; } /** * @return x */ @Override public boolean isInternal( IType cls ) { return false; } @Override public ILogger getLogger() { return DEFAULT_LOGGER; } @Override public Locale getLocale() { return Locale.getDefault(); } @Override public Date getCurrentTime() { return new Date(); } @Override public void addEnhancementMethods(IType typeToEnhance, Collection methodsToAddTo) { IModule module = TypeSystem.getCurrentModule(); addEnhancementMethods(typeToEnhance, methodsToAddTo, module, new HashSet<IModule>()); } private void addEnhancementMethods(IType typeToEnhance, Collection methodsToAddTo, IModule module, Set<IModule> visited) { if(visited.contains(module)) { return; } visited.add(module); if( GosuClassTypeLoader.getDefaultClassLoader(module) != null ) { GosuClassTypeLoader.getDefaultClassLoader(module).getEnhancementIndex().addEnhancementMethods( typeToEnhance, methodsToAddTo); } for(IModule dep : module.getModuleTraversalList()) { addEnhancementMethods(typeToEnhance, methodsToAddTo, dep, visited); } } @Override public void addEnhancementProperties(IType typeToEnhance, Map propertyInfosToAddTo, boolean caseSensitive) { IModule module = TypeSystem.getCurrentModule(); addEnhancementProperties(typeToEnhance, propertyInfosToAddTo, caseSensitive, module, new HashSet<IModule>()); } private void addEnhancementProperties(IType typeToEnhance, Map propertyInfosToAddTo, boolean caseSensitive, IModule module, Set<IModule> visited) { if(visited.contains(module)) { return; } visited.add(module); if( GosuClassTypeLoader.getDefaultClassLoader(module) != null ) { GosuClassTypeLoader.getDefaultClassLoader(module).getEnhancementIndex().addEnhancementProperties( typeToEnhance, propertyInfosToAddTo, caseSensitive); } for(IModule dep : module.getModuleTraversalList()) { addEnhancementProperties(typeToEnhance, propertyInfosToAddTo, caseSensitive, dep, visited); } } @Override public IQueryExpressionEvaluator getQueryExpressionEvaluator( IQueryExpression queryExpression ) { return null; } @Override public IFeatureFilter getQueryExpressionFeatureFilter() { return new IFeatureFilter() { @Override public boolean acceptFeature(IType beanType, IFeatureInfo fi) { return false; } }; } @Override public ClassLoader getPluginClassLoader() { return DefaultEntityAccess.class.getClassLoader(); } @Override public Object constructObject( Class cls ) { try { return cls.newInstance(); } catch( Exception e ) { throw GosuExceptionUtil.forceThrow( e ); } } @Override public IAttributeSource getAttributeSource( GlobalScope scope ) { IAttributeSource source = (IAttributeSource)_scopes.get( scope ); if( source == null ) { source = new ThreadLocalAttributeSource( scope ); _scopes.put( scope, source ); } return source; } public void clearAttributeScopes() { _scopes.clear(); } private static class ThreadLocalAttributeSource extends AbstractTypeSystemListener implements IAttributeSource { private GlobalScope _scope; private ThreadLocal _values = new ThreadLocal(); public ThreadLocalAttributeSource( GlobalScope scope ) { _scope = scope; TypeLoaderAccess.instance().addTypeLoaderListenerAsWeakRef( this ); } public GlobalScope getScope() { return _scope; } @Override public boolean hasAttribute( String strAttr ) { Map map = getMap(); return map.containsKey( strAttr ); } @Override public Object getAttribute( String strAttr ) { Map map = getMap(); return map.get(strAttr); } @Override public void setAttribute( String strAttr, Object value ) { Map map = getMap(); map.put( strAttr, value ); } @Override public boolean equals( Object o ) { if( this == o ) { return true; } if( o == null || getClass() != o.getClass() ) { return false; } final ThreadLocalAttributeSource that = (ThreadLocalAttributeSource)o; return _scope.equals( that._scope ); } @Override public int hashCode() { return _scope.hashCode(); } private Map getMap() { if( _values.get() == null ) { _values.set( new HashMap() ); } return (Map)_values.get(); } @Override public void refreshedTypes(RefreshRequest request) { } @Override public void refreshed() { } } @Override public Object[] convertToExternalIfNecessary( Object[] args, Class[] argTypes, Class methodOwner ) { return args; } @Override public Object convertToInternalIfNecessary( Object obj, Class methodOwner ) { return obj; } @Override public boolean isExternal( Class methodOwner ) { return false; } @Override public StringBuilder getPluginRepositories() { return new StringBuilder(); } @Override public String getWebServerPaths() { return ""; } @Override public boolean isUnreachableCodeDetectionOn() { return true; } @Override public boolean isWarnOnImplicitCoercionsOn() { return true; } @Override public IType getKeyType() { return null; } @Override public IPropertyInfo getEntityIdProperty( IType rootType ) { return null; } @Override public boolean shouldAddWarning( IType type, IParseIssue warning ) { return true; } @Override public boolean isServerMutable() { return true; } @Override public boolean isDevMode() { return true; } @Override public boolean isRetainDebugInfo() { return false; } @Override public ILanguageLevel getLanguageLevel() { return new StandardLanguageLevel(); } @Override public List<IGosuClassLoadingObserver> getGosuClassLoadingObservers() { return _classLoadingObservers; } @Override public boolean areUsesStatementsAllowedInStatementLists(ICompilableType gosuClass) { return false; } @Override public List<IDirectory> getAdditionalSourceRoots() { return Collections.EMPTY_LIST; } @Override public void reloadedTypes(String[] types) { //nothing to do } }