Package com.adaptrex.core.persistence.jpa

Source Code of com.adaptrex.core.persistence.jpa.JpaPersistence

/*
* Copyright 2012 Adaptrex, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.adaptrex.core.persistence.jpa;

import com.adaptrex.core.ext.data.Config;
import com.adaptrex.core.ext.data.Filter;
import com.adaptrex.core.ext.data.Sorter;
import com.adaptrex.core.ext.data.Store;
import com.adaptrex.core.persistence.AdaptrexPersistence;
import com.adaptrex.core.utilities.StringUtilities;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;
import javax.xml.parsers.SAXParserFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

public class JpaPersistence implements AdaptrexPersistence {
 
    private Map<String, Class<?>> entityClassCache = new HashMap<String, Class<?>>();
    private Logger log = LoggerFactory.getLogger(JpaPersistence.class);
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    private EntityManagerFactory entityManagerFactory;
       
    /*
        * Set up the entity manager factory.  Since JPA only allows a single persistence unit
        * (even if it's a compound unit), we don't need to worry about support for multiple factories
        */
    public JpaPersistence() {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        InputStream inputStream = cl.getResourceAsStream("META-INF/persistence.xml");

        if (inputStream == null) {
            log.warn("Could not load default entity manager factory:  persistence.xml could not be found");
            return;
        }

        try {
            SAXParserFactory.newInstance().newSAXParser().parse(inputStream, new DefaultHandler() {

                @Override
                public void startElement(String uri, String localName, String qName, Attributes attributes) {
                    if (!qName.equalsIgnoreCase("persistence-unit") || entityManagerFactory != null) {
                        return;
                    }

                    String persistenceUnitName = attributes.getValue("name");
                    log.debug("Creating JPA Persistence Unit: " + persistenceUnitName);
                    entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
                }
            });
        } catch (Exception e) {
            log.warn("Error", e);
        }
    }

    @Override
    public void shutdown() {
        entityManagerFactory.close();
    }
   
   

    @Override
    public Class<?> getEntityClass(String className) {
        try {
            if (entityClassCache.containsKey(className)) {
                return entityClassCache.get(className);
            }

            EntityManager em = entityManagerFactory.createEntityManager();
            Metamodel meta = em.getMetamodel();

            for (EntityType<?> et : meta.getEntities()) {
                if (et.getJavaType().getName().endsWith("." + className)) {
                    Class<?> clazz = et.getJavaType();
                    entityClassCache.put(className, clazz);
                    return clazz;
                }
            }
        } catch (Exception e) {
            log.warn("Error", e);
        }
        return null;
    }
 
    @Override
    public EntityManager getEntityManager() {
        try {
            return entityManagerFactory.createEntityManager();
        } catch (Exception e) {
            log.warn("Error", e);
            return null;
        }
    }

 
 
