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.Map;
27  import java.util.Set;
28  import javax.jcr.RepositoryException;
29  import javax.jcr.Value;
30  import javax.jcr.query.Query;
31  import javax.jcr.query.QueryResult;
32  import net.jcip.annotations.NotThreadSafe;
33  import org.modeshape.common.util.CheckArg;
34  import org.modeshape.common.util.StringUtil;
35  import org.modeshape.graph.property.Path;
36  import org.modeshape.graph.query.QueryResults;
37  import org.modeshape.graph.query.model.QueryCommand;
38  import org.modeshape.graph.query.parse.QueryParser;
39  import org.modeshape.graph.query.plan.PlanHints;
40  import org.modeshape.graph.query.validate.Schemata;
41  import org.modeshape.jcr.query.qom.JcrAbstractQuery;
42  import org.modeshape.jcr.query.qom.JcrLiteral;
43  
44  /**
45   * Implementation of {@link Query} that represents a {@link QueryCommand query command}.
46   */
47  @NotThreadSafe
48  public class JcrQuery extends JcrAbstractQuery {
49  
50      private QueryCommand query;
51      private final PlanHints hints;
52      private final Map<String, Object> variables;
53  
54      /**
55       * Creates a new JCR {@link Query} by specifying the query statement itself, the language in which the query is stated, the
56       * {@link QueryCommand} representation and, optionally, the node from which the query was loaded. The language must be a
57       * string from among those returned by {@code QueryManager#getSupportedQueryLanguages()}.
58       * 
59       * @param context the context that was used to create this query and that will be used to execute this query; may not be null
60       * @param statement the original statement as supplied by the client; may not be null
61       * @param language the language obtained from the {@link QueryParser}; may not be null
62       * @param query the parsed query representation; may not be null
63       * @param hints any hints that are to be used; may be null if there are no hints
64       * @param storedAtPath the path at which this query was stored, or null if this is not a stored query
65       */
66      public JcrQuery( JcrQueryContext context,
67                       String statement,
68                       String language,
69                       QueryCommand query,
70                       PlanHints hints,
71                       Path storedAtPath ) {
72          super(context, statement, language, storedAtPath);
73          assert query != null;
74          this.query = query;
75          this.hints = hints;
76          this.variables = null;
77      }
78  
79      protected QueryCommand query() {
80          return query;
81      }
82  
83      /**
84       * Get the underlying and immutable Abstract Query Model representation of this query.
85       * 
86       * @return the AQM representation; never null
87       */
88      public QueryCommand getAbstractQueryModel() {
89          return query;
90      }
91  
92      /**
93       * {@inheritDoc}
94       * 
95       * @see javax.jcr.query.Query#execute()
96       */
97      @SuppressWarnings( "deprecation" )
98      public QueryResult execute() throws RepositoryException {
99          context.isLive();
100         // Submit immediately to the workspace graph ...
101         Schemata schemata = context.getSchemata();
102         QueryResults result = context.execute(query, hints, variables);
103         checkForProblems(result.getProblems());
104         if (Query.XPATH.equals(language)) {
105             return new XPathQueryResult(context, statement, result, schemata);
106         } else if (Query.SQL.equals(language)) {
107             return new JcrSqlQueryResult(context, statement, result, schemata);
108         }
109         return new JcrQueryResult(context, statement, result, schemata);
110     }
111 
112     /**
113      * {@inheritDoc}
114      * 
115      * @see java.lang.Object#toString()
116      */
117     @Override
118     public String toString() {
119         return language + " -> " + statement + "\n" + StringUtil.createString(' ', Math.min(language.length() - 3, 0))
120                + "AQM -> " + query;
121     }
122 
123     /**
124      * {@inheritDoc}
125      * 
126      * @see javax.jcr.query.Query#bindValue(java.lang.String, javax.jcr.Value)
127      */
128     @Override
129     public void bindValue( String varName,
130                            Value value ) throws IllegalArgumentException, RepositoryException {
131         CheckArg.isNotNull(varName, "varName");
132         CheckArg.isNotNull(value, "value");
133         variables.put(varName, JcrLiteral.rawValue(value));
134     }
135 
136     /**
137      * {@inheritDoc}
138      * 
139      * @see javax.jcr.query.Query#getBindVariableNames()
140      */
141     @Override
142     public String[] getBindVariableNames() {
143         Set<String> keys = variables.keySet();
144         return keys.toArray(new String[keys.size()]);
145     }
146 
147     /**
148      * {@inheritDoc}
149      * 
150      * @see javax.jcr.query.Query#setLimit(long)
151      */
152     @Override
153     public void setLimit( long limit ) {
154         if (limit > Integer.MAX_VALUE) limit = Integer.MAX_VALUE;
155         query = query.withLimit((int)limit); // may not actually change if the limit matches the existing query
156     }
157 
158     /**
159      * {@inheritDoc}
160      * 
161      * @see javax.jcr.query.Query#setOffset(long)
162      */
163     @Override
164     public void setOffset( long offset ) {
165         if (offset > Integer.MAX_VALUE) offset = Integer.MAX_VALUE;
166         query = query.withOffset((int)offset); // may not actually change if the offset matches the existing query
167     }
168 }