org.cp.elements.lang.LogicalOperator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cp-elements Show documentation
Show all versions of cp-elements Show documentation
Java Simplified. Extensions and Useful Constructs for the Java Platform.
Codeprimate Elements (a.k.a. cp-elements) is a Java library and micro-framework used to simplify
the development of software applications written in Java. Elements packages several APIs into one
library in order to address various application concerns and aspects of software design and development
collectively and conveniently. Elements is a highly simple, yet robust and proven library built on
solid OO principles, software design patterns and best practices to effectively solve common
and reoccurring problems in software development.
/*
* Copyright 2016 Author or Authors.
*
* Licensed 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.cp.elements.lang;
import java.util.function.Supplier;
/**
* The LogicalOperator class defines class representations for the standard logical operators AND ({@literal &&})
* and OR ({@literal ||}).
*
* @author John J. Blum
* @see org.cp.elements.lang.RelationalOperator
* @since 1.0.0
*/
public abstract class LogicalOperator {
public static final LogicalOperator AND = new LogicalAnd();
public static final LogicalOperator OR = new LogicalOr();
public static final LogicalOperator XOR = new LogicalXor();
/**
* This method will negate outcome of the given logical operator when performing an evaluation on a group
* of conditions.
*
* @param op the LogicalOperator (such as AND or OR) to negate.
* @return the given logical operator decorated with logical not.
* @see LogicalNot
*/
public static LogicalOperator negate(LogicalOperator op) {
return new LogicalNot(op.getOpposite());
}
/**
* Indicates whether this logical operator is a binary operator. A binary operator is an operator with two operands.
* With LogicalOperator implementations, such as AND and OR, this is expanded to mean two or more operands.
*
* @return a boolean value indicating if this logical operator is a binary operator.
* @see #isTernary()
* @see #isUnary()
*/
public abstract boolean isBinary();
/**
* Indicates whether this logical operator is the ternary operator, which in Java is represented as
* (condition ? trueValue : falseValue), or as a if-then-else statement (ifTrue ? thenValue : elseValue).
*
* @return a boolean value indicating if this logical operator is the ternary operator.
* @see #isBinary()
* @see #isUnary()
*/
public abstract boolean isTernary();
/**
* Indicates whether this logical operator is a unary operator. A unary operator is an operator with only
* one operand, such as the NOT operator.
*
* @return a boolean value indicating if this logical operator is an unary operator.
* @see #isBinary()
* @see #isTernary()
*/
public abstract boolean isUnary();
/**
* Returns a description of this logical operator, such as 'and' or 'or'.
*
* @return a String value describing this logical operator.
* @see #getSymbol()
*/
public abstract String getDescription();
/**
* Gets the logical opposite of this logical operator. For instance, the logical opposite of AND is OR;
* the logical opposite of OR is AND. The logical opposite of NOT is NOT NOT (double negative) resulting in positive.
* For instance, NOT(NOT(TRUE)) is TRUE.
*
* @return the logical opposite of this logical operator.
*/
public abstract LogicalOperator getOpposite();
/**
* Gets the symbolic representation of this logical operator. For instance, the symbolic representation of AND
* in Java is {@literal &&}, and the symbolic representation of OR in Java is {@literal ||}.
*
* @return a String value representing the symbolic representation of this logical operator.
* @see #getDescription()
*/
public abstract String getSymbol();
/**
* Evaluates the given array of boolean conditions by applying this logical operator to all conditions collectively.
*
* @param conditions a boolean array of conditions to which this logical operator is applied.
* @return a boolean value resulting from the evaluation of the given boolean conditions with this logical operator.
*/
public abstract boolean evaluate(boolean... conditions);
/**
* Evaluates the given array of boolean based {@link Supplier}s by applying this logical operation to all conditions
* supplied collectively.
*
* @param suppliers an array of {@link Supplier}s supplying the boolean conditions to evaluate.
* @return a boolean value resulting from the evaluation of the given {@link Supplier}s of boolean values
* with this logical operater.
* @see java.util.function.Supplier
*/
@SuppressWarnings({ "unchecked", "varargs" })
public abstract boolean evaluate(Supplier... suppliers);
/**
* Gets a String representation of the logical operator.
*
* @return a String value representing the logical operator.
* @see org.cp.elements.lang.LogicalOperator#getDescription
*/
@Override
public String toString() {
return getDescription();
}
/**
* The abstract base class for all subclasses of the LogicalOperator class.
*/
protected static abstract class AbstractLogicalOperator extends LogicalOperator {
private final String description;
private final String symbol;
/**
* Constructs a instance of the LogicalOperator class with the given description and symbol
* for the logical operator.
*
* @param description a String value describing the logical operator.
* @param symbol a String value symbolically represending the logical operator.
* @throws IllegalArgumentException if either the description or symbol are not specified.
*/
protected AbstractLogicalOperator(String description, String symbol) {
Assert.hasText(description, "The description of this logical operator must be specified");
Assert.hasText(symbol, "The symbolic representation of this logical operator must be specified");
this.description = description;
this.symbol = symbol;
}
/**
* Indicates whether this logical operator is a binary operation. A binary operator is an operator with two operands.
* With LogicalOperator implementations, such as AND and OR, this is expanded to mean two or more operands.
*
* @return a boolean value indicating if this logical operator is a binary operator.
* @see #isTernary()
* @see #isUnary()
*/
@Override
public boolean isBinary() {
return false;
}
/**
* Indicates whether this logical operator is the ternary operator, which in Java is represented as
* (condition ? trueValue : falseValue), or as a if-then-else statement (ifTrue ? thenValue : elseValue).
*
* @return a boolean value indicating if this logical operator is the ternary operator.
* @see #isBinary()
* @see #isUnary()
*/
@Override
public boolean isTernary() {
return false;
}
/**
* Indicates whether this logical operator is a unary operator. A unary operator is an operator with only
* one operand, such as the NOT operator.
*
* @return a boolean value indicating if this logical operator is an unary operator.
* @see #isBinary()
* @see #isTernary()
*/
@Override
public boolean isUnary() {
return false;
}
/**
* Gets a description of this logical operator, such as 'and' or 'or'.
*
* @return a String value describing this logical operator.
* @see #getSymbol()
*/
@Override
public String getDescription() {
return this.description;
}
/**
* Gets the logical opposite of this logical operator. For instance, the logical opposite of AND is OR;
* the logical opposite of OR is AND. The logical opposite of NOT is NOT NOT (double negative) resulting
* in positive.
* For instance, NOT(NOT(TRUE)) is TRUE.
*
* @return the logical opposite of this logical operator.
*/
@Override
public LogicalOperator getOpposite() {
throw new UnsupportedOperationException(Constants.NOT_IMPLEMENTED);
}
/**
* Gets the symbolic representation of this logical operator. For instance, the symbolic representation of AND
* in Java is {@literal &&}, and the symbolic representation of OR in Java is {@literal ||}.
*
* @return a String value representing the symbolic representation of this logical operator.
* @see #getDescription()
*/
@Override
public String getSymbol() {
return this.symbol;
}
}
/**
* LogicalAnd is a {@link LogicalOperator} implementation of the binary, logical AND operator.
*/
static final class LogicalAnd extends AbstractLogicalOperator {
/**
* Constructs an instance of the LogicalAnd operator.
*/
LogicalAnd() {
super("and", "&&");
}
/* (non-Javadoc) */
@Override
public boolean isBinary() {
return true;
}
/* (non-Javadoc) */
@Override
public LogicalOperator getOpposite() {
return LogicalOperator.OR;
}
/* (non-Javadoc) */
@Override
public boolean evaluate(boolean... conditions) {
for (boolean condition : conditions) {
if (!condition) {
return false;
}
}
return true;
}
/* (non-Javadoc) */
@Override
@SafeVarargs
public final boolean evaluate(Supplier... suppliers) {
for (Supplier supplier : suppliers) {
if (!Boolean.TRUE.equals(supplier.get())) {
return false;
}
}
return true;
}
}
/**
* LogicalNot is a {@link LogicalOperator} implementation of the unary, logical NOT operator.
*/
static final class LogicalNot extends AbstractLogicalOperator {
private final LogicalOperator op;
/**
* Constructs an instance of the LogicalNot operator.
*
* @param op the LogicalOperator to negate.
*/
LogicalNot(LogicalOperator op) {
super("not", "!");
Assert.notNull(op, "The LogicalOperator to negate cannot be null");
this.op = op;
}
/* (non-Javadoc) */
@Override
public boolean isUnary() {
return true;
}
/* (non-Javadoc) */
@SuppressWarnings("unused")
LogicalOperator getOp() {
return this.op;
}
/* (non-Javadoc) */
@Override
public LogicalOperator getOpposite() {
return this;
}
/* (non-Javadoc) */
@Override
public boolean evaluate(boolean... conditions) {
return !this.op.evaluate(conditions);
}
/* (non-Javadoc) */
@Override
@SafeVarargs
public final boolean evaluate(Supplier... suppliers) {
return !this.op.evaluate(suppliers);
}
}
/**
* LogicalOr is a {@link LogicalOperator} implementation of the binary, logical OR operator.
*/
static final class LogicalOr extends AbstractLogicalOperator {
/**
* Constructs an instance of the LogicalOr operator.
*/
LogicalOr() {
super("or", "||");
}
/* (non-Javadoc) */
@Override
public boolean isBinary() {
return true;
}
/* (non-Javadoc) */
@Override
public LogicalOperator getOpposite() {
return LogicalOperator.AND;
}
/* (non-Javadoc) */
@Override
public boolean evaluate(boolean... conditions) {
for (boolean condition : conditions) {
if (condition) {
return true;
}
}
return false;
}
/* (non-Javadoc) */
@Override
@SafeVarargs
public final boolean evaluate(Supplier... suppliers) {
for (Supplier supplier : suppliers) {
if (Boolean.TRUE.equals(supplier.get())) {
return true;
}
}
return false;
}
}
/**
* LogicalXor is a {@link LogicalOperator} implementation of the binary, logical XOR operator.
*/
static final class LogicalXor extends AbstractLogicalOperator {
/**
* Constructs an instance of the LogicalXor operator.
*/
LogicalXor() {
super("xor", "^");
}
/* (non-Javadoc) */
@Override
public boolean isBinary() {
return true;
}
/* (non-Javadoc) */
@Override
public LogicalOperator getOpposite() {
return this;
}
@Override
public boolean evaluate(boolean... conditions) {
int count = 0;
for (int index = 0; index < conditions.length && count < 2; index++) {
if (conditions[index]) {
count++;
}
}
return (count == 1);
}
/* (non-Javadoc) */
@Override
@SafeVarargs
public final boolean evaluate(Supplier... suppliers) {
int count = 0;
for (int index = 0; index < suppliers.length && count < 2; index++) {
if (Boolean.TRUE.equals(suppliers[index].get())) {
count++;
}
}
return (count == 1);
}
}
}