org.jpmml.evaluator.FieldValue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pmml-evaluator Show documentation
Show all versions of pmml-evaluator Show documentation
JPMML class model evaluator
/*
* Copyright (c) 2013 Villu Ruusmann
*
* This file is part of JPMML-Evaluator
*
* JPMML-Evaluator is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JPMML-Evaluator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with JPMML-Evaluator. If not, see .
*/
package org.jpmml.evaluator;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import org.dmg.pmml.Array;
import org.dmg.pmml.DataType;
import org.dmg.pmml.Expression;
import org.dmg.pmml.Field;
import org.dmg.pmml.HasValue;
import org.dmg.pmml.HasValueSet;
import org.dmg.pmml.OpType;
import org.dmg.pmml.PMMLObject;
import org.jpmml.model.ToStringHelper;
/**
*
* A field value representation that meets the requirements of PMML type system.
*
*
* Type information has two components to it:
*
* - {@link #getOpType() Operational type}. Determines supported type equality and type comparison operations.
* - {@link #getDataType() Data type}. Determines supported type conversions.
*
*
*
* A field value is created after a {@link Field field}.
* It may be later refined by {@link Expression transformations} and {@link Function functions}.
*
*
* @see FieldValueUtil
*/
abstract
public class FieldValue implements Comparable, Serializable {
private DataType dataType = null;
private Object value = null;
FieldValue(DataType dataType, Object value){
setDataType(Objects.requireNonNull(dataType));
setValue(filterValue(Objects.requireNonNull(value)));
}
abstract
public OpType getOpType();
/**
*
* Checks if this value is equal to the reference value.
*
*/
public boolean equals(HasValue> hasValue){
if(hasValue instanceof HasParsedValue){
HasParsedValue> hasParsedValue = (HasParsedValue>)hasValue;
return equals(hasParsedValue);
}
return equalsString(ensureValue(hasValue));
}
public boolean equals(HasParsedValue> hasParsedValue){
FieldValue value = hasParsedValue.getValue(getDataType(), getOpType());
return this.equals(value);
}
/**
*
* Checks if this value is contained in the set of reference values.
*
*/
public boolean isIn(HasValueSet> hasValueSet){
if(hasValueSet instanceof HasParsedValueSet){
HasParsedValueSet> hasParsedValueSet = (HasParsedValueSet>)hasValueSet;
return isIn(hasParsedValueSet);
}
Array array = hasValueSet.getArray();
if(array == null){
throw new MissingElementException(MissingElementException.formatMessage(XPathUtil.formatElement((Class)hasValueSet.getClass()) + "/" + XPathUtil.formatElement(Array.class)), (PMMLObject)hasValueSet);
}
List> values = ArrayUtil.getContent(array);
return values.stream()
.anyMatch(value -> equalsValue(value));
}
public boolean isIn(HasParsedValueSet> hasParsedValueSet){
Set values = hasParsedValueSet.getValueSet(getDataType(), getOpType());
return values.contains(this);
}
/**
*
* Calculates the order between this value and the reference value.
*
*/
public int compareTo(HasValue> hasValue){
if(hasValue instanceof HasParsedValue){
HasParsedValue> hasParsedValue = (HasParsedValue>)hasValue;
return compareTo(hasParsedValue);
}
return compareToString(ensureValue(hasValue));
}
public int compareTo(HasParsedValue> hasParsedValue){
FieldValue value = hasParsedValue.getValue(getDataType(), getOpType());
return this.compareTo(value);
}
public boolean equalsString(String string){
Object value = TypeUtil.parse(getDataType(), string);
return (getValue()).equals(value);
}
/**
*
* A value-safe replacement for {@link #equals(Object)}.
*
*/
public boolean equalsValue(FieldValue value){
if(sameScalarType(value)){
return (getValue()).equals(value.getValue());
}
return equalsValue(value.getValue());
}
private boolean equalsValue(Object value){
value = TypeUtil.parseOrCast(getDataType(), value);
return (getValue()).equals(value);
}
public boolean isIn(Collection values){
Predicate predicate = new Predicate(){
@Override
public boolean test(FieldValue value){
if(Objects.equals(FieldValues.MISSING_VALUE, value)){
return false;
}
return equalsValue(value);
}
};
return values.stream()
.anyMatch(predicate);
}
public int compareToString(String string){
Object value = TypeUtil.parse(getDataType(), string);
return ((Comparable)getValue()).compareTo(value);
}
/**
*
* A value-safe replacement for {@link #compareTo(FieldValue)}
*
*/
public int compareToValue(FieldValue value){
if(sameScalarType(value)){
return ((Comparable)getValue()).compareTo(value.getValue());
}
return compareToValue(value.getValue());
}
private int compareToValue(Object value){
value = TypeUtil.parseOrCast(getDataType(), value);
return ((Comparable)getValue()).compareTo(value);
}
public V getMapping(HasParsedValueMapping hasParsedValueMapping){
Map values = hasParsedValueMapping.getValueMapping(getDataType(), getOpType());
return values.get(this);
}
private boolean isScalar(){
return (this instanceof Scalar);
}
private boolean sameScalarType(FieldValue value){
if(isScalar()){
return (getClass()).equals(value.getClass());
}
return false;
}
public String asString(){
return (String)getValue(DataType.STRING);
}
public Number asNumber(){
Object value = getValue();
if(value instanceof Number){
return (Number)value;
}
return (Double)getValue(DataType.DOUBLE);
}
public Integer asInteger(){
return (Integer)getValue(DataType.INTEGER);
}
public Float asFloat(){
Number number = asNumber();
return number.floatValue();
}
/**
* Getting the value of a field as {@link Double}:
*
* FieldValue value = ...;
* Double result = value.asDouble();
*
*
* Getting the value of a field as double
:
*
* FieldValue value = ...;
* double result = (value.asNumber()).doubleValue();
*
*
* @see #asNumber()
*/
public Double asDouble(){
Number number = asNumber();
return number.doubleValue();
}
public Boolean asBoolean(){
return (Boolean)getValue(DataType.BOOLEAN);
}
public LocalDateTime asLocalDateTime(){
return (LocalDateTime)getValue(DataType.DATE_TIME);
}
public LocalDate asLocalDate(){
return (LocalDate)getValue(DataType.DATE);
}
public LocalTime asLocalTime(){
return (LocalTime)getValue(DataType.TIME);
}
public ZonedDateTime asZonedDateTime(ZoneId zoneId){
try {
LocalDateTime dateTime = asLocalDateTime();
return dateTime.atZone(zoneId);
} catch(TypeCheckException tceDateTime){
try {
LocalDate localDate = asLocalDate();
LocalTime localTime = LocalTime.MIDNIGHT;
return ZonedDateTime.of(localDate, localTime, zoneId);
} catch(TypeCheckException tceDate){
// Ignored
}
try {
LocalDate localDate = LocalDate.now();
LocalTime localTime = asLocalTime();
return ZonedDateTime.of(localDate, localTime, zoneId);
} catch(TypeCheckException tceTime){
// Ignored
}
throw tceDateTime;
}
}
private Object getValue(DataType dataType){
Object value = getValue();
try {
return TypeUtil.cast(dataType, value);
} catch(TypeCheckException tce){
try {
if(value instanceof String){
String string = (String)value;
return TypeUtil.parse(dataType, string);
}
} catch(IllegalArgumentException iae){
// Ignored
}
throw tce;
}
}
@Override
public int compareTo(FieldValue that){
if((this.getOpType() != that.getOpType()) || (this.getDataType() != that.getDataType())){
throw new ClassCastException();
}
return compareToValue(that);
}
@Override
public int hashCode(){
return (31 * (getOpType().hashCode() ^ getDataType().hashCode())) + getValue().hashCode();
}
@Override
public boolean equals(Object object){
if(object instanceof FieldValue){
FieldValue that = (FieldValue)object;
return (this.getOpType() == that.getOpType()) && (this.getDataType() == that.getDataType()) && (this.getValue()).equals(that.getValue());
}
return false;
}
@Override
public String toString(){
ToStringHelper helper = new ToStringHelper(this)
.add("opType", getOpType())
.add("dataType", getDataType())
.add("value", getValue());
return helper.toString();
}
public DataType getDataType(){
return this.dataType;
}
private void setDataType(DataType dataType){
this.dataType = dataType;
}
public Object getValue(){
return this.value;
}
private void setValue(Object value){
this.value = value;
}
static
private String ensureValue(HasValue> hasValue){
String value = hasValue.getValue();
if(value == null){
throw new MissingAttributeException(MissingAttributeException.formatMessage(XPathUtil.formatElement((Class)hasValue.getClass()) + "@value"), (PMMLObject)hasValue);
}
return value;
}
static
private Object filterValue(Object value){
if(value instanceof Float){
return filterValue((Float)value);
} else
if(value instanceof Double){
return filterValue((Double)value);
}
return value;
}
static
private Float filterValue(Float value){
if(value.doubleValue() == 0f){
return Numbers.FLOAT_ZERO;
}
return value;
}
static
private Double filterValue(Double value){
if(value.doubleValue() == 0d){
return Numbers.DOUBLE_ZERO;
}
return value;
}
static
interface Scalar {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy