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