All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.mmm.persistence.impl.jpa.query.jpql.JpqlPropertyExpressionImpl Maven / Gradle / Ivy

/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0 */
package net.sf.mmm.persistence.impl.jpa.query.jpql;

import net.sf.mmm.persistence.api.query.jpql.JpqlCondition;
import net.sf.mmm.persistence.api.query.jpql.JpqlConditionalExpression;
import net.sf.mmm.persistence.api.query.jpql.JpqlCore;
import net.sf.mmm.persistence.api.query.jpql.JpqlOperator;
import net.sf.mmm.persistence.api.query.jpql.JpqlPropertyExpression;
import net.sf.mmm.util.nls.api.NlsClassCastException;
import net.sf.mmm.util.nls.api.NlsNullPointerException;
import net.sf.mmm.util.pojo.path.api.TypedProperty;
import net.sf.mmm.util.value.api.Range;

/**
 * This is the implementation of {@link JpqlPropertyExpression}.
 * 
 * @param  is the generic type of the property. May be {@link Object} for untyped access.
 * @param  is the generic type of the {@link AbstractJpqlConditionalExpression} that created this
 *        {@link JpqlPropertyExpression}.
 * 
 * @author Joerg Hohwiller (hohwille at users.sourceforge.net)
 * @since 0.9.0
 */
