/*
* Copyright 2016 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.kie.dmn.feel.lang.types;
import org.kie.dmn.api.feel.runtime.events.FEELEvent;
import org.kie.dmn.feel.FEEL;
import org.kie.dmn.feel.lang.SimpleType;
import org.kie.dmn.feel.lang.Symbol;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.runtime.FEELFunction;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.UnaryTest;
import org.kie.dmn.feel.runtime.functions.*;
import java.time.*;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public enum BuiltInType implements SimpleType {
UNKNOWN("unknown"),
NUMBER("number"),
STRING("string"),
DATE("date"),
TIME("time"),
DATE_TIME("date and time", "dateTime"),
DURATION("duration", "days and time duration", "years and months duration", "dayTimeDuration", "yearMonthDuration"),
BOOLEAN("boolean"),
RANGE("range"),
FUNCTION("function"),
LIST("list"),
CONTEXT("context"),
UNARY_TEST("unary test");
private final String[] names;
private final BuiltInTypeSymbol symbol;
BuiltInType(String... names) {
this.names = names;
this.symbol = new BuiltInTypeSymbol( names[0], this );
}
public String getName() {
return names[0];
}
public String[] getNames() {
return names;
}
public Object fromString(String value) {
switch ( this ) {
case NUMBER: return BuiltInFunctions.getFunction( NumberFunction.class).invoke( value, null, null ).cata(BuiltInType.justNull(), Function.identity());
case STRING: return value;
case DATE: return BuiltInFunctions.getFunction( DateFunction.class ).invoke( value ).cata(BuiltInType.justNull(), Function.identity());
case TIME: return BuiltInFunctions.getFunction( TimeFunction.class ).invoke( value ).cata(BuiltInType.justNull(), Function.identity());
case DATE_TIME: return BuiltInFunctions.getFunction( DateTimeFunction.class ).invoke( value ).cata(BuiltInType.justNull(), Function.identity());
case DURATION: return BuiltInFunctions.getFunction( DurationFunction.class ).invoke( value ).cata(BuiltInType.justNull(), Function.identity());
case BOOLEAN: return Boolean.parseBoolean( value );
case RANGE:
case FUNCTION:
case LIST:
case CONTEXT:
case UNARY_TEST:
return FEEL.newInstance().evaluate( value );
}
return null;
}
public String toString(Object value) {
return BuiltInFunctions.getFunction( StringFunction.class ).invoke( value ).cata(BuiltInType.justNull(), Function.identity());
}
static <T> Function<FEELEvent, T> justNull() {
// TODO we should add the EventListener here somehow?
return t -> null;
}
public Symbol getSymbol() { return symbol; }
@Override
public String toString() {
return "Type{ " +
names[0] +
" }";
}
public static Type determineTypeFromName( String name ) {
if( name == null ) {
return UNKNOWN;
}
for( BuiltInType t : BuiltInType.values() ) {
for( String n : t.getNames() ) {
if( n.equals( name ) ) {
return t;
}
}
}
return UNKNOWN;
}
public static Type determineTypeFromInstance( Object o ) {
if( o == null ) {
return UNKNOWN;
} else if( o instanceof Number ) {
return NUMBER;
} else if( o instanceof String ) {
return STRING;
} else if( o instanceof LocalDate ) {
return DATE;
} else if( o instanceof LocalTime || o instanceof OffsetTime ) {
return TIME;
} else if( o instanceof ZonedDateTime || o instanceof OffsetDateTime || o instanceof LocalDateTime ) {
return DATE_TIME;
} else if( o instanceof Duration || o instanceof Period ) {
return DURATION;
} else if( o instanceof Boolean ) {
return BOOLEAN;
} else if( o instanceof UnaryTest ) {
return UNARY_TEST;
} else if( o instanceof Range ) {
return RANGE;
} else if( o instanceof FEELFunction ) {
return FUNCTION;
} else if( o instanceof List ) {
return LIST;
} else if( o instanceof Map ) {
return CONTEXT;
}
return UNKNOWN;
}
public static boolean isInstanceOf( Object o, Type t ) {
if ( o == null ) {
return false; // See FEEL specifications Table 49.
}
if ( t == UNKNOWN ) {
return true;
}
return determineTypeFromInstance( o ) == t;
}
public static boolean isInstanceOf( Object o, String name ) {
return determineTypeFromInstance( o ) == determineTypeFromName( name );
}
@Override
public boolean isInstanceOf(Object o) {
return isInstanceOf(o, this);
}
@Override
public boolean isAssignableValue(Object value) {
if ( value == null ) {
return true; // a null-value can be assigned to any type.
}
return isInstanceOf(value, this);
}
}