001 /**
002 * Copyright 2005-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
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,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.krad.datadictionary.validation.result;
017
018 import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
019 import org.kuali.rice.krad.datadictionary.validation.ErrorLevel;
020 import org.kuali.rice.krad.datadictionary.validation.ValidationUtils;
021
022 import java.util.Iterator;
023 import java.util.LinkedHashMap;
024 import java.util.Map;
025
026 /**
027 *
028 * @author Kuali Rice Team (rice.collab@kuali.org)
029 */
030 public class DictionaryValidationResult implements Iterable<ConstraintValidationResult> {
031
032 private Map<String, EntryValidationResult> entryValidationResultMap;
033 private ErrorLevel errorLevel;
034
035 private int numberOfErrors;
036 private int numberOfWarnings;
037
038 private Iterator<ConstraintValidationResult> iterator;
039
040 public DictionaryValidationResult() {
041 this.entryValidationResultMap = new LinkedHashMap<String, EntryValidationResult>();
042 this.errorLevel = ErrorLevel.ERROR;
043 this.numberOfErrors = 0;
044 this.numberOfWarnings = 0;
045 }
046
047 public void addConstraintValidationResult(AttributeValueReader attributeValueReader, ConstraintValidationResult constraintValidationResult) {
048
049 // Don't bother to store this if the error level of the constraint validation result is lower than the level this dictionary validation result is tracking
050 if (constraintValidationResult.getStatus().getLevel() < errorLevel.getLevel())
051 return;
052
053 switch (constraintValidationResult.getStatus()) {
054 case ERROR:
055 numberOfErrors++;
056 break;
057 case WARN:
058 numberOfWarnings++;
059 break;
060 default:
061 // Do nothing
062 }
063
064 // Give the constraint a chance to override the entry and attribute name - important if the attribute name is not the same as the one in the attribute value reader!
065 String entryName = constraintValidationResult.getEntryName();
066 String attributeName = constraintValidationResult.getAttributeName();
067 String attributePath = constraintValidationResult.getAttributePath();
068
069 if (entryName == null){
070 entryName = attributeValueReader.getEntryName();
071 }
072
073 if (attributeName == null){
074 attributeName = attributeValueReader.getAttributeName();
075 }
076
077 if (attributePath == null){
078 attributePath = attributeValueReader.getPath();
079 }
080
081 constraintValidationResult.setEntryName(entryName);
082 constraintValidationResult.setAttributeName(attributeName);
083 constraintValidationResult.setAttributePath(attributePath);
084
085 String entryKey = getEntryValdidationResultKey(entryName, attributePath);
086 getEntryValidationResult(entryKey).getAttributeValidationResult(attributeName).addConstraintValidationResult(constraintValidationResult);
087 }
088
089 public ConstraintValidationResult addError(AttributeValueReader attributeValueReader, String constraintName, String errorKey, String... errorParameters) {
090 ConstraintValidationResult constraintValidationResult = getConstraintValidationResult(attributeValueReader.getEntryName(), attributeValueReader.getAttributeName(), attributeValueReader.getPath(), constraintName);
091 constraintValidationResult.setError(errorKey, errorParameters);
092 numberOfErrors++;
093 return constraintValidationResult;
094 }
095
096 public ConstraintValidationResult addError(String constraintLabelKey, AttributeValueReader attributeValueReader, String constraintName, String errorKey, String... errorParameters) {
097 ConstraintValidationResult constraintValidationResult = getConstraintValidationResult(attributeValueReader.getEntryName(), attributeValueReader.getAttributeName(), attributeValueReader.getPath(), constraintName);
098 constraintValidationResult.setError(errorKey, errorParameters);
099 constraintValidationResult.setConstraintLabelKey(constraintLabelKey);
100 numberOfErrors++;
101 return constraintValidationResult;
102 }
103
104 public ConstraintValidationResult addWarning(AttributeValueReader attributeValueReader, String constraintName, String errorKey, String... errorParameters) {
105 if (errorLevel.getLevel() > ErrorLevel.WARN.getLevel())
106 return new ConstraintValidationResult(constraintName, ErrorLevel.WARN);
107
108 ConstraintValidationResult constraintValidationResult = getConstraintValidationResult(attributeValueReader.getEntryName(), attributeValueReader.getAttributeName(), attributeValueReader.getPath(), constraintName);
109 constraintValidationResult.setWarning(errorKey, errorParameters);
110 numberOfWarnings++;
111 return constraintValidationResult;
112 }
113
114 public ConstraintValidationResult addSuccess(AttributeValueReader attributeValueReader, String constraintName) {
115 if (errorLevel.getLevel() > ErrorLevel.OK.getLevel())
116 return new ConstraintValidationResult(constraintName, ErrorLevel.OK);
117
118 return getConstraintValidationResult(attributeValueReader.getEntryName(), attributeValueReader.getAttributeName(), attributeValueReader.getPath(), constraintName);
119 }
120
121 public ConstraintValidationResult addSkipped(AttributeValueReader attributeValueReader, String constraintName) {
122 if (errorLevel.getLevel() > ErrorLevel.OK.getLevel())
123 return new ConstraintValidationResult(constraintName, ErrorLevel.INAPPLICABLE);
124
125 ConstraintValidationResult constraintValidationResult = getConstraintValidationResult(attributeValueReader.getEntryName(), attributeValueReader.getAttributeName(), attributeValueReader.getPath(), constraintName);
126 constraintValidationResult.setStatus(ErrorLevel.INAPPLICABLE);
127 return constraintValidationResult;
128 }
129
130 public ConstraintValidationResult addNoConstraint(AttributeValueReader attributeValueReader, String constraintName) {
131 if (errorLevel.getLevel() > ErrorLevel.OK.getLevel())
132 return new ConstraintValidationResult(constraintName, ErrorLevel.NOCONSTRAINT);
133
134 ConstraintValidationResult constraintValidationResult = getConstraintValidationResult(attributeValueReader.getEntryName(), attributeValueReader.getAttributeName(), attributeValueReader.getPath(), constraintName);
135 constraintValidationResult.setStatus(ErrorLevel.NOCONSTRAINT);
136 return constraintValidationResult;
137 }
138
139 public Iterator<ConstraintValidationResult> iterator() {
140
141 iterator = new Iterator<ConstraintValidationResult>() {
142
143 private Iterator<EntryValidationResult> entryIterator;
144 private Iterator<AttributeValidationResult> attributeIterator;
145 private Iterator<ConstraintValidationResult> constraintIterator;
146
147 @Override
148 public boolean hasNext() {
149 Iterator<ConstraintValidationResult> currentConstraintIterator = getCurrentConstraintIterator();
150 return currentConstraintIterator != null && currentConstraintIterator.hasNext();
151 }
152
153 @Override
154 public ConstraintValidationResult next() {
155 Iterator<ConstraintValidationResult> currentConstraintIterator = getCurrentConstraintIterator();
156 return currentConstraintIterator != null ? currentConstraintIterator.next() : null;
157 }
158
159 @Override
160 public void remove() {
161 throw new RuntimeException("Can't remove from this iterator!");
162 }
163
164 private Iterator<ConstraintValidationResult> getCurrentConstraintIterator() {
165 if (constraintIterator == null || constraintIterator.hasNext() == false) {
166 Iterator<AttributeValidationResult> currentAttributeIterator = getCurrentAttributeIterator();
167 if (currentAttributeIterator != null && currentAttributeIterator.hasNext()) {
168 AttributeValidationResult currentAttributeValidationResult = currentAttributeIterator.next();
169 constraintIterator = currentAttributeValidationResult.iterator();
170 }
171 }
172 return constraintIterator;
173 }
174
175 private Iterator<AttributeValidationResult> getCurrentAttributeIterator() {
176 if (attributeIterator == null || attributeIterator.hasNext() == false) {
177 Iterator<EntryValidationResult> currentEntryIterator = getCurrentEntryIterator();
178 if (currentEntryIterator != null && currentEntryIterator.hasNext()) {
179 EntryValidationResult currentEntryValidationResult = currentEntryIterator.next();
180 attributeIterator = currentEntryValidationResult.iterator();
181 }
182 }
183 return attributeIterator;
184 }
185
186 private Iterator<EntryValidationResult> getCurrentEntryIterator() {
187 if (entryIterator == null) // || entryIterator.hasNext() == false)
188 entryIterator = entryValidationResultMap.values().iterator();
189 return entryIterator;
190 }
191
192 };
193
194 return iterator;
195 }
196
197 protected EntryValidationResult getEntryValidationResult(String entryName) {
198 EntryValidationResult entryValidationResult = entryValidationResultMap.get(entryName);
199 if (entryValidationResult == null) {
200 entryValidationResult = new EntryValidationResult(entryName);
201 entryValidationResultMap.put(entryName, entryValidationResult);
202 }
203 return entryValidationResult;
204 }
205
206 private ConstraintValidationResult getConstraintValidationResult(String entryName, String attributeName, String attributePath, String constraintName) {
207 String entryKey = getEntryValdidationResultKey(entryName, attributePath);
208 ConstraintValidationResult constraintValidationResult = getEntryValidationResult(entryKey).getAttributeValidationResult(attributeName).getConstraintValidationResult(constraintName);
209 constraintValidationResult.setEntryName(entryName);
210 constraintValidationResult.setAttributeName(attributeName);
211 constraintValidationResult.setAttributePath(attributePath);
212 return constraintValidationResult;
213 }
214
215 /**
216 * Returns the key to the EntryValidationResult entry in the EntryValidationResultMap.
217 * Most cases entry key will be the entryName, unless the attribute is part of a collection,
218 * in which case entry key will be suffixed with index of attribute's parent item.
219 *
220 * @param entryName
221 * @param attributePath
222 * @return
223 */
224 private String getEntryValdidationResultKey(String entryName, String attributePath) {
225 if (attributePath.contains("[")){
226 return entryName + "[" + ValidationUtils.getLastPathIndex(attributePath) + "]";
227 }
228 return entryName;
229 }
230
231 /**
232 * @return the errorLevel
233 */
234 public ErrorLevel getErrorLevel() {
235 return this.errorLevel;
236 }
237
238 /**
239 * @param errorLevel the errorLevel to set
240 */
241 public void setErrorLevel(ErrorLevel errorLevel) {
242 this.errorLevel = errorLevel;
243 }
244
245 /**
246 * @return the numberOfErrors
247 */
248 public int getNumberOfErrors() {
249 return this.numberOfErrors;
250 }
251
252 /**
253 * @return the numberOfWarnings
254 */
255 public int getNumberOfWarnings() {
256 return this.numberOfWarnings;
257 }
258
259 }