Package com.spaceprogram.simplejpa

Source Code of com.spaceprogram.simplejpa.ObjectBuilder

package com.spaceprogram.simplejpa;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import javax.persistence.EnumType;
import javax.persistence.PersistenceException;

import net.sf.cglib.proxy.Enhancer;

import com.amazonaws.services.simpledb.model.Attribute;
import com.spaceprogram.simplejpa.query.QueryImpl;

/**
* User: treeder
* Date: May 11, 2008
* Time: 4:01:28 PM
*
* Additional Contributions
*  - Yair Ben-Meir reformy@gmail.com
*/
public class ObjectBuilder {

    private static Logger logger = Logger.getLogger(ObjectBuilder.class.getName());

    public static <T> T buildObject(EntityManagerSimpleJPA em, Class<T> tClass, Object id, List<Attribute> atts) {
        T newInstance;
        /*
        Why was this here?  Should we merge if it exists though?
        newInstance = em.cacheGet(tClass, id);
        if (newInstance != null) {
            return newInstance;
        }*/
        AnnotationInfo ai = em.getFactory().getAnnotationManager().getAnnotationInfo(tClass);
        try {
//            newInstance = tClass.newInstance();
            // check for DTYPE to see if it's a subclass, must be a faster way to do this you'd think?
            for (Attribute att : atts) {
                if (att.getName().equals(EntityManagerFactoryImpl.DTYPE)) {
                    logger.finest("dtype=" + att.getValue());
                    ai = em.getFactory().getAnnotationManager().getAnnotationInfoByDiscriminator(att.getValue());
                    if(ai == null) {
                        throw new PersistenceException(new ClassNotFoundException("Could not build object with dtype = " + att.getValue() + ". Class not found or is not an @Entity."));
                    }
                    tClass = ai.getMainClass();
                    // check cache again with new class
                    newInstance = em.cacheGet(tClass, id);
                    if (newInstance != null) return newInstance;
                    break;
                }
            }
            ObjectWithInterceptor owi = newEnancedInstance(em, tClass);
            newInstance = (T) owi.getBean();
            for (PersistentProperty field : ai.getPersistentProperties()) {
                String attName = field.getFieldName();
                String columnName = field.getColumnName();
                if (field.isForeignKeyRelationship()) {
                    // lazy it up
                    Set<String> keys = getForeignKeys(em, field, columnName, atts);
                    logger.finest("keys=" + keys);
                    if (keys == null || keys.isEmpty()) {
                        continue;
                    }
                    // todo: stick a cache in here and check the cache for the instance before creating the lazy loader.
                    logger.finest("creating new lazy loading instance for field " + field.getFieldName() + " of class " + tClass.getSimpleName() + " with id " + id);
//                    Object toSet = newLazyLoadingInstance(retType, keys);
                    owi.getInterceptor().putForeignKey(attName, keys);
                } else if (field.isInverseRelationship()) {
                    Class typeInList = field.getPropertyClass();
                    // todo: should this return null if there are no elements??
//                    LazyList lazyList = new LazyList(this, newInstance, annotation.mappedBy(), id, typeInList, factory.getAnnotationManager().getAnnotationInfo(typeInList));

                    List<PersistentProperty.OrderClause> orderBy = null;
                    if (List.class.isAssignableFrom(field.getRawClass()))
                    {
                        orderBy = field.getOrderClauses();
                    }
                   
                    LazyList lazyList = new LazyList(em, typeInList, oneToManyQuery(em, attName, field.getMappedBy(), id, typeInList, orderBy));
//                    Class retType = field.getReturnType();
                    // todo: assuming List for now, handle other collection types
                    field.setProperty(newInstance, lazyList);
                } else if (field.isLob() || field.isJsonLob()) {
                    // handled in Proxy
                    String lobKeyAttributeName = field.getColumnName();
                    String lobKeyVal = getValueToSet(atts, lobKeyAttributeName, columnName);
                    logger.finest("lobkeyval to set on interceptor=" + lobKeyVal + " - fromatt=" + lobKeyAttributeName);
                    // TODO add multivalue support for LOB keys
                    if (lobKeyVal != null) owi.getInterceptor().putForeignKey(attName, Collections.singleton(lobKeyVal));
                } else if (field.getEnumType() != null) {
                    String val = getValueToSet(atts, attName, columnName);
                    if(val != null){
                        Object enumVal = getEnumValue(field, val);
                        field.setProperty(newInstance, enumVal);
                    }
                }
                else if(field.isId()) {
                    field.setProperty(newInstance, id);
                }
                else {
                    Collection<String> val = getValuesToSet(atts, attName, columnName);
                    if (val != null && !val.isEmpty()) {
                        em.setFieldValue(tClass, newInstance, field, val);
                    }
                }
            }
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
        em.cachePut(id, newInstance);
        return newInstance;

    }

    static Object getEnumValue(PersistentProperty field, String val) {
        EnumType enumType = field.getEnumType();
        Class<? extends Enum> retType = (Class<? extends Enum>)field.getPropertyClass();
        Object enumVal = null;
        if (enumType == EnumType.STRING) {
            enumVal = Enum.valueOf(retType, val);
        } else { // ordinal
            enumVal = retType.getEnumConstants()[Integer.parseInt(val)];
        }
        return enumVal;
    }

    private static ObjectWithInterceptor newEnancedInstance(EntityManagerSimpleJPA em, Class tClass) {
        LazyInterceptor interceptor = new LazyInterceptor(em);
        Enhancer e = new Enhancer();
        e.setSuperclass(tClass);
        e.setCallback(interceptor);
        Object bean = e.create();
        ObjectWithInterceptor cwi = new ObjectWithInterceptor(bean, interceptor);
        return cwi;
    }

    private static Set<String> getForeignKeys(EntityManagerSimpleJPA em, PersistentProperty getter, String columnName, List<Attribute> atts) {
        String fkAttName = columnName != null ? columnName : NamingHelper.foreignKey(getter.getFieldName());
        HashSet<String> keys = new HashSet<String>(atts.size());
        for (Attribute att : atts) {
            if (att.getName().equals(fkAttName)) {
                keys.add(att.getValue());
            }
        }
        return keys;
    }

    private static Collection<String> getValuesToSet(List<Attribute> atts, String propertyName, String columnName) {
        Collection<String> values = new ArrayList<String>();
        if(columnName != null) propertyName = columnName;
        for (Attribute att : atts) {
            String attName = att.getName();
            if (attName.equals(propertyName)) {
                values.add(att.getValue());
            }
        }
        return values;
    }

    private static String getValueToSet(List<Attribute> atts, String propertyName, String columnName) {
        if(columnName != null) propertyName = columnName;
        for (Attribute att : atts) {
            String attName = att.getName();
            if (attName.equals(propertyName)) {
                String val = att.getValue();
                return val;
            }
        }
        return null;
    }


    private static QueryImpl oneToManyQuery(EntityManagerSimpleJPA em, String attName, String foreignKeyFieldName, Object id, Class typeInList, List<PersistentProperty.OrderClause> orderBy) {
        if (foreignKeyFieldName == null || foreignKeyFieldName.length() == 0) {
            // use the class containing the OneToMany
            foreignKeyFieldName = attName;
        }
        AnnotationInfo ai = em.getFactory().getAnnotationManager().getAnnotationInfo(typeInList);
        Class refType = ai.getPersistentProperty(foreignKeyFieldName).getPropertyClass();
        AnnotationInfo refAi = em.getAnnotationManager().getAnnotationInfo(refType);
        String query = createOneToManyQuery(typeInList, foreignKeyFieldName, refAi, id, orderBy);
       
        logger.finer("OneToMany query=" + query);
        return new QueryImpl(em, query);
    }

    static String createOneToManyQuery(Class typeInList, String foreignKeyFieldName, AnnotationInfo refAi, Object id, List<PersistentProperty.OrderClause> orderBy) {
        String foreignIdAttr = refAi.getIdMethod().getFieldName();
        String query = "select o from " + typeInList.getName() + " o where o." + foreignKeyFieldName + "." + foreignIdAttr + " = '" + id + "'";

        if (orderBy != null) {
            for(PersistentProperty.OrderClause clause : orderBy)
            {
                query += " and o." + clause.field + " is not null";
                query += " order by o." + clause.field;
                if (clause.order != null) query += " " + clause.order.toString();
            }
        }
        return query;
    }


}
TOP

Related Classes of com.spaceprogram.simplejpa.ObjectBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.