001 /* 002 * Copyright 2002-2004 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.rules.reporting; 017 018 import java.util.Stack; 019 020 import org.apache.commons.logging.Log; 021 import org.apache.commons.logging.LogFactory; 022 import org.springframework.rules.constraint.Constraint; 023 import org.springframework.core.style.ToStringCreator; 024 import org.springframework.rules.constraint.*; 025 026 /** 027 * @author Keith Donald 028 */ 029 public abstract class ValidationResultsBuilder { 030 protected static final Log logger = LogFactory 031 .getLog(ValidationResultsBuilder.class); 032 private Constraint top; 033 private Stack levels = new Stack(); 034 035 public void pushAnd() { 036 And and = new And(); 037 add(and); 038 } 039 040 public void pushOr() { 041 Or or = new Or(); 042 add(or); 043 } 044 045 public void pushNot() { 046 Not not = new Not(); 047 add(not); 048 } 049 050 private void add(Constraint predicate) { 051 if (top != null) { 052 if (top instanceof Not) { 053 if (logger.isDebugEnabled()) { 054 logger.debug("Negating predicate [" + predicate + "]"); 055 } 056 ((Not)this.top).setConstraint(predicate); 057 } else { 058 if (logger.isDebugEnabled()) { 059 logger.debug("Aggregating nested predicate [" + predicate 060 + "]"); 061 } 062 ((CompoundConstraint)this.top).add(predicate); 063 } 064 } 065 levels.push(predicate); 066 this.top = predicate; 067 if (logger.isDebugEnabled()) { 068 logger.debug("Predicate [" + predicate + "] is at the top."); 069 } 070 } 071 072 public void push(Constraint constraint) { 073 if (this.top instanceof CompoundConstraint) { 074 if (logger.isDebugEnabled()) { 075 logger.debug("Adding constraint [" + constraint + "]"); 076 } 077 ((CompoundConstraint)this.top).add(constraint); 078 } else if (this.top instanceof Not) { 079 if (logger.isDebugEnabled()) { 080 logger.debug("Negating constraint [" + constraint + "]"); 081 } 082 ((Not)this.top).setConstraint(constraint); 083 } else if (this.top == null) { 084 constraintViolated(constraint); 085 } else { 086 throw new IllegalArgumentException(constraint.toString()); 087 } 088 } 089 090 public void pop(boolean result) { 091 Constraint p = (Constraint)levels.pop(); 092 if (logger.isDebugEnabled()) { 093 logger.debug("Top [" + p + "] popped; result was " + result 094 + "; stack now has " + levels.size() + " elements"); 095 } 096 if (levels.isEmpty()) { 097 if (!result) { 098 constraintViolated(top); 099 } else { 100 constraintSatisfied(); 101 } 102 top = null; 103 } else { 104 this.top = (Constraint)levels.peek(); 105 if (result) { 106 if (logger.isDebugEnabled()) { 107 logger.debug("Removing compound predicate [" + p 108 + "]; tested true."); 109 } 110 ((CompoundConstraint)this.top).remove(p); 111 } 112 } 113 } 114 115 protected void clear() { 116 levels.clear(); 117 top = null; 118 } 119 120 public boolean negated() { 121 if (levels.size() == 0) { 122 return false; 123 } 124 return peek() instanceof Not; 125 } 126 127 private Constraint peek() { 128 return (Constraint)levels.peek(); 129 } 130 131 protected abstract void constraintViolated(Constraint constraint); 132 protected abstract void constraintSatisfied(); 133 134 public String toString() { 135 return new ToStringCreator(this).append("topOfStack", top).append( 136 "levelsStack", levels).toString(); 137 } 138 139 }