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 }