Package it.eng.qbe.model.structure.builder.jpa

Source Code of it.eng.qbe.model.structure.builder.jpa.JPAModelStructureBuilder

/**

SpagoBI - The Business Intelligence Free Platform

Copyright (C) 2005-2009 Engineering Ingegneria Informatica S.p.A.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

**/
package it.eng.qbe.model.structure.builder.jpa;

import it.eng.qbe.datasource.jpa.JPADataSource;
import it.eng.qbe.model.properties.initializer.IModelStructurePropertiesInitializer;
import it.eng.qbe.model.properties.initializer.ModelStructurePropertiesInitializerFactory;
import it.eng.qbe.model.structure.IModelEntity;
import it.eng.qbe.model.structure.IModelField;
import it.eng.qbe.model.structure.IModelStructure;
import it.eng.qbe.model.structure.IModelViewEntityDescriptor;
import it.eng.qbe.model.structure.IModelViewEntityDescriptor.IModelViewRelationshipDescriptor;
import it.eng.qbe.model.structure.ModelCalculatedField;
import it.eng.qbe.model.structure.ModelEntity;
import it.eng.qbe.model.structure.ModelStructure;
import it.eng.qbe.model.structure.ModelViewEntity;
import it.eng.qbe.model.structure.builder.IModelStructureBuilder;
import it.eng.spagobi.utilities.assertion.Assert;

import java.lang.reflect.Member;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
import javax.persistence.metamodel.EmbeddableType;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.log4j.Logger;


/**
* @author Andrea Gioia (andrea.gioia@eng.it)
*/
public class JPAModelStructureBuilder implements IModelStructureBuilder {
 
  private static transient Logger logger = Logger.getLogger(JPAModelStructureBuilder.class);

  private JPADataSource dataSource; 
  private EntityManager entityManager;
  IModelStructurePropertiesInitializer propertiesInitializer;


  /**
   * Constructor
   * @param dataSource the JPA DataSource
   */
  public JPAModelStructureBuilder(JPADataSource dataSource) {
    if(dataSource == null) {
      throw new IllegalArgumentException("DataSource parameter cannot be null");
    }
    setDataSource( dataSource );
    propertiesInitializer = ModelStructurePropertiesInitializerFactory.getDataMartStructurePropertiesInitializer(dataSource);
  }
 
  /**
   * This method builds a JPA datamart structure.
   * @return DataMartModelStructure
   */
  public IModelStructure build() {
    ModelStructure modelStructure;
    String modelName;
    Metamodel jpaMetamodel;
    Set<EntityType<?>> jpaEntities;
   
    logger.debug("IN");
   
    try {
      modelStructure = new ModelStructure();
 
      modelName = getDataSource().getConfiguration().getModelName();
      Assert.assertNotNull(getDataSource(), "datasource cannot be null")
      setEntityManager(getDataSource().getEntityManager());
      Assert.assertNotNull(getEntityManager(), "Impossible to find the jar file associated to datamart named: [" + modelName + "]");
     
     
      propertiesInitializer.addProperties(modelStructure)
      Map calculatedFields = getDataSource().getConfiguration().loadCalculatedFields();
      modelStructure.setCalculatedFields(calculatedFields);
       
      jpaMetamodel = getEntityManager().getMetamodel();   
      jpaEntities = jpaMetamodel.getEntities();
      logger.debug("Jpa metamodel contains ["+ jpaEntities.size() + "] entity types");
     
      for(EntityType<?> entityType: jpaEntities) {
        logger.debug("Adding entity type [" + entityType + "] to model structure");
        String entityTypeName =  entityType.getJavaType().getName();
        addEntity(modelStructure, modelName, entityTypeName)
        logger.info("Entity type [" + entityType + "] succesfully added to model structure");
      }   
     
     
      /*
       * 1) Load Views definitions and adds to the model structure (with outbound relations from Business Views)
       */
      List<ModelViewEntity> addedViewsEntities = new ArrayList<ModelViewEntity>();
      List<IModelViewEntityDescriptor> list = getDataSource().getConfiguration().loadViews();
      if(list.size() > 0) {
        for (int i=0; i<list.size(); i++){
          IModelViewEntityDescriptor viewDescriptor = list.get(i);

          ModelViewEntity viewEntity = new ModelViewEntity(viewDescriptor, modelName, modelStructure, null);
          addedViewsEntities.add(viewEntity);
          propertiesInitializer.addProperties(viewEntity);
          modelStructure.addRootEntity(modelName, viewEntity);
        }
      }
     
      /*
       * 2) Re-scan model structure to add nodes referencing view (inbound relations to Business Views)
       */
     
      //visit all entities
      List<IModelEntity> allEntities = visitModelStructure(modelStructure,modelName);
     
      for (int i=0; i<list.size(); i++){
        IModelViewEntityDescriptor viewDescriptor = list.get(i);
        List<IModelViewRelationshipDescriptor> viewRelationshipsDescriptors = viewDescriptor.getRelationshipDescriptors();
        for (IModelViewRelationshipDescriptor  viewRelationshipDescriptor : viewRelationshipsDescriptors){
          if (!viewRelationshipDescriptor.isOutbound()){
            String sourceEntityUniqueName = viewRelationshipDescriptor.getSourceEntityUniqueName();
            IModelEntity entity = modelStructure.getEntity(sourceEntityUniqueName)
            logger.debug("Source Entity Unique name: "+entity.getUniqueName());
           
            //Add node for first level entities (using UniqueName)
            ModelViewEntity viewEntity = new ModelViewEntity(viewDescriptor, modelName, modelStructure, entity);
            propertiesInitializer.addProperties(viewEntity);
            entity.addSubEntity(viewEntity);
           
            //Add node for subentities (using Entity Type matching)
            for(IModelEntity modelEntity : allEntities){
              logger.debug("Searched Entity type: "+entity.getType());
              logger.debug("Current Entity type: "+modelEntity.getType());
              if (modelEntity.getType().equals(entity.getType())){
                ModelViewEntity viewEntitySub = new ModelViewEntity(viewDescriptor, modelName, modelStructure, modelEntity);
                propertiesInitializer.addProperties(viewEntitySub);
                logger.debug(" ** Found matching for: "+modelEntity.getType()+" with "+entity.getType());
                modelEntity.addSubEntity(viewEntitySub);
                addedViewsEntities.add(viewEntitySub);
              }
            } 
          }
        }
      }
     
      /*
       * 3) Now add nodes corresponding to relations between Business Views (BV-to-BV)
       *     Analyzing only outbound relationships because
       *    we always have an inbound relationships that's specular
       */
      for (ModelViewEntity viewEntity : addedViewsEntities){
        //Outbound relationships
        viewEntity.addOutboundRelationshipsToViewEntities();
      }

      logger.info("Model structure for model [" + modelName + "] succesfully built");
     
      return modelStructure;
    }
    catch (Exception e){
      e.printStackTrace();
      logger.debug("Impossible to build model structure", e);
      throw new RuntimeException("Impossible to build model structure", e);
    }
    catch(Throwable t) {
      throw new RuntimeException("Impossible to build model structure", t);
   
    } finally {
      logger.debug("OUT");
    }
  }
 
