Package org.paquitosoft.lml.model.action

Source Code of org.paquitosoft.lml.model.action.ReadEntityAction

package org.paquitosoft.lml.model.action;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.List;
import org.paquitosoft.lml.model.util.ModelUtilities;
import org.paquitosoft.lml.model.annotation.PersistentAttribute;
import org.paquitosoft.lml.model.annotation.AssociatedEntityList;
import org.paquitosoft.lml.model.annotation.AssociationType;
import org.paquitosoft.lml.model.dao.DAOFactory;
import org.paquitosoft.lml.model.dao.IDefaultDAO;
import org.paquitosoft.lml.model.exception.DataNotFoundException;
import org.paquitosoft.lml.model.exception.InternalErrorException;
import org.paquitosoft.lml.model.exception.ReflectionException;
import org.paquitosoft.lml.util.LMLGlobalOperations;

/**
*  This action is used to get an unique entity by its identifier.
*
* @author paquitosoft
*/
public class ReadEntityAction<T> implements INonTransactionalAction {

    private Class<T> entityType;
   
    private T entity;
   
    private Object entityId;
   
    private Integer detailLevel;
   
    /**
     * This constructor is used by external classes when they need to
     * look for an entity.
     *
     * @param entityType
     * @param entityId
     * @param detailLevel
     */
    public ReadEntityAction(Class<T> entityType, Object entityId, Integer detailLevel) {
        this.entityType = entityType;
        this.entityId = entityId;
        this.detailLevel = detailLevel;
    }
   
    /**
     * This constructor is used for child classes or packages classes that only needs to
     * fill an entity (they deal with the task of look for the entity itself).
     *
     * @param entity
     * @param detailLevel
     */
    protected ReadEntityAction(T entity, Integer detailLevel) {
        this.entity = entity;
        this.detailLevel = detailLevel;
    }
   
    public T execute(Connection connection) throws InternalErrorException {
       
        // Look for the entity only when it's needed
        T result = entity;
        if (result == null) {
           
            // Create an instance of default dao
            IDefaultDAO dao = DAOFactory.getDefaultDAO(connection);

            // Read entity table
            result = dao.read(entityType, entityId);

        }
       
        // Complete with related entities
        fillEntity(result, detailLevel, connection);
       
        return result;
    }

    /**
     * This method is used to complete an entity with the information of its related
     *  entities depending on the detailLevel.
     *
     * @param entity
     * @throws org.paquitosoft.lml.model.exception.InternalErrorException
     */
    protected void fillEntity(Object entity, Integer detailLevel, Connection connection) throws InternalErrorException {

        if (detailLevel != null && 1 < detailLevel) {

            List<Field> associatedFields = ModelUtilities.getAllAssociatedEntityFields(entity.getClass());
            List<Field> associatedLists = ModelUtilities.getAllAnnotatedEntityFields(entity.getClass(), AssociatedEntityList.class);
           
            for (Field f : associatedFields) {
                f.setAccessible(true);               
                try {
                    Object id = ModelUtilities.getEntityIdentifier(f.get(entity));
                    f.set(entity, new ReadEntityAction(f.getType(), id, detailLevel - 1).execute(connection));
                } catch (DataNotFoundException e) {
                    if (AssociationType.REQUIRED.equals(f.getAnnotation(PersistentAttribute.class).readAssociationType())) {
                        throw e;
                    }
                } catch (ReflectionException e) {
                    throw new InternalErrorException("ReadEntityAction::fillEntity", e);
                } catch (IllegalAccessException e) {
                    throw new InternalErrorException("ReadEntityAction::fillEntity", e);
                }
            }

            for (Field f : associatedLists) {
                f.setAccessible(true);
                try {
                    // Get the query
                    String query = ModelUtilities.generateFindRelatedEntitiesQuery(f);
                   
                    // Get the entity identifier/s
                    Object id = ModelUtilities.getEntityIdentifier(entity);
                   
                    // If pk is a compund key we must extract each value (they are sorted by name)
                    if (id.equals(entity)) {
                        List<Field> pkFields = ModelUtilities.getEntityIdentifierFields(entity.getClass());
                        Object[] pkFieldValues = new Object[pkFields.size()];
                        for (int i = 0; i < pkFields.size(); i++) {
                            pkFields.get(i).setAccessible(true);
                            pkFieldValues[i] = pkFields.get(i).get(entity);
                        }
                        id = pkFieldValues;
                    }

                    // The action depends on the type of association (1-N or N-M)
                    INonTransactionalAction action = null;
                    AssociatedEntityList ann = f.getAnnotation(AssociatedEntityList.class);
                    if (ann != null && ann.joinTableName().length() > 0) {
                        action = new FindExternalRelatedEntitiesAction(entity, f, ann.joinTableName(), detailLevel - 1);
                    } else {
                        action = new FindEntitiesAction(query, LMLGlobalOperations.getCollectionType(f), detailLevel - 1, id);
                    }

                    // Search the collection and set it into the related attribute
                    f.set(entity, action.execute(connection));
                   
                } catch (DataNotFoundException exception) {
                    if (AssociationType.REQUIRED.equals(f.getAnnotation(AssociatedEntityList.class).readAssociationType())) {
                        throw exception;
                    }
                } catch (ReflectionException e) {
                    throw new InternalErrorException("ReadEntityAction::fillEntity", e);
                } catch (IllegalAccessException e) {
                    throw new InternalErrorException("ReadEntityAction::fillEntity", e);
                }

            }
           
        }
       
    }
   
}
TOP

Related Classes of org.paquitosoft.lml.model.action.ReadEntityAction

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.