
org.kuali.student.datadictionary.util.DictionaryValidator Maven / Gradle / Ivy
/*
* Copyright 2011 The Kuali Foundation
*
* Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
*
* 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.kuali.student.datadictionary.util;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.core.api.uif.DataType;
import org.kuali.rice.krad.datadictionary.AttributeDefinition;
import org.kuali.rice.krad.datadictionary.DataObjectEntry;
import org.kuali.rice.krad.datadictionary.validation.ValidationUtils;
import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
import org.kuali.rice.krad.datadictionary.validation.constraint.LookupConstraint;
import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
import org.kuali.rice.krad.datadictionary.validation.constraint.WhenConstraint;
public class DictionaryValidator {
private DateTimeService dateTimeService;
private DataObjectEntry doe;
private Set alreadyValidated;
public DictionaryValidator(DataObjectEntry doe,
Set alreadyValidated) {
this.doe = doe;
this.alreadyValidated = alreadyValidated;
}
public DateTimeService getDateTimeService() {
return dateTimeService;
}
public void setDateTimeService(DateTimeService dateTimeService) {
this.dateTimeService = dateTimeService;
}
public List validate() {
List errors = new ArrayList();
if (doe.getFullClassName() == null) {
errors.add("The class name cannot be be left null");
}
if (doe.getEntryClass() == null) {
errors.add("The entry class should not be left null");
}
if (!doe.getEntryClass().getName().equals(doe.getFullClassName())) {
errors.add("The entry class should match the full class name");
}
// else if (this.getClass (ode.getName ()) == null)
// {
// errors.add ("The name does not exist on the class path");
// }
if (doe.getAttributes() == null) {
errors.add("getAttribues () is null");
return errors;
}
if (doe.getCollections() == null) {
errors.add("getCollections () is null");
return errors;
}
if (doe.getComplexAttributes() == null) {
errors.add("getComplexAttributes ()");
return errors;
}
if (doe.getCollections().isEmpty()
&& doe.getComplexAttributes().isEmpty()
&& doe.getAttributes().isEmpty()) {
errors.add("No fields of any kind defined for this complex object structure");
return errors;
}
Set fieldNames = new HashSet();
for (AttributeDefinition ad : doe.getAttributes()) {
if (ad.getName() != null) {
if (!fieldNames.add(ad.getName())) {
errors.add(ad.getName() + " is defined more than once");
}
}
errors.addAll(validateAttributeDefinition(ad));
}
doe.completeValidation();
return errors;
}
private List validateAttributeDefinition(AttributeDefinition ad) {
List errors = new ArrayList();
if (ad.getName() == null) {
errors.add("name cannot be null");
} else if (ad.getName().trim().equals("")) {
errors.add("name cannot be blank");
} else if (ad.getDataType() == null) {
errors.add(ad.getName() + " has a null data type");
// } else if (ad.getDataType().equals(DataType.COMPLEX)) {
// errorIfNotNull(errors, ad, "exclusiveMin", ad.getExclusiveMin());
// errorIfNotNull(errors, ad, "inclusiveMax", ad.getInclusiveMax());
// errorIfNotNull(errors, ad, "max length", ad.getMaxLength());
// errorIfNotNull(errors, ad, "min length", ad.getMinLength());
// errorIfNotNull(errors, ad, "valid chars", ad.getValidCharactersConstraint());
// errorIfNotNull(errors, ad, "lookup", ad.getLookupDefinition());
}
// validateConversion(errors, ad.getName(), "defaultValue", ad.getDataType(), ad.getDefaultValue());
validateConversion(errors, ad.getName(), "exclusiveMin", ad.getDataType(), ad.getExclusiveMin());
validateConversion(errors, ad.getName(), "inclusiveMax", ad.getDataType(), ad.getInclusiveMax());
//TODO: Cross compare to make sure min is not greater than max and that default value is valid itself
if (ad.getLookupDefinition() != null) {
errors.addAll(validateLookup(ad, ad.getLookupDefinition()));
}
if (ad.getCaseConstraint() != null) {
errors.addAll(validateCase(ad, ad.getCaseConstraint()));
}
if (ad.getValidCharactersConstraint() != null) {
errors.addAll(validateValidChars(ad, ad.getValidCharactersConstraint()));
}
return errors;
}
private void errorIfNotNull(List errors, AttributeDefinition fd,
String validation,
Object value) {
if (value != null) {
errors.add("field " + fd.getName() + " has a " + validation
+ " but it cannot be specified on a complex type");
}
}
private Object validateConversion(List errors, String fieldName,
String propertyName, DataType dataType,
Object value) {
if (value == null) {
return null;
}
switch (dataType) {
case STRING:
return value.toString().trim();
// case DATE, TRUNCATED_DATE, BOOLEAN, INTEGER, FLOAT, DOUBLE, LONG, COMPLEX
case LONG:
try {
return ValidationUtils.getLong(value);
} catch (NumberFormatException ex) {
errors.add(
"field " + fieldName
+ " has a " + propertyName
+ " that cannot be converted into a long integer");
}
return null;
case INTEGER:
try {
return ValidationUtils.getInteger(value);
} catch (NumberFormatException ex) {
errors.add(
"field " + fieldName
+ " has a " + propertyName + " that cannot be converted into an integer");
}
return null;
case FLOAT:
try {
return ValidationUtils.getFloat(value);
} catch (NumberFormatException ex) {
errors.add(
"field " + fieldName
+ " has a " + propertyName
+ " that cannot be converted into a floating point value");
}
return null;
case DOUBLE:
try {
return ValidationUtils.getFloat(value);
} catch (NumberFormatException ex) {
errors.add(
"field " + fieldName
+ " has a " + propertyName
+ " that cannot be converted into a double sized floating point value");
}
return null;
case BOOLEAN:
if (value instanceof Boolean) {
return ((Boolean) value).booleanValue();
}
if (value instanceof String) {
if (((String) value).trim().equalsIgnoreCase("true")) {
return true;
}
if (((String) value).trim().equalsIgnoreCase("false")) {
return true;
}
}
errors.add(
"field " + fieldName
+ " has a " + propertyName
+ " that cannot be converted into a boolean true/false");
return null;
case DATE:
case TRUNCATED_DATE:
if (value instanceof Date) {
return (Date) value;
}
try {
// TODO: make the date parser configurable like the validator is
return ValidationUtils.getDate(value, dateTimeService);
} catch (Exception e) {
errors.add(
"field " + fieldName
+ " has a " + propertyName
+ " that cannot be converted into a date");
}
return null;
default:
errors.add(
"field " + fieldName
+ " has a " + propertyName
+ " that cannot be converted into an unknown/unhandled data type");
return null;
}
}
private List validateValidChars(AttributeDefinition fd,
ValidCharactersConstraint vc) {
List errors = new ArrayList();
String validChars = vc.getValue();
/*
int typIdx = validChars.indexOf(":");
String processorType = "regex";
if (-1 == typIdx) {
validChars = "[" + validChars + "]*";
} else {
processorType = validChars.substring(0, typIdx);
validChars = validChars.substring(typIdx + 1);
}
if (!processorType.equalsIgnoreCase("regex")) {
errors.add(
"field " + fd.getName()
+ " has an invalid valid chars processor type: a simple list of characters or a regex: is supported");
return errors;
}
*/
try {
Pattern pattern = Pattern.compile(validChars);
} catch (PatternSyntaxException ex) {
errors.add("field " + fd.getName()
+ " has in invalid character pattern for a regular expression: "
+ validChars);
}
return errors;
}
private List validateLookup(AttributeDefinition fd, LookupConstraint lc) {
List errors = new ArrayList();
if (lc.getParams() == null) {
errors.add("field " + fd.getName() + " has a lookup with null parameters");
}
//TODO: more validation
return errors;
}
public static final String GREATER_THAN_EQUAL = "greater_than_equal";
public static final String LESS_THAN_EQUAL = "less_than_equal";
public static final String GREATER_THAN = "greater_than";
public static final String LESS_THAN = "less_than";
public static final String EQUALS = "equals";
public static final String NOT_EQUAL = "not_equal";
private static final String[] VALID_OPERATORS = {
NOT_EQUAL, EQUALS, GREATER_THAN_EQUAL, LESS_THAN_EQUAL, GREATER_THAN, LESS_THAN
};
private List validateCase(AttributeDefinition fd, CaseConstraint cc) {
List errors = new ArrayList();
if (cc.getOperator() == null) {
errors.add("field " + fd.getName()
+ " has a case constraint with no operator");
} else {
boolean found = false;
for (int i = 0; i < VALID_OPERATORS.length; i++) {
if (VALID_OPERATORS[i].equalsIgnoreCase(cc.getOperator())) {
found = true;
break;
}
}
if (!found) {
errors.add("field " + fd.getName()
+ " has a case constraint with an unknown operator "
+ cc.getOperator());
}
}
if (cc.getPropertyName() == null) {
errors.add(
"field " + fd.getName()
+ " has a case constraint with a null for the field to use for the comparison");
} else if (cc.getPropertyName().trim().equals("")) {
errors.add(
"field " + fd.getName()
+ " has a case constraint with blanks for the field to use for the comparison");
}
if (cc.getWhenConstraint() == null) {
errors.add("field " + fd.getName()
+ " has a case constraint but null when statements");
return errors;
}
if (cc.getWhenConstraint().size() == 0) {
errors.add("field " + fd.getName()
+ " has a case constraint but has no when statements");
}
for (WhenConstraint wc : cc.getWhenConstraint()) {
if (wc.getConstraint() == null) {
errors.add(
"field " + fd.getName()
+ " has a as case constraint with a when statement that has no overriding constraints specified");
}
}
//TODO: more validation
return errors;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy