Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package net.java.ao;
  
  import java.sql.ResultSet;
  import java.util.HashMap;
  import java.util.Map;
 

A read-only representation of a database row proxy, mapped to the specified Entity type.

This implementation is used for streaming and intended to be as lightweight as possible. It only supports getters or designated Accessor methods. Calling setters or save will result in an exception. Other method calls will be ignored.

As much as possible, reflection calls should be kept out of this implementation. If there is information needed about the implemented type, please use net.java.ao.schema.info.EntityInfo to cache them.

TODO There is currently some overlap with EntityProxy. As soon as this is battle-hardened, these can be refactored into an abstract superclass, for example.

Parameters:
<T> the type of Entity
<K> the primary key type
Author(s):
ahennecke
 
 public class ReadOnlyEntityProxy<T extends RawEntity<K>, K> implements InvocationHandler
 {
     private final K key;
     
     private final EntityInfo<T, K> entityInfo;
 
     private final EntityManager manager;
     
     private ImplementationWrapper<T> implementation;
     private final Map<StringObjectvalues = new HashMap<StringObject>();
 
     public ReadOnlyEntityProxy(
             EntityManager manager,
             EntityInfo<T, K> entityInfo,
             K key) {
         this. = manager;
         this. = entityInfo;
         this. = key;
     }
 
     @SuppressWarnings("unchecked")
     public Object invoke(Object proxyMethod methodObject[] argsthrows Throwable {
         // optimise reflection call
         String methodName = method.getName();
         
         if(methodName.equals("getEntityProxy")) {
             return this;
         } else if (methodName.equals("getEntityType")) {
             return getType();
         } else if (methodName.equals("save")) {
             // someone tried to call "save" at a read-only instance. We don't simply ignore that but rather throw an
             // exception, so the client knows that the call did not do what he expected.
             throw new RuntimeException("'save' method called on a read-only entity of type " + .getEntityType().getSimpleName());
         } 
 
         if ( == null) {
              = new ImplementationWrapper<T>();
             .init((T) proxy);
         }
 
         MethodImplWrapper methodImpl = .getMethod(methodNamemethod.getParameterTypes());
         if (methodImpl != null) {
             final Class<?> declaringClass = methodImpl.getMethod().getDeclaringClass();
             if (!Object.class.equals(declaringClass)) {
                 // We don't want to return get the class Class using Class.forName as this doesn't play well
                 // with multiple ClassLoaders (if the AO library has a separate class loader to the AO client)
                 // Instead just compare the classNames
                 final String callingClassName = Common.getCallingClassName(1);
                 if (callingClassName == null || !callingClassName.equals(declaringClass.getName())) {
                     return methodImpl.getMethod().invoke(methodImpl.getInstance(), args);
                 }
             }
         }
 
         if (methodName.equals("getEntityManager")) {
             return getManager();
         } else if (methodName.equals("hashCode")) {
             return hashCodeImpl();
         } else if (methodName.equals("equals")) {
             return equalsImpl((RawEntity<K>) proxyargs[0]);
         } else if (methodName.equals("toString")) {
             return toStringImpl();
         } else if (methodName.equals("init")) {
             return null;
        }
        
        if (.hasAccessor(method)) {
            return invokeGetter((RawEntity<?>) proxygetKey(), .getField(method).getName(), method.getReturnType());
        } else if (.hasMutator(method)) {
            // someone tried to call "save" at a read-only instance. We don't simply ignore that but rather throw an
            // exception, so the client knows that the call did not do what he expected.
            throw new RuntimeException("Setter method called on a read-only entity of type " + .getEntityType().getSimpleName() + ": " + methodName);
        }
        
        return null;
    }
    @SuppressWarnings({ "rawtypes""unchecked" })
    public void addValue(String fieldNameResultSet resthrows SQLException {
        FieldInfo fieldInfo = .getField(fieldName);
        Class type = fieldInfo.getJavaType();
        String polyName = fieldInfo.getPolymorphicName();
        
        Object value = convertValue(resfieldNamepolyNametype);
        .put(fieldNamevalue);
    }
    public K getKey() {
        return ;
    }
    public int hashCodeImpl() {
        return (.hashCode() + .hashCode()) % (2 << 15);
    }
    public boolean equalsImpl(RawEntity<K> proxyObject obj) {
        if (proxy == obj) {
            return true;
        }
        if (obj instanceof RawEntity<?>) {
            RawEntity<?> entity = (RawEntity<?>) obj;
            
            String ourTableName = getTableNameConverter().getName(proxy.getEntityType());
            String theirTableName = getTableNameConverter().getName(entity.getEntityType());
            return Common.getPrimaryKeyValue(entity).equals() && theirTableName.equals(ourTableName);
        }
        return false;
    }
    {
    }
    public String toStringImpl() {
        return .getName() + " {" + .getPrimaryKey().getName() + " = " + .toString() + "}";
    }
    {
    }
    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj instanceof ReadOnlyEntityProxy<?, ?>) {
            ReadOnlyEntityProxy<?, ?> proxy = (ReadOnlyEntityProxy<?, ?>) obj;
            if (proxy.entityInfo.equals() && proxy.key.equals()) {
                return true;
            }
        }
        return false;
    }
    @Override
    public int hashCode() {
        return hashCodeImpl();
    }
    Class<T> getType() {
        return .getEntityType();
    }
    private EntityManager getManager() {
        return ;
    }
    @SuppressWarnings("unchecked")
    private <V> V invokeGetter(RawEntity<?> entity, K keyString nameClass<V> typethrows Throwable {
        Object value = .get(name);
        if (instanceOf(valuetype)) {
            return handleNullReturn((V) valuetype);
        } else if (isBigDecimal(valuetype)) { // Oracle for example returns BigDecimal when we expect doubles
            return (V) handleBigDecimal(valuetype);
        } 
        
        return handleNullReturn(nulltype);
    }
    
    private <V> V convertValue(ResultSet resString fieldString polyNameClass<V> typethrows SQLException
    {
        if (isNull(resfield))
        {
            return null;
        }
        
        if (polyName != null) {
            Class<? extends RawEntity<?>> entityType = (Class<? extends RawEntity<?>>) type;
            entityType = getManager().getPolymorphicTypeMapper().invert(entityTyperes.getString(polyName));
            
            type = (Class<V>) entityType;       // avoiding Java cast oddities with generics
        }
        
        final TypeManager manager = getTypeManager();
        final TypeInfo<V> databaseType = manager.getType(type);
        
        if (databaseType == null) {
            throw new RuntimeException("UnrecognizedType: " + type.toString());
        }
        
        return databaseType.getLogicalType().pullFromDatabase(getManager(), restypefield);
    }
    private TypeManager getTypeManager()
    {
        return getManager().getProvider().getTypeManager();
    }
    private boolean isNull(ResultSet resString fieldthrows SQLException
    {
        res.getObject(field);
        return res.wasNull();
    }
    @SuppressWarnings("unchecked")
    private <V> V handleNullReturn(V backClass<V> type) {
        if (back != null) {
            return back;
        }
        
        if (type.isPrimitive()) {
            if (type.equals(boolean.class)) {
                return (V) .;
            } else if (type.equals(char.class)) {
                return (V) new Character(' ');
            } else if (type.equals(int.class)) {
                return (V) new Integer(0);
            } else if (type.equals(short.class)) {
                return (V) new Short("0");
            } else if (type.equals(long.class)) {
                return (V) new Long("0");
            } else if (type.equals(float.class)) {
                return (V) new Float("0");
            } else if (type.equals(double.class)) {
                return (V) new Double("0");
            } else if (type.equals(byte.class)) {
                return (V) new Byte("0");
            }
        }
        return null;
    }
    private boolean instanceOf(Object valueClass<?> type) {
        if (value == null) {
            return true;
        }
        
        if (type.isPrimitive()) {
            if (type.equals(boolean.class)) {
                return instanceOf(valueBoolean.class);
            } else if (type.equals(char.class)) {
                return instanceOf(valueCharacter.class);
            } else if (type.equals(byte.class)) {
                return instanceOf(valueByte.class);
            } else if (type.equals(short.class)) {
                return instanceOf(valueShort.class);
            } else if (type.equals(int.class)) {
                return instanceOf(valueInteger.class);
            } else if (type.equals(long.class)) {
                return instanceOf(valueLong.class);
            } else if (type.equals(float.class)) {
                return instanceOf(valueFloat.class);
            } else if (type.equals(double.class)) {
                return instanceOf(valueDouble.class);
            }
        } else {
            return type.isInstance(value);
        }
        return false;
    }

    
Some DB (Oracle) return BigDecimal for about any number
    private boolean isBigDecimal(Object valueClass<?> type)
    {
        if (!(value instanceof BigDecimal))
        {
            return false;
        }
        return type.equals(int.class) || type.equals(long.class) || type.equals(float.class) || type.equals(double.class);
    }
    private Object handleBigDecimal(Object valueClass<?> type)
    {
        final BigDecimal bd = (BigDecimalvalue;
        if (type.equals(int.class))
        {
            return bd.intValue();
        }
        else if (type.equals(long.class))
        {
            return bd.longValue();
        }
        else if (type.equals(float.class))
        {
            return bd.floatValue();
        }
        else if (type.equals(double.class))
        {
            return bd.doubleValue();
        }
        else
        {
            throw new RuntimeException("Could not resolve actual type for object :" + value + ", expected type is " + type);
        }
    }
New to GrepCode? Check out our FAQ X