  private List<IModelEntity> visitModelStructure(ModelStructure modelStructure, String modelName){
    List<IModelEntity> rootEntities = modelStructure.getRootEntities(modelName);
    List<IModelEntity> subEntities = new ArrayList<IModelEntity>();
    List<IModelEntity> allSubEntities = new ArrayList<IModelEntity>();
    for (IModelEntity entity : rootEntities){
      subEntities.addAll(entity.getAllSubEntities());
      visitLevel(entity.getAllSubEntities(),allSubEntities,1);
    }
   
    allSubEntities.addAll(subEntities);
    allSubEntities.addAll(rootEntities);
    return allSubEntities;
  }
 
  private void visitLevel(List<IModelEntity> entities, List<IModelEntity>allEntities, int iterationLevel){
    //logger.debug("visitLevel "+iterationLevel);
    if (iterationLevel < 8){
      for (IModelEntity entity:entities){
        allEntities.addAll(entity.getAllSubEntities());
        visitLevel(entity.getAllSubEntities(),allEntities,iterationLevel+1);
      }
    }
  }
 
 
  private void addEntity (IModelStructure modelStructure, String modelName, String entityType){

    String entityName = getEntityNameFromEntityType(entityType);   
    IModelEntity dataMartEntity = modelStructure.addRootEntity(modelName, entityName, null, null, entityType);
    propertiesInitializer.addProperties(dataMartEntity);
   
    //addKeyFields(dataMartEntity);   
    List subEntities = addNormalFields(dataMartEntity);
    addCalculatedFields(dataMartEntity);
    addSubEntities(dataMartEntity, subEntities, 0);
   
  }
 
  private String getEntityNameFromEntityType(String entityType) {
    String entityName = entityType;
    entityName = (entityName.lastIndexOf('.') > 0 ?
          entityName.substring(entityName.lastIndexOf('.') + 1 , entityName.length()) :
          entityName);
         
    return entityName;
  }

