Package com.adaptrex.core.persistence.cayenne

Source Code of com.adaptrex.core.persistence.cayenne.CayenneStoreData

/*
* 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.cayenne;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.query.EJBQLQuery;
import org.apache.cayenne.query.Ordering;
import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.query.SortOrder;
import org.apache.log4j.Logger;

import com.adaptrex.core.ext.ExtConfig;
import com.adaptrex.core.ext.ExtTypeFormatter;
import com.adaptrex.core.ext.Filter;
import com.adaptrex.core.ext.ModelInstance;
import com.adaptrex.core.ext.Sorter;
import com.adaptrex.core.persistence.api.AdaptrexEntityType;
import com.adaptrex.core.persistence.api.BaseStoreData;
import com.adaptrex.core.persistence.api.AdaptrexStoreData;
import com.adaptrex.core.utilities.StringUtilities;

public class CayenneStoreData extends BaseStoreData implements AdaptrexStoreData {
  private ExtConfig extConfig;
 
  private static Logger log = Logger.getLogger(CayenneStoreData.class);
 
  public CayenneStoreData(ExtConfig extConfig) {
    this.extConfig = extConfig;
  }
 
  @Override
  public List<Map<String, Object>> getData() throws Exception {
    List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
   
    Class<?> clazz = extConfig.getEntityClass();
    CayennePersistenceManager cayenne = (CayennePersistenceManager) extConfig.getORMPersistenceManager();
    ObjectContext objectContext = cayenne.getReadOnlyObjectContext();
    AdaptrexEntityType adaptrexEntity = cayenne.getAdaptrexEntity(clazz.getSimpleName());
   
    /*
     * If we have a where clause, fall back to JPQL
     */
    if (this.getWhere() != null && !this.getWhere().isEmpty()) {
      return getWhereFallback(cayenne, objectContext, clazz, data);
    }
   
    try {
     
      /*
       * Create the expressions
       */
      Expression expression = null;
      for (Filter filter : this.getFilters()) {
        Object val = filter.getValue();
        if (val == null || String.valueOf(val).isEmpty()) continue;
       
        String key = filter.getProperty();
        String extFieldType = adaptrexEntity.getField(key).getFieldDefinition().getType();
       
        Expression newExpression = null;
       
        /*
         * String filter
         *
         * Should be consistent with ExtJS filtering
         * By default, the settings are:  exactMatch:false, caseSensitive:false, anyMatch:false
         */
        if (extFieldType.equals(ExtTypeFormatter.STRING)) {
          if (filter.getCaseSensitive()) {
            if (filter.getExactMatch()) {
              newExpression = ExpressionFactory.matchExp(key, val);
            } else if (filter.getAnyMatch()) {
              newExpression = ExpressionFactory.likeExp(key, "%" + val + "%");
            } else {
              newExpression = ExpressionFactory.likeExp(key, val + "%");
            }
          } else {
            if (filter.getExactMatch()) {
              newExpression = ExpressionFactory.likeIgnoreCaseExp(key, val);
            } else if (filter.getAnyMatch()) {
              newExpression = ExpressionFactory.likeIgnoreCaseExp(key, "%" + val + "%");
            } else {
              newExpression = ExpressionFactory.likeIgnoreCaseExp(key, val + "%");
            }           
          }

        /*
         * Boolean filter
         */
        } else if (extFieldType.equals(ExtTypeFormatter.BOOLEAN)) {
          newExpression = ExpressionFactory.matchExp(key, String.valueOf(val).toLowerCase().equals("true"));         
       
       
        /*
         * Integer filter
         *
         * Inline stores allow flexibility not directly available in Ext.  Since we
         * control the component tags, we can test for various additional conditions.
         * Since this is server side only, local filtering should not also be applied
         */       
        } else if (extFieldType.equals(ExtTypeFormatter.INT)) {
          Integer numVal = null;
          try {
            numVal = (val instanceof Integer)
                ? (Integer) val
                : Integer.valueOf(String.valueOf(val));
          } catch (Exception e) {
            log.warn("Adaptrex Store Error: Filter: Couldn't parse integer: " + val);
            continue;
          }
         
          /*
           * Filter based on various conditions
           */
          Integer t = filter.getFilterType();
          if (t == Filter.EQUAL) {
            newExpression = ExpressionFactory.matchExp(key, numVal);
          } else if (t == Filter.NOT_EQUAL) {
            newExpression = ExpressionFactory.noMatchExp(key, numVal);
          } else if (t == Filter.LESS_THAN) {
            newExpression = ExpressionFactory.lessExp(key, numVal);
          } else if (t == Filter.LESS_THAN_EQUAL) {
            newExpression = ExpressionFactory.lessOrEqualExp(key, numVal);
          } else if (t == Filter.GREATER_THAN) {
            newExpression = ExpressionFactory.greaterExp(key, numVal);
          } else if (t == Filter.GREATER_THAN_EQUAL) {
            newExpression = ExpressionFactory.greaterOrEqualExp(key, numVal);
          }         

        /*
         * Float filter
         *
         * Similar to integer filter in that we can test for additional conditions
         * not avaialable in standard Ext filtering.  Do not rely on these filters
         * to work as local filters.  Also, since we can't currently test for float
         * equality, we should only be checking for less than or greater than at
         * this time.
         *
         * In the future, we may add additional filter settings which would allow
         * us to test for float equality up to a certain precision.
         */
        } else if (extFieldType.equals(ExtTypeFormatter.FLOAT)) {
          Double numVal = null;
          try {
            numVal = (val instanceof Double)
                ? (Double) val
                : Double.valueOf(String.valueOf(val));
          } catch (Exception e) {
            log.warn("Adaptrex Store Error: Filter: Couldn't parse float: " + val);
            continue;
          }
         
          Integer t = filter.getFilterType();
          if (t == Filter.EQUAL) {
            log.warn("Adaptrex Store Error: Filter: Float equality not implemented: " + val);
            continue;
          } else if (t == Filter.NOT_EQUAL) {
            log.warn("Adaptrex Store Error: Filter: Float inequality not implemented: " + val);
            continue;
          } else if (t == Filter.LESS_THAN || t == Filter.LESS_THAN_EQUAL) {
            newExpression = ExpressionFactory.lessOrEqualExp(key, numVal);
          } else if (t == Filter.GREATER_THAN || t == Filter.GREATER_THAN_EQUAL) {
            newExpression = ExpressionFactory.greaterOrEqualExp(key, numVal);
          }           
       
         
        /*
         * Date filter
         *
         * Also simililar to integer.  We can test for several date comparison
         * conditions not available in standard Ext filtering.
         */
        } else if (extFieldType.equals(ExtTypeFormatter.DATE)) {
          Date dateVal = (Date) ExtTypeFormatter.parse(val, Date.class);
                   
          Integer t = filter.getFilterType();
          if (t == Filter.EQUAL) {
            newExpression = ExpressionFactory.matchExp(key, dateVal);
          } else if (t == Filter.NOT_EQUAL) {
            newExpression = ExpressionFactory.noMatchExp(key, dateVal);
          } else if (t == Filter.LESS_THAN) {
            newExpression = ExpressionFactory.lessExp(key, dateVal);
          } else if (t == Filter.LESS_THAN_EQUAL) {
            newExpression = ExpressionFactory.lessOrEqualExp(key, dateVal);
          } else if (t == Filter.GREATER_THAN) {
            newExpression = ExpressionFactory.greaterExp(key, dateVal);
          } else if (t == Filter.GREATER_THAN_EQUAL) {
            newExpression = ExpressionFactory.greaterOrEqualExp(key, dateVal);
          }
        }           
       
        if (expression == null) {
          expression = newExpression;
        } else {
          expression = expression.andExp(newExpression);
        }
      }

     
      /*
       * Create query
       */
      SelectQuery query = new SelectQuery(clazz, expression);
      SelectQuery countQuery = new SelectQuery(clazz, expression);
     
      /*
       * Add sorters
       */
      List<String> spentSort = new ArrayList<String>();
      this.getGroupers().addAll(this.getSorters());
      for (Sorter sorter : this.getGroupers()) {
        String prop = sorter.getProperty();
        if (spentSort.contains(prop)) continue;
        spentSort.add(prop);
       
        String d = sorter.getDirection();
        boolean isDesc = d != null && d.toLowerCase().equals("desc");
       
        Ordering ordering = new Ordering(prop, isDesc ? SortOrder.DESCENDING : SortOrder.ASCENDING);
        query.addOrdering(ordering);
      }

     
      /*
       * Start and limit
       */
      if (this.getLimit() != null) query.setFetchLimit(this.getLimit());
      if (this.getStart() != null) query.setFetchOffset(this.getStart().intValue());
      for (Object entity : objectContext.performQuery(query)) {
        data.add(new ModelInstance(extConfig, entity).getData());
      }

     
      /*
       * Total Count / Inspired by http://goo.gl/W6rhG
       */
      this.setTotalCount(CayenneTools.count(
          (DataContext) objectContext, countQuery));
     
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
   
    return data;
  }
 
 
  private List<Map<String, Object>> getWhereFallback(
      CayennePersistenceManager cayenne, ObjectContext objectContext, Class<?> clazz, List<Map<String, Object>> data) throws Exception {

    String className = clazz.getSimpleName();
    String alias = className.toLowerCase().substring(0, 1);

    /*
     * Start the JPQL
     */
    StringBuffer jpql = new StringBuffer();
    jpql.append("SELECT " + alias + " FROM " + className + " " + alias + " ");
    jpql.append("WHERE " + this.getWhere());
   
    StringBuffer jpqlCount = new StringBuffer();
    jpqlCount.append("SELECT COUNT (" + alias + ") FROM " + className + " " + alias + " ");
    jpqlCount.append("WHERE " + this.getWhere());
   
    /*
     * ExtJS sends sorting parameters along with grouping parameters
     * for the same grouper.  Unsure if this behavior makes sense or
     * may change in the future.  Instead, we should filter out the
     * duplicate sort.
     */
    List<String> spentSort = new ArrayList<String>();
    String sortClause = "";
    this.getGroupers().addAll(this.getSorters());
    if (this.getGroupers().size() > 0) {
      for (Sorter sorter : this.getGroupers()) {
        String prop = sorter.getProperty();
        if (spentSort.contains(prop)) continue;
        spentSort.add(prop);
        if (!sortClause.isEmpty()) sortClause += ",";
        sortClause += alias + "." + prop + " " + sorter.getDirection();
      }
    }
   
    if (!sortClause.isEmpty()) {
      jpql.append(" ORDER BY " + sortClause);
    }

    /*
     * Create EJBQL queries
     */
    EJBQLQuery selectQuery = new EJBQLQuery(jpql.toString());
    EJBQLQuery countQuery = new EJBQLQuery(jpqlCount.toString());
   
    /*
     * Add named parameters
     */
    Map<String,Object> params = this.getParams();
    for (String key : params.keySet()) {
      String capKey = StringUtilities.capitalize(key);
     
      /*
       * Make sure we have a field for this parameter
       */
      Method paramGetter = null;
      try {
        paramGetter = clazz.getMethod("get" + capKey);
      } catch (Exception e) {}
      if (paramGetter == null) {
        try {
          paramGetter = clazz.getMethod("is" + capKey);
        } catch (Exception e) {}
      }
      if (paramGetter == null) continue;

      Object paramObj = ExtTypeFormatter.parse(params.get(key), paramGetter.getReturnType());

      selectQuery.setParameter(key, paramObj);
      countQuery.setParameter(key, paramObj);
    }

    this.setTotalCount((Long) objectContext.performQuery(countQuery).get(0));

    if (this.getLimit() != null) selectQuery.setFetchLimit(this.getLimit());
    if (this.getStart() != null) selectQuery.setFetchOffset(this.getStart().intValue());
   
    for (Object entity : objectContext.performQuery(selectQuery)) {
      data.add(new ModelInstance(extConfig, entity).getData());
    }
   
    return data;
  }
}
TOP

Related Classes of com.adaptrex.core.persistence.cayenne.CayenneStoreData

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.