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;
25
26 import java.math.BigDecimal;
27 import java.util.Comparator;
28 import java.util.Map;
29 import java.util.Set;
30 import javax.jcr.AccessDeniedException;
31 import javax.jcr.Node;
32 import javax.jcr.NodeIterator;
33 import javax.jcr.PropertyType;
34 import javax.jcr.RepositoryException;
35 import javax.jcr.Value;
36 import javax.jcr.ValueFactory;
37 import javax.jcr.query.InvalidQueryException;
38 import javax.jcr.query.Query;
39 import javax.jcr.query.QueryManager;
40 import javax.jcr.version.VersionException;
41 import net.jcip.annotations.Immutable;
42 import org.modeshape.common.text.ParsingException;
43 import org.modeshape.common.util.CheckArg;
44 import org.modeshape.graph.ExecutionContext;
45 import org.modeshape.graph.Location;
46 import org.modeshape.graph.property.Name;
47 import org.modeshape.graph.property.NamespaceRegistry;
48 import org.modeshape.graph.property.Path;
49 import org.modeshape.graph.property.ValueFactories;
50 import org.modeshape.graph.query.QueryResults;
51 import org.modeshape.graph.query.model.QueryCommand;
52 import org.modeshape.graph.query.model.TypeSystem;
53 import org.modeshape.graph.query.model.Visitors;
54 import org.modeshape.graph.query.parse.QueryParser;
55 import org.modeshape.graph.query.plan.PlanHints;
56 import org.modeshape.graph.query.validate.Schemata;
57 import org.modeshape.jcr.JcrRepository.QueryLanguage;
58 import org.modeshape.jcr.api.query.qom.QueryObjectModelFactory;
59 import org.modeshape.jcr.query.JcrQuery;
60 import org.modeshape.jcr.query.JcrQueryContext;
61 import org.modeshape.jcr.query.JcrSearch;
62 import org.modeshape.jcr.query.JcrTypeSystem;
63 import org.modeshape.jcr.query.qom.JcrQueryObjectModel;
64 import org.modeshape.jcr.query.qom.JcrQueryObjectModelFactory;
65 import org.modeshape.jcr.query.qom.JcrSelectQuery;
66 import org.modeshape.jcr.query.qom.JcrSetQuery;
67 import org.modeshape.jcr.query.qom.JcrSetQueryObjectModel;
68
69 /**
70 * Place-holder implementation of {@link QueryManager} interface.
71 */
72 @Immutable
73 class JcrQueryManager implements QueryManager {
74
75 public static final int MAXIMUM_RESULTS_FOR_FULL_TEXT_SEARCH_QUERIES = Integer.MAX_VALUE;
76
77 private final JcrSession session;
78 private final JcrQueryContext context;
79 private final JcrTypeSystem typeSystem;
80 private final QueryObjectModelFactory factory;
81
82 JcrQueryManager( JcrSession session ) {
83 this.session = session;
84 this.context = new SessionQueryContext(this.session);
85 this.typeSystem = new SessionTypeSystem(this.session);
86 this.factory = new JcrQueryObjectModelFactory(this.context);
87 }
88
89 /**
90 * {@inheritDoc}
91 *
92 * @see javax.jcr.query.QueryManager#getQOMFactory()
93 */
94 @Override
95 public javax.jcr.query.qom.QueryObjectModelFactory getQOMFactory() {
96 return factory;
97 }
98
99 /**
100 * {@inheritDoc}
101 *
102 * @see javax.jcr.query.QueryManager#createQuery(java.lang.String, java.lang.String)
103 */
104 public Query createQuery( String statement,
105 String language ) throws InvalidQueryException, RepositoryException {
106 CheckArg.isNotNull(statement, "statement");
107 CheckArg.isNotNull(language, "language");
108 return createQuery(statement, language, null);
109 }
110
111 /**
112 * Creates a new JCR {@link Query} by specifying the query expression itself, the language in which the query is stated, the
113 * {@link QueryCommand} representation and, optionally, the node from which the query was loaded. The language must be a
114 * string from among those returned by {@code QueryManager#getSupportedQueryLanguages()}.
115 *
116 * @param expression the original query expression as supplied by the client; may not be null
117 * @param language the language in which the expression is represented; may not be null
118 * @param storedAtPath the path at which this query was stored, or null if this is not a stored query
119 * @return query the JCR query object; never null
120 * @throws InvalidQueryException if expression is invalid or language is unsupported
121 * @throws RepositoryException if the session is no longer live
122 */
123 @SuppressWarnings( "deprecation" )
124 public Query createQuery( String expression,
125 String language,
126 Path storedAtPath ) throws InvalidQueryException, RepositoryException {
127 session.checkLive();
128 // Look for a parser for the specified language ...
129 QueryParser parser = session.repository().queryParsers().getParserFor(language);
130 if (parser == null) {
131 Set<String> languages = session.repository().queryParsers().getLanguages();
132 throw new InvalidQueryException(JcrI18n.invalidQueryLanguage.text(language, languages));
133 }
134 if (parser.getLanguage().equals(FullTextSearchParser.LANGUAGE)) {
135 // This is a full-text search ...
136 return new JcrSearch(this.context, expression, parser.getLanguage(), storedAtPath);
137 }
138 try {
139 // Parsing must be done now ...
140 QueryCommand command = parser.parseQuery(expression, typeSystem);
141 if (command == null) {
142 // The query is not well-formed and cannot be parsed ...
143 throw new InvalidQueryException(JcrI18n.queryCannotBeParsedUsingLanguage.text(language, expression));
144 }
145 PlanHints hints = new PlanHints();
146 hints.showPlan = true;
147 hints.hasFullTextSearch = true; // always include the score
148 if (Query.XPATH.equals(language)) {
149 hints.validateColumnExistance = false;
150 }
151 return resultWith(expression, parser.getLanguage(), command, hints, storedAtPath);
152 } catch (ParsingException e) {
153 // The query is not well-formed and cannot be parsed ...
154 String reason = e.getMessage();
155 throw new InvalidQueryException(JcrI18n.queryCannotBeParsedUsingLanguage.text(language, expression, reason));
156 } catch (org.modeshape.graph.query.parse.InvalidQueryException e) {
157 // The query was parsed, but there is an error in the query
158 String reason = e.getMessage();
159 throw new InvalidQueryException(JcrI18n.queryInLanguageIsNotValid.text(language, expression, reason));
160 }
161 }
162
163 /**
164 * Creates a new JCR {@link Query} by specifying the query expression itself, the language in which the query is stated, the
165 * {@link QueryCommand} representation. This method is more efficient than {@link #createQuery(String, String, Path)} if the
166 * QueryCommand is created directly.
167 *
168 * @param command the query command; may not be null
169 * @return query the JCR query object; never null
170 * @throws InvalidQueryException if expression is invalid or language is unsupported
171 * @throws RepositoryException if the session is no longer live
172 */
173 public Query createQuery( QueryCommand command ) throws InvalidQueryException, RepositoryException {
174 session.checkLive();
175 if (command == null) {
176 // The query is not well-formed and cannot be parsed ...
177 throw new InvalidQueryException(JcrI18n.queryInLanguageIsNotValid.text(QueryLanguage.JCR_SQL2, command));
178 }
179 // Produce the expression string ...
180 String expression = Visitors.readable(command);
181 try {
182 // Parsing must be done now ...
183 PlanHints hints = new PlanHints();
184 hints.showPlan = true;
185 hints.hasFullTextSearch = true; // always include the score
186 return resultWith(expression, QueryLanguage.JCR_SQL2, command, hints, null);
187 } catch (org.modeshape.graph.query.parse.InvalidQueryException e) {
188 // The query was parsed, but there is an error in the query
189 String reason = e.getMessage();
190 throw new InvalidQueryException(JcrI18n.queryInLanguageIsNotValid.text(QueryLanguage.JCR_SQL2, expression, reason));
191 }
192 }
193
194 /**
195 * {@inheritDoc}
196 *
197 * @see javax.jcr.query.QueryManager#getQuery(javax.jcr.Node)
198 */
199 public Query getQuery( Node node ) throws InvalidQueryException, RepositoryException {
200 AbstractJcrNode jcrNode = CheckArg.getInstanceOf(node, AbstractJcrNode.class, "node");
201
202 // Check the type of the node ...
203 JcrNodeType nodeType = jcrNode.getPrimaryNodeType();
204 if (!nodeType.getInternalName().equals(JcrNtLexicon.QUERY)) {
205 NamespaceRegistry registry = session.getExecutionContext().getNamespaceRegistry();
206 throw new InvalidQueryException(JcrI18n.notStoredQuery.text(jcrNode.path().getString(registry)));
207 }
208
209 // These are both mandatory properties for nodes of nt:query
210 String statement = jcrNode.getProperty(JcrLexicon.STATEMENT).getString();
211 String language = jcrNode.getProperty(JcrLexicon.LANGUAGE).getString();
212
213 return createQuery(statement, language, jcrNode.path());
214 }
215
216 /**
217 * {@inheritDoc}
218 *
219 * @see javax.jcr.query.QueryManager#getSupportedQueryLanguages()
220 */
221 public String[] getSupportedQueryLanguages() {
222 // Make a defensive copy ...
223 Set<String> languages = session.repository().queryParsers().getLanguages();
224 return languages.toArray(new String[languages.size()]);
225 }
226
227 protected Query resultWith( String expression,
228 String language,
229 QueryCommand command,
230 PlanHints hints,
231 Path storedAtPath ) {
232 if (command instanceof JcrSelectQuery) {
233 JcrSelectQuery query = (JcrSelectQuery)command;
234 return new JcrQueryObjectModel(context, expression, language, query, hints, storedAtPath);
235 }
236 if (command instanceof JcrSetQuery) {
237 JcrSetQuery query = (JcrSetQuery)command;
238 return new JcrSetQueryObjectModel(this.context, expression, language, query, hints, storedAtPath);
239 }
240 return new JcrQuery(context, expression, language, command, hints, storedAtPath);
241 }
242
243 // protected void checkForProblems( Problems problems ) throws RepositoryException {
244 // if (problems.hasErrors()) {
245 // // Build a message with the problems ...
246 // StringBuilder msg = new StringBuilder();
247 // for (Problem problem : problems) {
248 // if (problem.getStatus() != Status.ERROR) continue;
249 // msg.append(problem.getMessageString()).append("\n");
250 // }
251 // throw new RepositoryException(msg.toString());
252 // }
253 // }
254 //
255 // @NotThreadSafe
256 // protected static abstract class AbstractQuery implements Query {
257 // protected final JcrSession session;
258 // protected final String language;
259 // protected final String statement;
260 // private Path storedAtPath;
261 //
262 // /**
263 // * Creates a new JCR {@link Query} by specifying the query statement itself, the language in which the query is stated,
264 // * the {@link QueryCommand} representation and, optionally, the node from which the query was loaded. The language must be
265 // * a string from among those returned by {@code QueryManager#getSupportedQueryLanguages()}.
266 // *
267 // * @param session the session that was used to create this query and that will be used to execute this query; may not be
268 // * null
269 // * @param statement the original statement as supplied by the client; may not be null
270 // * @param language the language obtained from the {@link QueryParser}; may not be null
271 // * @param storedAtPath the path at which this query was stored, or null if this is not a stored query
272 // */
273 // protected AbstractQuery( JcrSession session,
274 // String statement,
275 // String language,
276 // Path storedAtPath ) {
277 // assert session != null;
278 // assert statement != null;
279 // assert language != null;
280 // this.session = session;
281 // this.language = language;
282 // this.statement = statement;
283 // this.storedAtPath = storedAtPath;
284 // }
285 //
286 // protected final JcrSession session() {
287 // return this.session;
288 // }
289 //
290 // /**
291 // * {@inheritDoc}
292 // *
293 // * @see javax.jcr.query.Query#getLanguage()
294 // */
295 // public String getLanguage() {
296 // return language;
297 // }
298 //
299 // /**
300 // * {@inheritDoc}
301 // *
302 // * @see javax.jcr.query.Query#getStatement()
303 // */
304 // public String getStatement() {
305 // return statement;
306 // }
307 //
308 // /**
309 // * {@inheritDoc}
310 // *
311 // * @see javax.jcr.query.Query#getStoredQueryPath()
312 // */
313 // public String getStoredQueryPath() throws ItemNotFoundException {
314 // if (storedAtPath == null) {
315 // throw new ItemNotFoundException(JcrI18n.notStoredQuery.text());
316 // }
317 // return storedAtPath.getString(session.getExecutionContext().getNamespaceRegistry());
318 // }
319 //
320 // /**
321 // * {@inheritDoc}
322 // *
323 // * @see javax.jcr.query.Query#storeAsNode(java.lang.String)
324 // */
325 // public Node storeAsNode( String absPath ) throws PathNotFoundException, ConstraintViolationException, RepositoryException {
326 // session.checkLive();
327 // NamespaceRegistry namespaces = this.session.namespaces();
328 //
329 // Path path;
330 // try {
331 // path = session.getExecutionContext().getValueFactories().getPathFactory().create(absPath);
332 // } catch (IllegalArgumentException iae) {
333 // throw new RepositoryException(JcrI18n.invalidPathParameter.text("absPath", absPath));
334 // }
335 // Path parentPath = path.getParent();
336 //
337 // Node parentNode = session.getNode(parentPath);
338 //
339 // if (!parentNode.isCheckedOut()) {
340 // throw new VersionException(JcrI18n.nodeIsCheckedIn.text(parentNode.getPath()));
341 // }
342 //
343 // Node queryNode = parentNode.addNode(path.relativeTo(parentPath).getString(namespaces),
344 // JcrNtLexicon.QUERY.getString(namespaces));
345 //
346 // queryNode.setProperty(JcrLexicon.LANGUAGE.getString(namespaces), this.language);
347 // queryNode.setProperty(JcrLexicon.STATEMENT.getString(namespaces), this.statement);
348 //
349 // this.storedAtPath = path;
350 //
351 // return queryNode;
352 // }
353 //
354 // protected void checkForProblems( Problems problems ) throws RepositoryException {
355 // if (problems.hasErrors()) {
356 // // Build a message with the problems ...
357 // StringBuilder msg = new StringBuilder();
358 // for (Problem problem : problems) {
359 // if (problem.getStatus() != Status.ERROR) continue;
360 // msg.append(problem.getMessageString()).append("\n");
361 // }
362 // throw new RepositoryException(msg.toString());
363 // }
364 // }
365 // }
366 //
367 // /**
368 // * Implementation of {@link Query} that represents a {@link QueryCommand} query.
369 // */
370 // @NotThreadSafe
371 // protected static class JcrQuery extends AbstractQuery {
372 // private final QueryCommand query;
373 // private final PlanHints hints;
374 // private final Map<String, Object> variables;
375 //
376 // /**
377 // * Creates a new JCR {@link Query} by specifying the query statement itself, the language in which the query is stated,
378 // * the {@link QueryCommand} representation and, optionally, the node from which the query was loaded. The language must be
379 // * a string from among those returned by {@code QueryManager#getSupportedQueryLanguages()}.
380 // *
381 // * @param session the session that was used to create this query and that will be used to execute this query; may not be
382 // * null
383 // * @param statement the original statement as supplied by the client; may not be null
384 // * @param language the language obtained from the {@link QueryParser}; may not be null
385 // * @param query the parsed query representation; may not be null
386 // * @param hints any hints that are to be used; may be null if there are no hints
387 // * @param storedAtPath the path at which this query was stored, or null if this is not a stored query
388 // */
389 // protected JcrQuery( JcrSession session,
390 // String statement,
391 // String language,
392 // QueryCommand query,
393 // PlanHints hints,
394 // Path storedAtPath ) {
395 // super(session, statement, language, storedAtPath);
396 // assert query != null;
397 // this.query = query;
398 // this.hints = hints;
399 // this.variables = null;
400 // }
401 //
402 // /**
403 // * Get the underlying and immutable Abstract Query Model representation of this query.
404 // *
405 // * @return the AQM representation; never null
406 // */
407 // public QueryCommand getAbstractQueryModel() {
408 // return query;
409 // }
410 //
411 // /**
412 // * {@inheritDoc}
413 // *
414 // * @see javax.jcr.query.Query#execute()
415 // */
416 // public QueryResult execute() throws RepositoryException {
417 // session.checkLive();
418 // // Submit immediately to the workspace graph ...
419 // Schemata schemata = session.workspace().nodeTypeManager().schemata();
420 // QueryResults result = session.repository().queryManager().query(session.workspace().getName(),
421 // query,
422 // schemata,
423 // hints,
424 // variables);
425 // checkForProblems(result.getProblems());
426 // if (Query.XPATH.equals(language)) {
427 // return new XPathQueryResult(session, statement, result, schemata);
428 // } else if (Query.SQL.equals(language)) {
429 // return new JcrSqlQueryResult(session, statement, result, schemata);
430 // }
431 // return new JcrQueryResult(session, statement, result, schemata);
432 // }
433 //
434 // /**
435 // * {@inheritDoc}
436 // *
437 // * @see java.lang.Object#toString()
438 // */
439 // @Override
440 // public String toString() {
441 // return language + " -> " + statement + "\n" + StringUtil.createString(' ', Math.min(language.length() - 3, 0))
442 // + "AQM -> " + query;
443 // }
444 //
445 // @Override
446 // public void bindValue( String varName,
447 // Value value ) throws IllegalArgumentException, RepositoryException {
448 // throw new UnsupportedRepositoryOperationException();
449 // }
450 //
451 // @Override
452 // public String[] getBindVariableNames() throws RepositoryException {
453 // throw new UnsupportedRepositoryOperationException();
454 // }
455 //
456 // @Override
457 // public void setLimit( long limit ) {
458 // throw new IllegalStateException();
459 // }
460 //
461 // @Override
462 // public void setOffset( long offset ) {
463 // throw new IllegalStateException();
464 // }
465 // }
466 //
467 // @NotThreadSafe
468 // protected static class JcrSearch extends AbstractQuery {
469 //
470 // /**
471 // * Creates a new JCR {@link Query} by specifying the query statement itself, the language in which the query is stated,
472 // * the {@link QueryCommand} representation and, optionally, the node from which the query was loaded. The language must be
473 // * a string from among those returned by {@code QueryManager#getSupportedQueryLanguages()}.
474 // *
475 // * @param session the session that was used to create this query and that will be used to execute this query; may not be
476 // * null
477 // * @param statement the original statement as supplied by the client; may not be null
478 // * @param language the language obtained from the {@link QueryParser}; may not be null
479 // * @param storedAtPath the path at which this query was stored, or null if this is not a stored query
480 // */
481 // protected JcrSearch( JcrSession session,
482 // String statement,
483 // String language,
484 // Path storedAtPath ) {
485 // super(session, statement, language, storedAtPath);
486 // }
487 //
488 // /**
489 // * {@inheritDoc}
490 // *
491 // * @see javax.jcr.query.Query#execute()
492 // */
493 // public QueryResult execute() throws RepositoryException {
494 // // Submit immediately to the workspace graph ...
495 // Schemata schemata = session.workspace().nodeTypeManager().schemata();
496 // QueryResults result = session.repository().queryManager().search(session.workspace().getName(),
497 // statement,
498 // MAXIMUM_RESULTS_FOR_FULL_TEXT_SEARCH_QUERIES,
499 // 0);
500 // checkForProblems(result.getProblems());
501 // return new JcrQueryResult(session, statement, result, schemata);
502 // }
503 //
504 // /**
505 // * {@inheritDoc}
506 // *
507 // * @see java.lang.Object#toString()
508 // */
509 // @Override
510 // public String toString() {
511 // return language + " -> " + statement;
512 // }
513 //
514 // @Override
515 // public void bindValue( String varName,
516 // Value value ) throws IllegalArgumentException, RepositoryException {
517 // throw new UnsupportedRepositoryOperationException();
518 // }
519 //
520 // @Override
521 // public String[] getBindVariableNames() throws RepositoryException {
522 // throw new UnsupportedRepositoryOperationException();
523 // }
524 //
525 // @Override
526 // public void setLimit( long limit ) {
527 // throw new IllegalStateException();
528 // }
529 //
530 // @Override
531 // public void setOffset( long offset ) {
532 // throw new IllegalStateException();
533 // }
534 // }
535 //
536 // protected static final String JCR_SCORE_COLUMN_NAME = "jcr:score";
537 // protected static final String JCR_PATH_COLUMN_NAME = "jcr:path";
538 //
539 // /**
540 // * The results of a query. This is not thread-safe because it relies upon JcrSession, which is not thread-safe. Also,
541 // although
542 // * the results of a query never change, the objects returned by the iterators may vary if the session information changes.
543 // */
544 // @NotThreadSafe
545 // public static class JcrQueryResult implements QueryResult, org.modeshape.jcr.api.query.QueryResult {
546 // protected final JcrSession session;
547 // protected final QueryResults results;
548 // protected final Schemata schemata;
549 // protected final String queryStatement;
550 // private List<String> columnTypes;
551 // private List<String> columnTables;
552 //
553 // protected JcrQueryResult( JcrSession session,
554 // String query,
555 // QueryResults graphResults,
556 // Schemata schemata ) {
557 // this.session = session;
558 // this.results = graphResults;
559 // this.schemata = schemata;
560 // this.queryStatement = query;
561 // assert this.session != null;
562 // assert this.results != null;
563 // assert this.schemata != null;
564 // assert this.queryStatement != null;
565 // }
566 //
567 // protected QueryResults results() {
568 // return results;
569 // }
570 //
571 // public List<String> getColumnNameList() {
572 // return results.getColumns().getColumnNames();
573 // }
574 //
575 // /**
576 // * {@inheritDoc}
577 // *
578 // * @see javax.jcr.query.QueryResult#getColumnNames()
579 // */
580 // public String[] getColumnNames() /*throws RepositoryException*/{
581 // List<String> names = getColumnNameList();
582 // return names.toArray(new String[names.size()]); // make a defensive copy ...
583 // }
584 //
585 // /**
586 // * {@inheritDoc}
587 // *
588 // * @see org.modeshape.jcr.api.query.QueryResult#getColumnTypes()
589 // */
590 // @Override
591 // public String[] getColumnTypes() {
592 // if (columnTypes == null) {
593 // // Discover the types ...
594 // columnTypes = loadColumnTypes(results.getColumns());
595 // }
596 // return columnTypes.toArray(new String[columnTypes.size()]);
597 // }
598 //
599 // protected List<String> loadColumnTypes( Columns columns ) {
600 // List<String> types = new ArrayList<String>(columns.getColumnCount());
601 // for (Column column : columns) {
602 // String typeName = null;
603 // Table table = schemata.getTable(column.selectorName());
604 // if (table != null) {
605 // Schemata.Column typedColumn = table.getColumn(column.propertyName());
606 // typeName = typedColumn.getPropertyType();
607 // }
608 // if (typeName == null) {
609 // // Might be fabricated column, so just assume string ...
610 // typeName = PropertyType.nameFromValue(PropertyType.STRING);
611 // }
612 // types.add(typeName);
613 // }
614 //
615 // return types;
616 // }
617 //
618 // /**
619 // * {@inheritDoc}
620 // *
621 // * @see org.modeshape.jcr.api.query.QueryResult#getSelectorNames()
622 // */
623 // @Override
624 // public String[] getSelectorNames() {
625 // if (columnTables == null) {
626 // // Discover the types ...
627 // Columns columns = results.getColumns();
628 // List<String> tables = new ArrayList<String>(columns.getColumnCount());
629 // for (Column column : columns) {
630 // String tableName = "";
631 // Table table = schemata.getTable(column.selectorName());
632 // if (table != null) tableName = table.getName().name();
633 // tables.add(tableName);
634 // }
635 // columnTables = tables;
636 // }
637 // return columnTables.toArray(new String[columnTables.size()]);
638 // }
639 //
640 // /**
641 // * {@inheritDoc}
642 // *
643 // * @see javax.jcr.query.QueryResult#getNodes()
644 // */
645 // public NodeIterator getNodes() throws RepositoryException {
646 // // Find all of the nodes in the results. We have to do this pre-emptively, since this
647 // // is the only method to throw RepositoryException ...
648 // final int numRows = results.getRowCount();
649 // if (numRows == 0) return new JcrEmptyNodeIterator();
650 //
651 // final List<AbstractJcrNode> nodes = new ArrayList<AbstractJcrNode>(numRows);
652 // final String selectorName = results.getColumns().getSelectorNames().get(0);
653 // final int locationIndex = results.getColumns().getLocationIndex(selectorName);
654 // for (Object[] tuple : results.getTuples()) {
655 // Location location = (Location)tuple[locationIndex];
656 // if (!session.wasRemovedInSession(location)) {
657 // nodes.add(session.getNode(location.getPath()));
658 // }
659 // }
660 // return new QueryResultNodeIterator(nodes);
661 // }
662 //
663 // /**
664 // * {@inheritDoc}
665 // *
666 // * @see javax.jcr.query.QueryResult#getRows()
667 // */
668 // public RowIterator getRows() /*throws RepositoryException*/{
669 // // We can actually delay the loading of the nodes until the rows are accessed ...
670 // final int numRows = results.getRowCount();
671 // final List<Object[]> tuples = results.getTuples();
672 // if (results.getColumns().getLocationCount() == 1) {
673 // return new SingleSelectorQueryResultRowIterator(session, queryStatement, results, tuples.iterator(), numRows);
674 // }
675 // return new QueryResultRowIterator(session, queryStatement, results, tuples.iterator(), numRows);
676 // }
677 //
678 // /**
679 // * Get a description of the query plan, if requested.
680 // *
681 // * @return the query plan, or null if the plan was not requested
682 // */
683 // public String getPlan() {
684 // return results.getPlan();
685 // }
686 //
687 // /**
688 // * {@inheritDoc}
689 // *
690 // * @see java.lang.Object#toString()
691 // */
692 // @Override
693 // public String toString() {
694 // return results.toString();
695 // }
696 // }
697 //
698 // /**
699 // * The {@link NodeIterator} implementation returned by the {@link JcrQueryResult}.
700 // *
701 // * @see JcrQueryResult#getNodes()
702 // */
703 // @NotThreadSafe
704 // protected static class QueryResultNodeIterator implements NodeIterator {
705 // private final Iterator<? extends Node> nodes;
706 // private final int size;
707 // private long position = 0L;
708 //
709 // protected QueryResultNodeIterator( List<? extends Node> nodes ) {
710 // this.nodes = nodes.iterator();
711 // this.size = nodes.size();
712 // }
713 //
714 // /**
715 // * {@inheritDoc}
716 // *
717 // * @see javax.jcr.NodeIterator#nextNode()
718 // */
719 // public Node nextNode() {
720 // Node node = nodes.next();
721 // ++position;
722 // return node;
723 // }
724 //
725 // /**
726 // * {@inheritDoc}
727 // *
728 // * @see javax.jcr.RangeIterator#getPosition()
729 // */
730 // public long getPosition() {
731 // return position;
732 // }
733 //
734 // /**
735 // * {@inheritDoc}
736 // *
737 // * @see javax.jcr.RangeIterator#getSize()
738 // */
739 // public long getSize() {
740 // return size;
741 // }
742 //
743 // /**
744 // * {@inheritDoc}
745 // *
746 // * @see javax.jcr.RangeIterator#skip(long)
747 // */
748 // public void skip( long skipNum ) {
749 // for (long i = 0L; i != skipNum; ++i)
750 // nextNode();
751 // }
752 //
753 // /**
754 // * {@inheritDoc}
755 // *
756 // * @see java.util.Iterator#hasNext()
757 // */
758 // public boolean hasNext() {
759 // return nodes.hasNext();
760 // }
761 //
762 // /**
763 // * {@inheritDoc}
764 // *
765 // * @see java.util.Iterator#next()
766 // */
767 // public Object next() {
768 // return nextNode();
769 // }
770 //
771 // /**
772 // * {@inheritDoc}
773 // *
774 // * @see java.util.Iterator#remove()
775 // */
776 // public void remove() {
777 // throw new UnsupportedOperationException();
778 // }
779 // }
780 //
781 // /**
782 // * The {@link RowIterator} implementation returned by the {@link JcrQueryResult}.
783 // *
784 // * @see JcrQueryResult#getRows()
785 // */
786 // @NotThreadSafe
787 // protected static class QueryResultRowIterator implements RowIterator {
788 // protected final List<String> columnNames;
789 // private final Iterator<Object[]> tuples;
790 // private final Set<String> selectorNames;
791 // protected final JcrSession session;
792 // protected final Columns columns;
793 // protected final String query;
794 // private int[] locationIndexes;
795 // private long position = 0L;
796 // private long numRows;
797 // private Row nextRow;
798 //
799 // protected QueryResultRowIterator( JcrSession session,
800 // String query,
801 // QueryResults results,
802 // Iterator<Object[]> tuples,
803 // long numRows ) {
804 // this.tuples = tuples;
805 // this.query = query;
806 // this.columns = results.getColumns();
807 // this.columnNames = this.columns.getColumnNames();
808 // this.session = session;
809 // this.numRows = numRows;
810 // this.selectorNames = new HashSet<String>(columns.getSelectorNames());
811 // int i = 0;
812 // locationIndexes = new int[selectorNames.size()];
813 // for (String selectorName : selectorNames) {
814 // locationIndexes[i++] = columns.getLocationIndex(selectorName);
815 // }
816 // }
817 //
818 // public boolean hasSelector( String selectorName ) {
819 // return this.selectorNames.contains(selectorName);
820 // }
821 //
822 // /**
823 // * {@inheritDoc}
824 // *
825 // * @see javax.jcr.query.RowIterator#nextRow()
826 // */
827 // public Row nextRow() {
828 // if (nextRow == null) {
829 // // Didn't call 'hasNext()' ...
830 // if (!hasNext()) {
831 // throw new NoSuchElementException();
832 // }
833 // }
834 // assert nextRow != null;
835 // Row result = nextRow;
836 // nextRow = null;
837 // return result;
838 // }
839 //
840 // /**
841 // * {@inheritDoc}
842 // *
843 // * @see javax.jcr.RangeIterator#getPosition()
844 // */
845 // public long getPosition() {
846 // return position;
847 // }
848 //
849 // /**
850 // * {@inheritDoc}
851 // *
852 // * @see javax.jcr.RangeIterator#getSize()
853 // */
854 // public long getSize() {
855 // return numRows;
856 // }
857 //
858 // /**
859 // * {@inheritDoc}
860 // *
861 // * @see javax.jcr.RangeIterator#skip(long)
862 // */
863 // public void skip( long skipNum ) {
864 // for (long i = 0L; i != skipNum; ++i) {
865 // tuples.next();
866 // }
867 // position += skipNum;
868 // }
869 //
870 // /**
871 // * {@inheritDoc}
872 // *
873 // * @see java.util.Iterator#hasNext()
874 // */
875 // public boolean hasNext() {
876 // if (nextRow != null) {
877 // return true;
878 // }
879 // while (tuples.hasNext()) {
880 // final Object[] tuple = tuples.next();
881 // ++position;
882 // try {
883 // // Get the next row ...
884 // nextRow = getNextRow(tuple);
885 // if (nextRow != null) return true;
886 // } catch (RepositoryException e) {
887 // // The node could not be found in this session, so skip it ...
888 // }
889 // --numRows;
890 // }
891 // return false;
892 // }
893 //
894 // protected Row getNextRow( Object[] tuple ) throws RepositoryException {
895 // // Make sure that each node referenced by the tuple exists and is accessible ...
896 // Node[] nodes = new Node[locationIndexes.length];
897 // int index = 0;
898 // for (int locationIndex : locationIndexes) {
899 // Location location = (Location)tuple[locationIndex];
900 // if (session.wasRemovedInSession(location)) {
901 // // Skip this record because one of the nodes no longer exists ...
902 // return null;
903 // }
904 // try {
905 // nodes[index++] = session.getNode(location.getPath());
906 // } catch (AccessDeniedException e) {
907 // // No access to this node, so skip the record ...
908 // return null;
909 // }
910 // }
911 // return new MultiSelectorQueryResultRow(this, nodes, locationIndexes, tuple);
912 // }
913 //
914 // /**
915 // * {@inheritDoc}
916 // *
917 // * @see java.util.Iterator#next()
918 // */
919 // public Object next() {
920 // return nextRow();
921 // }
922 //
923 // /**
924 // * {@inheritDoc}
925 // *
926 // * @see java.util.Iterator#remove()
927 // */
928 // public void remove() {
929 // throw new UnsupportedOperationException();
930 // }
931 // }
932 //
933 // /**
934 // * The {@link RowIterator} implementation returned by the {@link JcrQueryResult}.
935 // *
936 // * @see JcrQueryResult#getRows()
937 // */
938 // @NotThreadSafe
939 // protected static class SingleSelectorQueryResultRowIterator extends QueryResultRowIterator {
940 // protected final int locationIndex;
941 // protected final int scoreIndex;
942 //
943 // protected SingleSelectorQueryResultRowIterator( JcrSession session,
944 // String query,
945 // QueryResults results,
946 // Iterator<Object[]> tuples,
947 // long numRows ) {
948 // super(session, query, results, tuples, numRows);
949 // String selectorName = columns.getSelectorNames().get(0);
950 // locationIndex = columns.getLocationIndex(selectorName);
951 // scoreIndex = columns.getFullTextSearchScoreIndexFor(selectorName);
952 // }
953 //
954 // /**
955 // * {@inheritDoc}
956 // *
957 // * @see org.modeshape.jcr.JcrQueryManager.QueryResultRowIterator#getNextRow(java.lang.Object[])
958 // */
959 // @Override
960 // protected Row getNextRow( Object[] tuple ) throws RepositoryException {
961 // Location location = (Location)tuple[locationIndex];
962 // if (!session.wasRemovedInSession(location)) {
963 // Node node = session.getNode(location.getPath());
964 // return createRow(node, tuple);
965 // }
966 // return null;
967 // }
968 //
969 // protected Row createRow( Node node,
970 // Object[] tuple ) {
971 // return new SingleSelectorQueryResultRow(this, node, tuple);
972 // }
973 // }
974 //
975 // protected static class SingleSelectorQueryResultRow implements Row, org.modeshape.jcr.api.query.Row {
976 // protected final SingleSelectorQueryResultRowIterator iterator;
977 // protected final Node node;
978 // protected final Object[] tuple;
979 // private Value[] values = null;
980 //
981 // protected SingleSelectorQueryResultRow( SingleSelectorQueryResultRowIterator iterator,
982 // Node node,
983 // Object[] tuple ) {
984 // this.iterator = iterator;
985 // this.node = node;
986 // this.tuple = tuple;
987 // assert this.iterator != null;
988 // assert this.node != null;
989 // assert this.tuple != null;
990 // }
991 //
992 // /**
993 // * {@inheritDoc}
994 // *
995 // * @see org.modeshape.jcr.api.query.Row#getNode(java.lang.String)
996 // */
997 // @Override
998 // public Node getNode( String selectorName ) throws RepositoryException {
999 // if (iterator.hasSelector(selectorName)) {
1000 // throw new RepositoryException(JcrI18n.selectorNotUsedInQuery.text(selectorName, iterator.query));
1001 // }
1002 // return node;
1003 // }
1004 //
1005 // /**
1006 // * {@inheritDoc}
1007 // *
1008 // * @see javax.jcr.query.Row#getValue(java.lang.String)
1009 // */
1010 // public Value getValue( String columnName ) throws ItemNotFoundException, RepositoryException {
1011 // return node.getProperty(columnName).getValue();
1012 // }
1013 //
1014 // /**
1015 // * {@inheritDoc}
1016 // *
1017 // * @see javax.jcr.query.Row#getValues()
1018 // */
1019 // public Value[] getValues() throws RepositoryException {
1020 // if (values == null) {
1021 // int i = 0;
1022 // values = new Value[iterator.columnNames.size()];
1023 // for (String columnName : iterator.columnNames) {
1024 // values[i++] = getValue(columnName);
1025 // }
1026 // }
1027 // return values;
1028 // }
1029 //
1030 // @Override
1031 // public Node getNode() throws RepositoryException {
1032 // throw new UnsupportedRepositoryOperationException();
1033 // }
1034 //
1035 // @Override
1036 // public String getPath() throws RepositoryException {
1037 // throw new UnsupportedRepositoryOperationException();
1038 // }
1039 //
1040 // @Override
1041 // public String getPath( String selectorName ) throws RepositoryException {
1042 // throw new UnsupportedRepositoryOperationException();
1043 // }
1044 //
1045 // @Override
1046 // public double getScore() throws RepositoryException {
1047 // throw new UnsupportedRepositoryOperationException();
1048 // }
1049 //
1050 // @Override
1051 // public double getScore( String selectorName ) throws RepositoryException {
1052 // throw new UnsupportedRepositoryOperationException();
1053 // }
1054 // }
1055 //
1056 // protected static class MultiSelectorQueryResultRow implements Row, org.modeshape.jcr.api.query.Row {
1057 // protected final QueryResultRowIterator iterator;
1058 // protected final Object[] tuple;
1059 // private Value[] values = null;
1060 // private Node[] nodes;
1061 // private int[] locationIndexes;
1062 //
1063 // protected MultiSelectorQueryResultRow( QueryResultRowIterator iterator,
1064 // Node[] nodes,
1065 // int[] locationIndexes,
1066 // Object[] tuple ) {
1067 // this.iterator = iterator;
1068 // this.tuple = tuple;
1069 // this.nodes = nodes;
1070 // this.locationIndexes = locationIndexes;
1071 // assert this.iterator != null;
1072 // assert this.tuple != null;
1073 // }
1074 //
1075 // /**
1076 // * {@inheritDoc}
1077 // *
1078 // * @see org.modeshape.jcr.api.query.Row#getNode(java.lang.String)
1079 // */
1080 // @Override
1081 // public Node getNode( String selectorName ) throws RepositoryException {
1082 // try {
1083 // int locationIndex = iterator.columns.getLocationIndex(selectorName);
1084 // for (int i = 0; i != this.locationIndexes.length; ++i) {
1085 // if (this.locationIndexes[i] == locationIndex) {
1086 // return nodes[i];
1087 // }
1088 // }
1089 // } catch (NoSuchElementException e) {
1090 // throw new RepositoryException(e.getLocalizedMessage(), e);
1091 // }
1092 // assert false;
1093 // return null;
1094 // }
1095 //
1096 // /**
1097 // * {@inheritDoc}
1098 // *
1099 // * @see javax.jcr.query.Row#getValue(java.lang.String)
1100 // */
1101 // public Value getValue( String columnName ) throws ItemNotFoundException, RepositoryException {
1102 // try {
1103 // int locationIndex = iterator.columns.getLocationIndexForColumn(columnName);
1104 // for (int i = 0; i != this.locationIndexes.length; ++i) {
1105 // if (this.locationIndexes[i] == locationIndex) {
1106 // Node node = nodes[i];
1107 // return node != null ? node.getProperty(columnName).getValue() : null;
1108 // }
1109 // }
1110 // } catch (NoSuchElementException e) {
1111 // throw new RepositoryException(e.getLocalizedMessage(), e);
1112 // }
1113 // assert false;
1114 // return null;
1115 // }
1116 //
1117 // /**
1118 // * {@inheritDoc}
1119 // *
1120 // * @see javax.jcr.query.Row#getValues()
1121 // */
1122 // public Value[] getValues() throws RepositoryException {
1123 // if (values == null) {
1124 // int i = 0;
1125 // values = new Value[iterator.columnNames.size()];
1126 // for (String columnName : iterator.columnNames) {
1127 // values[i++] = getValue(columnName);
1128 // }
1129 // }
1130 // return values;
1131 // }
1132 //
1133 // @Override
1134 // public Node getNode() throws RepositoryException {
1135 // throw new UnsupportedRepositoryOperationException();
1136 // }
1137 //
1138 // @Override
1139 // public String getPath() throws RepositoryException {
1140 // throw new UnsupportedRepositoryOperationException();
1141 // }
1142 //
1143 // @Override
1144 // public String getPath( String selectorName ) throws RepositoryException {
1145 // throw new UnsupportedRepositoryOperationException();
1146 // }
1147 //
1148 // @Override
1149 // public double getScore() throws RepositoryException {
1150 // throw new UnsupportedRepositoryOperationException();
1151 // }
1152 //
1153 // @Override
1154 // public double getScore( String selectorName ) throws RepositoryException {
1155 // throw new UnsupportedRepositoryOperationException();
1156 // }
1157 // }
1158 //
1159 // protected static class XPathQueryResult extends JcrQueryResult {
1160 // private final List<String> columnNames;
1161 //
1162 // protected XPathQueryResult( JcrSession session,
1163 // String query,
1164 // QueryResults graphResults,
1165 // Schemata schemata ) {
1166 // super(session, query, graphResults, schemata);
1167 // List<String> columnNames = new LinkedList<String>(graphResults.getColumns().getColumnNames());
1168 // if (graphResults.getColumns().hasFullTextSearchScores() && !columnNames.contains(JCR_SCORE_COLUMN_NAME)) {
1169 // columnNames.add(0, JCR_SCORE_COLUMN_NAME);
1170 // }
1171 // columnNames.add(0, JCR_PATH_COLUMN_NAME);
1172 // this.columnNames = Collections.unmodifiableList(columnNames);
1173 // }
1174 //
1175 // /**
1176 // * {@inheritDoc}
1177 // *
1178 // * @see org.modeshape.jcr.JcrQueryManager.JcrQueryResult#getColumnNameList()
1179 // */
1180 // @Override
1181 // public List<String> getColumnNameList() {
1182 // return columnNames;
1183 // }
1184 //
1185 // /**
1186 // * {@inheritDoc}
1187 // *
1188 // * @see org.modeshape.jcr.JcrQueryManager.JcrQueryResult#getRows()
1189 // */
1190 // @Override
1191 // public RowIterator getRows() {
1192 // final int numRows = results.getRowCount();
1193 // final List<Object[]> tuples = results.getTuples();
1194 // return new XPathQueryResultRowIterator(session, queryStatement, results, tuples.iterator(), numRows);
1195 // }
1196 // }
1197 //
1198 // protected static class XPathQueryResultRowIterator extends SingleSelectorQueryResultRowIterator {
1199 // private final ValueFactories factories;
1200 // private final SessionCache cache;
1201 //
1202 // protected XPathQueryResultRowIterator( JcrSession session,
1203 // String query,
1204 // QueryResults results,
1205 // Iterator<Object[]> tuples,
1206 // long numRows ) {
1207 // super(session, query, results, tuples, numRows);
1208 // factories = session.executionContext.getValueFactories();
1209 // cache = session.cache();
1210 // }
1211 //
1212 // @Override
1213 // protected Row createRow( Node node,
1214 // Object[] tuple ) {
1215 // return new XPathQueryResultRow(this, node, tuple);
1216 // }
1217 //
1218 // protected Value jcrPath( Path path ) {
1219 // return new JcrValue(factories, cache, PropertyType.PATH, path);
1220 // }
1221 //
1222 // protected Value jcrScore( Float score ) {
1223 // return new JcrValue(factories, cache, PropertyType.DOUBLE, score);
1224 // }
1225 // }
1226 //
1227 // protected static class XPathQueryResultRow extends SingleSelectorQueryResultRow {
1228 // protected XPathQueryResultRow( SingleSelectorQueryResultRowIterator iterator,
1229 // Node node,
1230 // Object[] tuple ) {
1231 // super(iterator, node, tuple);
1232 // }
1233 //
1234 // /**
1235 // * {@inheritDoc}
1236 // *
1237 // * @see javax.jcr.query.Row#getValue(java.lang.String)
1238 // */
1239 // @Override
1240 // public Value getValue( String columnName ) throws ItemNotFoundException, RepositoryException {
1241 // if (JCR_PATH_COLUMN_NAME.equals(columnName)) {
1242 // Location location = (Location)tuple[iterator.locationIndex];
1243 // return ((XPathQueryResultRowIterator)iterator).jcrPath(location.getPath());
1244 // }
1245 // if (JCR_SCORE_COLUMN_NAME.equals(columnName)) {
1246 // Float score = (Float)tuple[iterator.scoreIndex];
1247 // return ((XPathQueryResultRowIterator)iterator).jcrScore(score);
1248 // }
1249 // return super.getValue(columnName);
1250 // }
1251 // }
1252 //
1253 // protected static class JcrSqlQueryResult extends JcrQueryResult {
1254 //
1255 // private final List<String> columnNames;
1256 // private boolean addedScoreColumn;
1257 // private boolean addedPathColumn;
1258 //
1259 // protected JcrSqlQueryResult( JcrSession session,
1260 // String query,
1261 // QueryResults graphResults,
1262 // Schemata schemata ) {
1263 // super(session, query, graphResults, schemata);
1264 // List<String> columnNames = new LinkedList<String>(graphResults.getColumns().getColumnNames());
1265 // if (!columnNames.contains(JCR_SCORE_COLUMN_NAME)) {
1266 // columnNames.add(0, JCR_SCORE_COLUMN_NAME);
1267 // addedScoreColumn = true;
1268 // }
1269 // if (!columnNames.contains(JCR_PATH_COLUMN_NAME)) {
1270 // columnNames.add(0, JCR_PATH_COLUMN_NAME);
1271 // addedPathColumn = true;
1272 // }
1273 // this.columnNames = Collections.unmodifiableList(columnNames);
1274 // }
1275 //
1276 // /**
1277 // * {@inheritDoc}
1278 // *
1279 // * @see org.modeshape.jcr.JcrQueryManager.JcrQueryResult#getColumnNameList()
1280 // */
1281 // @Override
1282 // public List<String> getColumnNameList() {
1283 // return columnNames;
1284 // }
1285 //
1286 // @Override
1287 // protected List<String> loadColumnTypes( Columns columns ) {
1288 // List<String> types = new ArrayList<String>(columns.getColumnCount() + (addedScoreColumn ? 1 : 0)
1289 // + (addedPathColumn ? 1 : 0));
1290 // String stringtype = PropertyType.nameFromValue(PropertyType.STRING);
1291 // if (addedScoreColumn) types.add(0, stringtype);
1292 // if (addedPathColumn) types.add(0, stringtype);
1293 //
1294 // for (Column column : columns) {
1295 // String typeName = null;
1296 // Table table = schemata.getTable(column.selectorName());
1297 // if (table != null) {
1298 // Schemata.Column typedColumn = table.getColumn(column.propertyName());
1299 // typeName = typedColumn.getPropertyType();
1300 // }
1301 // if (typeName == null) {
1302 // // Might be fabricated column, so just assume string ...
1303 // typeName = stringtype;
1304 // }
1305 // types.add(typeName);
1306 // }
1307 //
1308 // return types;
1309 // }
1310 //
1311 // /**
1312 // * {@inheritDoc}
1313 // *
1314 // * @see org.modeshape.jcr.JcrQueryManager.JcrQueryResult#getRows()
1315 // */
1316 // @Override
1317 // public RowIterator getRows() {
1318 // final int numRows = results.getRowCount();
1319 // final List<Object[]> tuples = results.getTuples();
1320 // return new JcrSqlQueryResultRowIterator(session, queryStatement, results, tuples.iterator(), numRows);
1321 // }
1322 // }
1323 //
1324 // protected static class JcrSqlQueryResultRowIterator extends SingleSelectorQueryResultRowIterator {
1325 // private final ValueFactories factories;
1326 // private final SessionCache cache;
1327 //
1328 // protected JcrSqlQueryResultRowIterator( JcrSession session,
1329 // String query,
1330 // QueryResults results,
1331 // Iterator<Object[]> tuples,
1332 // long numRows ) {
1333 // super(session, query, results, tuples, numRows);
1334 // factories = session.executionContext.getValueFactories();
1335 // cache = session.cache();
1336 // }
1337 //
1338 // @Override
1339 // protected Row createRow( Node node,
1340 // Object[] tuple ) {
1341 // return new JcrSqlQueryResultRow(this, node, tuple);
1342 // }
1343 //
1344 // protected Value jcrPath( Path path ) {
1345 // return new JcrValue(factories, cache, PropertyType.PATH, path);
1346 // }
1347 //
1348 // protected Value jcrScore( Float score ) {
1349 // return new JcrValue(factories, cache, PropertyType.DOUBLE, score);
1350 // }
1351 // }
1352 //
1353 // protected static class JcrSqlQueryResultRow extends SingleSelectorQueryResultRow {
1354 // protected JcrSqlQueryResultRow( SingleSelectorQueryResultRowIterator iterator,
1355 // Node node,
1356 // Object[] tuple ) {
1357 // super(iterator, node, tuple);
1358 // }
1359 //
1360 // /**
1361 // * {@inheritDoc}
1362 // *
1363 // * @see javax.jcr.query.Row#getValue(java.lang.String)
1364 // */
1365 // @Override
1366 // public Value getValue( String columnName ) throws ItemNotFoundException, RepositoryException {
1367 // if (JCR_PATH_COLUMN_NAME.equals(columnName)) {
1368 // Location location = (Location)tuple[iterator.locationIndex];
1369 // return ((JcrSqlQueryResultRowIterator)iterator).jcrPath(location.getPath());
1370 // }
1371 // if (JCR_SCORE_COLUMN_NAME.equals(columnName)) {
1372 // Float score = (Float)tuple[iterator.scoreIndex];
1373 // return ((JcrSqlQueryResultRowIterator)iterator).jcrScore(score);
1374 // }
1375 // return super.getValue(columnName);
1376 // }
1377 // }
1378 //
1379 // @Override
1380 // public QueryObjectModelFactory getQOMFactory() {
1381 // throw new IllegalStateException();
1382 // }
1383
1384 protected static class SessionQueryContext implements JcrQueryContext {
1385 private final JcrSession session;
1386 private final ValueFactories factories;
1387 private final SessionCache cache;
1388
1389 protected SessionQueryContext( JcrSession session ) {
1390 this.session = session;
1391 this.factories = session.getExecutionContext().getValueFactories();
1392 this.cache = session.cache();
1393 }
1394
1395 /**
1396 * {@inheritDoc}
1397 *
1398 * @see org.modeshape.jcr.query.JcrQueryContext#createValue(int, java.lang.Object)
1399 */
1400 @Override
1401 public Value createValue( int propertyType,
1402 Object value ) {
1403 return new JcrValue(factories, cache, PropertyType.PATH, value);
1404 }
1405
1406 /**
1407 * {@inheritDoc}
1408 *
1409 * @see org.modeshape.jcr.query.JcrQueryContext#emptyNodeIterator()
1410 */
1411 @Override
1412 public NodeIterator emptyNodeIterator() {
1413 return new JcrEmptyNodeIterator();
1414 }
1415
1416 /**
1417 * {@inheritDoc}
1418 *
1419 * @see org.modeshape.jcr.query.JcrQueryContext#execute(org.modeshape.graph.query.model.QueryCommand,
1420 * org.modeshape.graph.query.plan.PlanHints, java.util.Map)
1421 */
1422 @Override
1423 public QueryResults execute( QueryCommand query,
1424 PlanHints hints,
1425 Map<String, Object> variables ) throws RepositoryException {
1426 session.checkLive();
1427 // Submit immediately to the workspace graph ...
1428 Schemata schemata = session.workspace().nodeTypeManager().schemata();
1429 return session.repository().queryManager().query(session.workspace().getName(), query, schemata, hints, variables);
1430 }
1431
1432 /**
1433 * {@inheritDoc}
1434 *
1435 * @see org.modeshape.jcr.query.JcrQueryContext#getExecutionContext()
1436 */
1437 @Override
1438 public ExecutionContext getExecutionContext() {
1439 return session.getExecutionContext();
1440 }
1441
1442 /**
1443 * {@inheritDoc}
1444 *
1445 * @see org.modeshape.jcr.query.JcrQueryContext#getNode(Location)
1446 */
1447 @Override
1448 public Node getNode( Location location ) throws AccessDeniedException, RepositoryException {
1449 if (!session.wasRemovedInSession(location)) {
1450 return session.getNode(location.getPath());
1451 }
1452 return null;
1453 }
1454
1455 /**
1456 * {@inheritDoc}
1457 *
1458 * @see org.modeshape.jcr.query.JcrQueryContext#getSchemata()
1459 */
1460 @Override
1461 public Schemata getSchemata() {
1462 return session.nodeTypeManager().schemata();
1463 }
1464
1465 /**
1466 * {@inheritDoc}
1467 *
1468 * @see org.modeshape.jcr.query.JcrQueryContext#isLive()
1469 */
1470 @Override
1471 public boolean isLive() {
1472 return session.isLive();
1473 }
1474
1475 /**
1476 * {@inheritDoc}
1477 *
1478 * @see org.modeshape.jcr.query.JcrQueryContext#search(java.lang.String, int, int)
1479 */
1480 @Override
1481 public QueryResults search( String searchExpression,
1482 int maxRowCount,
1483 int offset ) throws RepositoryException {
1484 return session.repository().queryManager().search(session.workspace().getName(),
1485 searchExpression,
1486 maxRowCount,
1487 offset);
1488 }
1489
1490 /**
1491 * {@inheritDoc}
1492 *
1493 * @see org.modeshape.jcr.query.JcrQueryContext#store(java.lang.String, org.modeshape.graph.property.Name,
1494 * java.lang.String, java.lang.String)
1495 */
1496 @Override
1497 public Node store( String absolutePath,
1498 Name nodeType,
1499 String language,
1500 String statement ) throws RepositoryException {
1501 session.checkLive();
1502 NamespaceRegistry namespaces = session.namespaces();
1503
1504 Path path;
1505 try {
1506 path = session.getExecutionContext().getValueFactories().getPathFactory().create(absolutePath);
1507 } catch (IllegalArgumentException iae) {
1508 throw new RepositoryException(JcrI18n.invalidPathParameter.text("absolutePath", absolutePath));
1509 }
1510 Path parentPath = path.getParent();
1511
1512 Node parentNode = session.getNode(parentPath);
1513
1514 if (!parentNode.isCheckedOut()) {
1515 throw new VersionException(JcrI18n.nodeIsCheckedIn.text(parentNode.getPath()));
1516 }
1517
1518 Node queryNode = parentNode.addNode(path.relativeTo(parentPath).getString(namespaces),
1519 JcrNtLexicon.QUERY.getString(namespaces));
1520
1521 queryNode.setProperty(JcrLexicon.LANGUAGE.getString(namespaces), language);
1522 queryNode.setProperty(JcrLexicon.STATEMENT.getString(namespaces), statement);
1523
1524 return queryNode;
1525 }
1526
1527 }
1528
1529 protected static class SessionTypeSystem implements JcrTypeSystem {
1530 protected final JcrSession session;
1531 protected final TypeSystem delegate;
1532
1533 protected SessionTypeSystem( JcrSession session ) {
1534 this.session = session;
1535 this.delegate = session.getExecutionContext().getValueFactories().getTypeSystem();
1536 }
1537
1538 @Override
1539 public Set<String> getTypeNames() {
1540 return delegate.getTypeNames();
1541 }
1542
1543 @Override
1544 public TypeFactory<?> getTypeFactory( Object prototype ) {
1545 return delegate.getTypeFactory(prototype);
1546 }
1547
1548 @Override
1549 public TypeFactory<?> getTypeFactory( String typeName ) {
1550 return delegate.getTypeFactory(typeName);
1551 }
1552
1553 @Override
1554 public TypeFactory<String> getStringFactory() {
1555 return delegate.getStringFactory();
1556 }
1557
1558 @Override
1559 public TypeFactory<?> getReferenceFactory() {
1560 return delegate.getReferenceFactory();
1561 }
1562
1563 @Override
1564 public TypeFactory<?> getPathFactory() {
1565 return delegate.getPathFactory();
1566 }
1567
1568 @Override
1569 public TypeFactory<Long> getLongFactory() {
1570 return delegate.getLongFactory();
1571 }
1572
1573 @Override
1574 public TypeFactory<Double> getDoubleFactory() {
1575 return delegate.getDoubleFactory();
1576 }
1577
1578 @Override
1579 public String getDefaultType() {
1580 return delegate.getDefaultType();
1581 }
1582
1583 @Override
1584 public Comparator<Object> getDefaultComparator() {
1585 return delegate.getDefaultComparator();
1586 }
1587
1588 @Override
1589 public TypeFactory<BigDecimal> getDecimalFactory() {
1590 return delegate.getDecimalFactory();
1591 }
1592
1593 @Override
1594 public TypeFactory<?> getDateTimeFactory() {
1595 return delegate.getDateTimeFactory();
1596 }
1597
1598 @Override
1599 public String getCompatibleType( String type1,
1600 String type2 ) {
1601 return delegate.getCompatibleType(type1, type2);
1602 }
1603
1604 @Override
1605 public TypeFactory<Boolean> getBooleanFactory() {
1606 return delegate.getBooleanFactory();
1607 }
1608
1609 @Override
1610 public TypeFactory<?> getBinaryFactory() {
1611 return delegate.getBinaryFactory();
1612 }
1613
1614 @Override
1615 public String asString( Object value ) {
1616 return delegate.asString(value);
1617 }
1618
1619 @Override
1620 public ValueFactory getValueFactory() {
1621 return session.getValueFactory();
1622 }
1623 }
1624 }