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.persistence.AdaptrexSession;
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.Temporal;
import javax.persistence.TemporalType;
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 Map<String, List<String>> memberAnnotationCache = new HashMap<String, List<String>>();
    private Map<String, String> fieldTypeCache = new HashMap<String, String>();
   
    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;
    }

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

    @Override
    public Object getEntity(AdaptrexSession session, Class<?> clazz, Integer id) {
  EntityManager em = (EntityManager) session.getNativeSession();
  return em.find(clazz, id);
    }

    /* *******************************************************************
     *
     * Save Single Entity
     *
     */
    @Override
    public Object saveEntity(AdaptrexSession session, Object entity) {
  EntityManager em = (EntityManager) session.getNativeSession();
  em.getTransaction().begin();
  entity = em.merge(entity);
  em.flush();
  em.getTransaction().commit();
  return entity;
    }

    /* *******************************************************************
     *
     * Delete Single Entity
     *
     */
    @Override
    public Object deleteEntity(AdaptrexSession session, String entityName, Integer id) {
  EntityManager em = (EntityManager) session.getNativeSession();
  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(AdaptrexSession session, Store store) {
  Config config = store.getConfig();
  List<Object> list = new ArrayList<Object>();

  EntityManager em = (EntityManager) session.getNativeSession();

  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);
  }

  return list;
    }

    /* ************************************************************************************
     *
     * Everything below this is experimental.  Possibly moved under a separate interface
     *
     */
    @Override
    public boolean isIdField(Class<?> clazz, String fieldName) {
  return hasMemberAnnotation(clazz, fieldName, "Id");
    }

    /*
     * TODO: Do we want to move ManyToMany to a separate method?
     */
    @Override
    public boolean isOneToMany(Class<?> clazz, String fieldName) {
  return hasMemberAnnotation(clazz, fieldName, "OneToMany")
    || hasMemberAnnotation(clazz, fieldName, "ManyToMany");
    }

    @Override
    public boolean isManyToOne(Class<?> clazz, String fieldName) {
  return hasMemberAnnotation(clazz, fieldName, "ManyToOne");
    }

    @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;
  }
    }

   
   
    @Override
    public String getFieldType(Class<?> clazz, String fieldName) {
  String fieldType = fieldTypeCache.get(clazz.getName() + "." + fieldName);
  if (fieldType != null) return fieldType;
 
  Field field = null;
  try {
      field = clazz.getDeclaredField(fieldName);
  } catch (Exception e) {}
  if (field == null) return null;
  String columnType = field.getType().getSimpleName().toLowerCase();

  if (columnType.equals("integer") || columnType.equals("long")) {
      columnType = "int";
  } else if (columnType.equals("double")) {
      columnType = "float";
  } else if (columnType.equals("time")) {
      columnType = "time";
  } else if (columnType.equals("calendar") || columnType.equals("date")) {
      columnType = "date";
  }
 
  if (columnType.equals("date")) {
      Temporal a = field.getAnnotation(Temporal.class);
      if (a == null) {
    try {
        Method getter = clazz.getMethod("get" + StringUtilities.capitalize(fieldName));
        if (getter != null) {
      a = getter.getAnnotation(Temporal.class);
        }
    } catch (Exception e) {}
      }
      if (a != null && a.value().equals(TemporalType.TIME)) {
    columnType = "time";
      }     
  }
 
  fieldTypeCache.put(clazz.getName() + "." + fieldName, columnType);
  return columnType;
    }
   
   
   
   
   
   
   
   
   
   
    private boolean hasMemberAnnotation(Class<?> clazz, String member, String annotationName) {
  List<String> memberAnnotations = memberAnnotationCache.get(clazz.getName() + "." + member);
  if (memberAnnotations == null) {
      memberAnnotations = getMemberAnnotations(clazz, member);
  }
  return memberAnnotations.contains(annotationName);
    }

   
    /*
     * This gets a list of all annotations on a class field (or it's getter)
     */
    private List<String> getMemberAnnotations(Class<?> clazz, String member) {
  List<String> list = memberAnnotationCache.get(clazz.getName() + "." + member);
  if (list != null) {
      return list;
  }
 
  list = new ArrayList<String>();
  try {
      Field field = clazz.getDeclaredField(member);
      if (field != null) {
    for (Annotation annotation : field.getDeclaredAnnotations()) {
        list.add(annotation.annotationType().getSimpleName());
    }
      }
  } catch (Exception e) {
  }

  try {
      Method getter = clazz.getMethod("get" + StringUtilities.capitalize(member));
      if (getter != null) {
    for (Annotation annotation : getter.getDeclaredAnnotations()) {
        list.add(annotation.annotationType().getSimpleName());
    }
      }
  } catch (Exception e) {
  }

  memberAnnotationCache.put(clazz.getName() + "." + member, list);
  return list;
    }
   
    private static String capitalize(String string) {
  return string.substring(0, 1).toUpperCase() + string.substring(1);
    }


    @Override
    public Object getNativeSession() {
  return entityManagerFactory.createEntityManager();
    }

    @Override
    public void closeNativeSession(Object entityManager) {
  ((EntityManager) entityManager).close();
    }
}
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.