You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 20:09:00 UTC
svn commit: r171353 [3/13] - in /incubator/jdo/trunk/query20: ./ src/
src/conf/ src/java/ src/java/org/ src/java/org/apache/
src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/
src/java/org/apache/jdo/impl/jdoql/
src/java/org/apache/jdo/impl/jdoql/jdoqlc/
src/java/org/apache/jdo/impl/jdoql/scope/
src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/jdoql/
src/java/org/apache/jdo/jdoql/tree/
Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryImpl.java?rev=171353&view=auto
==============================================================================
--- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryImpl.java (added)
+++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryImpl.java Sun May 22 11:08:57 2005
@@ -0,0 +1,732 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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
+ *
+ * http://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.
+ */
+
+/*
+ * QueryImpl.java
+ *
+ * Created on August 31, 2001
+ */
+
+package org.apache.jdo.impl.jdoql;
+
+import java.io.IOException;
+import java.util.*;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+import javax.jdo.Extent;
+import javax.jdo.Transaction;
+
+import org.apache.jdo.impl.jdoql.jdoqlc.JDOQLAST;
+import org.apache.jdo.impl.jdoql.jdoqlc.JDOQLC;
+import org.apache.jdo.impl.jdoql.scope.ParameterTable;
+import org.apache.jdo.impl.jdoql.scope.VariableTable;
+import org.apache.jdo.impl.jdoql.tree.Tree;
+import org.apache.jdo.jdoql.JDOQueryException;
+import org.apache.jdo.query.QueryResult;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.store.StoreManager;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * This class implements the JDO query interface
+ * (see {@link javax.jdo.Query}).
+ *
+ * @author Michael Bouschen
+ */
+public class QueryImpl
+ implements Query
+{
+ /** The pm for this query instance. */
+ private transient PersistenceManagerInternal pm;
+
+ /** The candidate class as specified by setClass. */
+ private transient Class candidateClass;
+
+ /** The name of the candidate class (Needed for serialization support). */
+ private String candidateClassName;
+
+ /** The candidates as specified by setCandidates. */
+ private transient Object candidates;
+
+ /** The import declaration string as specified by declareImports. */
+ private String importDeclarations;
+
+ /** The parameter declaration string as specified by declareParameters. */
+ private String parameterDeclarations;
+
+ /** The variable declaration string as specified by declareVariables. */
+ private String variableDeclarations;
+
+ /** The ordering specification string as specified by setOrdering. */
+ private String orderingSpecification;
+
+ /** The filter expression string as specified by setFilter. */
+ private String filterExpression;
+
+ /**
+ * The ignoreCache flag as specified by setIgnoreCache. The constructor
+ * defaults it to the PM setting.
+ */
+ private boolean ignoreCache;
+
+ /** The internal query representation as compilation result. */
+ private transient Tree compiledTree = null;
+
+ /**
+ * The internal query representation set by the constructor taking a
+ * compiled query.
+ */
+ private Tree queryTree;
+
+ /** Represents parameter values. */
+ private ParameterTable paramtab;
+
+ /** Represents variable values. */
+ private VariableTable vartab;
+
+ /** Set of open query result instances. */
+ private transient Set openQueryResults = new HashSet();
+
+ /** I18N support */
+ private final static I18NHelper msg =
+ I18NHelper.getInstance(QueryImpl.class);
+
+ /**
+ * Create an empty query instance with no elements.
+ */
+ public QueryImpl(PersistenceManagerInternal pm)
+ {
+ // check valid PersistenceManager
+ if (pm == null)
+ throw new JDOQueryException(msg.msg("EXC_UnboundQuery")); //NOI18N
+
+ this.pm = pm;
+ this.ignoreCache = pm.getIgnoreCache();
+ this.paramtab = new ParameterTable();
+ this.vartab = new VariableTable();
+ }
+
+ /**
+ * Create a new Query using elements from another Query. The other Query
+ * must have been created by the same JDO implementation. It might be active
+ * in a different PersistenceManager or might have been serialized and
+ * restored.
+ * <P>All of the settings of the other Query are copied to this Query,
+ * except for the candidate Collection or Extent.
+ * @param compiled another Query from the same JDO implementation
+ */
+ public QueryImpl(PersistenceManagerInternal pm, Object compiled)
+ {
+ this(pm);
+ if (compiled == null) {
+ throw new JDOQueryException(
+ msg.msg("EXC_NullQueryInstance")); //NOI18N
+ }
+
+ if (compiled instanceof QueryImpl) {
+ QueryImpl other = (QueryImpl)compiled;
+ if (other.candidateClass != null) {
+ this.candidateClass = other.candidateClass;
+ }
+ else if (other.candidateClassName != null) {
+ // Support for deserialized query instances:
+ // after deserialization other.candidateClass is not set,
+ // but other.candidateClassName is set =>
+ // use PM algorithm to calculate the candidateClass instance
+ try {
+ this.candidateClass =
+ pm.loadClass(other.candidateClassName, null);
+ }
+ catch (ClassNotFoundException ex) {
+ throw new JDOQueryException(
+ msg.msg("EXC_UnknownCandidateClass", //NOI18N
+ other.candidateClassName), ex);
+ }
+ }
+ this.importDeclarations = other.importDeclarations;
+ this.parameterDeclarations = other.parameterDeclarations;
+ this.variableDeclarations = other.variableDeclarations;
+ this.orderingSpecification = other.orderingSpecification;
+ this.filterExpression = other.filterExpression;
+ this.ignoreCache = other.ignoreCache;
+ // Set compiled tree to null in order to ensure that this Query
+ // instance is compiled prior to execution.
+ // A possible optimization might want to reuse compilation results
+ // from the other query, but this requires serializing the typeInfo
+ // from the JDOQLAST.
+ this.compiledTree = null;
+ this.queryTree = other.queryTree;
+ this.paramtab = other.paramtab;
+ this.vartab = other.vartab;
+ checkQueryTreeCandidateClass();
+ }
+ else if (compiled instanceof Tree) {
+ this.queryTree = (Tree)compiled;
+ // TBD: check compiledTree?
+ this.compiledTree = null;
+ checkQueryTreeCandidateClass();
+ }
+ else {
+ throw new JDOQueryException(
+ msg.msg("EXC_InvalidCompiledQuery", //NOI18N
+ compiled.getClass().getName()));
+ }
+ }
+
+ /**
+ * Create a new Query specifying the Class of the candidate instances.
+ * @param cls the Class of the candidate instances
+ */
+ public QueryImpl(PersistenceManagerInternal pm, Class cls)
+ {
+ this(pm);
+ setClass(cls);
+ }
+
+ /**
+ * Create a new Query with the candidate Extent; the class
+ * is taken from the Extent.
+ * @param cln the Extent of candidate instances
+ */
+ public QueryImpl(PersistenceManagerInternal pm, Extent cln)
+ {
+ this(pm);
+ setClass(cln.getCandidateClass());
+ setCandidates(cln);
+ }
+
+ /**
+ * Create a query instance with the candidate class and
+ * candidate collection specified.
+ * @param cls the Class of the candidate instances.
+ * @param cln the Collection of candidate instances.
+ */
+ public QueryImpl(PersistenceManagerInternal pm, Class cls, Collection cln)
+ {
+ this(pm);
+ setClass(cls);
+ setCandidates(cln);
+ }
+
+ /**
+ * Create a new Query with the Class of the candidate instances and Filter.
+ * @param cls the Class of results
+ * @param filter the filter for candidate instances
+ */
+ public QueryImpl(PersistenceManagerInternal pm, Class cls, String filter)
+ {
+ this(pm);
+ setClass(cls);
+ setFilter(filter);
+ }
+
+ /**
+ * Create a new Query with the Class of the candidate instances,
+ * candidate Collection, and filter.
+ * @param cls the Class of candidate instances
+ * @param cln the Collection of candidate instances
+ * @param filter the filter for candidate instances
+ */
+ public QueryImpl(PersistenceManagerInternal pm, Class cls, Collection cln,
+ String filter)
+ {
+ this(pm);
+ setClass(cls);
+ setCandidates(cln);
+ setFilter(filter);
+ }
+
+ /**
+ * Create a new Query with the
+ * candidate Extent and filter; the class
+ * is taken from the Extent.
+ * @param cln the Extent of candidate instances
+ * @param filter the filter for candidate instances
+ */
+ public QueryImpl(PersistenceManagerInternal pm, Extent cln, String filter)
+ {
+ this(pm);
+ setClass(cln.getCandidateClass());
+ setCandidates(cln);
+ setFilter(filter);
+ }
+
+ /** Set the class of the candidate instances of the query.
+ * <P>The class specifies the class
+ * of the candidates of the query. Elements of the candidate collection
+ * that are of the specified class are filtered before being
+ * put into the result Collection.
+ *
+ * @param cls the Class of the candidate instances.
+ */
+ public void setClass(Class cls)
+ {
+ synchronized (this.paramtab) {
+ this.candidateClass = cls;
+ this.compiledTree = null;
+ }
+ }
+
+ /**
+ * Set the candidate Extent to query.
+ * @param pcs the Candidate Extent.
+ */
+ public void setCandidates(Extent pcs)
+ {
+ synchronized (this.paramtab) {
+ this.candidates = pcs;
+ }
+ }
+
+ /**
+ * Set the candidate Collection to query.
+ * @param pcs the Candidate collection.
+ */
+ public void setCandidates(Collection pcs)
+ {
+ synchronized (this.paramtab) {
+ this.candidates = pcs;
+ }
+ }
+
+ /**
+ * Set the filter for the query.
+ * @param filter the query filter.
+ */
+ public void setFilter(String filter)
+ {
+ synchronized (this.paramtab) {
+ this.filterExpression = filter;
+ this.compiledTree = null;
+ }
+ }
+
+ /**
+ * Set the import statements to be used to identify the fully qualified name
+ * of variables or parameters. Parameters and unbound variables might
+ * come from a different class from the candidate class, and the names
+ * need to be declared in an import statement to eliminate ambiguity.
+ * Import statements are specified as a String with semicolon-separated
+ * statements.
+ * <P>The String parameter to this method follows the syntax of the
+ * import statement of the Java language.
+ * @param imports import statements separated by semicolons.
+ */
+ public void declareImports(String imports)
+ {
+ synchronized (this.paramtab) {
+ this.importDeclarations = imports;
+ this.compiledTree = null;
+ }
+ }
+
+ /**
+ * Declare the list of parameters query execution.
+ *
+ * The parameter declaration is a String containing one or more query
+ * parameter declarations separated with commas. Each parameter named
+ * in the parameter declaration must be bound to a value when
+ * the query is executed.
+ * <P>The String parameter to this method follows the syntax for formal
+ * parameters in the Java language.
+ * @param parameters the list of parameters separated by commas.
+ */
+ public void declareParameters(String parameters)
+ {
+ synchronized (this.paramtab) {
+ this.parameterDeclarations = parameters;
+ this.compiledTree = null;
+ }
+ }
+
+ /**
+ * Declare the unbound variables to be used in the query. Variables
+ * might be used in the filter, and these variables must be declared
+ * with their type. The unbound variable declaration is a String
+ * containing one or more unbound variable declarations separated
+ * with semicolons. It follows the syntax for local variables in
+ * the Java language.
+ * @param variables the variables separated by semicolons.
+ */
+ public void declareVariables(String variables)
+ {
+ synchronized (this.paramtab) {
+ this.variableDeclarations = variables;
+ this.compiledTree = null;
+ }
+ }
+
+ /**
+ * Set the ordering specification for the result Collection. The
+ * ordering specification is a String containing one or more ordering
+ * declarations separated by commas.
+ *
+ * <P>Each ordering declaration is the name of the field on which
+ * to order the results followed by one of the following words:
+ * "ascending" or "descending".
+ *
+ *<P>The field must be declared in the candidate class or must be
+ * a navigation expression starting with a field in the candidate class.
+ *
+ *<P>Valid field types are primitive types except boolean; wrapper types
+ * except Boolean; BigDecimal; BigInteger; String; and Date.
+ * @param ordering the ordering specification.
+ */
+ public void setOrdering(String ordering)
+ {
+ synchronized (this.paramtab) {
+ this.orderingSpecification = ordering;
+ this.compiledTree = null;
+ }
+ }
+
+ /**
+ * Set the ignoreCache option. The default value for this option was
+ * set by the PersistenceManagerFactory or the PersistenceManager used
+ * to create this Query.
+ *
+ * The ignoreCache option setting specifies whether the query should execute
+ * entirely in the back end, instead of in the cache. If this flag is set
+ * to true, an implementation might be able to optimize the query
+ * execution by ignoring changed values in the cache. For optimistic
+ * transactions, this can dramatically improve query response times.
+ * @param ignoreCache the setting of the ignoreCache option.
+ */
+ public void setIgnoreCache(boolean ignoreCache)
+ {
+ synchronized (this.paramtab) {
+ this.ignoreCache = ignoreCache;
+ }
+ }
+
+ /**
+ * Get the ignoreCache option setting.
+ * @return the ignoreCache option setting.
+ * @see #setIgnoreCache
+ */
+ public boolean getIgnoreCache()
+ {
+ return ignoreCache;
+ }
+
+ /**
+ * Verify the elements of the query and provide a hint to the query to
+ * prepare and optimize an execution plan.
+ */
+ public void compile()
+ {
+ // check valid PersistenceManager
+ if (pm == null)
+ throw new JDOQueryException(msg.msg("EXC_UnboundQuery")); //NOI18N
+
+ synchronized (this.paramtab) {
+ if (this.compiledTree == null) {
+ JDOQLC jdoqlc = new JDOQLC(pm);
+ if (queryTree != null) {
+ jdoqlc.setQueryTree(queryTree);
+ }
+ else {
+ // define the query parts including syntax checks
+ jdoqlc.setClass(candidateClass);
+ jdoqlc.declareImports(importDeclarations);
+ jdoqlc.declareParameters(parameterDeclarations);
+ jdoqlc.declareVariables(variableDeclarations);
+ jdoqlc.setFilter(filterExpression);
+ jdoqlc.setOrdering(orderingSpecification);
+ }
+
+ // call semantic analysis
+ JDOQLAST ast = jdoqlc.semanticCheck(paramtab, vartab);
+ // call optimizer
+ compiledTree = (Tree)jdoqlc.optimize(ast);
+ }
+ }
+ }
+
+ /**
+ * Execute the query and return the filtered Collection.
+ * @return the filtered Collection.
+ * @see #executeWithArray(Object[] parameters)
+ */
+ public Object execute()
+ {
+ synchronized (this.paramtab) {
+ compile();
+ pm.assertIsOpen();
+ checkTransaction();
+ checkCandidates();
+ // Each execute call gets its own copy of paramtab and vartab.
+ // This allows multiple execution of the same query in parallel.
+ ParameterTable params = paramtab.getCopy();
+ params.initValueHandling();
+ params.checkUnboundParams();
+ VariableTable vars = vartab.getCopy();
+ vars.initValueHandling();
+ StoreManager srm = pm.getStoreManager();
+ QueryResult queryResult =
+ srm.newQueryResult(new QueryResultHelperImpl(
+ pm, compiledTree, candidates, params, vars));
+ openQueryResults.add(queryResult);
+ return queryResult;
+ }
+ }
+
+ /**
+ * Execute the query and return the filtered Collection.
+ * @return the filtered Collection.
+ * @see #executeWithArray(Object[] parameters)
+ * @param p1 the value of the first parameter declared.
+ */
+ public Object execute(Object p1)
+ {
+ Object[] params = new Object[1];
+ params[0] = p1;
+ return executeWithArray(params);
+ }
+
+ /**
+ * Execute the query and return the filtered Collection.
+ * @return the filtered Collection.
+ * @see #executeWithArray(Object[] parameters)
+ * @param p1 the value of the first parameter declared.
+ * @param p2 the value of the second parameter declared.
+ */
+ public Object execute(Object p1, Object p2)
+ {
+ Object[] params = new Object[2];
+ params[0] = p1;
+ params[1] = p2;
+ return executeWithArray(params);
+ }
+
+ /**
+ * Execute the query and return the filtered Collection.
+ * @return the filtered Collection.
+ * @see #executeWithArray(Object[] parameters)
+ * @param p1 the value of the first parameter declared.
+ * @param p2 the value of the second parameter declared.
+ * @param p3 the value of the third parameter declared.
+ */
+ public Object execute(Object p1, Object p2, Object p3)
+ {
+ Object[] params = new Object[3];
+ params[0] = p1;
+ params[1] = p2;
+ params[2] = p3;
+ return executeWithArray(params);
+ }
+
+ /**
+ * Execute the query and return the filtered Collection.
+ * @return the filtered Collection.
+ * @see #executeWithArray(Object[] parameters)
+ * @param parameters the Map containing all of the parameters.
+ */
+ public Object executeWithMap(Map parameters)
+ {
+ synchronized (this.paramtab)
+ {
+ compile();
+ pm.assertIsOpen();
+ checkTransaction();
+ checkCandidates();
+ // Each execute call gets its own copy of paramtab and vartab.
+ // This allows multiple execution of the same query in parallel.
+ ParameterTable params = paramtab.getCopy();
+ params.initValueHandling();
+ params.setValues(pm, parameters);
+ params.checkUnboundParams();
+ VariableTable vars = vartab.getCopy();
+ vars.initValueHandling();
+ StoreManager srm = pm.getStoreManager();
+ QueryResult queryResult =
+ srm.newQueryResult(new QueryResultHelperImpl(
+ pm, compiledTree, candidates, params, vars));
+ openQueryResults.add(queryResult);
+ return queryResult;
+ }
+ }
+
+ /** Execute the query and return the filtered Collection.
+ *
+ * <P>The execution of the query obtains the values of the parameters and
+ * matches them against the declared parameters in order. The names
+ * of the declared parameters are ignored. The type of
+ * the declared parameters must match the type of the passed parameters,
+ * except that the passed parameters might need to be unwrapped to get
+ * their primitive values.
+ *
+ * <P>The filter, import, declared parameters, declared variables, and
+ * ordering statements are verified for consisten1cy.
+ *
+ * <P>Each element in the candidate Collection is examined to see that it
+ * is assignment compatible to the Class of the query. It is then evaluated
+ * by the boolean expression of the filter. The element passes the filter
+ * if there exist unique values for all variables for which the filter
+ * expression evaluates to true.
+ * @return the filtered Collection.
+ * @param parameters the Object array with all of the parameters.
+ */
+ public Object executeWithArray(Object[] parameters)
+ {
+ synchronized (this.paramtab)
+ {
+ compile();
+ pm.assertIsOpen();
+ checkTransaction();
+ checkCandidates();
+ // Each execute call gets its own copy of paramtab and vartab.
+ // This allows multiple execution of the same query in parallel.
+ ParameterTable params = paramtab.getCopy();
+ params.initValueHandling();
+ params.setValues(pm, parameters);
+ params.checkUnboundParams();
+ VariableTable vars = vartab.getCopy();
+ vars.initValueHandling();
+ StoreManager srm = pm.getStoreManager();
+ QueryResult queryResult =
+ srm.newQueryResult(new QueryResultHelperImpl(
+ pm, compiledTree, candidates, params, vars));
+ openQueryResults.add(queryResult);
+ return queryResult;
+ }
+ }
+
+ /**
+ * Get the PersistenceManager associated with this Query.
+ *
+ * <P>If this Query was restored from a serialized form, it has no
+ * PersistenceManager, and this method returns null.
+ * @return the PersistenceManager associated with this Query.
+ */
+ public PersistenceManager getPersistenceManager()
+ {
+ return (pm == null) ? null : pm.getCurrentWrapper();
+ }
+
+ /**
+ * Close a query result and release any resources associated with it. The
+ * parameter is the return from execute(...) and might have iterators open
+ * on it. Iterators associated with the query result are invalidated: they
+ * return false to hasNext() and throw NoSuchElementException to next().
+ * @param queryResult the result of execute(...) on this Query instance.
+ */
+ public void close (Object queryResult)
+ {
+ if (queryResult instanceof QueryResult) {
+ openQueryResults.remove(queryResult);
+ ((QueryResult)queryResult).close();
+ }
+ }
+
+ /**
+ * Close all query results associated with this Query instance, and release
+ * all resources associated with them. The query results might have
+ * iterators open on them. Iterators associated with the query results are
+ * invalidated: they return false to hasNext() and
+ * throw NoSuchElementException to next().
+ */
+ public void closeAll ()
+ {
+ for(Iterator i = openQueryResults.iterator(); i.hasNext();) {
+ QueryResult queryResult = (QueryResult)i.next();
+ queryResult.close();
+ }
+ openQueryResults.clear();
+ }
+
+ //========= Internal helper methods ==========
+
+ /**
+ * This method verifies that if there is no transaction in progress then
+ * the NontransactionalRead flag must be set to true.
+ */
+ private void checkTransaction()
+ {
+ Transaction tx = pm.currentTransaction();
+ if ((!tx.isActive()) & !tx.getNontransactionalRead() )
+ throw new JDOQueryException(msg.msg("EXC_NoTransaction")); //NOI18N
+ }
+
+ /**
+ * This method checks a valid candidates setting for this query.
+ */
+ private void checkCandidates()
+ {
+ if (candidates == null) {
+ if (queryTree != null) {
+ candidates = pm.getExtent(queryTree.getCandidateClass(), true);
+ }
+ else if (candidateClass != null) {
+ candidates = pm.getExtent(candidateClass, true);
+ }
+ else {
+ throw new JDOQueryException(msg.msg("EXC_MissingCandidateClass")); //NOI18N
+ }
+ }
+ }
+
+ /**
+ * This method checks the candidate class of the underlying query
+ * tree. If this query instance was created from a query tree, and
+ * subsequently serialized and deserialized then The class instance of
+ * the candidate class is not set. The class instance of the candidate
+ * class is not part of the serialized state of a querty tree; only the
+ * name gets stored. In this case the method uses the PM algorithm to
+ * calculate the class instance of the candidate class and stores it in
+ * the query tree.
+ */
+ private void checkQueryTreeCandidateClass()
+ {
+ if (queryTree == null)
+ return;
+
+ if (queryTree.getCandidateClass() == null) {
+ String candidateClassName =
+ queryTree.getSerializedCandidateClassName();
+ if (candidateClassName != null) {
+ try {
+ queryTree.setCandidateClass(
+ pm.loadClass(candidateClassName, null));
+ }
+ catch (ClassNotFoundException ex) {
+ throw new JDOQueryException(
+ msg.msg("EXC_UnknownCandidateClass", //NOI18N
+ candidateClassName), ex);
+ }
+ }
+ }
+ }
+
+ /** Serialization support. */
+ private void readObject(java.io.ObjectInputStream in)
+ throws java.io.IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+ this.openQueryResults = new HashSet();
+ }
+
+ /** Deserialization support. */
+ private void writeObject(java.io.ObjectOutputStream out)
+ throws IOException
+ {
+ if (candidateClass != null)
+ this.candidateClassName = candidateClass.getName();
+ out.defaultWriteObject();
+ }
+}
Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryResultHelperImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryResultHelperImpl.java?rev=171353&view=auto
==============================================================================
--- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryResultHelperImpl.java (added)
+++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/QueryResultHelperImpl.java Sun May 22 11:08:57 2005
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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
+ *
+ * http://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.
+ */
+
+/*
+ * QueryResultHelperImpl.java
+ *
+ * Created on August 31, 2001
+ */
+
+package org.apache.jdo.impl.jdoql;
+
+import java.util.*;
+
+import javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.JDOHelper;
+import javax.jdo.JDOUserException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.impl.jdoql.jdoqlc.JDOQLAST;
+import org.apache.jdo.impl.jdoql.scope.ParameterTable;
+import org.apache.jdo.impl.jdoql.scope.VariableTable;
+import org.apache.jdo.query.QueryResultHelper;
+import org.apache.jdo.jdoql.tree.Expression;
+import org.apache.jdo.jdoql.tree.QueryTree;
+import org.apache.jdo.jdoql.tree.TreeWalker;
+import org.apache.jdo.jdoql.tree.ValueTable;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ * This class implements the helper interface to support the query
+ * execution strategy of the StoreManager. When a query is executed,
+ * the filter is parsed. The parsed query, candidate collection or extent,
+ * and actual parameters of the execute are stored in the
+ * QueryResultHelper.
+ *
+ * @author Michael Bouschen
+ */
+public class QueryResultHelperImpl
+ implements QueryResultHelper
+{
+ /** The query PM */
+ private PersistenceManagerInternal pm;
+
+ /** The query tree. */
+ private QueryTree queryTree;
+
+ /** The candidates for this query evalutaion. */
+ private Object candidates;
+
+ /** The table of parameter values. */
+ private ParameterTable parameters;
+
+ /** The table of variable values. */
+ private VariableTable variables;
+
+ /** The memory query evaluator. */
+ private MemoryQuery eval;
+
+ /** The tree walker used when applying the filter and do the ordering. */
+ private TreeWalker treeWalker;
+
+ /** The candidate class taken from the queryTree. */
+ private Class candidateClass;
+
+ /** The ordering comparator. */
+ private OrderingComparator ordering;
+
+ /** Logger */
+ private static Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.jdoql"); //NOI18N
+
+ /** I18N support */
+ protected final static I18NHelper msg =
+ I18NHelper.getInstance(QueryResultHelperImpl.class);
+
+ /**
+ *
+ */
+ public QueryResultHelperImpl(PersistenceManagerInternal pm,
+ QueryTree queryTree, Object candidates,
+ ParameterTable parameters, VariableTable variables)
+ {
+ this.pm = pm;
+ this.queryTree = queryTree;
+ this.candidates = candidates;
+ this.parameters = parameters;
+ this.variables = variables;
+ this.candidateClass = queryTree.getCandidateClass();
+ this.eval = new MemoryQuery(pm, parameters, variables);
+ this.treeWalker = new TreeWalker();
+ this.ordering = new OrderingComparator(treeWalker, eval);
+ if (logger.isTraceEnabled()) {
+ String repr = null;
+ if (queryTree == null)
+ repr = "null"; //NOI18N
+ else if (queryTree instanceof JDOQLAST)
+ repr = ((JDOQLAST)queryTree).treeToString();
+ else
+ repr = queryTree.toString();
+ logger.trace("QueryTree\n" + repr); //NOI18N
+ }
+ }
+
+ /** Return the candidate Collection or Extent specified by
+ * the user.
+ * @return the candidate Collection or Extent.
+ */
+ public Object getCandidates()
+ {
+ return candidates;
+ }
+
+ /** This method filters the specified collection, removing all elements that
+ * are not assignment compatible to the candidate Class specified by the
+ * user, and then orders the results according to the ordering expression
+ * specified by the user. A new List is returned.
+ * @param candidates the collection of instances to be filtered and ordered
+ * @return the filtered parameter collection ordered by the ordering
+ * expression.
+ */
+ public List orderCandidates(Collection candidates)
+ {
+ List list = new ArrayList();
+ for (Iterator i = candidates.iterator(); i.hasNext();) {
+ Object next = i.next();
+ if (candidateClass.isInstance(next))
+ list.add(next);
+ }
+ ordering.setQueryTree(queryTree);
+ Collections.sort(list, ordering);
+ if (logger.isTraceEnabled())
+ logger.trace("orderCandidates -> " + list); //NOI18N
+ return list;
+ }
+
+ /** This method determines whether the specified object is assignment
+ * compatible to the candidate Class specified by the user and satisfies
+ * the query filter.
+ * @return <CODE>true</CODE> if the specified object is of the candidate
+ * class and satisfies the query filter; <CODE>false otherwise</CODE>
+ * @param obj the candidate object.
+ */
+ public boolean applyFilter (Object obj)
+ {
+ boolean satisfies = false;
+ if (candidateClass.isInstance(obj)) {
+ // check whether obj is bound to the same pm as the one from the query
+ checkPM(pm, obj);
+ eval.setCurrent(obj);
+ Object result = treeWalker.walk(queryTree.getFilter(), eval);
+ satisfies = ((result instanceof Boolean) && ((Boolean)result).booleanValue());
+ }
+ if (logger.isTraceEnabled())
+ logger.trace("applyFilter -> " + satisfies + "\t" + obj); //NOI18N
+ return satisfies;
+ }
+
+ /** Return the query tree which is either specified by the user or compiled
+ * from a JDOQL query.
+ * @return the query tree
+ */
+ public QueryTree getQueryTree()
+ {
+ return queryTree;
+ }
+
+ /** This method returns the parameter values passed by the user
+ * in the execute(...) method.
+ * @return a ValueTable representing the parameter values
+ */
+ public ValueTable getParameterValues()
+ {
+ return parameters;
+ }
+
+ //========= Helper method ==========
+
+ /**
+ * Checks the PersistenceManager of the specified value to be
+ * identical to the one from the query instance.
+ */
+ public static void checkPM(PersistenceManagerInternal queryPM, Object value)
+ {
+ if (value instanceof Collection) {
+ // iterate collection and call checkPM for all elements
+ for (Iterator i = ((Collection)value).iterator(); i.hasNext();)
+ checkPM(queryPM, i.next());
+ }
+ else if (value instanceof Object[]) {
+ // iterate array and call checkPM for all elements
+ // No need to check array of primitive types
+ Object[] array = (Object[])value;
+ for (int i = 0; i < array.length; i++)
+ checkPM(queryPM, array[i]);
+ }
+ else
+ {
+ PersistenceManager instancePM =
+ JDOHelper.getPersistenceManager(value);
+ if ((instancePM != null) && !instancePM.equals(queryPM)) {
+ // instancePM is NOT the one from the query => exception
+ throw new JDOUserException(
+ msg.msg("EXC_InstanceBoundToDifferentPM", value)); //NOI18N
+ }
+ }
+ }
+
+}
+
Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/ErrorMsg.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/ErrorMsg.java?rev=171353&view=auto
==============================================================================
--- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/ErrorMsg.java (added)
+++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/ErrorMsg.java Sun May 22 11:08:57 2005
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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
+ *
+ * http://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.
+ */
+
+/*
+ * ErrorMsg.java
+ *
+ * Created on August 28, 2001
+ */
+
+package org.apache.jdo.impl.jdoql.jdoqlc;
+
+import java.util.ResourceBundle;
+
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOUnsupportedOptionException;
+
+import org.apache.jdo.jdoql.JDOQueryException;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ *
+ * @author Michael Bouschen
+ */
+public class ErrorMsg
+{
+ /**
+ * The context is included in an error message. It usually defines the query
+ * method with the invalid definition (such as declareParameters, setFilter,
+ * etc.).
+ */
+ protected String context = null;
+
+ /** I18N support */
+ protected final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.jdoql.Bundle", ErrorMsg.class.getClassLoader()); //NOI18N
+
+ /** Return the current context string */
+ public String getContext()
+ {
+ return context;
+ }
+
+ /** Set the specified string as the current context string. */
+ public void setContext(String name)
+ {
+ context = name;
+ }
+
+ /**
+ * Indicates an error situation.
+ * @param line line number
+ * @param col column number
+ * @param text error message
+ */
+ public void error(int line, int col, String text)
+ throws JDOQueryException
+ {
+ if (line > 1) {
+ // include line and column info
+ Object args[] = {context, new Integer(line), new Integer(col), text};
+ throw new JDOQueryException(
+ msg.msg("EXC_PositionInfoMsgLineColumn", args)); //NOI18N
+ }
+ else if (col > 0)
+ {
+ // include column info
+ Object args[] = {context, new Integer(col), text};
+ throw new JDOQueryException(
+ msg.msg("EXC_PositionInfoMsgColumn", args)); //NOI18N
+ }
+ else
+ {
+ Object args[] = {context, text};
+ throw new JDOQueryException(
+ msg.msg("EXC_PositionInfoMsg", args)); //NOI18N
+ }
+ }
+
+ /**
+ * Indicates that a feature is not supported by the current release.
+ * @param line line number
+ * @param col column number
+ * @param text message
+ */
+ public void unsupported(int line, int col, String text)
+ throws JDOUnsupportedOptionException
+ {
+ if (line > 1)
+ {
+ // include line and column info
+ Object args[] = {context, new Integer(line), new Integer(col), text};
+ throw new JDOUnsupportedOptionException(
+ msg.msg("EXC_PositionInfoMsgLineColumn", args)); //NOI18N
+ }
+ else if (col > 0)
+ {
+ // include column info
+ Object args[] = {context, new Integer(col), text};
+ throw new JDOUnsupportedOptionException(
+ msg.msg("EXC_PositionInfoMsgColumn", args)); //NOI18N
+ }
+ else
+ {
+ Object args[] = {context, text};
+ throw new JDOUnsupportedOptionException(
+ msg.msg("EXC_PositionInfoMsg", args)); //NOI18N
+ }
+ }
+
+ /**
+ * Indicates a fatal situation (implementation error).
+ * @param text error message
+ */
+ public void fatal(String text)
+ throws JDOFatalInternalException
+ {
+ throw new JDOFatalInternalException(text);
+ }
+
+ /**
+ * Indicates a fatal situation (implementation error).
+ * @param text error message
+ */
+ public void fatal(String text, Exception nested)
+ throws JDOFatalInternalException
+ {
+ throw new JDOFatalInternalException(text, nested);
+ }
+}
Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQL.g
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQL.g?rev=171353&view=auto
==============================================================================
--- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQL.g (added)
+++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQL.g Sun May 22 11:08:57 2005
@@ -0,0 +1,843 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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
+ *
+ * http://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.
+ */
+
+/*
+ * JDOQL.g
+ *
+ * Created on August 28, 2001
+ */
+
+header
+{
+ package org.apache.jdo.impl.jdoql.jdoqlc;
+
+ import antlr.MismatchedTokenException;
+ import antlr.MismatchedCharException;
+ import antlr.NoViableAltException;
+ import antlr.NoViableAltForCharException;
+ import antlr.TokenStreamRecognitionException;
+
+ import org.apache.jdo.jdoql.JDOQueryException;
+ import org.apache.jdo.impl.jdoql.tree.*;
+ import org.apache.jdo.util.I18NHelper;
+}
+
+//===== Lexical Analyzer Class Definitions =====
+
+/**
+ * This class defines the lexical analysis for the JDOQL compiler.
+ *
+ * @author Michael Bouschen
+ */
+class JDOQLLexer extends Lexer;
+options
+{
+ k = 2;
+ exportVocab = JDOQL;
+ charVocabulary = '\u0000'..'\uFFFE'; //NOI18N
+}
+
+tokens {
+
+ IMPORT = "import" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ IMPORT_ON_DEMAND <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>;
+ THIS = "this" <AST=org.apache.jdo.impl.jdoql.tree.ThisExpr>; //NOI18N
+ ASCENDING = "ascending" <AST=org.apache.jdo.impl.jdoql.tree.AscendingOrderingExpr>; //NOI18N
+ DESCENDING = "descending" <AST=org.apache.jdo.impl.jdoql.tree.DescendingOrderingExpr>; //NOI18N
+
+ // types
+
+ BOOLEAN = "boolean" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ BYTE = "byte" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ CHAR = "char" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ SHORT = "short" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ INT = "int" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ FLOAT = "float" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ LONG = "long" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+ DOUBLE = "double" <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>; //NOI18N
+
+ // literals
+
+ NULL = "null" <AST=org.apache.jdo.impl.jdoql.tree.ConstantExpr>; //NOI18N
+ TRUE = "true" <AST=org.apache.jdo.impl.jdoql.tree.BooleanLiteralExpr>; //NOI18N
+ FALSE = "false" <AST=org.apache.jdo.impl.jdoql.tree.BooleanLiteralExpr>; //NOI18N
+
+ // other tokens
+
+ EQUAL <AST=org.apache.jdo.impl.jdoql.tree.EqualsExpr>;
+ NOT_EQUAL <AST=org.apache.jdo.impl.jdoql.tree.NotEqualsExpr>;
+ GE <AST=org.apache.jdo.impl.jdoql.tree.GreaterThanEqualsExpr>;
+ GT <AST=org.apache.jdo.impl.jdoql.tree.GreaterThanExpr>;
+ LE <AST=org.apache.jdo.impl.jdoql.tree.LessThanEqualsExpr>;
+ LT <AST=org.apache.jdo.impl.jdoql.tree.LessThanExpr>;
+
+ PLUS <AST=org.apache.jdo.impl.jdoql.tree.PlusExpr>;
+ MINUS <AST=org.apache.jdo.impl.jdoql.tree.MinusExpr>;
+ STAR <AST=org.apache.jdo.impl.jdoql.tree.TimesExpr>;
+ DIV <AST=org.apache.jdo.impl.jdoql.tree.DivideExpr>;
+
+ BOR <AST=org.apache.jdo.impl.jdoql.tree.OrExpr>;
+ OR <AST=org.apache.jdo.impl.jdoql.tree.ConditionalOrExpr>;
+ BAND <AST=org.apache.jdo.impl.jdoql.tree.AndExpr>;
+ AND <AST=org.apache.jdo.impl.jdoql.tree.ConditionalAndExpr>;
+ LNOT <AST=org.apache.jdo.impl.jdoql.tree.NotExpr>;
+ BNOT <AST=org.apache.jdo.impl.jdoql.tree.ComplementExpr>;
+
+ INT_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.IntLiteralExpr>;
+ LONG_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.IntLiteralExpr>;
+ FLOAT_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.FloatLiteralExpr>;
+ DOUBLE_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.DoubleLiteralExpr>;
+ CHAR_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.CharLiteralExpr>;
+ STRING_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.ConstantExpr>;
+ IDENT <AST=org.apache.jdo.impl.jdoql.tree.IdentifierExpr>;
+
+ DOT <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>;
+
+ // lexer only
+
+ LPAREN;
+ RPAREN;
+ COMMA;
+ SEMI;
+ WS;
+ NEWLINE;
+ ESC;
+ HEX_DIGIT;
+ EXPONENT;
+ FLOATINGPOINT_SUFFIX;
+ UNICODE_ESCAPE;
+ UNICODE_CHAR;
+}
+
+{
+ /** The error message support class. */
+ protected ErrorMsg errorMsg;
+
+ /** The width of a tab stop. */
+ protected static final int TABSIZE = 4;
+
+ /** */
+ protected static final int EOF_CHAR = 65535; // = (char) -1 = EOF
+
+ /** I18N support. */
+ protected static final I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.jdoql.Bundle", JDOQLLexer.class.getClassLoader()); //NOI18N
+
+ /**
+ *
+ */
+ public void init(ErrorMsg errorMsg)
+ {
+ this.errorMsg = errorMsg;
+ }
+
+ /**
+ *
+ */
+ public void tab()
+ {
+ int column = getColumn();
+ int newColumn = (((column-1)/TABSIZE)+1)*TABSIZE+1;
+ setColumn(newColumn);
+ }
+
+ /**
+ *
+ */
+ public void reportError(int line, int column, String s)
+ {
+ errorMsg.error(line, column, s);
+ }
+
+ /**
+ * Report lexer exception errors caught in nextToken()
+ */
+ public void reportError(RecognitionException e)
+ {
+ handleANTLRException(e, errorMsg);
+ }
+
+ /**
+ * Lexer error-reporting function
+ */
+ public void reportError(String s)
+ {
+ errorMsg.error(0, 0, s);
+ }
+
+ /**
+ * Lexer warning-reporting function
+ */
+ public void reportWarning(String s)
+ {
+ throw new JDOQueryException(s);
+ }
+
+ /**
+ *
+ */
+ public static void handleANTLRException(ANTLRException ex, ErrorMsg errorMsg)
+ {
+ if (ex instanceof MismatchedCharException) {
+ MismatchedCharException mismatched = (MismatchedCharException)ex;
+ if (mismatched.mismatchType == MismatchedCharException.CHAR) {
+ if (mismatched.foundChar == EOF_CHAR) {
+ errorMsg.error(mismatched.getLine(), mismatched.getColumn(),
+ msg.msg("EXC_UnexpectedEOF")); //NOI18N
+ }
+ else {
+ errorMsg.error(mismatched.getLine(), mismatched.getColumn(),
+ msg.msg("EXC_ExpectedCharFound", //NOI18N
+ String.valueOf((char)mismatched.expecting),
+ String.valueOf((char)mismatched.foundChar)));
+ }
+ return;
+ }
+ }
+ else if (ex instanceof MismatchedTokenException) {
+ MismatchedTokenException mismatched = (MismatchedTokenException)ex;
+ Token token = mismatched.token;
+ if ((mismatched.mismatchType == MismatchedTokenException.TOKEN) &&
+ (token != null)) {
+ if (token.getType() == Token.EOF_TYPE) {
+ errorMsg.error(token.getLine(), token.getColumn(),
+ msg.msg("EXC_UnexpectedEOF")); //NOI18N
+ }
+ else {
+ errorMsg.error(token.getLine(), token.getColumn(),
+ msg.msg("EXC_SyntaxErrorAt", token.getText())); //NOI18N
+ }
+ return;
+ }
+ }
+ else if (ex instanceof NoViableAltException) {
+ Token token = ((NoViableAltException)ex).token;
+ if (token != null) {
+ if (token.getType() == Token.EOF_TYPE) {
+ errorMsg.error(token.getLine(), token.getColumn(),
+ msg.msg("EXC_UnexpectedEOF")); //NOI18N
+ }
+ else {
+ errorMsg.error(token.getLine(), token.getColumn(),
+ msg.msg("EXC_UnexpectedToken", token.getText())); //NOI18N
+ }
+ return;
+ }
+ }
+ else if (ex instanceof NoViableAltForCharException) {
+ NoViableAltForCharException noViableAlt = (NoViableAltForCharException)ex;
+ errorMsg.error(noViableAlt.getLine(), noViableAlt.getColumn(),
+ msg.msg("EXC_UnexpectedChar", String.valueOf((char)noViableAlt.foundChar)));//NOI18N
+ }
+ else if (ex instanceof TokenStreamRecognitionException) {
+ handleANTLRException(((TokenStreamRecognitionException)ex).recog, errorMsg);
+ }
+
+ // no special handling from aboves matches the exception if this line is reached =>
+ // make it a syntax error
+ int line = 0;
+ int column = 0;
+ if (ex instanceof RecognitionException) {
+ line = ((RecognitionException)ex).getLine();
+ column = ((RecognitionException)ex).getColumn();
+ }
+ errorMsg.error(line, column, msg.msg("EXC_SyntaxError")); //NOI18N
+ }
+}
+
+// OPERATORS
+
+// The following Java operators are included although not supported by JDOQL:
+// ASSIGN, DIV_ASSIGN, PLUS_ASSIGN, INC, MINUS_ASSIGN, DEC, STAR_ASSIGN,
+// SR, SL, BOR_ASSIGN, BAND_ASSIGN
+// The lexer recognizes them, but the parser will result in a syntax error.
+// This gurantees an error message. Othewise the java operator pre-decrement
+// is mapped to two unray minus. Two unray minus are valid in JDOQL, but not
+// indented.
+
+LPAREN : '(' ;
+RPAREN : ')' ;
+COMMA : ',' ;
+//DOT : '.' ;
+ASSIGN : "=" ; //NOI18N
+EQUAL : "==" ; //NOI18N
+LNOT : '!' ;
+BNOT : '~' ;
+NOT_EQUAL : "!=" ; //NOI18N
+DIV : '/' ;
+DIV_ASSIGN : "/=" ; //NOI18N
+PLUS : '+' ;
+PLUS_ASSIGN : "+=" ; //NOI18N
+INC : "++" ; //NOI18N
+MINUS : '-' ;
+MINUS_ASSIGN : "-=" ; //NOI18N
+DEC : "--" ; //NOI18N
+STAR : '*' ;
+STAR_ASSIGN : "*=" ; //NOI18N
+SR : ">>" ; //NOI18N
+GE : ">=" ; //NOI18N
+GT : ">" ; //NOI18N
+SL : "<<" ; //NOI18N
+LE : "<=" ; //NOI18N
+LT : '<' ;
+BOR : '|' ;
+BOR_ASSIGN : "|=" ; //NOI18N
+OR : "||" ; //NOI18N
+BAND : '&' ;
+BAND_ASSIGN : "&=" ; //NOI18N
+AND : "&&" ; //NOI18N
+SEMI : ';' ;
+
+// Whitespace -- ignored
+WS
+ : ( ' '
+ | '\t'
+ | '\f'
+ )+
+ { _ttype = Token.SKIP; }
+ ;
+
+NEWLINE
+ : ( "\r\n" //NOI18N
+ | '\r'
+ | '\n'
+ )
+ {
+ newline();
+ _ttype = Token.SKIP;
+ }
+ ;
+
+// character literals
+CHAR_LITERAL
+ : '\'' ( ESC | ~'\'' ) '\''
+ ;
+
+// string literals
+STRING_LITERAL
+ : '"' ( ESC | ~'"')* '"' //NOI18N
+ ;
+
+protected
+ESC
+ : '\\'
+ ( 'n'
+ | 'r'
+ | 't'
+ | 'b'
+ | 'f'
+ | '"' //NOI18N
+ | '\''
+ | '\\'
+ | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+ | ('0'..'3')
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : ('0'..'7')
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ )?
+ )?
+ | ('4'..'7')
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : ('0'..'9')
+ )?
+ )
+ ;
+
+protected
+HEX_DIGIT
+ : ('0'..'9'|'A'..'F'|'a'..'f')
+ ;
+
+INT_LITERAL
+ {
+ boolean isDecimal=false;
+ int tokenType = DOUBLE_LITERAL;
+ }
+ : '.' {_ttype = DOT;}
+ (('0'..'9')+ {tokenType = DOUBLE_LITERAL;}
+ (EXPONENT)?
+ (tokenType = FLOATINGPOINT_SUFFIX)?
+ { _ttype = tokenType; })?
+ | ( '0' {isDecimal = true;} // special case for just '0'
+ ( ('x'|'X')
+ (
+ options {
+ warnWhenFollowAmbig=false;
+ }
+ : HEX_DIGIT
+ )+
+ | ('0'..'7')+
+ )?
+ | ('1'..'9') ('0'..'9')* {isDecimal=true;}
+ )
+ ( ('l'|'L') { _ttype = LONG_LITERAL; }
+ | {isDecimal}?
+ {tokenType = DOUBLE_LITERAL;}
+ ( '.' ('0'..'9')* (EXPONENT)?
+ (tokenType = FLOATINGPOINT_SUFFIX)?
+ | EXPONENT (tokenType = FLOATINGPOINT_SUFFIX)?
+ | tokenType = FLOATINGPOINT_SUFFIX
+ )
+ { _ttype = tokenType; }
+ )?
+ ;
+
+protected
+EXPONENT
+ : ('e'|'E') ('+'|'-')? ('0'..'9')+
+ ;
+
+protected
+FLOATINGPOINT_SUFFIX returns [int tokenType]
+ : 'f' { tokenType = FLOAT_LITERAL; }
+ | 'F' { tokenType = FLOAT_LITERAL; }
+ | 'd' { tokenType = DOUBLE_LITERAL; }
+ | 'D' { tokenType = DOUBLE_LITERAL; }
+ ;
+
+IDENT
+ options {paraphrase = "an identifier"; testLiterals=true;} //NOI18N
+ : ( 'a'..'z'
+ | 'A'..'Z'
+ | '_'
+ | '$'
+ | UNICODE_ESCAPE
+ | c1:'\u0080'..'\uFFFE'
+ {
+ if (!Character.isJavaIdentifierStart(c1)) {
+ errorMsg.error(getLine(), getColumn(),
+ msg.msg("EXC_UnexpectedChar", String.valueOf(c1)));//NOI18N
+ }
+ }
+ )
+ ( 'a'..'z'
+ | 'A'..'Z'
+ | '_'
+ | '$'
+ | '0'..'9'
+ | UNICODE_ESCAPE
+ | c2:'\u0080'..'\uFFFE'
+ {
+ if (!Character.isJavaIdentifierPart(c2)) {
+ errorMsg.error(getLine(), getColumn(),
+ msg.msg("EXC_UnexpectedChar", String.valueOf(c2)));//NOI18N
+ }
+ }
+ )*
+ ;
+
+protected
+UNICODE_ESCAPE
+ : '\\' ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+ {
+ try {
+ String tmp = text.toString();
+ char c = (char)Integer.parseInt(tmp.substring(tmp.length() - 4, tmp.length()), 16);
+ // problems using ANTLR feature $setText => use generated code
+ text.setLength(_begin);
+ text.append(new Character(c).toString());
+ }
+ catch (NumberFormatException ex) {
+ errorMsg.fatal(msg.msg("ERR_UnexpectedExceptionUnicode"), ex); //NOI18N
+ }
+ }
+ ;
+
+//===== Parser Class Definitions =====
+
+/**
+ * This class defines the syntax analysis (parser) of the JDOQL compiler.
+ *
+ * @author Michael Bouschen
+ */
+class JDOQLParser extends Parser;
+
+options {
+ k = 2; // two token lookahead
+ exportVocab = JDOQL;
+ buildAST = true;
+ ASTLabelType = "JDOQLAST"; // NOI18N
+}
+
+tokens
+{
+ // "imaginary" tokens, that have no corresponding real input
+
+ QUERY_TREE <AST=org.apache.jdo.impl.jdoql.tree.Tree>;
+ CANDIDATE_CLASS <AST=org.apache.jdo.impl.jdoql.tree.CandidateClassImpl>;
+ PARAMETER_DECL <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>;
+ VARIABLE_DECL <AST=org.apache.jdo.impl.jdoql.tree.VariableDecl>;
+
+ // operators
+ OBJECT_EQUAL <AST=org.apache.jdo.impl.jdoql.tree.EqualsExpr>;
+ OBJECT_NOT_EQUAL <AST=org.apache.jdo.impl.jdoql.tree.NotEqualsExpr>;
+ COLLECTION_EQUAL <AST=org.apache.jdo.impl.jdoql.tree.EqualsExpr>;
+ COLLECTION_NOT_EQUAL <AST=org.apache.jdo.impl.jdoql.tree.NotEqualsExpr>;
+ UNARY_MINUS <AST=org.apache.jdo.impl.jdoql.tree.UnaryMinusExpr>;
+ UNARY_PLUS <AST=org.apache.jdo.impl.jdoql.tree.UnaryPlusExpr>;
+ CONCAT <AST=org.apache.jdo.impl.jdoql.tree.PlusExpr>;
+ CAST <AST=org.apache.jdo.impl.jdoql.tree.CastExpr>;
+
+ // special dot expressions
+ FIELD_ACCESS <AST=org.apache.jdo.impl.jdoql.tree.FieldAccessExpr>;
+ STATIC_FIELD_ACCESS <AST=org.apache.jdo.impl.jdoql.tree.FieldAccessExpr>;
+ NAVIGATION <AST=org.apache.jdo.impl.jdoql.tree.FieldAccessExpr>;
+ CONTAINS <AST=org.apache.jdo.impl.jdoql.tree.ContainsCallExpr>;
+ STARTS_WITH <AST=org.apache.jdo.impl.jdoql.tree.StartsWithCallExpr>;
+ ENDS_WITH <AST=org.apache.jdo.impl.jdoql.tree.EndsWithCallExpr>;
+ IS_EMPTY <AST=org.apache.jdo.impl.jdoql.tree.IsEmptyCallExpr>;
+
+ // identifier types
+ VARIABLE_ACCESS <AST=org.apache.jdo.impl.jdoql.tree.VariableAccessExpr>;
+ PARAMETER_ACCESS <AST=org.apache.jdo.impl.jdoql.tree.ParameterAccessExpr>;
+
+ // types
+ TYPE <AST=org.apache.jdo.impl.jdoql.tree.TypeImpl>;
+
+ // constant value
+ CONSTANT <AST=org.apache.jdo.impl.jdoql.tree.ConstantExpr>;
+
+ // Query Tree nodes
+ BOOLEAN_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.BooleanLiteralExpr>;
+ BYTE_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.ByteLiteralExpr>;
+ SHORT_LITERAL <AST=org.apache.jdo.impl.jdoql.tree.ShortLiteralExpr>;
+
+ // temporary node removed by Semantic
+ ARG_LIST <AST=org.apache.jdo.impl.jdoql.tree.NodeImpl>;
+}
+
+{
+ /** The error message support class. */
+ protected ErrorMsg errorMsg;
+
+ /** I18N support. */
+ protected final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.jdoql.Bundle", JDOQLParser.class.getClassLoader()); //NOI18N
+
+ /**
+ *
+ */
+ public void init(ErrorMsg errorMsg)
+ {
+ this.errorMsg = errorMsg;
+ }
+
+ /**
+ * ANTLR method called when an error was detected.
+ */
+ public void reportError(RecognitionException ex)
+ {
+ JDOQLLexer.handleANTLRException(ex, errorMsg);
+ }
+
+ /**
+ * ANTLR method called when an error was detected.
+ */
+ public void reportError(String s)
+ {
+ errorMsg.error(0, 0, s);
+ }
+
+ /**
+ *
+ */
+ public void reportError(int line, int column, String s)
+ {
+ errorMsg.error(line, column, s);
+ }
+
+ /**
+ * ANTLR method called when a warning was detected.
+ */
+ public void reportWarning(String s)
+ {
+ throw new JDOQueryException(s);
+ }
+
+}
+
+// ----------------------------------
+// rules: import declaration
+// ----------------------------------
+
+parseImports
+{
+ errorMsg.setContext("declareImports"); //NOI18N
+}
+ : ( declareImport ( SEMI! declareImport )* )? ( SEMI! )? EOF!
+ ;
+
+declareImport
+ : i:IMPORT^ q:qualifiedNameStar
+ {
+ if (#q.getType() == STAR) {
+ #i.setType(IMPORT_ON_DEMAND);
+ #i.setFirstChild(#q.getFirstChild());
+ }
+ }
+ ;
+
+// ----------------------------------
+// rules: parameter declaration
+// ----------------------------------
+
+parseParameters
+{
+ errorMsg.setContext("declareParameters"); //NOI18N
+}
+ : ( declareParameter ( COMMA! declareParameter )* )? ( COMMA! )? EOF!
+ ;
+
+declareParameter
+ : type IDENT
+ {
+ ParameterDecl paramDecl =
+ new ParameterDecl(new Token(PARAMETER_DECL,"parameterDecl")); //NOI18N
+ paramDecl.setFirstChild(#declareParameter);
+ #declareParameter = paramDecl;
+ }
+ ;
+
+// ----------------------------------
+// rules: variables declaration
+// ----------------------------------
+
+parseVariables
+{
+ errorMsg.setContext("declareVariables"); //NOI18N
+}
+ : ( declareVariable ( SEMI! declareVariable )* )? ( SEMI! )? EOF!
+ ;
+
+declareVariable
+ : type IDENT
+ {
+ VariableDecl variableDecl =
+ new VariableDecl(new Token(VARIABLE_DECL,"variableDecl")); //NOI18N
+ variableDecl.setFirstChild(#declareVariable);
+ #declareVariable = variableDecl;
+ }
+ ;
+
+// ----------------------------------
+// rules ordering specification
+// ----------------------------------
+
+parseOrdering
+{
+ errorMsg.setContext("setOrdering"); //NOI18N
+}
+ : ( orderSpec ( COMMA! orderSpec )* )? ( COMMA! )? EOF!
+ ;
+
+orderSpec
+ : e:expression ( ASCENDING^ | DESCENDING^ )
+ ;
+
+// ----------------------------------
+// rules filer expression
+// ----------------------------------
+
+parseFilter
+{
+ errorMsg.setContext("setFilter"); //NOI18N
+}
+ : e:expression EOF!
+ ;
+
+// This is a list of expressions.
+expressionList
+ : expression (COMMA! expression)*
+ ;
+
+expression
+ : invalidExpression
+ ;
+
+// assignment expression: not supported => syntax error
+invalidExpression
+ : conditionalOrExpression
+ (
+ op:invalidOperator
+ {
+ errorMsg.error(#op.getLine(), #op.getColumn(),
+ msg.msg("EXC_UnexpectedToken", #op.getText())); //NOI18N
+ }
+ invalidExpression
+ )?
+ ;
+
+invalidOperator
+ : ASSIGN | PLUS_ASSIGN | MINUS_ASSIGN | STAR_ASSIGN |
+ DIV_ASSIGN | BAND_ASSIGN | BOR_ASSIGN | SR | SL
+ ;
+
+// conditional or ||
+conditionalOrExpression
+ : conditionalAndExpression (OR^ conditionalAndExpression)*
+ ;
+
+// conditional and &&
+conditionalAndExpression
+ : inclusiveOrExpression (AND^ inclusiveOrExpression)*
+ ;
+
+// bitwise or logical or |
+inclusiveOrExpression
+ : andExpression (BOR^ andExpression)*
+ ;
+
+// bitwise or logical and &
+andExpression
+ : equalityExpression (BAND^ equalityExpression)*
+ ;
+
+// equality/inequality ==/!=
+equalityExpression
+ : relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
+ ;
+// boolean relational expressions
+relationalExpression
+ : additiveExpression
+ ( ( LT^
+ | GT^
+ | LE^
+ | GE^
+ )
+ additiveExpression
+ )*
+ ;
+
+// binary addition/subtraction
+additiveExpression
+ : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
+ ;
+// multiplication/division/modulo
+multiplicativeExpression
+ : unaryExpression ((STAR^ | DIV^ ) unaryExpression)*
+ ;
+
+unaryExpression
+ : MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
+ | PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
+ | i:INC^ unaryExpression
+ {
+ errorMsg.error(#i.getLine(), #i.getColumn(),
+ msg.msg("EXC_UnexpectedToken", #i.getText())); //NOI18N
+ }
+ | d:DEC^ unaryExpression
+ {
+ errorMsg.error(#d.getLine(), #d.getColumn(),
+ msg.msg("EXC_UnexpectedToken", #d.getText())); //NOI18N
+ }
+ | unaryExpressionNotPlusMinus
+ ;
+
+unaryExpressionNotPlusMinus
+ : BNOT^ unaryExpression
+ | LNOT^ unaryExpression
+ | ( LPAREN type RPAREN unaryExpression )=>
+ lp:LPAREN^ {#lp.setType(CAST);} type RPAREN! unaryExpression
+ | postfixExpression
+ ;
+
+// qualified names, field access, method invocation
+postfixExpression
+ : primary
+ ( DOT^ IDENT ( argList )? )*
+ ;
+
+argList
+ : LPAREN!
+ ( expressionList
+ {
+ NodeImpl argListRoot = new NodeImpl(new Token(ARG_LIST,"argList")); //NOI18N
+ argListRoot.setFirstChild(#argList);
+ #argList = argListRoot;
+ }
+ | /* empty list */
+ {
+ NodeImpl argListRoot = new NodeImpl(new Token(ARG_LIST,"argList")); //NOI18N
+ #argList = argListRoot;
+ }
+ )
+ RPAREN!
+ ;
+
+// the basic element of an expression
+primary
+ : IDENT
+ | literal
+ | THIS
+ | LPAREN! expression RPAREN!
+ ;
+
+literal
+ : TRUE
+ | FALSE
+ | INT_LITERAL
+ | LONG_LITERAL
+ | FLOAT_LITERAL
+ | DOUBLE_LITERAL
+ | c:CHAR_LITERAL
+ {
+ // strip quotes from the token text
+ String text = #c.getText();
+ #c.setText(text.substring(1,text.length()-1));
+ }
+ | s:STRING_LITERAL
+ {
+ // strip quotes from the token text
+ String text = #s.getText();
+ #s.setText(text.substring(1,text.length()-1));
+ }
+ | NULL
+ ;
+
+qualifiedName
+ : IDENT ( DOT^ IDENT )*
+ ;
+
+qualifiedNameStar
+ : IDENT ( DOT^ IDENT )* ( DOT! STAR^ )?
+ ;
+
+type
+ : qualifiedName
+ | primitiveType
+ ;
+
+// The primitive types.
+primitiveType
+ : BOOLEAN
+ | BYTE
+ | CHAR
+ | SHORT
+ | INT
+ | FLOAT
+ | LONG
+ | DOUBLE
+ ;
Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLAST.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLAST.java?rev=171353&view=auto
==============================================================================
--- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLAST.java (added)
+++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLAST.java Sun May 22 11:08:57 2005
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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
+ *
+ * http://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.
+ */
+
+/*
+ * JDOQLAST.java
+ *
+ * Created on August 28, 2001
+ */
+
+package org.apache.jdo.impl.jdoql.jdoqlc;
+
+import org.apache.jdo.model.java.JavaType;
+
+import antlr.Token;
+import antlr.CommonAST;
+import antlr.collections.AST;
+
+
+/**
+ * This class represents a node in the intermediate representation (AST)
+ * used by the query compiler.
+ * It provides
+ * - line info
+ * - column info
+ * - type info (JavaType instance): the semantic analysis calculates
+ * the type of an expression and adds this info to each node.
+ * @author Michael Bouschen
+ */
+public class JDOQLAST
+ extends CommonAST
+ implements Cloneable
+{
+ /** The line info */
+ protected int line = 0;
+
+ /** The column info */
+ protected int column = 0;
+
+ /** The type info */
+ protected transient JavaType typeInfo;
+
+ /** */
+ public JDOQLAST()
+ {
+ }
+
+ /** */
+ public JDOQLAST(int type, String text, JavaType typeInfo)
+ {
+ initialize(type, text, typeInfo);
+ }
+
+ /** */
+ public JDOQLAST(JDOQLAST ast)
+ {
+ initialize(ast);
+ }
+
+ /** */
+ public void initialize(Token t)
+ {
+ setType(t.getType());
+ setText(t.getText());
+ setLine(t.getLine());
+ setColumn(t.getColumn());
+ }
+
+ /** */
+ public void initialize(int type, String text, JavaType typeInfo)
+ {
+ setType(type);
+ setText(text);
+ setTypeInfo(typeInfo);
+ }
+
+ /** */
+ public void initialize(AST _ast)
+ {
+ JDOQLAST ast = (JDOQLAST)_ast;
+ setType(ast.getType());
+ setText(ast.getText());
+ setLine(ast.getLine());
+ setColumn(ast.getColumn());
+ setTypeInfo(ast.getTypeInfo());
+ }
+
+ /** */
+ public void setLine(int line)
+ {
+ this.line = line;
+ }
+
+ /** */
+ public int getLine()
+ {
+ return line;
+ }
+
+ /** */
+ public void setColumn(int column)
+ {
+ this.column = column;
+ }
+
+ /** */
+ public int getColumn()
+ {
+ return column;
+ }
+
+ /** */
+ public void setTypeInfo(JavaType typeInfo)
+ {
+ this.typeInfo = typeInfo;
+ }
+
+ /** */
+ public JavaType getTypeInfo()
+ {
+ return typeInfo;
+ }
+
+ /**
+ * Returns a string representation of this JDOQLAST.
+ * @return a string representation of the object.
+ */
+ public String toString()
+ {
+ JavaType typeInfo = getTypeInfo();
+ StringBuffer repr = new StringBuffer();
+ // token text
+ repr.append((getText() == null ? "null" : getText())); //NOI18N
+ repr.append(" ["); //NOI18N
+ // token type
+ repr.append(getType());
+ // line/column info
+ repr.append(", ("); //NOI18N
+ repr.append(getLine() + "/" + getColumn()); //NOI18N
+ repr.append("), "); //NOI18N
+ // type info
+ repr.append(typeInfo);
+ repr.append(", "); //NOI18N
+ // node class info
+ String className = getClass().getName();
+ int index = className.lastIndexOf('.');
+ if (index > -1)
+ className = className.substring(index+1);
+ repr.append(className);
+ repr.append("]"); //NOI18N
+ return repr.toString();
+ }
+
+ /**
+ * Returns a string representation of this JDOQLAST including
+ * all child nodes.
+ * @return a string representation of this JDOQLAST including all
+ * child nodes.
+ */
+ public String treeToString()
+ {
+ StringBuffer repr = new StringBuffer();
+ treeToString(0, repr);
+ return repr.toString();
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ * The returned JDOQLAST shares the same state as this object, meaning
+ * the fields type, text, line, column, and typeInfo have the same values.
+ * But it is not bound to any tree structure, thus the child is null
+ * and the sibling is null.
+ * @return a clone of this instance.
+ */
+ protected Object clone()
+ throws CloneNotSupportedException
+ {
+ JDOQLAST clone = (JDOQLAST)super.clone();
+ clone.setFirstChild(null);
+ clone.setNextSibling(null);
+ return clone;
+ }
+
+ // Internal helper method
+
+ /** */
+ private void treeToString(int indent, StringBuffer repr)
+ {
+ // indent
+ for (int i = 0; i < indent; i++) {
+ repr.append(" "); //NOI18N
+ }
+
+ // append string representation of current node
+ repr.append(toString());
+
+ // child nodes in new line
+ repr.append("\n");
+
+ // append string representation(s) of child nodes
+ for (JDOQLAST node = (JDOQLAST)this.getFirstChild();
+ node != null;
+ node = (JDOQLAST)node.getNextSibling()) {
+ node.treeToString(indent+1, repr);
+ }
+ }
+}
+
Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLASTFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLASTFactory.java?rev=171353&view=auto
==============================================================================
--- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLASTFactory.java (added)
+++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLASTFactory.java Sun May 22 11:08:57 2005
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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
+ *
+ * http://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.
+ */
+
+/*
+ * JDOQLASTFactory.java
+ *
+ * Created on September 3, 2001
+ */
+
+package org.apache.jdo.impl.jdoql.jdoqlc;
+
+import antlr.collections.AST;
+import antlr.ASTFactory;
+
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ * Factory to create and connect JDOQLAST nodes.
+ *
+ * @author Michael Bouschen
+ */
+public class JDOQLASTFactory
+ extends ASTFactory
+{
+ /** The singleton JDOQLASTFactory instance. */
+ private static JDOQLASTFactory factory = new JDOQLASTFactory();
+
+ /** I18N support. */
+ private final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.jdoql.Bundle", JDOQLASTFactory.class.getClassLoader()); //NOI18N
+
+ /**
+ * Get an instance of JDOQLASTFactory.
+ * @return an instance of JDOQLASTFactory
+ */
+ public static JDOQLASTFactory getInstance()
+ {
+ return factory;
+ }
+
+ /**
+ *
+ */
+ protected JDOQLASTFactory()
+ {
+ this.theASTNodeTypeClass = JDOQLAST.class;
+ this.theASTNodeType = this.theASTNodeTypeClass.getName();
+ }
+
+ /**
+ *
+ */
+ public AST create()
+ {
+ return new JDOQLAST();
+ }
+
+ /**
+ *
+ */
+ public AST create(AST tr)
+ {
+ return create((JDOQLAST)tr);
+ }
+
+ /**
+ *
+ */
+ public JDOQLAST create(JDOQLAST tr)
+ {
+ try {
+ return (tr==null) ? null : (JDOQLAST)tr.clone();
+ }
+ catch(CloneNotSupportedException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_UnexpectedExceptionClone"), ex); //NOI18N
+ }
+ }
+}
+
Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLC.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLC.java?rev=171353&view=auto
==============================================================================
--- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLC.java (added)
+++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/jdoqlc/JDOQLC.java Sun May 22 11:08:57 2005
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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
+ *
+ * http://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.
+ */
+
+/*
+ * JDOQLC.java
+ *
+ * Created on August 28, 2001
+ */
+
+package org.apache.jdo.impl.jdoql.jdoqlc;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Collection;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.impl.jdoql.scope.ParameterTable;
+import org.apache.jdo.impl.jdoql.scope.VariableTable;
+import org.apache.jdo.impl.jdoql.tree.Tree;
+import org.apache.jdo.jdoql.JDOQueryException;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+import antlr.TokenBuffer;
+import antlr.ANTLRException;
+
+/**
+ * This class controls the JDOQL compiler passes.
+ *
+ * @author Michael Bouschen
+ */
+public class JDOQLC
+{
+ /** The persistence manager of the query instance. */
+ protected PersistenceManagerInternal pm;
+
+ /** Type support. */
+ protected TypeSupport typeSupport;
+
+ /** Error message helper. */
+ protected ErrorMsg errorMsg;
+
+ /** The candidate class. */
+ protected Class candidateClass;
+
+ /** The AST representing the filter expression. */
+ protected JDOQLAST filterAST = null;
+
+ /** The AST representing the import declarations. */
+ protected JDOQLAST importsAST = null;
+
+ /** The AST representing the parameter declarations. */
+ protected JDOQLAST paramsAST = null;
+
+ /** The AST representing the variable declarations. */
+ protected JDOQLAST varsAST = null;
+
+ /** The AST representing the ordering specification. */
+ protected JDOQLAST orderingAST = null;
+
+ /** The complete query tree. */
+ protected JDOQLAST queryTree = null;
+
+ /** I18N support */
+ private final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.jdoql.Bundle", //NOI18N
+ JDOQLC.class.getClassLoader());
+
+ /** Logger */
+ private static Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.jdoql.jdoqlc"); //NOI18N
+
+ /**
+ *
+ */
+ public JDOQLC(PersistenceManagerInternal pm)
+ {
+ this.pm = pm;
+ this.typeSupport = new TypeSupport();
+ this.errorMsg = new ErrorMsg();
+ }
+
+ /**
+ *
+ */
+ public void setClass(Class candidateClass)
+ {
+ // Method semanticCheck checks for valid candidateClass
+ this.candidateClass = candidateClass;
+ }
+
+ /**
+ *
+ */
+ public void declareImports(String imports)
+ {
+ if (imports == null) {
+ importsAST = null;
+ return;
+ }
+
+ try {
+ JDOQLParser parser = createStringParser(imports);
+ parser.parseImports();
+ importsAST = (JDOQLAST)parser.getAST();
+ }
+ catch (ANTLRException ex) {
+ JDOQLLexer.handleANTLRException(ex, errorMsg);
+ }
+ }
+
+ /**
+ *
+ */
+ public void declareParameters(String parameters)
+ {
+ if (parameters == null) {
+ paramsAST = null;
+ return;
+ }
+
+ try {
+ JDOQLParser parser = createStringParser(parameters);
+ parser.parseParameters();
+ paramsAST = (JDOQLAST)parser.getAST();
+ }
+ catch (ANTLRException ex) {
+ JDOQLLexer.handleANTLRException(ex, errorMsg);
+ }
+ }
+
+ /**
+ *
+ */
+ public void declareVariables(String variables)
+ {
+ if (variables == null) {
+ varsAST = null;
+ return;
+ }
+
+ try {
+ JDOQLParser parser = createStringParser(variables);
+ parser.parseVariables();
+ varsAST = (JDOQLAST)parser.getAST();
+ }
+ catch (ANTLRException ex) {
+ JDOQLLexer.handleANTLRException(ex, errorMsg);
+ }
+ }
+
+ /**
+ *
+ */
+ public void setOrdering(String ordering)
+ {
+ if (ordering == null) {
+ orderingAST = null;
+ return;
+ }
+
+ try {
+ JDOQLParser parser = createStringParser(ordering);
+ parser.parseOrdering();
+ orderingAST = (JDOQLAST)parser.getAST();
+ }
+ catch (ANTLRException ex) {
+ JDOQLLexer.handleANTLRException(ex, errorMsg);
+ }
+ }
+
+ /**
+ *
+ */
+ public void setFilter(String filter)
+ {
+ if ((filter == null) || (filter.trim().length() == 0)) {
+ // If there is no filter specified use "true" as filter.
+ // This is the case if
+ // - setFilter is not called at all (filter == null)
+ // - the filter is empty or contians whitespecace only.
+ // Internally the filter has to be specified,
+ // otherwise semantic analysis has problems with empty AST.
+ filter = "true"; //NOI18N
+ }
+
+ try {
+ JDOQLParser parser = createStringParser(filter);
+ parser.parseFilter();
+ filterAST = (JDOQLAST)parser.getAST();
+ }
+ catch (ANTLRException ex) {
+ JDOQLLexer.handleANTLRException(ex, errorMsg);
+ }
+ }
+
+ /**
+ *
+ */
+ public void setQueryTree(JDOQLAST queryTree)
+ {
+ this.queryTree = queryTree;
+ }
+
+ /**
+ *
+ */
+ public JDOQLAST semanticCheck(ParameterTable paramtab, VariableTable vartab)
+ {
+ boolean trace = logger.isTraceEnabled();
+ ClassLoader applClassLoader = null;
+
+ Semantic semantic = new Semantic();
+ semantic.init(typeSupport, paramtab, vartab, errorMsg);
+ semantic.setASTFactory(JDOQLASTFactory.getInstance());
+
+ if (queryTree == null) {
+ // check candidate class
+ if (candidateClass == null) {
+ throw new JDOQueryException(
+ msg.msg("EXC_MissingCandidateClass")); //NOI18N
+ }
+ applClassLoader = candidateClass.getClassLoader();
+ // create complete tree representation
+ queryTree = semantic.createQueryTree(
+ candidateClass, importsAST, paramsAST,
+ varsAST, orderingAST, filterAST);
+ }
+ else {
+ Tree tree = (Tree)queryTree;
+ Class clazz = tree.getCandidateClass();
+ if (clazz != null)
+ applClassLoader = clazz.getClassLoader();
+ tree.initANTLRAST();
+ }
+
+ // set the candidateClass class loader
+ typeSupport.initApplicationJavaModel(applClassLoader);
+
+ if (trace)
+ logger.trace("AST\n" + queryTree.treeToString()); //NOI18N
+
+ try {
+ if (logger.isDebugEnabled())
+ logger.debug("Start semantic analysis"); //NOI18N
+ semantic.query(queryTree);
+ queryTree = (JDOQLAST)semantic.getAST();
+ if (trace)
+ logger.trace("Typed AST\n" + queryTree.treeToString()); //NOI18N
+ }
+ catch (ANTLRException ex) {
+ ex.printStackTrace();
+ errorMsg.fatal(
+ msg.msg("ERR_UnexpectedExceptionSemantic"), ex); //NOI18N
+ }
+ return queryTree;
+ }
+
+ /**
+ *
+ */
+ public JDOQLAST optimize(JDOQLAST tree)
+ {
+ // Do not include parameters into optimization => paramtab == null
+ return optimize(tree, null);
+ }
+
+ /**
+ *
+ */
+ public JDOQLAST optimize(JDOQLAST tree, ParameterTable paramtab)
+ {
+ Tree ast = null;
+ Optimizer optimizer= new Optimizer();
+ optimizer.init(pm, paramtab, errorMsg);
+ optimizer.setASTFactory(JDOQLASTFactory.getInstance());
+
+ try {
+ if (logger.isDebugEnabled())
+ logger.debug("START optimizer"); //NOI18N
+ optimizer.query(tree);
+ ast = (Tree)optimizer.getAST();
+ if (logger.isTraceEnabled())
+ logger.trace("Optimized AST\n" + queryTree.treeToString()); //NOI18N
+ }
+ catch (ANTLRException ex) {
+ ex.printStackTrace();
+ errorMsg.fatal(
+ msg.msg("ERR_UnexpectedExceptionOptimizer"), ex); //NOI18N
+ }
+ return ast;
+ }
+
+ //========= Internal helper methods ==========
+
+ /**
+ *
+ */
+ private JDOQLParser createStringParser(String text)
+ {
+ Reader in = new StringReader(text);
+ JDOQLLexer lexer = new JDOQLLexer(in);
+ lexer.init(errorMsg);
+ TokenBuffer buffer = new TokenBuffer(lexer);
+ JDOQLParser parser = new JDOQLParser(buffer);
+ parser.init(errorMsg);
+ parser.setASTFactory(JDOQLASTFactory.getInstance());
+ return parser;
+ }
+
+}