View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.jcr.query.qom;
25  
26  import java.util.ArrayList;
27  import java.util.List;
28  import javax.jcr.RepositoryException;
29  import javax.jcr.Value;
30  import javax.jcr.query.Query;
31  import javax.jcr.query.qom.And;
32  import javax.jcr.query.qom.BindVariableValue;
33  import javax.jcr.query.qom.ChildNode;
34  import javax.jcr.query.qom.ChildNodeJoinCondition;
35  import javax.jcr.query.qom.Column;
36  import javax.jcr.query.qom.Comparison;
37  import javax.jcr.query.qom.Constraint;
38  import javax.jcr.query.qom.DescendantNode;
39  import javax.jcr.query.qom.DescendantNodeJoinCondition;
40  import javax.jcr.query.qom.DynamicOperand;
41  import javax.jcr.query.qom.EquiJoinCondition;
42  import javax.jcr.query.qom.FullTextSearch;
43  import javax.jcr.query.qom.FullTextSearchScore;
44  import javax.jcr.query.qom.Join;
45  import javax.jcr.query.qom.JoinCondition;
46  import javax.jcr.query.qom.Length;
47  import javax.jcr.query.qom.Literal;
48  import javax.jcr.query.qom.LowerCase;
49  import javax.jcr.query.qom.NodeLocalName;
50  import javax.jcr.query.qom.NodeName;
51  import javax.jcr.query.qom.Not;
52  import javax.jcr.query.qom.Or;
53  import javax.jcr.query.qom.Ordering;
54  import javax.jcr.query.qom.PropertyExistence;
55  import javax.jcr.query.qom.PropertyValue;
56  import javax.jcr.query.qom.QueryObjectModelFactory;
57  import javax.jcr.query.qom.SameNode;
58  import javax.jcr.query.qom.SameNodeJoinCondition;
59  import javax.jcr.query.qom.Source;
60  import javax.jcr.query.qom.StaticOperand;
61  import javax.jcr.query.qom.UpperCase;
62  import org.modeshape.common.util.CheckArg;
63  import org.modeshape.graph.query.model.ArithmeticOperator;
64  import org.modeshape.graph.query.model.JoinType;
65  import org.modeshape.graph.query.model.Operator;
66  import org.modeshape.graph.query.model.Order;
67  import org.modeshape.graph.query.model.SelectorName;
68  import org.modeshape.graph.query.model.SetQuery.Operation;
69  import org.modeshape.graph.query.plan.PlanHints;
70  import org.modeshape.jcr.api.query.qom.ArithmeticOperand;
71  import org.modeshape.jcr.api.query.qom.Between;
72  import org.modeshape.jcr.api.query.qom.Limit;
73  import org.modeshape.jcr.api.query.qom.NodeDepth;
74  import org.modeshape.jcr.api.query.qom.NodePath;
75  import org.modeshape.jcr.api.query.qom.QueryCommand;
76  import org.modeshape.jcr.api.query.qom.QueryObjectModelConstants;
77  import org.modeshape.jcr.api.query.qom.SetCriteria;
78  import org.modeshape.jcr.api.query.qom.SetQuery;
79  import org.modeshape.jcr.api.query.qom.Subquery;
80  import org.modeshape.jcr.query.JcrQueryContext;
81  
82  /**
83   * An implementation of the JCR {@link QueryObjectModelFactory}. Note that this implementation constructs the query components but
84   * does not validate any of the parameters or the resulting query definition. All validation is performed when the query is
85   * {@link Query#execute() executed}.
86   */
87  public class JcrQueryObjectModelFactory
88      implements QueryObjectModelFactory, org.modeshape.jcr.api.query.qom.QueryObjectModelFactory {
89  
90      public static final String LANGUAGE = Query.JCR_JQOM;
91      private final JcrQueryContext context;
92  
93      public JcrQueryObjectModelFactory( JcrQueryContext context ) {
94          this.context = context;
95      }
96  
97      protected SelectorName selectorName( String name ) {
98          return new SelectorName(name);
99      }
100 
101     /**
102      * {@inheritDoc}
103      * 
104      * @see javax.jcr.query.qom.QueryObjectModelFactory#createQuery(javax.jcr.query.qom.Source, javax.jcr.query.qom.Constraint,
105      *      javax.jcr.query.qom.Ordering[], javax.jcr.query.qom.Column[])
106      */
107     @Override
108     public JcrQueryObjectModel createQuery( Source source,
109                                             Constraint constraint,
110                                             Ordering[] orderings,
111                                             Column[] columns ) {
112 
113         JcrSelectQuery query = select(source, constraint, orderings, columns, null, false);
114         String statement = query.toString();
115         // Set up the hints ...
116         PlanHints hints = new PlanHints();
117         hints.showPlan = true;
118         // We want to allow use of residual properties (not in the schemata) for criteria ...
119         hints.validateColumnExistance = true;
120         return new JcrQueryObjectModel(context, statement, LANGUAGE, query, hints, null);
121     }
122 
123     /**
124      * {@inheritDoc}
125      * 
126      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#select(javax.jcr.query.qom.Source,
127      *      javax.jcr.query.qom.Constraint, javax.jcr.query.qom.Ordering[], javax.jcr.query.qom.Column[],
128      *      org.modeshape.jcr.api.query.qom.Limit, boolean)
129      */
130     @Override
131     public JcrSelectQuery select( Source source,
132                                   Constraint constraint,
133                                   Ordering[] orderings,
134                                   Column[] columns,
135                                   Limit limit,
136                                   boolean distinct ) {
137         JcrSource jcrSource = CheckArg.getInstanceOf(source, JcrSource.class, "source");
138         JcrConstraint jcrConstraint = null;
139         if (constraint != null) {
140             jcrConstraint = CheckArg.getInstanceOf(constraint, JcrConstraint.class, "constraint");
141         }
142         List<JcrColumn> jcrColumns = null;
143         if (columns != null) {
144             jcrColumns = new ArrayList<JcrColumn>();
145             for (int i = 0; i != columns.length; ++i) {
146                 jcrColumns.add(CheckArg.getInstanceOf(columns[i], JcrColumn.class, "column[" + i + "]"));
147             }
148         }
149         List<JcrOrdering> jcrOrderings = null;
150         if (orderings != null) {
151             jcrOrderings = new ArrayList<JcrOrdering>();
152             for (int i = 0; i != orderings.length; ++i) {
153                 jcrOrderings.add(CheckArg.getInstanceOf(orderings[i], JcrOrdering.class, "orderings[" + i + "]"));
154             }
155         }
156         JcrLimit jcrLimit = limit == null ? JcrLimit.NONE : new JcrLimit(limit.getRowLimit(), limit.getOffset());
157         return new JcrSelectQuery(jcrSource, jcrConstraint, jcrOrderings, jcrColumns, jcrLimit, distinct);
158     }
159 
160     /**
161      * {@inheritDoc}
162      * 
163      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#union(QueryCommand, QueryCommand, Ordering[], Limit, boolean)
164      */
165     @Override
166     public SetQuery union( QueryCommand left,
167                            QueryCommand right,
168                            Ordering[] orderings,
169                            Limit limit,
170                            boolean all ) {
171         return setQuery(left, Operation.UNION, right, orderings, limit, all);
172     }
173 
174     /**
175      * {@inheritDoc}
176      * 
177      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#intersect(org.modeshape.jcr.api.query.qom.QueryCommand,
178      *      org.modeshape.jcr.api.query.qom.QueryCommand, javax.jcr.query.qom.Ordering[], org.modeshape.jcr.api.query.qom.Limit,
179      *      boolean)
180      */
181     @Override
182     public SetQuery intersect( QueryCommand left,
183                                QueryCommand right,
184                                Ordering[] orderings,
185                                Limit limit,
186                                boolean all ) {
187         return setQuery(left, Operation.INTERSECT, right, orderings, limit, all);
188     }
189 
190     /**
191      * {@inheritDoc}
192      * 
193      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#except(org.modeshape.jcr.api.query.qom.QueryCommand,
194      *      org.modeshape.jcr.api.query.qom.QueryCommand, javax.jcr.query.qom.Ordering[], org.modeshape.jcr.api.query.qom.Limit,
195      *      boolean)
196      */
197     @Override
198     public SetQuery except( QueryCommand left,
199                             QueryCommand right,
200                             Ordering[] orderings,
201                             Limit limit,
202                             boolean all ) {
203         return setQuery(left, Operation.EXCEPT, right, orderings, limit, all);
204     }
205 
206     public JcrSetQuery setQuery( QueryCommand left,
207                                  Operation operation,
208                                  QueryCommand right,
209                                  Ordering[] orderings,
210                                  Limit limit,
211                                  boolean all ) {
212         JcrQueryCommand jcrLeft = CheckArg.getInstanceOf(left, JcrQueryCommand.class, "left");
213         JcrQueryCommand jcrRight = CheckArg.getInstanceOf(left, JcrQueryCommand.class, "left");
214         List<JcrOrdering> jcrOrderings = new ArrayList<JcrOrdering>();
215         for (int i = 0; i != orderings.length; ++i) {
216             jcrOrderings.add(CheckArg.getInstanceOf(orderings[i], JcrOrdering.class, "orderings[" + i + "]"));
217         }
218         JcrLimit jcrLimit = limit == null ? JcrLimit.NONE : new JcrLimit(limit.getRowLimit(), limit.getOffset());
219         return new JcrSetQuery(jcrLeft, operation, jcrRight, all, jcrOrderings, jcrLimit);
220     }
221 
222     /**
223      * {@inheritDoc}
224      * 
225      * @see javax.jcr.query.qom.QueryObjectModelFactory#selector(java.lang.String, java.lang.String)
226      */
227     @Override
228     public JcrNamedSelector selector( String nodeTypeName,
229                                       String selectorName ) {
230         CheckArg.isNotNull(nodeTypeName, "nodeTypeName");
231         CheckArg.isNotNull(selectorName, "selectorName");
232         return new JcrNamedSelector(selectorName(nodeTypeName), selectorName(selectorName));
233     }
234 
235     /**
236      * {@inheritDoc}
237      * 
238      * @see javax.jcr.query.qom.QueryObjectModelFactory#column(java.lang.String, java.lang.String, java.lang.String)
239      */
240     @Override
241     public JcrColumn column( String selectorName,
242                              String propertyName,
243                              String columnName ) {
244         CheckArg.isNotNull(selectorName, "selectorName");
245         if (propertyName == null) {
246             return new JcrColumn(selectorName(selectorName));
247         }
248         CheckArg.isNotNull(columnName, "columnName");
249         return new JcrColumn(selectorName(selectorName), selectorName, columnName);
250     }
251 
252     /**
253      * {@inheritDoc}
254      * 
255      * @see javax.jcr.query.qom.QueryObjectModelFactory#ascending(javax.jcr.query.qom.DynamicOperand)
256      */
257     @Override
258     public JcrOrdering ascending( DynamicOperand operand ) {
259         JcrDynamicOperand jcrOperand = CheckArg.getInstanceOf(operand, JcrDynamicOperand.class, "operand");
260         return new JcrOrdering(jcrOperand, Order.ASCENDING);
261     }
262 
263     /**
264      * {@inheritDoc}
265      * 
266      * @see javax.jcr.query.qom.QueryObjectModelFactory#descending(javax.jcr.query.qom.DynamicOperand)
267      */
268     @Override
269     public JcrOrdering descending( DynamicOperand operand ) {
270         JcrDynamicOperand jcrOperand = CheckArg.getInstanceOf(operand, JcrDynamicOperand.class, "operand");
271         return new JcrOrdering(jcrOperand, Order.DESCENDING);
272     }
273 
274     /**
275      * {@inheritDoc}
276      * 
277      * @see javax.jcr.query.qom.QueryObjectModelFactory#and(javax.jcr.query.qom.Constraint, javax.jcr.query.qom.Constraint)
278      */
279     @Override
280     public And and( Constraint constraint1,
281                     Constraint constraint2 ) {
282         JcrConstraint jcrConstraint1 = CheckArg.getInstanceOf(constraint1, JcrConstraint.class, "constraint1");
283         JcrConstraint jcrConstraint2 = CheckArg.getInstanceOf(constraint2, JcrConstraint.class, "constraint2");
284         return new JcrAnd(jcrConstraint1, jcrConstraint2);
285     }
286 
287     /**
288      * {@inheritDoc}
289      * 
290      * @see javax.jcr.query.qom.QueryObjectModelFactory#bindVariable(java.lang.String)
291      */
292     @Override
293     public BindVariableValue bindVariable( String bindVariableName ) {
294         CheckArg.isNotNull(bindVariableName, "bindVariableName");
295         return new JcrBindVariableName(bindVariableName);
296     }
297 
298     /**
299      * {@inheritDoc}
300      * 
301      * @see javax.jcr.query.qom.QueryObjectModelFactory#childNode(java.lang.String, java.lang.String)
302      */
303     @Override
304     public ChildNode childNode( String selectorName,
305                                 String path ) {
306         CheckArg.isNotNull(selectorName, "selectorName");
307         CheckArg.isNotNull(path, "path");
308         return new JcrChildNode(selectorName(selectorName), path);
309     }
310 
311     /**
312      * {@inheritDoc}
313      * 
314      * @see javax.jcr.query.qom.QueryObjectModelFactory#childNodeJoinCondition(java.lang.String, java.lang.String)
315      */
316     @Override
317     public ChildNodeJoinCondition childNodeJoinCondition( String childSelectorName,
318                                                           String parentSelectorName ) {
319         CheckArg.isNotNull(childSelectorName, "childSelectorName");
320         CheckArg.isNotNull(parentSelectorName, "parentSelectorName");
321         return new JcrChildNodeJoinCondition(selectorName(parentSelectorName), selectorName(childSelectorName));
322     }
323 
324     /**
325      * {@inheritDoc}
326      * 
327      * @see javax.jcr.query.qom.QueryObjectModelFactory#comparison(javax.jcr.query.qom.DynamicOperand, java.lang.String,
328      *      javax.jcr.query.qom.StaticOperand)
329      */
330     @Override
331     public Comparison comparison( DynamicOperand operand1,
332                                   String operator,
333                                   StaticOperand operand2 ) {
334         JcrDynamicOperand jcrOperand1 = CheckArg.getInstanceOf(operand1, JcrDynamicOperand.class, "operand1");
335         CheckArg.isNotEmpty(operator, "operator");
336         JcrStaticOperand jcrOperand2 = CheckArg.getInstanceOf(operand2, JcrStaticOperand.class, "operand2");
337         operator = operator.trim();
338         Operator op = null;
339         if (QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO.equals(operator)) op = Operator.EQUAL_TO;
340         else if (QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN.equals(operator)) op = Operator.GREATER_THAN;
341         else if (QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO.equals(operator)) op = Operator.GREATER_THAN_OR_EQUAL_TO;
342         else if (QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN.equals(operator)) op = Operator.LESS_THAN;
343         else if (QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO.equals(operator)) op = Operator.LESS_THAN_OR_EQUAL_TO;
344         else if (QueryObjectModelConstants.JCR_OPERATOR_LIKE.equals(operator)) op = Operator.LIKE;
345         else if (QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO.equals(operator)) op = Operator.NOT_EQUAL_TO;
346         if (op == null) {
347             throw new IllegalArgumentException("Unknown or unsupported comparison operator: " + operator);
348         }
349         return new JcrComparison(jcrOperand1, op, jcrOperand2);
350     }
351 
352     /**
353      * {@inheritDoc}
354      * 
355      * @see javax.jcr.query.qom.QueryObjectModelFactory#descendantNode(java.lang.String, java.lang.String)
356      */
357     @Override
358     public DescendantNode descendantNode( String selectorName,
359                                           String path ) {
360         CheckArg.isNotNull(selectorName, "selectorName");
361         CheckArg.isNotNull(path, "path");
362         return new JcrDescendantNode(selectorName(selectorName), path);
363     }
364 
365     /**
366      * {@inheritDoc}
367      * 
368      * @see javax.jcr.query.qom.QueryObjectModelFactory#descendantNodeJoinCondition(java.lang.String, java.lang.String)
369      */
370     @Override
371     public DescendantNodeJoinCondition descendantNodeJoinCondition( String descendantSelectorName,
372                                                                     String ancestorSelectorName ) {
373         CheckArg.isNotNull(descendantSelectorName, "descendantSelectorName");
374         CheckArg.isNotNull(ancestorSelectorName, "ancestorSelectorName");
375         return new JcrDescendantNodeJoinCondition(selectorName(ancestorSelectorName), selectorName(descendantSelectorName));
376     }
377 
378     /**
379      * {@inheritDoc}
380      * 
381      * @see javax.jcr.query.qom.QueryObjectModelFactory#equiJoinCondition(java.lang.String, java.lang.String, java.lang.String,
382      *      java.lang.String)
383      */
384     @Override
385     public EquiJoinCondition equiJoinCondition( String selector1Name,
386                                                 String property1Name,
387                                                 String selector2Name,
388                                                 String property2Name ) {
389         CheckArg.isNotNull(selector1Name, "selector1Name");
390         CheckArg.isNotNull(property1Name, "property1Name");
391         CheckArg.isNotNull(selector2Name, "selector2Name");
392         CheckArg.isNotNull(selector2Name, "selector2Name");
393         return new JcrEquiJoinCondition(selectorName(selector1Name), property1Name, selectorName(selector2Name), selector2Name);
394     }
395 
396     /**
397      * {@inheritDoc}
398      * 
399      * @see javax.jcr.query.qom.QueryObjectModelFactory#fullTextSearch(java.lang.String, java.lang.String,
400      *      javax.jcr.query.qom.StaticOperand)
401      */
402     @Override
403     public FullTextSearch fullTextSearch( String selectorName,
404                                           String propertyName,
405                                           StaticOperand fullTextSearchExpression ) throws RepositoryException {
406         CheckArg.isNotNull(selectorName, "selectorName");
407         CheckArg.isNotNull(fullTextSearchExpression, "fullTextSearchExpression");
408         return new JcrFullTextSearch(selectorName(selectorName), propertyName, fullTextSearchExpression);
409     }
410 
411     /**
412      * {@inheritDoc}
413      * 
414      * @see javax.jcr.query.qom.QueryObjectModelFactory#fullTextSearchScore(java.lang.String)
415      */
416     @Override
417     public FullTextSearchScore fullTextSearchScore( String selectorName ) {
418         CheckArg.isNotNull(selectorName, "selectorName");
419         return new JcrFullTextSearchScore(selectorName(selectorName));
420     }
421 
422     /**
423      * {@inheritDoc}
424      * 
425      * @see javax.jcr.query.qom.QueryObjectModelFactory#join(javax.jcr.query.qom.Source, javax.jcr.query.qom.Source,
426      *      java.lang.String, javax.jcr.query.qom.JoinCondition)
427      */
428     @Override
429     public Join join( Source left,
430                       Source right,
431                       String joinType,
432                       JoinCondition joinCondition ) {
433         JcrSource leftSource = CheckArg.getInstanceOf(left, JcrSource.class, "left");
434         JcrSource rightSource = CheckArg.getInstanceOf(right, JcrSource.class, "right");
435         JcrJoinCondition jcrJoinCondition = CheckArg.getInstanceOf(joinCondition, JcrJoinCondition.class, "joinCondition");
436         CheckArg.isNotEmpty(joinType, "joinType");
437         joinType = joinType.trim();
438         JoinType type = null;
439         if (QueryObjectModelConstants.JCR_JOIN_TYPE_CROSS.equals(joinType)) type = JoinType.CROSS;
440         else if (QueryObjectModelConstants.JCR_JOIN_TYPE_INNER.equals(joinType)) type = JoinType.INNER;
441         else if (QueryObjectModelConstants.JCR_JOIN_TYPE_FULL_OUTER.equals(joinType)) type = JoinType.FULL_OUTER;
442         else if (QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER.equals(joinType)) type = JoinType.LEFT_OUTER;
443         else if (QueryObjectModelConstants.JCR_JOIN_TYPE_RIGHT_OUTER.equals(joinType)) type = JoinType.RIGHT_OUTER;
444         if (type == null) {
445             throw new IllegalArgumentException("Unknown or unsupported join type: " + joinType);
446         }
447         return new JcrJoin(leftSource, type, rightSource, jcrJoinCondition);
448     }
449 
450     /**
451      * {@inheritDoc}
452      * 
453      * @see javax.jcr.query.qom.QueryObjectModelFactory#length(javax.jcr.query.qom.PropertyValue)
454      */
455     @Override
456     public Length length( PropertyValue propertyValue ) {
457         JcrPropertyValue jcrPropValue = CheckArg.getInstanceOf(propertyValue, JcrPropertyValue.class, "propertyValue");
458         return new JcrLength(jcrPropValue);
459     }
460 
461     /**
462      * {@inheritDoc}
463      * 
464      * @see javax.jcr.query.qom.QueryObjectModelFactory#literal(javax.jcr.Value)
465      */
466     @Override
467     public Literal literal( Value literalValue ) throws RepositoryException {
468         CheckArg.isNotNull(literalValue, "literalValue");
469         return new JcrLiteral(literalValue);
470     }
471 
472     /**
473      * {@inheritDoc}
474      * 
475      * @see javax.jcr.query.qom.QueryObjectModelFactory#lowerCase(javax.jcr.query.qom.DynamicOperand)
476      */
477     @Override
478     public LowerCase lowerCase( DynamicOperand operand ) {
479         JcrDynamicOperand jcrOperand = CheckArg.getInstanceOf(operand, JcrDynamicOperand.class, "operand");
480         return new JcrLowerCase(jcrOperand);
481     }
482 
483     /**
484      * {@inheritDoc}
485      * 
486      * @see javax.jcr.query.qom.QueryObjectModelFactory#nodeLocalName(java.lang.String)
487      */
488     @Override
489     public NodeLocalName nodeLocalName( String selectorName ) {
490         CheckArg.isNotNull(selectorName, "selectorName");
491         return new JcrNodeLocalName(selectorName(selectorName));
492     }
493 
494     /**
495      * {@inheritDoc}
496      * 
497      * @see javax.jcr.query.qom.QueryObjectModelFactory#nodeName(java.lang.String)
498      */
499     @Override
500     public NodeName nodeName( String selectorName ) {
501         CheckArg.isNotNull(selectorName, "selectorName");
502         return new JcrNodeName(selectorName(selectorName));
503     }
504 
505     /**
506      * {@inheritDoc}
507      * 
508      * @see javax.jcr.query.qom.QueryObjectModelFactory#not(javax.jcr.query.qom.Constraint)
509      */
510     @Override
511     public Not not( Constraint constraint ) {
512         JcrConstraint jcrConstraint = CheckArg.getInstanceOf(constraint, JcrConstraint.class, "constraint");
513         return new JcrNot(jcrConstraint);
514     }
515 
516     /**
517      * {@inheritDoc}
518      * 
519      * @see javax.jcr.query.qom.QueryObjectModelFactory#or(javax.jcr.query.qom.Constraint, javax.jcr.query.qom.Constraint)
520      */
521     @Override
522     public Or or( Constraint constraint1,
523                   Constraint constraint2 ) {
524         JcrConstraint jcrConstraint1 = CheckArg.getInstanceOf(constraint1, JcrConstraint.class, "constraint1");
525         JcrConstraint jcrConstraint2 = CheckArg.getInstanceOf(constraint2, JcrConstraint.class, "constraint2");
526         return new JcrOr(jcrConstraint1, jcrConstraint2);
527     }
528 
529     /**
530      * {@inheritDoc}
531      * 
532      * @see javax.jcr.query.qom.QueryObjectModelFactory#propertyExistence(java.lang.String, java.lang.String)
533      */
534     @Override
535     public PropertyExistence propertyExistence( String selectorName,
536                                                 String propertyName ) {
537         CheckArg.isNotNull(selectorName, "selectorName");
538         CheckArg.isNotNull(propertyName, "propertyName");
539         return new JcrPropertyExistence(selectorName(selectorName), propertyName);
540     }
541 
542     /**
543      * {@inheritDoc}
544      * 
545      * @see javax.jcr.query.qom.QueryObjectModelFactory#propertyValue(java.lang.String, java.lang.String)
546      */
547     @Override
548     public PropertyValue propertyValue( String selectorName,
549                                         String propertyName ) {
550         CheckArg.isNotNull(selectorName, "selectorName");
551         CheckArg.isNotNull(propertyName, "propertyName");
552         return new JcrPropertyValue(selectorName(selectorName), propertyName);
553     }
554 
555     /**
556      * {@inheritDoc}
557      * 
558      * @see javax.jcr.query.qom.QueryObjectModelFactory#sameNode(java.lang.String, java.lang.String)
559      */
560     @Override
561     public SameNode sameNode( String selectorName,
562                               String path ) {
563         CheckArg.isNotNull(selectorName, "selectorName");
564         CheckArg.isNotNull(path, "path");
565         return new JcrSameNode(selectorName(selectorName), path);
566     }
567 
568     /**
569      * {@inheritDoc}
570      * 
571      * @see javax.jcr.query.qom.QueryObjectModelFactory#sameNodeJoinCondition(java.lang.String, java.lang.String,
572      *      java.lang.String)
573      */
574     @Override
575     public SameNodeJoinCondition sameNodeJoinCondition( String selector1Name,
576                                                         String selector2Name,
577                                                         String selector2Path ) {
578         CheckArg.isNotNull(selector1Name, "selector1Name");
579         CheckArg.isNotNull(selector1Name, "selector1Name");
580         return new JcrSameNodeJoinCondition(selectorName(selector1Name), selectorName(selector1Name), selector2Path);
581     }
582 
583     /**
584      * {@inheritDoc}
585      * 
586      * @see javax.jcr.query.qom.QueryObjectModelFactory#upperCase(javax.jcr.query.qom.DynamicOperand)
587      */
588     @Override
589     public UpperCase upperCase( DynamicOperand operand ) {
590         JcrDynamicOperand jcrOperand = CheckArg.getInstanceOf(operand, JcrDynamicOperand.class, "operand");
591         return new JcrUpperCase(jcrOperand);
592     }
593 
594     /**
595      * {@inheritDoc}
596      * 
597      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#nodePath(java.lang.String)
598      */
599     @Override
600     public NodePath nodePath( String selectorName ) {
601         CheckArg.isNotNull(selectorName, "selectorName");
602         return new JcrNodePath(selectorName(selectorName));
603     }
604 
605     /**
606      * {@inheritDoc}
607      * 
608      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#nodeDepth(java.lang.String)
609      */
610     @Override
611     public NodeDepth nodeDepth( String selectorName ) {
612         CheckArg.isNotNull(selectorName, "selectorName");
613         return new JcrNodeDepth(selectorName(selectorName));
614     }
615 
616     /**
617      * {@inheritDoc}
618      * 
619      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#limit(int, int)
620      */
621     @Override
622     public Limit limit( int rowLimit,
623                         int offset ) {
624         CheckArg.isPositive(rowLimit, "rowLimit");
625         CheckArg.isNonNegative(offset, "offset");
626         return new JcrLimit(rowLimit, offset);
627     }
628 
629     /**
630      * {@inheritDoc}
631      * 
632      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#between(javax.jcr.query.qom.DynamicOperand,
633      *      javax.jcr.query.qom.StaticOperand, javax.jcr.query.qom.StaticOperand, boolean, boolean)
634      */
635     @Override
636     public Between between( DynamicOperand operand,
637                             StaticOperand lowerBound,
638                             StaticOperand upperBound,
639                             boolean includeLowerBound,
640                             boolean includeUpperBound ) {
641         JcrDynamicOperand jcrOperand = CheckArg.getInstanceOf(operand, JcrDynamicOperand.class, "operand");
642         JcrStaticOperand lower = CheckArg.getInstanceOf(lowerBound, JcrStaticOperand.class, "lowerBound");
643         JcrStaticOperand upper = CheckArg.getInstanceOf(upperBound, JcrStaticOperand.class, "upperBound");
644         return new JcrBetween(jcrOperand, lower, upper, includeLowerBound, includeUpperBound);
645     }
646 
647     /**
648      * {@inheritDoc}
649      * 
650      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#in(javax.jcr.query.qom.DynamicOperand,
651      *      javax.jcr.query.qom.StaticOperand[])
652      */
653     @Override
654     public SetCriteria in( DynamicOperand operand,
655                            StaticOperand... values ) {
656         JcrDynamicOperand jcrOperand = CheckArg.getInstanceOf(operand, JcrDynamicOperand.class, "operand");
657         List<JcrStaticOperand> jcrValues = new ArrayList<JcrStaticOperand>();
658         for (StaticOperand value : values) {
659             JcrStaticOperand jcrValue = CheckArg.getInstanceOf(value, JcrStaticOperand.class, "values");
660             jcrValues.add(jcrValue);
661         }
662         return new JcrSetCriteria(jcrOperand, jcrValues);
663     }
664 
665     /**
666      * {@inheritDoc}
667      * 
668      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#subquery(org.modeshape.jcr.api.query.qom.QueryCommand)
669      */
670     @Override
671     public Subquery subquery( QueryCommand subqueryCommand ) {
672         JcrQueryCommand jcrCommand = CheckArg.getInstanceOf(subqueryCommand, JcrQueryCommand.class, "subqueryCommand");
673         return new JcrSubquery(jcrCommand);
674     }
675 
676     /**
677      * {@inheritDoc}
678      * 
679      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#add(javax.jcr.query.qom.DynamicOperand,
680      *      javax.jcr.query.qom.DynamicOperand)
681      */
682     @Override
683     public ArithmeticOperand add( DynamicOperand left,
684                                   DynamicOperand right ) {
685         return arithmeticOperand(left, ArithmeticOperator.ADD, right);
686     }
687 
688     /**
689      * {@inheritDoc}
690      * 
691      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#subtract(javax.jcr.query.qom.DynamicOperand,
692      *      javax.jcr.query.qom.DynamicOperand)
693      */
694     @Override
695     public ArithmeticOperand subtract( DynamicOperand left,
696                                        DynamicOperand right ) {
697         return arithmeticOperand(left, ArithmeticOperator.SUBTRACT, right);
698     }
699 
700     /**
701      * {@inheritDoc}
702      * 
703      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#multiply(javax.jcr.query.qom.DynamicOperand,
704      *      javax.jcr.query.qom.DynamicOperand)
705      */
706     @Override
707     public ArithmeticOperand multiply( DynamicOperand left,
708                                        DynamicOperand right ) {
709         return arithmeticOperand(left, ArithmeticOperator.MULTIPLY, right);
710     }
711 
712     /**
713      * {@inheritDoc}
714      * 
715      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#divide(javax.jcr.query.qom.DynamicOperand,
716      *      javax.jcr.query.qom.DynamicOperand)
717      */
718     @Override
719     public ArithmeticOperand divide( DynamicOperand left,
720                                      DynamicOperand right ) {
721         return arithmeticOperand(left, ArithmeticOperator.DIVIDE, right);
722     }
723 
724     public ArithmeticOperand arithmeticOperand( DynamicOperand left,
725                                                 ArithmeticOperator operator,
726                                                 DynamicOperand right ) {
727         JcrDynamicOperand leftOperand = CheckArg.getInstanceOf(left, JcrDynamicOperand.class, "left");
728         JcrDynamicOperand rightOperand = CheckArg.getInstanceOf(left, JcrDynamicOperand.class, "left");
729         return new JcrArithmeticOperand(leftOperand, operator, rightOperand);
730     }
731 
732     /**
733      * {@inheritDoc}
734      * 
735      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#referenceValue(java.lang.String)
736      */
737     @Override
738     public JcrReferenceValue referenceValue( String selectorName ) {
739         return new JcrReferenceValue(selectorName(selectorName), null);
740     }
741 
742     /**
743      * {@inheritDoc}
744      * 
745      * @see org.modeshape.jcr.api.query.qom.QueryObjectModelFactory#referenceValue(java.lang.String, java.lang.String)
746      */
747     @Override
748     public JcrReferenceValue referenceValue( String selectorName,
749                                              String propertyName ) {
750         return new JcrReferenceValue(selectorName(selectorName), propertyName);
751     }
752 
753 }