/*
* 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.core.impl;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.kie.dmn.api.core.DMNContext;
import org.kie.dmn.api.core.DMNType;
import org.kie.dmn.api.core.DMNUnaryTest;
import org.kie.dmn.core.compiler.DMNFEELHelper;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.impl.MapBackedType;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.runtime.UnaryTest;
import org.kie.dmn.feel.util.EvalHelper;
public abstract class BaseDMNTypeImpl
implements DMNType {
private String namespace;
private String name;
private String id;
private boolean collection;
private List<UnaryTest> allowedValues;
private DMNType baseType;
private Type feelType;
public BaseDMNTypeImpl(String namespace, String name, String id, boolean collection, DMNType baseType, Type feelType) {
this.namespace = namespace;
this.name = name;
this.id = id;
this.collection = collection;
this.feelType = feelType;
this.baseType = baseType;
}
@Override
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public boolean isCollection() {
return collection;
}
public void setCollection(boolean collection) {
this.collection = collection;
}
@Override
public Map<String, DMNType> getFields() {
return Collections.emptyMap();
}
@Override
public boolean isComposite() {
return false;
}
@Override
public List<DMNUnaryTest> getAllowedValues() {
return allowedValues != null ? Collections.unmodifiableList((List) allowedValues) : Collections.emptyList();
}
public List<UnaryTest> getAllowedValuesFEEL() {
return allowedValues;
}
public void setAllowedValues(List<UnaryTest> allowedValues) {
this.allowedValues = allowedValues;
}
@Override
public DMNType getBaseType() {
return baseType;
}
public void setBaseType(DMNType baseType) {
this.baseType = baseType;
}
public abstract BaseDMNTypeImpl clone();
public void setFeelType(Type feelType) {
this.feelType = feelType;
}
public Type getFeelType() {
return feelType;
}
@Override
public String toString() {
return "DMNType{ "+getNamespace()+" : "+getName()+" }";
}
@Override
public boolean isInstanceOf(Object o) {
if ( o == null ) {
return false; // See FEEL specifications Table 49.
}
// try first to recurse in case of Collection..
if ( isCollection() && o instanceof Collection ) {
Collection<Object> elements = (Collection) o;
for ( Object e : elements ) {
if ( !internalIsInstanceOf(e) || !valueMatchesInUnaryTests(e) ) {
return false;
}
}
return true;
}
// .. normal case, or collection of 1 element: singleton list
// spec defines that "a=[a]", i.e., singleton collections should be treated as the single element
// and vice-versa
return internalIsInstanceOf(o) && valueMatchesInUnaryTests(o);
}
private boolean valueMatchesInUnaryTests(Object o) {
if ( allowedValues == null || allowedValues.isEmpty() ) {
return true;
} else {
return DMNFEELHelper.valueMatchesInUnaryTests(allowedValues, EvalHelper.coerceNumber(o), null);
}
}
protected abstract boolean internalIsInstanceOf(Object o);
@Override
public boolean isAssignableValue(Object value) {
if ( value == null ) {
return true; // a null-value can be assigned to any type.
}
// try first to recurse in case of Collection..
if ( isCollection() && value instanceof Collection ) {
Collection<Object> elements = (Collection) value;
for ( Object e : elements ) {
if ( !internalIsAssignableValue(e) || !valueMatchesInUnaryTests(e) ) {
return false;
}
}
return true;
}
// .. normal case, or collection of 1 element: singleton list
// spec defines that "a=[a]", i.e., singleton collections should be treated as the single element
// and vice-versa
return internalIsAssignableValue( value ) && valueMatchesInUnaryTests(value);
}
protected abstract boolean internalIsAssignableValue(Object o);
}