/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2015 ForgeRock AS. All rights reserved.
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://forgerock.org/license/CDDLv1.0.html
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at http://forgerock.org/license/CDDLv1.0.html
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*/
package org.forgerock.openidm.repo.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.forgerock.guava.common.base.Function;
import org.forgerock.guava.common.collect.FluentIterable;
/**
* A utility class containing factory methods for creating {@link Clause}s.
*/
public final class Clauses {
/**
* An abstract clause implementation to combine clauses with each other through
* the {@link Clause} interface's and(), or(), and not() methods.
*/
private static abstract class AbstractClause implements Clause {
public Clause and(String clause) {
return and(where(clause));
}
public Clause and(Clause and) {
return new AndClause(this, and);
}
public Clause or(String clause) {
return or(where(clause));
}
public Clause or(Clause or) {
return new OrClause(this, or);
}
public Clause not() {
return new NotClause(this);
}
@Override
public String toString() {
return toSQL();
}
}
/**
* A simple clause to wrap a String expression.
*/
private static class SimpleClause extends AbstractClause implements Clause {
private final String clause;
SimpleClause(String clause) {
this.clause = clause;
}
public String toSQL() {
return clause;
}
}
/**
* An abstract composite clause implementation to join multiple clauses using AND or OR.
*/
private abstract static class CompositeClause extends AbstractClause implements Clause {
protected final List<Clause> clauses = new ArrayList<Clause>();
CompositeClause(Clause... clauses) {
this(Arrays.asList(clauses));
}
CompositeClause(Iterable<Clause> clauses) {
for (Clause clause : clauses) {
this.clauses.add(clause);
}
}
String toSQL(String operand) {
return new StringBuffer("(")
.append(StringUtils.join(FluentIterable.from(clauses)
.transform(new Function<Clause, String>() {
@Override
public String apply(Clause value) {
return value.toSQL();
}
}), operand))
.append(")")
.toString();
}
}
/**
* A composite clause that models an OR-expression of multiple clauses.
*/
private static class OrClause extends CompositeClause implements Clause {
OrClause(Clause... clauses) {
super(clauses);
}
OrClause(Iterable<Clause> clauses) {
super(clauses);
}
@Override
public Clause and(Clause clause) {
return new AndClause(Arrays.asList(this, clause));
}
@Override
public Clause or(Clause clause) {
clauses.add(clause);
return this;
}
public String toSQL() {
return super.toSQL(" OR ");
}
}
/**
* A composite clause that models an AND-expression of multiple clauses.
*/
private static class AndClause extends CompositeClause implements Clause {
AndClause(Clause... clauses) {
super(Arrays.asList(clauses));
}
AndClause(Iterable<Clause> clauses) {
super(clauses);
}
@Override
public Clause and(Clause clause) {
clauses.add(clause);
return this;
}
@Override
public OrClause or(Clause clause) {
return new OrClause(Arrays.asList(this, clause));
}
public String toSQL() {
return super.toSQL(" AND ");
}
}
/**
* A clause that models the negation of another clause.
*/
private static class NotClause extends AbstractClause implements Clause {
private final Clause clause;
NotClause(Clause clause) {
this.clause = clause;
}
public String toSQL() {
return "NOT " + clause.toSQL();
}
}
/**
* Returns a new where-clause from the provided String expression.
*
* @param clause a clause/expression
* @return a Clause object
*/
public static Clause where(String clause) {
return new SimpleClause(clause);
}
/**
* Returns a not-clause from the provided String expression.
*
* @param clause a clause/expression
* @return a Clause object
*/
public static Clause not(String clause) {
return new NotClause(where(clause));
}
/**
* Returns a negative of the provided clause.
*
* @param clause a clause/expression
* @return a Clause object
*/
public static Clause not(Clause clause) {
return new NotClause(clause);
}
/**
* Returns a composite "AND" clause of the provided constituent clauses.
*
* @param clauses a iterable (list) of clauses
* @return a composite "and" clause
*/
public static Clause and(Iterable<Clause> clauses) {
return new AndClause(clauses);
}
/**
* Returns a composite "OR" clause of the provided constituent clauses.
*
* @param clauses a iterable (list) of clauses
* @return a composite "or" clause
*/
public static Clause or(Iterable<Clause> clauses) {
return new OrClause(clauses);
}
private Clauses() {
// no construction
}
}