  /**
   * This method adds the normal fields to the datamart entry structure
   * @param dataMartEntity:  the datamart structure to complete
   */
  public List addNormalFields(IModelEntity dataMartEntity) {   
    logger.debug("Adding the field "+dataMartEntity.getName());
    String[] propertyNames;
    List subEntities = new ArrayList();     
    EntityType thisEntityType = null;
   
    Metamodel classMetadata = getEntityManager().getMetamodel();
   
    for(Iterator it = classMetadata.getEntities().iterator(); it.hasNext(); ) {
      EntityType et = (EntityType)it.next();
      if(et.getJavaType().getName().equals(dataMartEntity.getType())){
        thisEntityType = et;
        break;
      }
    } 
   
    if(thisEntityType==null){
      return new ArrayList();
    }
   
    Set<Attribute> attributes = thisEntityType.getAttributes();
    Iterator<Attribute> attributesIt = attributes.iterator();
   
   
    while(attributesIt.hasNext()){
      Attribute a = attributesIt.next();
      //normal attribute
      if(a.getPersistentAttributeType().equals(PersistentAttributeType.BASIC)){   
        addField(a, dataMartEntity,"");
      }else// relation
        if(a.getPersistentAttributeType().equals(PersistentAttributeType.MANY_TO_ONE)){
          Class c = a.getJavaType();
          String entityType = c.getName();
          String columnName = a.getName();
          String entityName =  a.getName(); //getEntityNameFromEntityType(entityType);
           IModelEntity subentity = new ModelEntity(entityName, null, columnName, entityType, dataMartEntity.getStructure());   
           subEntities.add(subentity);   
      }else//composite key
        if(a.getPersistentAttributeType().equals(PersistentAttributeType.EMBEDDED)){
        Set<Attribute> keyAttre = ((EmbeddableType)((SingularAttribute)a).getType()).getAttributes();
        Iterator<Attribute> keyIter = keyAttre.iterator();
        while(keyIter.hasNext()){
          addField(keyIter.next(), dataMartEntity, a.getName()+".")
        }
      }
    }
   
    logger.debug("Field "+dataMartEntity.getName()+" added");
    return subEntities;
  }
 
  /**
   * Add an attribute to the model
   * @param attr the attribute
   * @param dataMartEntity the parent entity
   */
  private void addField(Attribute attr, IModelEntity dataMartEntity, String keyPrefix){
    String n = attr.getName();
    Member m = attr.getJavaMember();
    Class c = attr.getJavaType();
    String type = c.getName();
   
    // TODO: SCALE E PREC
    int scale = 0;
    int precision = 0;

    IModelField datamartField = dataMartEntity.addNormalField(keyPrefix+ attr.getName());
    datamartField.setType(type);
    datamartField.setPrecision(precision);
    datamartField.setLength(scale);
    propertiesInitializer.addProperties(datamartField);
  }
 
  // TODO: controllare correttezza per jpa...se va bene generalizzare metodo sia per jpa che hibernate!
  private void addCalculatedFields(IModelEntity dataMartEntity) {
    logger.debug("Adding the calculated field "+dataMartEntity.getName());
    List calculatedFileds;
    ModelCalculatedField calculatedField;
   
    calculatedFileds = dataMartEntity.getStructure().getCalculatedFieldsByEntity(dataMartEntity.getUniqueName());
    if(calculatedFileds != null) {
      for(int i = 0; i < calculatedFileds.size(); i++) {
        calculatedField = (ModelCalculatedField)calculatedFileds.get(i);
        dataMartEntity.addCalculatedField(calculatedField);
        propertiesInitializer.addProperties(calculatedField);
      }
    }
    logger.debug("Added the calculated field "+dataMartEntity.getName());
  }
 
  // TODO: controllare correttezza per jpa...se va bene generalizzare metodo sia per jpa che hibernate!
  private void addSubEntities(IModelEntity dataMartEntity, List subEntities, int recursionLevel) {
   
    Iterator it = subEntities.iterator();
    while (it.hasNext()) {
      IModelEntity subentity = (IModelEntity)it.next();
      if (subentity.getType().equalsIgnoreCase(dataMartEntity.getType())){
        // ciclo di periodo 0!
      } else if(recursionLevel > 10) {
        // prune recursion tree
      } else {
        addSubEntity(dataMartEntity, subentity, recursionLevel+1);
      }
    }
  }

  // TODO: controllare correttezza per jpa...se va bene generalizzare metodo sia per jpa che hibernate! 
  private void addSubEntity (IModelEntity parentEntity, IModelEntity subEntity, int recursionLevel){
    logger.debug("Adding the sub entity field "+subEntity.getName()+" child of "+parentEntity.getName());
    IModelEntity dataMartEntity;       
   
    //String entityName = getEntityNameFromEntityType(entityType);   
    dataMartEntity = parentEntity.addSubEntity(subEntity.getName(), subEntity.getRole(), subEntity.getType());
    propertiesInitializer.addProperties(dataMartEntity);
   
    //addKeyFields(dataMartEntity);     
    List subEntities = addNormalFields(dataMartEntity);   
    addCalculatedFields(dataMartEntity);
    addSubEntities(dataMartEntity, subEntities, recursionLevel);
    logger.debug("Added the sub entity field "+subEntity.getName()+" child of "+parentEntity.getName());
  }
 
  /**
   * @return the JPADataSource
   */
  public JPADataSource getDataSource() {
    return dataSource;
  }

  /**
   * @param JPADataSource the datasource to set
   */
  public void setDataSource(JPADataSource dataSource) {
    this.dataSource = dataSource;
  }

  /**
   * @return the entityManager
   */
  public EntityManager getEntityManager() {
    return entityManager;
  }

  /**
   * @param entityManager the entityManager to set
   */
  public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
  }
}
TOP

Related Classes of it.eng.qbe.model.structure.builder.jpa.JPAModelStructureBuilder

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.