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