/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jackrabbit.core.security.user; import org.apache.jackrabbit.api.security.user.Authorizable; import org.apache.jackrabbit.api.security.user.QueryBuilder; import javax.jcr.RepositoryException; import javax.jcr.Value; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class XPathQueryBuilder implements QueryBuilder<XPathQueryBuilder.Condition> { /** * Relational operators for comparing a property to a value. Correspond * to the general comparison operators as define in JSR-170. * The {@link #EX} tests for existence of a property. */ enum RelationOp { NE("!="), EQ("="), LT("<"), LE("<="), GT(">"), GE("=>"), EX(""), LIKE("like"); private final String op; RelationOp(String op) { this.op = op; } public String getOp() { return op; } } interface Condition { void accept(ConditionVisitor visitor) throws RepositoryException; } interface ConditionVisitor { void visit(NodeCondition nodeCondition) throws RepositoryException; void visit(PropertyCondition condition) throws RepositoryException; void visit(ContainsCondition condition); void visit(ImpersonationCondition condition); void visit(NotCondition condition) throws RepositoryException; void visit(AndCondition condition) throws RepositoryException; void visit(OrCondition condition) throws RepositoryException; } private Class<? extends Authorizable> selector = Authorizable.class; private String groupName; private boolean declaredMembersOnly; private Condition condition; private String sortProperty; private Direction sortDirection = Direction.ASCENDING; private boolean sortIgnoreCase; private Value bound; private long offset; private long maxCount = -1; Class<? extends Authorizable> getSelector() { return selector; } public String getGroupName() { return groupName; } public boolean isDeclaredMembersOnly() { return declaredMembersOnly; } Condition getCondition() { return condition; } String getSortProperty() { return sortProperty; } Direction getSortDirection() { return sortDirection; } boolean getSortIgnoreCase() { return sortIgnoreCase; } Value getBound() { return bound; } long getOffset() { return offset; } long getMaxCount() { return maxCount; } //------------------------------------------< QueryBuilder >--- public void setSelector(Class<? extends Authorizable> selector) { this.selector = selector; } public void setScope(String groupName, boolean declaredOnly) { this.groupName = groupName; declaredMembersOnly = declaredOnly; } public void setCondition(Condition condition) { this.condition = condition; } public void setSortOrder(String propertyName, Direction direction, boolean ignoreCase) { sortProperty = propertyName; sortDirection = direction; sortIgnoreCase = ignoreCase; } public void setSortOrder(String propertyName, Direction direction) { setSortOrder(propertyName, direction, false); } public void setLimit(Value bound, long maxCount) { offset = 0; // Unset any previously set offset this.bound = bound; this.maxCount = maxCount; } public void setLimit(long offset, long maxCount) { bound = null; // Unset any previously set bound this.offset = offset; this.maxCount = maxCount; } public Condition property(String relPath, RelationOp op, Value value) { return new PropertyCondition(relPath, op, value); } public Condition nameMatches(String pattern) { return new NodeCondition(pattern); } public Condition neq(String relPath, Value value) { return new PropertyCondition(relPath, RelationOp.NE, value); } public Condition eq(String relPath, Value value) { return new PropertyCondition(relPath, RelationOp.EQ, value); } public Condition lt(String relPath, Value value) { return new PropertyCondition(relPath, RelationOp.LT, value); } public Condition le(String relPath, Value value) { return new PropertyCondition(relPath, RelationOp.LE, value); } public Condition gt(String relPath, Value value) { return new PropertyCondition(relPath, RelationOp.GT, value); } public Condition ge(String relPath, Value value) { return new PropertyCondition(relPath, RelationOp.GE, value); } public Condition exists(String relPath) { return new PropertyCondition(relPath, RelationOp.EX); } public Condition like(String relPath, String pattern) { return new PropertyCondition(relPath, RelationOp.LIKE, pattern); } public Condition contains(String relPath, String searchExpr) { return new ContainsCondition(relPath, searchExpr); } public Condition impersonates(String name) { return new ImpersonationCondition(name); } public Condition not(Condition condition) { return new NotCondition(condition); } public Condition and(Condition condition1, Condition condition2) { return new AndCondition(condition1, condition2); } public Condition or(Condition condition1, Condition condition2) { return new OrCondition(condition1, condition2); } //------------------------------------------< private >--- static class NodeCondition implements Condition { private final String pattern; public NodeCondition(String pattern) { this.pattern = pattern; } public String getPattern() { return pattern; } public void accept(ConditionVisitor visitor) throws RepositoryException { visitor.visit(this); } } static class PropertyCondition implements Condition { private final String relPath; private final RelationOp op; private final Value value; private final String pattern; public PropertyCondition(String relPath, RelationOp op, Value value) { this.relPath = relPath; this.op = op; this.value = value; pattern = null; } public PropertyCondition(String relPath, RelationOp op, String pattern) { this.relPath = relPath; this.op = op; value = null; this.pattern = pattern; } public PropertyCondition(String relPath, RelationOp op) { this.relPath = relPath; this.op = op; value = null; pattern = null; } public String getRelPath() { return relPath; } public RelationOp getOp() { return op; } public Value getValue() { return value; } public String getPattern() { return pattern; } public void accept(ConditionVisitor visitor) throws RepositoryException { visitor.visit(this); } } static class ContainsCondition implements Condition { private final String relPath; private final String searchExpr; public ContainsCondition(String relPath, String searchExpr) { this.relPath = relPath; this.searchExpr = searchExpr; } public String getRelPath() { return relPath; } public String getSearchExpr() { return searchExpr; } public void accept(ConditionVisitor visitor) { visitor.visit(this); } } static class ImpersonationCondition implements Condition { private final String name; public ImpersonationCondition(String name) { this.name = name; } public String getName() { return name; } public void accept(ConditionVisitor visitor) { visitor.visit(this); } } static class NotCondition implements Condition { private final Condition condition; public NotCondition(Condition condition) { this.condition = condition; } public Condition getCondition() { return condition; } public void accept(ConditionVisitor visitor) throws RepositoryException { visitor.visit(this); } } abstract static class CompoundCondition implements Condition, Iterable<Condition> { private final List<Condition> conditions = new ArrayList<Condition>(); public CompoundCondition() { super(); } public CompoundCondition(Condition condition1, Condition condition2) { conditions.add(condition1); conditions.add(condition2); } public void addCondition(Condition condition) { conditions.add(condition); } public Iterator<Condition> iterator() { return conditions.iterator(); } } static class AndCondition extends CompoundCondition { public AndCondition(Condition condition1, Condition condition2) { super(condition1, condition2); } public void accept(ConditionVisitor visitor) throws RepositoryException { visitor.visit(this); } } static class OrCondition extends CompoundCondition { public OrCondition(Condition condition1, Condition condition2) { super(condition1, condition2); } public void accept(ConditionVisitor visitor) throws RepositoryException { visitor.visit(this); } } }