/**
* Copyright (C) 2015 Valkyrie RCP
*
* 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.valkyriercp.rules.reporting;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.style.ToStringCreator;
import org.valkyriercp.rules.constraint.*;
import java.util.Stack;
/**
* @author Keith Donald
*/
public abstract class ValidationResultsBuilder {
protected static final Log logger = LogFactory
.getLog(ValidationResultsBuilder.class);
private Constraint top;
private Stack levels = new Stack();
public void pushAnd() {
And and = new And();
add(and);
}
public void pushOr() {
Or or = new Or();
add(or);
}
public void pushNot() {
Not not = new Not();
add(not);
}
private void add(Constraint predicate) {
if (top != null) {
if (top instanceof Not) {
if (logger.isDebugEnabled()) {
logger.debug("Negating predicate [" + predicate + "]");
}
((Not)this.top).setConstraint(predicate);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Aggregating nested predicate [" + predicate
+ "]");
}
((CompoundConstraint)this.top).add(predicate);
}
}
levels.push(predicate);
this.top = predicate;
if (logger.isDebugEnabled()) {
logger.debug("Predicate [" + predicate + "] is at the top.");
}
}
public void push(Constraint constraint) {
if (this.top instanceof CompoundConstraint) {
if (logger.isDebugEnabled()) {
logger.debug("Adding constraint [" + constraint + "]");
}
((CompoundConstraint)this.top).add(constraint);
} else if (this.top instanceof Not) {
if (logger.isDebugEnabled()) {
logger.debug("Negating constraint [" + constraint + "]");
}
((Not)this.top).setConstraint(constraint);
} else if (this.top == null) {
constraintViolated(constraint);
} else {
throw new IllegalArgumentException(constraint.toString());
}
}
public void pop(boolean result) {
Constraint p = (Constraint)levels.pop();
if (logger.isDebugEnabled()) {
logger.debug("Top [" + p + "] popped; result was " + result
+ "; stack now has " + levels.size() + " elements");
}
if (levels.isEmpty()) {
if (!result) {
constraintViolated(top);
} else {
constraintSatisfied();
}
top = null;
} else {
this.top = (Constraint)levels.peek();
if (result) {
if (logger.isDebugEnabled()) {
logger.debug("Removing compound predicate [" + p
+ "]; tested true.");
}
((CompoundConstraint)this.top).remove(p);
}
}
}
protected void clear() {
levels.clear();
top = null;
}
public boolean negated() {
if (levels.size() == 0) {
return false;
}
return peek() instanceof Not;
}
private Constraint peek() {
return (Constraint)levels.peek();
}
protected abstract void constraintViolated(Constraint constraint);
protected abstract void constraintSatisfied();
public String toString() {
return new ToStringCreator(this).append("topOfStack", top).append(
"levelsStack", levels).toString();
}
}