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

org.apache.cayenne.exp.property.BaseProperty Maven / Gradle / Ivy

The newest version!
/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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
 *
 *    https://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 org.apache.cayenne.exp.property;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.FunctionExpressionFactory;
import org.apache.cayenne.exp.parser.ASTPath;
import org.apache.cayenne.exp.path.CayennePath;
import org.apache.cayenne.query.ColumnSelect;
import org.apache.cayenne.query.Ordering;
import org.apache.cayenne.query.Orderings;
import org.apache.cayenne.query.SortOrder;
import org.apache.cayenne.reflect.PropertyUtils;

/**
 * Property that represents generic attribute.
 * 

* Provides equality checks and sorting API along with some utility methods. * * @see org.apache.cayenne.exp.property * @since 4.2 */ public class BaseProperty implements Property { /** * Path of this property */ protected final CayennePath path; /** * Expression provider for the property */ protected final Supplier expressionSupplier; /** * Explicit type of the property */ protected final Class type; /** * Constructs a new property with the given name and expression * * @param path path value of the property (will be used as alias for the expression) * @param expression expression for property * @param type of the property * * @see PropertyFactory#createBase(String, Expression, Class) */ @SuppressWarnings({"unchecked", "Convert2Lambda", "Anonymous2MethodRef"}) protected BaseProperty(CayennePath path, Expression expression, Class type) { this.path = path; // can't use lambda here, see CAY-2635 if(expression == null) { this.expressionSupplier = new Supplier<>() { @Override public Expression get() { return ExpressionFactory.pathExp(path); } }; } else { this.expressionSupplier = new Supplier<>() { @Override public Expression get() { return expression.deepCopy(); } }; } this.type = (Class)type; } /** * @return Name of the property in the object. */ public String getName() { if(path.isEmpty()) { // this one to keep compatible with pre 5.0 logic return null; } // TODO: should we use it only for a single-segment path? return path.value(); } /** * @return path this property represents * @since 5.0 */ public CayennePath getPath() { return path; } /** * @return alias for this property */ public String getAlias() { if(getPath().isEmpty()) { return null; } // check if default name for Path expression is overridden Expression exp = getExpression(); if(exp instanceof ASTPath) { if(((ASTPath) exp).getPath().equals(getPath())) { return null; } } return getName(); } /** * This method returns fresh copy of the expression for each call. * @return expression that represents this Property */ public Expression getExpression() { return expressionSupplier.get(); } @Override public int hashCode() { int result = getPath().isEmpty() ? expressionSupplier.get().hashCode() : getPath().hashCode(); if(type != null) { result = 31 * result + type.hashCode(); } return result; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } BaseProperty property = (BaseProperty) o; if (!path.isEmpty() && !path.equals(property.path)) { return false; } if (path.isEmpty() && !expressionSupplier.get().equals(property.expressionSupplier.get())) { return false; } return Objects.equals(type, property.type); } /** * @return An expression representing null. */ public Expression isNull() { return ExpressionFactory.matchExp(getExpression(), null); } /** * @return An expression representing a non-null value. */ public Expression isNotNull() { return ExpressionFactory.noMatchExp(getExpression(), null); } /** * @return Ascending sort orderings on this property. */ public Ordering asc() { return new Ordering(getExpression(), SortOrder.ASCENDING); } /** * @return Ascending sort orderings on this property. */ public Orderings ascs() { return new Orderings(asc()); } /** * @return Ascending case-insensitive sort orderings on this property. */ public Ordering ascInsensitive() { return new Ordering(getExpression(), SortOrder.ASCENDING_INSENSITIVE); } /** * @return Ascending case-insensitive sort orderings on this property. */ public Orderings ascInsensitives() { return new Orderings(ascInsensitive()); } /** * @return Descending sort orderings on this property. */ public Ordering desc() { return new Ordering(getExpression(), SortOrder.DESCENDING); } /** * @return Descending sort orderings on this property. */ public Orderings descs() { return new Orderings(desc()); } /** * @return Descending case-insensitive sort orderings on this property. */ public Ordering descInsensitive() { return new Ordering(getExpression(), SortOrder.DESCENDING_INSENSITIVE); } /** * @return Descending case-insensitive sort orderings on this property. */ public Orderings descInsensitives() { return new Orderings(descInsensitive()); } /** * Extracts property value from an object using JavaBean-compatible * introspection with one addition - a property can be a dot-separated * property name path. */ @SuppressWarnings("unchecked") public E getFrom(Object bean) { return (E) PropertyUtils.getProperty(bean, getName()); } /** * Extracts property value from a collection of objects using * JavaBean-compatible introspection with one addition - a property can be a * dot-separated property name path. */ public List getFromAll(Collection beans) { List result = new ArrayList<>(beans.size()); for (Object bean : beans) { result.add(getFrom(bean)); } return result; } /** * Sets a property value in 'obj' using JavaBean-compatible introspection * with one addition - a property can be a dot-separated property name path. */ public void setIn(Object bean, E value) { PropertyUtils.setProperty(bean, getName(), value); } /** * Sets a property value in a collection of objects using * JavaBean-compatible introspection with one addition - a property can be a * dot-separated property name path. */ public void setInAll(Collection beans, E value) { for (Object bean : beans) { setIn(bean, value); } } /** * @see FunctionExpressionFactory#countExp(Expression) */ public NumericProperty count() { return PropertyFactory.createNumeric(FunctionExpressionFactory.countExp(getExpression()), Long.class); } /** * @see FunctionExpressionFactory#countDistinctExp(Expression) */ public NumericProperty countDistinct() { return PropertyFactory.createNumeric(FunctionExpressionFactory.countDistinctExp(getExpression()), Long.class); } /** * @see FunctionExpressionFactory#customAggregateExp(String, Expression) * * @since 5.0 */ public BaseProperty aggregate(String function, Class type) { return PropertyFactory.createBase(FunctionExpressionFactory.customAggregateExp(function, getExpression()), type); } /** * Creates alias with different name for this property */ public BaseProperty alias(String alias) { return PropertyFactory.createBase(alias, this.getExpression(), this.getType()); } /** * @return type of entity attribute described by this property */ public Class getType() { return type; } /** * @return An expression representing equality to TRUE. */ public Expression isTrue() { return ExpressionFactory.matchExp(getExpression(), Boolean.TRUE); } /** * @return An expression representing equality to FALSE. */ public Expression isFalse() { return ExpressionFactory.matchExp(getExpression(), Boolean.FALSE); } /** * @return An expression representing equality to a value. */ public Expression eq(E value) { return ExpressionFactory.matchExp(getExpression(), value); } /** * @return An expression representing equality between two attributes * (columns). */ public Expression eq(BaseProperty value) { return ExpressionFactory.matchExp(getExpression(), value.getExpression()); } /** * @return An expression representing inequality to a value. */ public Expression ne(E value) { return ExpressionFactory.noMatchExp(getExpression(), value); } /** * @return An expression representing inequality between two attributes * (columns). */ public Expression ne(BaseProperty value) { return ExpressionFactory.noMatchExp(getExpression(), value.getExpression()); } /** * @return An expression for finding objects with values in the given set. */ public Expression in(E firstValue, E... moreValues) { int moreValuesLength = moreValues != null ? moreValues.length : 0; Object[] values = new Object[moreValuesLength + 1]; values[0] = firstValue; if (moreValuesLength > 0) { System.arraycopy(moreValues, 0, values, 1, moreValuesLength); } return ExpressionFactory.inExp(getExpression(), values); } /** * @return An expression for finding objects with values not in the given * set. */ public Expression nin(E firstValue, E... moreValues) { int moreValuesLength = moreValues != null ? moreValues.length : 0; Object[] values = new Object[moreValuesLength + 1]; values[0] = firstValue; if (moreValuesLength > 0) { System.arraycopy(moreValues, 0, values, 1, moreValuesLength); } return ExpressionFactory.notInExp(getExpression(), values); } /** * @return An expression for finding objects with values in the given set. */ public Expression in(Collection values) { return ExpressionFactory.inExp(getExpression(), values); } /** * @return An expression for finding objects with values not in the given * set. */ public Expression nin(Collection values) { return ExpressionFactory.notInExp(getExpression(), values); } /** * @return An expression for finding objects with values in the given subquery */ public Expression in(ColumnSelect subquery) { return ExpressionFactory.inExp(getExpression(), subquery); } /** * @return An expression for finding objects with values not in the given subquery */ public Expression nin(ColumnSelect subquery) { return ExpressionFactory.notInExp(getExpression(), subquery); } /** * This operator allows to access properties of the enclosing query from the subquery. * It allows multiple nesting levels to access a corresponding query in case of multiple levels of subqueries. * * Example:

{@code
     * ObjectSelect.query(Artist.class)
     *                 .where(ExpressionFactory.notExists(ObjectSelect.query(Painting.class)
     *                         .where(Painting.TO_ARTIST.eq(Artist.ARTIST_ID_PK_PROPERTY.enclosing()))))
     * }
     * 
* * @return property that will be translated relative to a parent query */ public BaseProperty enclosing() { return PropertyFactory.createBase(ExpressionFactory.enclosingObjectExp(getExpression()), getType()); } /** * @return An expression for calling functionName with first argument equals to this property * and provided additional arguments */ public BaseProperty function(String functionName, Class returnType, BaseProperty... arguments) { Object[] expressions = new Expression[arguments.length + 1]; expressions[0] = getExpression(); for(int i=1; i<=arguments.length; i++) { expressions[i] = arguments[i-1].getExpression(); } return PropertyFactory.createBase(FunctionExpressionFactory.functionCall(functionName, expressions), returnType); } /** * @return An expression for calling functionName with first argument equals to this property * and provided additional arguments */ public BaseProperty function(String functionName, Class returnType, Object... arguments) { Object[] expressions = new Object[arguments.length + 1]; expressions[0] = getExpression(); System.arraycopy(arguments, 0, expressions, 1, arguments.length); return PropertyFactory.createBase(FunctionExpressionFactory.functionCall(functionName, expressions), returnType); } /** * @return An expression for using operator with first argument equals to this property * and provided additional arguments */ public BaseProperty operator(String operator, Class returnType, BaseProperty... arguments) { Object[] expressions = new Expression[arguments.length + 1]; expressions[0] = getExpression(); for(int i=1; i<=arguments.length; i++) { expressions[i] = arguments[i-1].getExpression(); } return PropertyFactory.createBase(FunctionExpressionFactory.operator(operator, expressions), returnType); } /** * @return An expression for using operator with first argument equals to this property * and provided additional arguments */ public BaseProperty operator(String operator, Class returnType, Object... arguments) { Object[] expressions = new Object[arguments.length + 1]; expressions[0] = getExpression(); System.arraycopy(arguments, 0, expressions, 1, arguments.length); return PropertyFactory.createBase(FunctionExpressionFactory.operator(operator, expressions), returnType); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy