de.tsl2.nano.bean.def.Constraint Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.descriptor Show documentation
Show all versions of tsl2.nano.descriptor Show documentation
TSL2 Framework Descriptor (currency-handling, generic formatter, descriptors for beans, collections, actions and values)
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Tom, Thomas Schneider
* created on: 01.12.2013
*
* Copyright: (c) Thomas Schneider 2013, all rights reserved
*/
package de.tsl2.nano.bean.def;
import java.math.BigDecimal;
import java.text.Format;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.core.Commit;
import org.simpleframework.xml.core.Complete;
import org.simpleframework.xml.core.Persist;
import de.tsl2.nano.action.IConstraint;
import de.tsl2.nano.action.IStatus;
import de.tsl2.nano.bean.BeanUtil;
import de.tsl2.nano.core.ManagedException;
import de.tsl2.nano.core.util.CollectionUtil;
import de.tsl2.nano.core.util.FormatUtil;
import de.tsl2.nano.format.GenericParser;
/**
* Checks constraints of a given value
*
* @author Tom, Thomas Schneider
* @version $Revision$
*/
@SuppressWarnings("unchecked")
public class Constraint extends AbstractConstraint implements IConstraint {
/** serialVersionUID */
private static final long serialVersionUID = -4402914326367553367L;
@Attribute(required = false)
Class type;
@Element(required = false)
protected Format format;
@Attribute(required = false)
protected boolean nullable = true;
@Attribute(required = false)
protected int length = UNDEFINED;
@Element(required = false)
Comparable min;
@Element(required = false)
Comparable max;
@Element(required = false)
T defaultValue;
@Attribute(required = false)
private int scale = UNDEFINED;
@Attribute(required = false)
private int precision = UNDEFINED;
@ElementList(inline = true, entry = "value", required = false)
private transient Collection allowedValues;
/**
* constructor
*/
public Constraint() {
}
public Constraint(Class type) {
this(type, null, null);
}
public Constraint(T defaultValue) {
this((Class) defaultValue.getClass(), null, null);
setDefault(defaultValue);
}
/**
* constructor
*
* @param type
* @param min
* @param max
*/
public Constraint(Class type, Comparable min, Comparable max) {
super();
setType(type);
setRange(min, max);
}
public Constraint(Class type, T... allowedValues) {
this(type, allowedValues != null ? Arrays.asList(allowedValues) : null);
}
/**
* tries to set values from given type and allowedValues. will set the length, scale and precision.
* @param type allowed type
* @param allowedValues allowed values. the first value will be used as default value.
*/
public Constraint(Class type, Collection allowedValues) {
super();
setType(type);
if (allowedValues != null && allowedValues.size() > 0) {
setRange(allowedValues);
setDefault(allowedValues.iterator().next());
int length = -1;
for (T v : allowedValues) {
length = Math.max(length, v.toString().length());
}
setLength(length);
if (BigDecimal.class.isAssignableFrom(type)) {
int scale = -1, precision = -1;
for (T v : allowedValues) {
BigDecimal b = (BigDecimal)v;
scale = Math.max(scale, b.scale());
precision = Math.max(precision, b.precision());
}
setScale(scale);
setPrecision(precision);
}
}
}
/**
* setBasicDef
*
* @param length {@link #length()}
* @param nullable {@link #nullable()}
* @param format {@link #getPattern()}
* @param defaultValue {@link #getDefault()}
* @param description {@link #getDescription()}
*/
@Override
public > C setBasicDef(int length,
boolean nullable,
Format format,
T defaultValue) {
this.length = length;
this.nullable = nullable;
this.format = format;
this.defaultValue = defaultValue;
if (defaultValue != null) {
IStatus s = checkStatus(getType() != null ? getType().getSimpleName() : "arg", defaultValue);
if (!s.ok()) {
throw new ManagedException(s.message());
}
}
return (C) this;
}
/**
* setNumberDef
*
* @param scale {@link #scale()}
* @param precision {@link #precision()}
*/
@Override
public > C setNumberDef(int scale, int precision) {
this.scale = scale;
this.precision = precision;
return (C) this;
}
/**
* {@inheritDoc}
*/
@Override
public > C setRange(Comparable min, Comparable max) {
this.min = min;
this.max = max;
return (C) this;
}
@Override
public > C setRange(Collection allowedValues) {
this.allowedValues = allowedValues;
return (C) this;
}
@Override
public Collection getAllowedValues() {
return allowedValues;
}
@Override
public Comparable getMinimum() {
return min;
}
@Override
public Comparable getMaximum() {
return max;
}
/**
* {@inheritDoc}
*/
@Override
public > C setFormat(Format format) {
this.format = format;
return (C) this;
}
/**
* @return Returns the scale.
*/
@Override
public int getScale() {
return scale;
}
/**
* {@inheritDoc}
*/
@Override
public > C setScale(int scale) {
this.scale = scale;
return (C) this;
}
/**
* @return Returns the precision.
*/
@Override
public int getPrecision() {
return precision;
}
/**
* {@inheritDoc}
*/
@Override
public > C setPrecision(int precision) {
this.precision = precision;
return (C) this;
}
/**
* @return Returns the nullable.
*/
@Override
public boolean isNullable() {
return nullable;
}
/**
* {@inheritDoc}
*/
@Override
public > C setNullable(boolean nullable) {
this.nullable = nullable;
return (C) this;
}
/**
* @return Returns the length.
*/
@Override
public int getLength() {
return length;
}
/**
* {@inheritDoc}
*/
@Override
public > C setLength(int length) {
this.length = length;
return (C) this;
}
/**
* @return Returns the defaultValue.
*/
@Override
public T getDefault() {
return defaultValue;
}
/**
* @param defaultValue The defaultValue to set.
*/
@Override
public > C setDefault(T defaultValue) {
this.defaultValue = defaultValue;
return (C) this;
}
@Override
public Format getFormat() {
return format;
}
public static Format createFormat(Class type) {
Format format = null;
if (Collection.class.isAssignableFrom(type)) {
// format = new CollectionExpressionTypeFormat((Class) generic);
} else if (Map.class.isAssignableFrom(type)) {
// format = new MapExpressionFormat((Class) generic);
} else if (type.isEnum()) {
format = FormatUtil.getDefaultFormat(type, true);
} else if (BeanUtil.isStandardType(type)) {
format = FormatUtil.getDefaultFormat(type, true);
//not all types have default formats
if (format == null) {
format = new GenericParser(type);
}
} else {
// setFormat(new ValueExpressionTypeFormat(type));
}
return format;
}
@Override
public Class getType() {
if (type == null) {
type = (Class) Object.class;
}
return type;
}
/** define maximum length */
@SuppressWarnings("rawtypes")
@Override
public > C setType(Class type) {
this.type = type;
if (type.isEnum()) {
setRange(CollectionUtil.getEnumValues((Class) type));
}
return (C) this;
}
@Persist
private void initSerialization() {
//simple-xml has problems on deserializing anonymous classes
if (format != null && format.getClass().isAnonymousClass()) {
format = null;
}
//the enum values should not be persisted
if (Enum.class.isAssignableFrom(getType())) {
allowedValues = null;
}
}
@Complete
private void afterSerialization() {
initDeserialization();
}
@SuppressWarnings("rawtypes")
@Commit
private void initDeserialization() {
if (Enum.class.isAssignableFrom(getType())) {
allowedValues = CollectionUtil.getEnumValues((Class) getType());
}
if (format == null) {
format = createFormat(getType());
}
}
}