All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.tsl2.nano.bean.def.Constraint Maven / Gradle / Ivy

Go to download

TSL2 Framework Descriptor (currency-handling, generic formatter, descriptors for beans, collections, actions and values)

There is a newer version: 2.5.1
Show newest version
/*
 * 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());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy