/* * Copyright 2010 Red Hat, Inc. and/or its affiliates. * * 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. */ package org.drools.core.base; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.math.BigDecimal; import java.math.BigInteger; import java.time.temporal.Temporal; import java.util.Date; import org.drools.core.common.EventFactHandle; import org.drools.core.factmodel.traits.Thing; import org.drools.core.factmodel.traits.Trait; import org.drools.core.facttemplates.FactTemplate; import org.drools.core.util.MathUtils; public class ValueType<T> implements Externalizable { private static final long serialVersionUID = 510l; public static final ValueType NULL_TYPE = new ValueType( "null", null, SimpleValueType.NULL); // primitive types public static final ValueType PCHAR_TYPE = new ValueType( "char", Character.TYPE, SimpleValueType.CHAR ); public static final ValueType PBYTE_TYPE = new ValueType( "byte", Byte.TYPE, SimpleValueType.INTEGER ); public static final ValueType PSHORT_TYPE = new ValueType( "short", Short.TYPE, SimpleValueType.INTEGER ); public static final ValueType PINTEGER_TYPE = new ValueType( "int", Integer.TYPE, SimpleValueType.INTEGER ); public static final ValueType PLONG_TYPE = new ValueType( "long", Long.TYPE, SimpleValueType.INTEGER ); public static final ValueType PFLOAT_TYPE = new ValueType( "float", Float.TYPE, SimpleValueType.DECIMAL ); public static final ValueType PDOUBLE_TYPE = new ValueType( "double", Double.TYPE, SimpleValueType.DECIMAL ); public static final ValueType PBOOLEAN_TYPE = new ValueType( "boolean", Boolean.TYPE, SimpleValueType.BOOLEAN ); // wrapper types public static final ValueType CHAR_TYPE = new ValueType( "Character", Character.class, SimpleValueType.CHAR ); public static final ValueType BYTE_TYPE = new ValueType( "Byte", Byte.class, SimpleValueType.INTEGER); public static final ValueType SHORT_TYPE = new ValueType( "Short", Short.class, SimpleValueType.INTEGER ); public static final ValueType INTEGER_TYPE = new ValueType( "Integer", Integer.class, SimpleValueType.INTEGER ); public static final ValueType LONG_TYPE = new ValueType( "Long", Long.class, SimpleValueType.INTEGER ); public static final ValueType FLOAT_TYPE = new ValueType( "Float", Float.class, SimpleValueType.DECIMAL ); public static final ValueType DOUBLE_TYPE = new ValueType( "Double", Double.class, SimpleValueType.DECIMAL ); public static final ValueType BOOLEAN_TYPE = new ValueType( "Boolean", Boolean.class, SimpleValueType.BOOLEAN ); public static final ValueType NUMBER_TYPE = new ValueType( "Number", Number.class, SimpleValueType.DATE ); public static final ValueType BIG_DECIMAL_TYPE = new BigDecimalValueType(); public static final ValueType BIG_INTEGER_TYPE = new BigIntegerValueType(); // other types public static final ValueType DATE_TYPE = new ValueType( "Date", Date.class, SimpleValueType.DATE ); public static final ValueType ARRAY_TYPE = new ValueType( "Array", Object[].class, SimpleValueType.LIST ); public static final ValueType STRING_TYPE = new StringValueType(); public static final ValueType OBJECT_TYPE = new ValueType( "Object", Object.class, SimpleValueType.OBJECT ); public static final ValueType FACTTEMPLATE_TYPE = new ValueType( "FactTemplate", FactTemplate.class, SimpleValueType.UNKNOWN ); public static final ValueType EVENT_TYPE = new ValueType( "Event", EventFactHandle.class, SimpleValueType.OBJECT ); public static final ValueType QUERY_TYPE = new ValueType( "Query", DroolsQuery.class, SimpleValueType.OBJECT ); public static final ValueType TRAIT_TYPE = new ValueType( "Trait", Thing.class, SimpleValueType.OBJECT ); public static final ValueType CLASS_TYPE = new ValueType( "Class", Class.class, SimpleValueType.OBJECT ); private String name; private Class<T> classType; private int simpleType; public ValueType() { this(null, null, 0); } private ValueType(final String name, final Class<T> classType, final int simpleType) { this.name = name; this.classType = classType; this.simpleType = simpleType; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String)in.readObject(); classType = (Class<T>)in.readObject(); simpleType = in.readInt(); } public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); out.writeObject(classType); out.writeInt(simpleType); } private Object readResolve() throws java.io.ObjectStreamException { return determineValueType( this.classType ); } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#getName() */ public String getName() { return this.name; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#getClassType() */ public Class<T> getClassType() { return this.classType; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#getSimpleType() */ public int getSimpleType() { return this.simpleType; } public static ValueType determineValueType(final Class<?> clazz) { if ( clazz == null ) { return ValueType.NULL_TYPE; } // primitives if ( clazz == FactTemplate.class ) { return ValueType.FACTTEMPLATE_TYPE; } else if ( clazz == DroolsQuery.class ) { return ValueType.QUERY_TYPE; } else if ( clazz == Character.TYPE ) { return ValueType.PCHAR_TYPE; } else if ( clazz == Byte.TYPE ) { return ValueType.PBYTE_TYPE; } else if ( clazz == Short.TYPE ) { return ValueType.PSHORT_TYPE; } else if ( clazz == Integer.TYPE ) { return ValueType.PINTEGER_TYPE; } else if ( clazz == Long.TYPE ) { return ValueType.PLONG_TYPE; } else if ( clazz == Float.TYPE ) { return ValueType.PFLOAT_TYPE; } else if ( clazz == Double.TYPE ) { return ValueType.PDOUBLE_TYPE; } else if ( clazz == Boolean.TYPE ) { return ValueType.PBOOLEAN_TYPE; } // Number Wrappers if ( clazz == Character.class ) { return ValueType.CHAR_TYPE; } else if ( clazz == Byte.class ) { return ValueType.BYTE_TYPE; } else if ( clazz == Short.class ) { return ValueType.SHORT_TYPE; } else if ( clazz == Integer.class ) { return ValueType.INTEGER_TYPE; } else if ( clazz == Long.class ) { return ValueType.LONG_TYPE; } else if ( clazz == Float.class ) { return ValueType.FLOAT_TYPE; } else if ( clazz == Double.class ) { return ValueType.DOUBLE_TYPE; } else if ( clazz == Boolean.class ) { return ValueType.BOOLEAN_TYPE; } else if ( clazz == BigDecimal.class ) { return ValueType.BIG_DECIMAL_TYPE; } else if ( clazz == BigInteger.class ) { return ValueType.BIG_INTEGER_TYPE; } else if ( Number.class.isAssignableFrom( clazz ) ) { return ValueType.NUMBER_TYPE; } // Other Object types if ( isDateType( clazz ) ) { return ValueType.DATE_TYPE; } else if ( clazz.isArray() ) { return ValueType.ARRAY_TYPE; } else if ( clazz == String.class ) { return ValueType.STRING_TYPE; } else if ( clazz == EventFactHandle.class ) { return ValueType.EVENT_TYPE; } else if ( clazz == Class.class ) { return ValueType.CLASS_TYPE; } else if ( Thing.class.isAssignableFrom( clazz ) || clazz.isAnnotationPresent( Trait.class ) ) { return ValueType.TRAIT_TYPE; } else { return ValueType.OBJECT_TYPE; } } public static boolean isDateType( Class<?> clazz ) { return Date.class.isAssignableFrom( clazz ) || Temporal.class.isAssignableFrom( clazz ); } public String toString() { return "ValueType = '" + this.name + "'"; } public int hashCode() { return this.name.hashCode(); } public boolean equals(final Object object) { if ( object == this ) { return true; } else if (object instanceof ValueType) { ValueType that = (ValueType)object; return classType == that.classType && simpleType == that.simpleType && (name == that.name || name != null && name.equals(that.name)); } return false; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#isBoolean() */ public boolean isBoolean() { return ((this.classType == Boolean.class) || (this.classType == Boolean.TYPE)); } public boolean isDate() { return this.classType == Date.class; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#isNumber() */ public boolean isNumber() { return ( this.simpleType == SimpleValueType.INTEGER || this.simpleType == SimpleValueType.DECIMAL || this.simpleType == SimpleValueType.CHAR || this.simpleType == SimpleValueType.NUMBER ) ; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#isIntegerNumber() */ public boolean isIntegerNumber() { return this.simpleType == SimpleValueType.INTEGER; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#isFloatNumber() */ public boolean isFloatNumber() { return this.simpleType == SimpleValueType.DECIMAL; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#isChar() */ public boolean isChar() { return this.simpleType == SimpleValueType.CHAR; } /* (non-Javadoc) * @see org.kie.base.ValueTypeInterface#isEvent() */ public boolean isEvent() { return this.classType == EventFactHandle.class; } public T coerce(Object value) { return (T)value; } public static class StringValueType extends ValueType<String> { public StringValueType() { super("String", String.class, SimpleValueType.STRING); } @Override public String coerce( Object value ) { if (value == null) { return null; } return value instanceof String ? (String)value : value.toString(); } } public static class BigIntegerValueType extends ValueType<BigInteger> { public BigIntegerValueType() { super("BigInteger", BigInteger.class, SimpleValueType.NUMBER); } @Override public BigInteger coerce( Object value ) { if (value == null) { return null; } return MathUtils.getBigInteger( value ); } } public static class BigDecimalValueType extends ValueType<BigDecimal> { public BigDecimalValueType() { super("BigDecimal", BigDecimal.class, SimpleValueType.NUMBER); } @Override public BigDecimal coerce( Object value ) { if (value == null) { return null; } return MathUtils.getBigDecimal( value ); } } }