/*
* (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* bstefanescu
*/
package org.nuxeo.ecm.webengine.forms.validation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.nuxeo.ecm.webengine.forms.validation.annotations.Enumeration;
import org.nuxeo.ecm.webengine.forms.validation.annotations.Length;
import org.nuxeo.ecm.webengine.forms.validation.annotations.NotNull;
import org.nuxeo.ecm.webengine.forms.validation.annotations.Range;
import org.nuxeo.ecm.webengine.forms.validation.annotations.Regex;
import org.nuxeo.ecm.webengine.forms.validation.annotations.Required;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class FormDescriptor {
protected FormValidator validator;
protected Map<String, Field> fields = new HashMap<String, Field>();
protected HashSet<String> requiredFields = new HashSet<String>();
public FormDescriptor(Class<?> type) throws ReflectiveOperationException {
Method[] methods = type.getMethods(); // get all inherited public methods
int mod = type.getModifiers();
if (!Modifier.isInterface(mod)) {
throw new IllegalArgumentException("Form type is not an interface");
}
for (Method m : methods) {
String name = m.getName();
if (!name.startsWith("get")) {
continue;
}
// get the field name
name = getFieldName(name, name.length());
Field field = new Field(m, name);
if (field.required) {
requiredFields.add(field.name);
}
fields.put(name, field);
}
org.nuxeo.ecm.webengine.forms.validation.annotations.FormValidator fv = type.getAnnotation(org.nuxeo.ecm.webengine.forms.validation.annotations.FormValidator.class);
if (fv != null) {
validator = fv.value().newInstance();
}
}
static class Field {
CompositeValidator validator;
String name;
Method m;
boolean isArray;
boolean required;
boolean notnull;
String defaultValue;
TypeConvertor<?> convertor;
Field(Method m, String name) throws ReflectiveOperationException {
validator = new CompositeValidator();
// not null
NotNull nn = m.getAnnotation(NotNull.class);
if (nn != null) {
String dv = nn.value();
if (dv.length() > 0) {
defaultValue = dv;
} else {
notnull = true;
}
}
// required
required = m.isAnnotationPresent(Required.class);
// enum
Enumeration aenum = m.getAnnotation(Enumeration.class);
if (aenum != null) {
validator.add(new EnumerationValidator(aenum.value()));
}
// regex
Regex regex = m.getAnnotation(Regex.class);
if (regex != null) {
validator.add(new RegexValidator(regex.value()));
}
// length
Length length = m.getAnnotation(Length.class);
if (length != null) {
if (length.value() > -1) {
validator.add(new ExactLengthValidator(length.value()));
} else {
validator.add(new LengthValidator(length.min(), length.max()));
}
}
// range
Range range = m.getAnnotation(Range.class);
if (range != null) {
validator.add(new RangeValidator(range.min(), range.max(), range.negate()));
}
// custom validator
org.nuxeo.ecm.webengine.forms.validation.annotations.FieldValidator custom = m.getAnnotation(org.nuxeo.ecm.webengine.forms.validation.annotations.FieldValidator.class);
if (custom != null) {
validator.add((FieldValidator) custom.value().newInstance());
}
// type convertor
Class<?> rtype = m.getReturnType();
isArray = rtype.isArray();
if (isArray) {
rtype = rtype.getComponentType();
}
convertor = TypeConvertor.getConvertor(rtype);
this.m = m;
this.name = name;
}
Object validate(String value) throws ValidationException {
if (value == null || value.length() == 0) {
value = null; // "" empty strings are treated as null values
if (notnull) {
throw new ValidationException();
} else if (defaultValue != null) {
value = defaultValue;
}
}
Object obj = value;
if (convertor != null) {
obj = convertor.convert(value);
}
if (validator != null) {
validator.validate(value, obj);
}
return obj;
}
Object[] validateArray(String[] values) throws ValidationException {
List<Object> result = new ArrayList<Object>();
for (String value : values) {
result.add(validate(value));
}
if (convertor != null) {
return result.toArray(convertor.newArray(values.length));
} else {
return result.toArray(new String[values.length]);
}
}
}
static String getFieldName(String key, int len) {
if (len == 4) {
return "" + Character.toLowerCase(key.charAt(3));
} else {
return Character.toLowerCase(key.charAt(3)) + key.substring(4);
}
}
}