/* *******************************************************************
    *
    * Get Single Entity
    *
    */
    @Override
    public Object getEntity(String entityName, Integer id) {
        EntityManager em = getEntityManager();
        return em.find(getEntityClass(entityName), id);
    }

    @Override
    public Object getEntity(Class<?> clazz, Integer id) {
        EntityManager em = getEntityManager();
        return em.find(clazz, id);
    }
 
 
    /* *******************************************************************
        *
        * Save Single Entity
        *
        */
    @Override
    public Object saveEntity(Object entity) {
        EntityManager em = getEntityManager();
        em.getTransaction().begin();
        entity = em.merge(entity);
        em.flush();
        em.getTransaction().commit();
        return entity;
    }

 
  /* *******************************************************************
   *
   * Delete Single Entity
   *
   */
  @Override
  public Object deleteEntity(String entityName, Integer id) {
    EntityManager em = getEntityManager();
    Object entity= em.find(getEntityClass(entityName), id);
    em.getTransaction().begin();
    em.remove(entity);
    em.getTransaction().commit();
    return entity;
  }
 
 
 
 
  /* *******************************************************************
   *
   * Entity List
   *
   */
  @SuppressWarnings("unchecked")
  @Override
  public List<Object> getEntityList(Store store) {
    Config config = store.getConfig();
    List<Object> list = new ArrayList<Object>();
   
    EntityManager em = entityManagerFactory.createEntityManager();
   
    Map<String,Object> parameters = new HashMap<String,Object>(config.getParams());
       
    try {
      Class<?> clazz = config.getClazz();
      String className = clazz.getSimpleName();
      String alias = className.toLowerCase().substring(0,1);
     
      /*
       * Core JPQL
       */
      String jpql = "SELECT " + alias + " FROM " + className + " " + alias;
     
      /*
       * Where
       */
      String where = "";
      if (config.getWhere() != null) {
        where += config.getWhere();
      }
     
      /*
       * Filter
       */
      for (Filter filter : config.getFilters()) {
        if (!where.isEmpty()) where += " AND ";
       
        String val = String.valueOf(filter.getValue());
        String prop = filter.getProperty();
       
       
        /*
         * Handle between inclusive
         */
        if (val.contains(">=<")) {
          String[] filterParts = val.split(">=<");
         
          where += "(" + alias + "." + filter.getProperty() + " BETWEEN :" +
              prop + "_low AND :" + prop + "_high)" +
                  "";
          parameters.put(prop + "_low", filterParts[0]);
          parameters.put(prop + "_high", filterParts[1]);
         
        /*
         * Handle "OR"
         */
        } else if (String.valueOf(filter.getValue()).contains("||")) {
          String whereOr = "";
          int i = 1;
         
          for (String orPart : String.valueOf(filter.getValue()).split("\\|\\|")) {
            whereOr += whereOr.isEmpty() ? "(" : " OR ";
            whereOr += alias + "." + filter.getProperty() + " = :" + filter.getProperty() + i;
            parameters.put(filter.getProperty() + i, orPart);
            i++;
          }
          whereOr += ")";
          where += whereOr;
         
        } else {
          String eqType = String.valueOf(filter.getValue()).contains("%") ? " like " : " = ";
          if (eqType.contains("like")) {
            where += "lower(" + alias + "." + filter.getProperty() + ")" + eqType + ":" + filter.getProperty();
          } else {
            where += alias + "." + filter.getProperty() + eqType + ":" + filter.getProperty();
          }
         
          parameters.put(filter.getProperty(), filter.getValue());
        }
      }
     
     
      /*
       * Add where clause
       */
      if (!where.isEmpty()) jpql += " WHERE " + where;
     
     
      if (config.getSorters().size() > 0) {
        String sortClause = "";
        for (Sorter sorter : config.getSorters()) {
          if (!sortClause.isEmpty()) sortClause += ",";
          sortClause += alias + "." + sorter.getProperty() + " " + sorter.getDirection();
        }
        jpql += " ORDER BY " + sortClause;
      }
     
      log.debug("JPQL: " + jpql);
      Query q = em.createQuery(jpql, clazz);
     
      /*
       * Add params
       * TODO: This is tedius... we want to automatically determine the
       * type for the field we're trying to set the parameter for
       */
      for (String key : parameters.keySet()) {
        Object paramObj = parameters.get(key);
       
        Class<?> paramType = q.getParameter(key).getParameterType();
        String typeName = paramType.getSimpleName().toLowerCase();
       
        try {
          if (typeName.equals("boolean")) {
            String stringVal = (String) paramObj;
            paramObj = stringVal.equals("1") || stringVal.equals("true") || stringVal.equals("Y");
           
          } else if (typeName.equals("date")) {
            paramObj = dateFormat.parse((String) paramObj);
           
          } else {
            Method m = paramType.getDeclaredMethod("valueOf", String.class);
            paramObj = m.invoke(null, paramObj);
          }
        } catch (Exception e) {}
       
        log.debug("  Param: " + key + " = " + paramObj);
        q.setParameter(key, paramObj);
      }

      store.setTotalCount(q.getResultList().size());
     
      if (config.getPageSize() != null) q.setMaxResults(config.getPageSize());
      if (config.getStart() != null) q.setFirstResult(config.getStart());
      list = q.getResultList();
    } catch (Exception e) {
      log.warn("Error", e);
    }
     
    em.close();
    return list;
  }

 
 
  /* ************************************************************************************
   *
   * Everything below this is experimental.  Possibly moved under a separate interface
   *
   */ 
  @Override
  public boolean isIdField(Class<?> clazz, String fieldName) {
    return getMemberAnnotation(clazz, fieldName, "Id") != null;
  }
 
  /*
   * TODO: Do we want to move ManyToMany to a separate method?
   */
  @Override
  public boolean isOneToMany(Class<?> clazz, String fieldName) {
    return getMemberAnnotation(clazz, fieldName, "OneToMany") != null
        || getMemberAnnotation(clazz, fieldName, "ManyToMany") != null;
  }

  @Override
  public boolean isManyToOne(Class<?> clazz, String fieldName) {
    return getMemberAnnotation(clazz, fieldName, "ManyToOne") != null;
  }
 
  @Override
  public Object getFieldValue(Object entity, String fieldName) {
    Method getter = null;
    Class<?> clazz = entity.getClass();
    try {getter = clazz.getMethod("get" + capitalize(fieldName));} catch (Exception e) {};
    if (getter == null) {
      try {getter = clazz.getMethod("is" + capitalize(fieldName));} catch (Exception e) {};
    }
    if (getter == null) return null;
   
    try {
      return getter.invoke(entity);
    } catch (Exception e) {
      log.warn("Error", e);
      return null;
    }
  }
 
 
 
 
 
  /*
   * This gets a list of all annotations on a class field (or it's getter)
   */
  private List<Annotation> getMemberAnnotations(Class<?> clazz, String member) {
    Annotation[] annotations;
    try {
      Field field = clazz.getDeclaredField(StringUtilities.uncapitalize(member));
      if (field != null) {
        annotations = field.getDeclaredAnnotations();
        if (annotations.length > 0) {
          return Arrays.asList(annotations);
        }
      }
    } catch (Exception e) {}
   
    try {
      Method getter = clazz.getMethod("get" + member);
      if (getter == null) getter = clazz.getMethod("is" + member);
      if (getter != null) {
        annotations = getter.getDeclaredAnnotations();
        if (annotations.length > 0) {
          return Arrays.asList(annotations);
        }
      }
    } catch (Exception e) {}
   
    return new ArrayList<Annotation>();
  }
 
  /*
   * This returns a specific annotation on a class field (or it's getter)
   */
  private Annotation getMemberAnnotation(Class<?> clazz, String member, String annotationName) {
    for (Annotation annotation : getMemberAnnotations(clazz, member)) {
      if (annotation.annotationType().getSimpleName().equals(annotationName)) {
        return annotation;
      }
    }
   
    return null;
  }
 
 
  private static String capitalize(String string) {
    return string.substring(0,1).toUpperCase() + string.substring(1);
  }
}
TOP

Related Classes of com.adaptrex.core.persistence.jpa.JpaPersistence

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.