/*
* (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.Array;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.nuxeo.ecm.webengine.WebEngine;
import org.nuxeo.runtime.api.Framework;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public abstract class TypeConvertor<T> {
public abstract Class<?> getType();
public abstract T convert(String value) throws ValidationException;
public Object[] newArray(int length) {
return (Object[]) Array.newInstance(getType(), length);
}
@SuppressWarnings("unchecked")
public static <T> TypeConvertor<T> getConvertor(Class<T> type) {
if (type == String.class) {
return null;
}
TypeConvertor<?> result = null;
if (type == Boolean.class) {
result = BOOLEAN;
} else if (type == Date.class) {
result = DATE;
} else if (type == Integer.class) {
result = INTEGER;
} else if (type == Float.class) {
result = FLOAT;
} else if (type == Long.class) {
result = LONG;
} else if (type == Double.class) {
result = DOUBLE;
} else if (type == Class.class) {
result = CLASS;
} else {
throw new IllegalArgumentException("Unsupported type: " + type);
}
return (TypeConvertor<T>) result;
}
public static final TypeConvertor<Boolean> BOOLEAN = new TypeConvertor<Boolean>() {
@Override
public Class<?> getType() {
return Boolean.class;
}
@Override
public Boolean convert(String value) throws ValidationException {
if ("true".equals(value)) {
return Boolean.TRUE;
} else if ("false".equals(value)) {
return Boolean.FALSE;
} else {
throw new ValidationException();
}
}
};
public static final TypeConvertor<Integer> INTEGER = new TypeConvertor<Integer>() {
@Override
public Class<?> getType() {
return Integer.class;
}
@Override
public Integer convert(String value) throws ValidationException {
try {
return Integer.valueOf(value);
} catch (NumberFormatException e) {
throw new ValidationException();
}
}
};
public static final TypeConvertor<Long> LONG = new TypeConvertor<Long>() {
@Override
public Class<?> getType() {
return Long.class;
}
@Override
public Long convert(String value) throws ValidationException {
try {
return Long.valueOf(value);
} catch (NumberFormatException e) {
throw new ValidationException();
}
}
};
public static final TypeConvertor<Float> FLOAT = new TypeConvertor<Float>() {
@Override
public Class<?> getType() {
return Float.class;
}
@Override
public Float convert(String value) throws ValidationException {
try {
return Float.valueOf(value);
} catch (NumberFormatException e) {
throw new ValidationException();
}
}
};
public static final TypeConvertor<Double> DOUBLE = new TypeConvertor<Double>() {
@Override
public Class<?> getType() {
return Double.class;
}
@Override
public Double convert(String value) throws ValidationException {
try {
return Double.valueOf(value);
} catch (NumberFormatException e) {
throw new ValidationException();
}
}
};
public static final TypeConvertor<Date> DATE = new TypeConvertor<Date>() {
@Override
public Class<?> getType() {
return Date.class;
}
@Override
public Date convert(String value) throws ValidationException {
try {
return parseDate(value);
} catch (IllegalArgumentException e) {
throw new ValidationException();
}
}
};
public static final TypeConvertor<Class<?>> CLASS = new TypeConvertor<Class<?>>() {
@Override
public Class<?> getType() {
return Class.class;
}
@Override
public Class<?> convert(String value) throws ValidationException {
try {
return loadClass(value);
} catch (ReflectiveOperationException e) {
throw new ValidationException();
}
}
};
public static Class<?> loadClass(String name) throws ReflectiveOperationException {
return Framework.getLocalService(WebEngine.class).loadClass(name);
}
private static final Pattern PATTERN = Pattern.compile("(\\d{4})(?:-(\\d{2}))?(?:-(\\d{2}))?(?:[Tt](?:(\\d{2}))?(?::(\\d{2}))?(?::(\\d{2}))?(?:\\.(\\d{3}))?)?([Zz])?(?:([+-])(\\d{2}):(\\d{2}))?");
/**
* Parse the serialized string form into a java.util.Date
*
* @param date The serialized string form of the date
* @return The created java.util.Date
*/
public static Date parseDate(String date) {
Matcher m = PATTERN.matcher(date);
if (m.find()) {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
int hoff = 0, moff = 0, doff = -1;
if (m.group(9) != null) {
doff = m.group(9).equals("-") ? 1 : -1;
hoff = doff * (m.group(10) != null ? Integer.parseInt(m.group(10)) : 0);
moff = doff * (m.group(11) != null ? Integer.parseInt(m.group(11)) : 0);
}
c.set(Calendar.YEAR, Integer.parseInt(m.group(1)));
c.set(Calendar.MONTH, m.group(2) != null ? Integer.parseInt(m.group(2)) - 1 : 0);
c.set(Calendar.DATE, m.group(3) != null ? Integer.parseInt(m.group(3)) : 1);
c.set(Calendar.HOUR_OF_DAY, m.group(4) != null ? Integer.parseInt(m.group(4)) + hoff : 0);
c.set(Calendar.MINUTE, m.group(5) != null ? Integer.parseInt(m.group(5)) + moff : 0);
c.set(Calendar.SECOND, m.group(6) != null ? Integer.parseInt(m.group(6)) : 0);
c.set(Calendar.MILLISECOND, m.group(7) != null ? Integer.parseInt(m.group(7)) : 0);
return c.getTime();
} else {
throw new IllegalArgumentException("Invalid Date Format");
}
}
}