| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.internal.queries; |
| |
| import java.util.*; |
| |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.expressions.*; |
| import org.eclipse.persistence.exceptions.*; |
| import org.eclipse.persistence.queries.*; |
| |
| /** |
| * <p><b>Purpose</b>: |
| * Mechanism used for all queries by example. |
| * </p> |
| * <p><b>Responsibilities</b>: |
| * Builds a selection criteria for this query given an example object and |
| * a QueryByExample policy. Works akin to EBQLMechanism which builds the |
| * selection criteria from an EJBQL string.</p> |
| * |
| * @author Stephen McRitchie |
| * @since 9.0.3.5 |
| */ |
| public class QueryByExampleMechanism extends ExpressionQueryMechanism { |
| protected boolean isParsed = false; |
| |
| /** Used for Query By Example. */ |
| protected Object exampleObject; |
| protected QueryByExamplePolicy queryByExamplePolicy; |
| |
| /** |
| * Initialize the state of the query |
| * @param query - owner of mechanism |
| */ |
| public QueryByExampleMechanism(DatabaseQuery query) { |
| super(query); |
| } |
| |
| /** |
| * Initialize the state of the query |
| * @param query - owner of mechanism |
| * @param expression - selection criteria |
| */ |
| public QueryByExampleMechanism(DatabaseQuery query, Expression expression) { |
| super(query, expression); |
| } |
| |
| /** |
| * INTERNAL: |
| * In the case of EJBQL or query by example, an expression needs to be |
| * generated. Build the required expression. |
| */ |
| @Override |
| public void buildSelectionCriteria(AbstractSession session) { |
| if (isParsed() || (getExampleObject() == null)) { |
| return; |
| } |
| ObjectLevelReadQuery query = (ObjectLevelReadQuery)getQuery(); |
| |
| query.checkDescriptor(session); |
| |
| QueryByExamplePolicy policy = getQueryByExamplePolicy(); |
| |
| if (policy == null) { |
| policy = new QueryByExamplePolicy(); |
| } |
| |
| if (query.getReferenceClass().isInstance(getExampleObject())) { |
| Expression exampleExpression = query.getDescriptor().getObjectBuilder().buildExpressionFromExample(getExampleObject(), policy, query.getExpressionBuilder(), new IdentityHashMap(), session); |
| |
| if (getSelectionCriteria() != null) { |
| setSelectionCriteria(getSelectionCriteria().and(exampleExpression)); |
| } else { |
| setSelectionCriteria(exampleExpression); |
| } |
| } else { |
| throw QueryException.exampleAndReferenceObjectClassMismatch(getExampleObject().getClass(), query.getReferenceClass(), query); |
| } |
| setIsParsed(true); |
| } |
| |
| /** |
| * PUBLIC: |
| * This method returns the current example object. The "example" object is an actual domain object, provided |
| * by the client, from which an expression is generated. |
| * This expression is used for a query of all objects from the same class, that match the attribute values of |
| * the "example" object. |
| */ |
| public Object getExampleObject() { |
| return exampleObject; |
| } |
| |
| /** |
| * PUBLIC: |
| * When using Query By Example, an instance of QueryByExamplePolicy is used to customize the query. |
| * The policy is useful when special operations are to be used for comparisons (notEqual, lessThan, |
| * greaterThan, like etc.), when a certain value is to be ignored, or when dealing with nulls. |
| */ |
| public QueryByExamplePolicy getQueryByExamplePolicy() { |
| return queryByExamplePolicy; |
| } |
| |
| /** |
| * INTERNAL: |
| * Is this query Parsed |
| */ |
| public boolean isParsed() { |
| return isParsed; |
| } |
| |
| /** |
| * Return true if this is a query by example mechanism |
| */ |
| @Override |
| public boolean isQueryByExampleMechanism() { |
| return true; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the example object of the query to be the newExampleObject. |
| * The example object is used for Query By Example. |
| * When doing a Query By Example, an instance of the desired object is created, and the fields are filled with |
| * the values that are required in the result set. From these values the corresponding expression is build |
| * by TopLink, and the query is executed, returning the set of results. |
| */ |
| public void setExampleObject(Object newExampleObject) { |
| exampleObject = newExampleObject; |
| } |
| |
| /** |
| * INTERNAL: |
| * Set the isParsed state |
| */ |
| public void setIsParsed(boolean newIsParsed) { |
| isParsed = newIsParsed; |
| } |
| |
| /** |
| * PUBLIC: |
| * The QueryByExamplePolicy, is a useful to customize the query when Query By Example is used. |
| * The pollicy will control what attributes should, or should not be included in the query. |
| * When dealing with nulls, using specail operations (notEqual, lessThan, like, etc.) |
| * for comparison, or chosing to include certain attributes at all times, it is useful to modify |
| * the policy accordingly. |
| */ |
| public void setQueryByExamplePolicy(QueryByExamplePolicy queryByExamplePolicy) { |
| this.queryByExamplePolicy = queryByExamplePolicy; |
| } |
| } |