Package com.breezejs.hib

Source Code of com.breezejs.hib.OdataCriteria

package com.breezejs.hib;

import java.util.HashMap;
import java.util.Iterator;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.internal.CriteriaImpl.OrderEntry;

import com.breezejs.OdataParameters;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;

/**
* Simple parsing for simple OData expressions.
* @author Steve
* @see http://www.odata.org/documentation/odata-v2-documentation/uri-conventions/
*/
public class OdataCriteria {
 
  // Maps OData operators to Hibernate criteria operators
  private static final HashMap<String, String> operatorMap = new HashMap<String, String>();
  static {
    operatorMap.put("eq", "=");
    operatorMap.put("ne", "<>");
    operatorMap.put("gt", ">");
    operatorMap.put("ge", ">=");
    operatorMap.put("lt", "<");
    operatorMap.put("le", "<=");
//    operatorMap.put("and", "and");
//    operatorMap.put("or", "or");
//    operatorMap.put("not", "not");
  }
 
  public static final String WHITESPACE = "\\s+";
 
  /**
   * Apply the OData $top, $skip, $orderby, and (crude) $filter parameters to the Criteria
   * @param crit
   * @param op
   * @return the same Criteria that was passed in, with operations added.
   */
  public static Criteria applyParameters(Criteria crit, OdataParameters op)
  {
      if (op.top > 0) crit.setMaxResults(op.top);
      if (op.skip > 0) crit.setFirstResult(op.skip);
      if (op.orderby != null) {
        for(String s: op.orderbys()) {
          String[] seg = s.split(WHITESPACE, 2);
          String field = seg[0].replace('/', '.');
          if (seg.length == 2 && "desc".equalsIgnoreCase(seg[1])) {
            crit.addOrder(Order.desc(field));
          } else {
            crit.addOrder(Order.asc(field));
          }
        }
      }
      if (op.filter != null) {
        addFilter(crit, op.filter);
      }
   
   
    return crit;
  }
 
  /**
   * Apply the OData $inlinecount and (crude) $filter parameters to the Criteria.
   * This creates a filter with a rowCount projection, so $skip, $top, $orderby, $select, $expand
   * are meaningless here.
   * @param crit a Criteria object.  Should be new or contain only filters when passed in.
   * @param op OdataParameters object - only op.inlineCount and op.filter are used.
   * @return the same Criteria that was passed in, with operations added.
   */
  public static Criteria applyInlineCount(Criteria crit, OdataParameters op)
  {
      if (op.filter != null) {
        addFilter(crit, op.filter);
      }
    crit.setProjection( Projections.rowCount());
    return crit;
  }

  /**
   * Apply the OData $inlinecount to the (already filtered) Criteria.
   * Removes $skip and $top and $orderby operations and adds a rowCount projection.
   * @param crit a Criteria object.  Should already contain only filters that affect the row count.
   * @return the same Criteria that was passed in, with operations added.
   */
  public static Criteria applyInlineCount(Criteria crit)
  {
      crit.setMaxResults(0);
      crit.setFirstResult(0);
      CriteriaImpl impl = (CriteriaImpl) crit;
      Iterator<OrderEntry> iter = impl.iterateOrderings();
      while (iter.hasNext()) {
        iter.next();
        iter.remove();
      }
    crit.setProjection( Projections.rowCount());
    return crit;
  }
 
  /**
   * Add simple filtering to the Criteria.  Handles OData filters of the form
   * $filter=country eq 'Brazil'
   * @param crit
   * @param filterString OData $filter.  Only filters of the form [field] [op] [value] are supported..
   */
  static void addFilter(Criteria crit, String filterString)
  {
    String[] filter = filterString.split(WHITESPACE, 3);
    if (filter.length != 3)
      throw new IllegalArgumentException("Filter string not handled: " + filterString);

    String field = filter[0].replace('/', '.');
    String op = filter[1].toLowerCase();
    String stringValue = filter[2];
   
    String restrictionOp = operatorMap.get(op);
    if (restrictionOp == null)
      throw new IllegalArgumentException("Filter string not handled: " + filterString);

    Object value;
    if (stringValue.charAt(0) == '\'') {
      // Remove quotes from string values
      value = stringValue.substring(1, stringValue.length() - 1);
    } else {
      // Non-quoted values are numbers or other fields
      value = Ints.tryParse(stringValue);
      if (value == null) {
        value = Longs.tryParse(stringValue);
      }
      if (value == null) {
        value = Doubles.tryParse(stringValue);
      }
      if (value == null) {
        // expression comparing two properties
        crit.add(new PropertyExpression(field, stringValue, restrictionOp));
        return;
      }
    }
   
    crit.add(new OperatorExpression(field, value, restrictionOp));
   
  }
 
  /*
Eq Equal /Suppliers?$filter=Address/City eq �Redmond�
Ne Not equal /Suppliers?$filter=Address/City ne �London�
Gt Greater than /Products?$filter=Price gt 20
Ge Greater than or equal /Products?$filter=Price ge 10
Lt Less than /Products?$filter=Price lt 20
Le Less than or equal /Products?$filter=Price le 100
And Logical and /Products?$filter=Price le 200 and Price gt 3.5
Or Logical or /Products?$filter=Price le 3.5 or Price gt 200
Not
   */
TOP

Related Classes of com.breezejs.hib.OdataCriteria

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.