public class JpqlPropertyExpressionImpl> extends
    AbstractJpqlPropertySupport implements JpqlPropertyExpression {

  /** The {@link AbstractJpqlConditionalExpression} that created this {@link JpqlPropertyExpression}. */
  private final EXPRESSION expression;

  /** The actual property represented by this object. */
  private final String mainProperty;

  /** @see #not() */
  private boolean not;

  /**
   * The constructor.
   * 
   * @param expression is the {@link AbstractJpqlConditionalExpression} that created this
   *        {@link JpqlPropertyExpression}.
   * @param path is the {@link JpqlCore#PROPERTY_BASE_PATH base path} for the property.
   * @param property is the actual {@link JpqlCore#PROPERTY property} for this expression.
   */
  public JpqlPropertyExpressionImpl(EXPRESSION expression, String path, String property) {

    super();
    this.expression = expression;
    if (path == null) {
      setPropertyBasePath(this.expression.getPropertyBasePath());
    } else {
      setPropertyBasePath(path);
    }
    this.mainProperty = property;
  }

  /**
   * @see AbstractJpqlConditionalExpression#appendConjunctionIfRequired()
   */
  protected void appendConjunctionIfRequired() {

    ensureNotDisposed();
    ((AbstractJpqlConditionalExpression) this.expression).appendConjunctionIfRequired();
  }

  /**
   * This method completes and {@link #dispose() disposes} this expression.
   */
  protected void complete() {

    ((AbstractJpqlConditionalExpression) this.expression).setExpressionAppended();
    dispose();
  }

  /**
   * @return the {@link JpqlContext}.
   */
  protected JpqlContext getContext() {

    return ((AbstractJpqlConditionalExpression) this.expression).getContext();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public JpqlPropertyExpression not() {

    this.not = !this.not;
    return this;
  }

  /**
   * @see #isCompare(JpqlOperator, Object)
   * 
   * @param operatorArgument - see #isCompareValue(String, JpqlOperator, Object)
   * @param value - see #isCompareValue(String, JpqlOperator, Object)
   * @param inverse - true if property is second argument and value is
   *        first (see {@link #isCompareInverse(JpqlOperator, Object)}), false otherwise.
   * @param convertGlob - true if {@link #convertGlobPattern(String)} shall be invoked for LIKEs,
   *        false otherwise.
   * @return the {@link AbstractJpqlConditionalExpression}.
   */
  private EXPRESSION isCompare(JpqlOperator operatorArgument, Object value, boolean inverse, boolean convertGlob) {

    appendConjunctionIfRequired();
    JpqlOperator operator = operatorArgument;
    if (this.not) {
      operator = operator.negate();
    }
    Object parameter = value;
    JpqlContext context = getContext();
    StringBuilder queryBuffer = context.getQueryBuffer();
    if (parameter == null) {
      appendProperty(this.mainProperty, context);
      if (operator == JpqlOperator.EQUAL) {
        queryBuffer.append(JPQL_CONDITION_IS_NULL);
      } else if (operator == JpqlOperator.NOT_EQUAL) {
        queryBuffer.append(JPQL_CONDITION_IS_NOT_NULL);
      } else {
        throw new NlsNullPointerException("value");
      }
    } else {
      if ((operator == JpqlOperator.LIKE) || (operator == JpqlOperator.NOT_LIKE)) {
        if (!(parameter instanceof CharSequence)) {
          throw new NlsClassCastException(parameter, CharSequence.class);
        }
        if (convertGlob) {
          parameter = convertGlobPattern(parameter.toString());
        }
      }
      if (inverse) {
        context.addParameter(parameter, this.mainProperty);
        queryBuffer.append(operator);
        appendProperty(this.mainProperty, context);
      } else {
        appendProperty(this.mainProperty, context);
        queryBuffer.append(operator);
        context.addParameter(parameter, this.mainProperty);
      }
    }
    complete();
    return this.expression;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isCompare(JpqlOperator operatorArgument, String basePath, String property) {

    appendConjunctionIfRequired();
    JpqlOperator operator = operatorArgument;
    if (this.not) {
      operator = operator.negate();
    }
    JpqlContext context = getContext();
    StringBuilder queryBuffer = context.getQueryBuffer();
    appendProperty(this.mainProperty, context);
    queryBuffer.append(operator);
    appendProperty(basePath, property, context);
    complete();
    return this.expression;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isCompare(JpqlOperator operator, String basePath, TypedProperty property) {

    return isCompare(operator, basePath, property.getPojoPath());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isCompare(JpqlOperator operator, T value) {

    return isCompare(operator, value, false, true);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isCompareInverse(JpqlOperator operator, T value) {

    return isCompare(operator, value, true, true);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isEqual(T value) {

    return isCompare(JpqlOperator.EQUAL, value);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isEqual(String basePath, String property) {

    return isCompare(JpqlOperator.EQUAL, basePath, property);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isEqual(String basePath, TypedProperty property) {

    return isCompare(JpqlOperator.EQUAL, basePath, property);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String convertGlobPattern(String pattern) {

    // TODO hohwille Do we need to escape % and _ before?
    return pattern.replace('*', '%').replace('?', '_');
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isLike(String pattern, boolean convertGlob) {

    return isCompare(JpqlOperator.LIKE, pattern, false, convertGlob);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isLikeInverse(String pattern, boolean convertGlob) {

    return isCompare(JpqlOperator.LIKE, pattern, true, convertGlob);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isCondition(JpqlCondition conditionArgument) {

    appendConjunctionIfRequired();
    JpqlCondition condition = conditionArgument;
    if (this.not) {
      condition = condition.negate();
    }
    JpqlContext context = getContext();
    StringBuilder queryBuffer = context.getQueryBuffer();
    appendProperty(this.mainProperty, context);
    queryBuffer.append(' ');
    queryBuffer.append(condition);
    complete();
    return this.expression;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isNull() {

    return isCondition(JpqlCondition.IS_NULL);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isEmpty() {

    return isCondition(JpqlCondition.IS_EMPTY);
  }

  /**
   * This method starts an {@link #isBetween(Object, Object) is between} expression.
   */
  private void startIsBetween() {

    String operator;
    if (this.not) {
      operator = JpqlCore.JPQL_OPERATOR_NOT_BETWEEN;
    } else {
      operator = JpqlCore.JPQL_OPERATOR_BETWEEN;
    }

    appendConjunctionIfRequired();
    JpqlContext context = getContext();
    appendProperty(this.mainProperty, context);
    context.getQueryBuffer().append(operator);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isBetween(T min, T max) {

    // property BETWEEN :min AND :max <=> property >= :min AND property <= :max
    if (min == null) {
      if (max == null) {
        throw new NlsNullPointerException("min & max");
      }
      return isCompare(JpqlOperator.LESS_EQUAL, max);
    } else if (max == null) {
      return isCompare(JpqlOperator.GREATER_EQUAL, min);
    }
    startIsBetween();
    JpqlContext context = getContext();
    StringBuilder queryBuffer = context.getQueryBuffer();
    context.addParameter(min, this.mainProperty + "Min");
    queryBuffer.append(JpqlCore.JPQL_CONJUNCTION_AND);
    context.addParameter(max, this.mainProperty + "Max");
    complete();
    return this.expression;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isBetween(Range range) {

    return isBetween(range.getMin(), range.getMax());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isBetween(String minBasePath, TypedProperty minProperty, String maxBasePath,
      TypedProperty maxProperty) {

    return isBetween(minBasePath, minProperty.getPojoPath(), maxBasePath, maxProperty.getPojoPath());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public EXPRESSION isBetween(String minBasePath, String minProperty, String maxBasePath, String maxProperty) {

    startIsBetween();
    JpqlContext context = getContext();
    StringBuilder queryBuffer = context.getQueryBuffer();
    appendProperty(minBasePath, minProperty, context);
    queryBuffer.append(JpqlCore.JPQL_CONJUNCTION_AND);
    appendProperty(maxBasePath, maxProperty, context);
    complete();
    return this.expression;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy