View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.jcr.query;
25  
26  import java.util.HashMap;
27  import java.util.Map;
28  import java.util.Set;
29  import javax.jcr.RepositoryException;
30  import javax.jcr.Value;
31  import javax.jcr.query.Query;
32  import javax.jcr.query.QueryResult;
33  import net.jcip.annotations.NotThreadSafe;
34  import org.modeshape.common.util.CheckArg;
35  import org.modeshape.common.util.StringUtil;
36  import org.modeshape.graph.property.Path;
37  import org.modeshape.graph.query.QueryResults;
38  import org.modeshape.graph.query.model.QueryCommand;
39  import org.modeshape.graph.query.parse.QueryParser;
40  import org.modeshape.graph.query.plan.PlanHints;
41  import org.modeshape.graph.query.validate.Schemata;
42  import org.modeshape.jcr.query.qom.JcrAbstractQuery;
43  import org.modeshape.jcr.query.qom.JcrLiteral;
44  
45  /**
46   * Implementation of {@link Query} that represents a {@link QueryCommand query command}.
47   */
48  @NotThreadSafe
49  public class JcrQuery extends JcrAbstractQuery {
50  
51      private QueryCommand query;
52      private final PlanHints hints;
53      private final Map<String, Object> variables;
54  
55      /**
56       * Creates a new JCR {@link Query} by specifying the query statement itself, the language in which the query is stated, the
57       * {@link QueryCommand} representation and, optionally, the node from which the query was loaded. The language must be a
58       * string from among those returned by {@code QueryManager#getSupportedQueryLanguages()}.
59       * 
60       * @param context the context that was used to create this query and that will be used to execute this query; may not be null
61       * @param statement the original statement as supplied by the client; may not be null
62       * @param language the language obtained from the {@link QueryParser}; may not be null
63       * @param query the parsed query representation; may not be null
64       * @param hints any hints that are to be used; may be null if there are no hints
65       * @param storedAtPath the path at which this query was stored, or null if this is not a stored query
66       */
67      public JcrQuery( JcrQueryContext context,
68                       String statement,
69                       String language,
70                       QueryCommand query,
71                       PlanHints hints,
72                       Path storedAtPath ) {
73          super(context, statement, language, storedAtPath);
74          assert query != null;
75          this.query = query;
76          this.hints = hints;
77          this.variables = new HashMap<String, Object>();
78      }
79  
80      protected QueryCommand query() {
81          return query;
82      }
83  
84      /**
85       * Get the underlying and immutable Abstract Query Model representation of this query.
86       * 
87       * @return the AQM representation; never null
88       */
89      public QueryCommand getAbstractQueryModel() {
90          return query;
91      }
92  
93      /**
94       * {@inheritDoc}
95       * 
96       * @see javax.jcr.query.Query#execute()
97       */
98      @SuppressWarnings( "deprecation" )
99      public QueryResult execute() throws RepositoryException {
100         context.isLive();
101         // Submit immediately to the workspace graph ...
102         Schemata schemata = context.getSchemata();
103         QueryResults result = context.execute(query, hints, variables);
104         checkForProblems(result.getProblems());
105         if (Query.XPATH.equals(language)) {
106             return new XPathQueryResult(context, statement, result, schemata);
107         } else if (Query.SQL.equals(language)) {
108             return new JcrSqlQueryResult(context, statement, result, schemata);
109         }
110         return new JcrQueryResult(context, statement, result, schemata);
111     }
112 
113     /**
114      * {@inheritDoc}
115      * 
116      * @see java.lang.Object#toString()
117      */
118     @Override
119     public String toString() {
120         return language + " -> " + statement + "\n" + StringUtil.createString(' ', Math.min(language.length() - 3, 0))
121                + "AQM -> " + query;
122     }
123 
124     /**
125      * {@inheritDoc}
126      * 
127      * @see javax.jcr.query.Query#bindValue(java.lang.String, javax.jcr.Value)
128      */
129     @Override
130     public void bindValue( String varName,
131                            Value value ) throws IllegalArgumentException, RepositoryException {
132         CheckArg.isNotNull(varName, "varName");
133         CheckArg.isNotNull(value, "value");
134         variables.put(varName, JcrLiteral.rawValue(value));
135     }
136 
137     /**
138      * {@inheritDoc}
139      * 
140      * @see javax.jcr.query.Query#getBindVariableNames()
141      */
142     @Override
143     public String[] getBindVariableNames() {
144         Set<String> keys = variables.keySet();
145         return keys.toArray(new String[keys.size()]);
146     }
147 
148     /**
149      * {@inheritDoc}
150      * 
151      * @see javax.jcr.query.Query#setLimit(long)
152      */
153     @Override
154     public void setLimit( long limit ) {
155         if (limit > Integer.MAX_VALUE) limit = Integer.MAX_VALUE;
156         query = query.withLimit((int)limit); // may not actually change if the limit matches the existing query
157     }
158 
159     /**
160      * {@inheritDoc}
161      * 
162      * @see javax.jcr.query.Query#setOffset(long)
163      */
164     @Override
165     public void setOffset( long offset ) {
166         if (offset > Integer.MAX_VALUE) offset = Integer.MAX_VALUE;
167         query = query.withOffset((int)offset); // may not actually change if the offset matches the existing query
168     }
169 }