/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * 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. * * @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. */ 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 */ 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; } }