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

com.gs.dmn.tck.MockTCKValueTranslator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 Goldman Sachs.
 *
 * 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 com.gs.dmn.tck;

import com.gs.dmn.DRGElementReference;
import com.gs.dmn.ast.TDRGElement;
import com.gs.dmn.ast.TInformationItem;
import com.gs.dmn.ast.TInputData;
import com.gs.dmn.ast.TItemDefinition;
import com.gs.dmn.context.DMNContext;
import com.gs.dmn.el.analysis.semantics.type.AnyType;
import com.gs.dmn.el.analysis.semantics.type.Type;
import com.gs.dmn.feel.analysis.semantics.type.*;
import com.gs.dmn.feel.lib.StandardFEELLib;
import com.gs.dmn.runtime.DMNRuntimeException;
import com.gs.dmn.runtime.Pair;
import com.gs.dmn.tck.ast.AnySimpleType;
import com.gs.dmn.tck.ast.Component;
import com.gs.dmn.tck.ast.ValueType;
import com.gs.dmn.transformation.basic.BasicDMNToNativeTransformer;
import org.apache.commons.lang3.StringUtils;

import javax.xml.namespace.QName;
import java.util.*;
import java.util.stream.Collectors;

public class MockTCKValueTranslator extends TCKValueTranslator {
    public MockTCKValueTranslator(BasicDMNToNativeTransformer transformer, StandardFEELLib feelLib) {
        super(transformer, feelLib);
    }

    //
    // Make java expressions from ValueType
    //
    @Override
    public String toNativeExpression(ValueType valueType, Type type, TDRGElement element) {
        TItemDefinition itemDefinition = findItemDefinition(element);
        return toNativeExpression(valueType, type, element, itemDefinition);
    }

    private String toNativeExpression(ValueType valueType, Type type, TDRGElement element, TItemDefinition itemDefinition) {
        AnySimpleType value = valueType.getValue();
        if (value != null) {
            String text = value.getText();
            String cleanText = removeWhiteSpaces(text);
            String path = makePath(cleanText, element);
            if (path !=  null) {
                return path;
            } else {
                if ("null".equals(text.trim()) || value.isNil()) {
                    return this.nativeFactory.nullLiteral();
                } else if (type == null) {
                    return text;
                } else if (type == StringType.STRING) {
                    return text;
                } else if (type == BooleanType.BOOLEAN) {
                    return this.nativeFactory.booleanLiteral(text);
                } else if (type == NumberType.NUMBER) {
                    text = text.trim();
                    if (text.startsWith("\"") && text.endsWith("\"")) {
                        text = text.substring(1, text.length() - 1);
                    }
                    if (element instanceof TInputData) {
                        if (this.transformer.isInteger(itemDefinition)) {
                            return this.transformer.makeIntegerForInput(text);
                        } else {
                            return this.transformer.makeDecimalForInput(text);
                        }
                    } else {
                        return this.transformer.makeDecimalForDecision(text);
                    }
                } else if (type == DateType.DATE) {
                    return this.transformer.makeDate(text);
                } else if (type == TimeType.TIME) {
                    return this.transformer.makeTime(text);
                } else if (type == DateTimeType.DATE_AND_TIME) {
                    return this.transformer.makeDateTime(text);
                } else if (type instanceof DurationType) {
                    return this.transformer.makeDuration(text);
                } else if (type == AnyType.ANY) {
                    return text;
                }

                throw new DMNRuntimeException(String.format("Cannot make value for input '%s' with type '%s'", valueType, type));
            }
        } else if (valueType.getList() != null) {
            return toNativeExpression(valueType.getList(), (ListType) type, element, itemDefinition);
        } else if (valueType.getComponent() != null) {
            if (type instanceof ItemDefinitionType) {
                return toNativeExpression(valueType.getComponent(), (ItemDefinitionType) type, element, itemDefinition);
            } else if (type instanceof ContextType) {
                return toNativeExpression(valueType.getComponent(), (ContextType) type, element, itemDefinition);
            } else {
                throw new DMNRuntimeException(String.format("Cannot make value for input '%s' with type '%s'", valueType, type));
            }
        }
        throw new DMNRuntimeException(String.format("Cannot make value for input '%s' with type '%s'", valueType, type));
    }

    private String toNativeExpression(com.gs.dmn.tck.ast.List list, ListType listType, TDRGElement element, TItemDefinition itemDefinition) {
        Type elementType = listType.getElementType();
        TItemDefinition elementItemDefinition = elementItemDefinition(itemDefinition);
        List javaList = new ArrayList<>();
        for (ValueType listValueType : list.getItem()) {
            String value = toNativeExpression(listValueType, elementType, element, elementItemDefinition);
            javaList.add(value);
        }
        String args = String.join(", ", javaList);
        return this.nativeFactory.makeBuiltinFunctionInvocation("asList", args);
    }

    private String toNativeExpression(List components, CompositeDataType type, TDRGElement element, TItemDefinition itemDefinition) {
        // Build list of members
        List> memberList = new ArrayList<>();
        Set present = new LinkedHashSet<>();
        for (Component c : components) {
            String member = c.getName();
            Type memberType = type.getMemberType(member);
            TItemDefinition memberItemDefinition = memberItemDefinition(itemDefinition, member);
            String value = toNativeExpression(c, memberType, element, memberItemDefinition);
            memberList.add(new Pair<>(member, value));
            present.add(member);
        }
        // Add the missing members
        Set members = type.getMembers();
        for (String member: members) {
            if (!present.contains(member)) {
                Type memberType = type.getMemberType(member);
                TItemDefinition memberItemDefinition = memberItemDefinition(itemDefinition, member);
                String value = this.transformer.getDefaultValue(memberType, memberItemDefinition);
                Pair pair = new Pair<>(member, value);
                memberList.add(pair);
            }
        }
        sortParameters(memberList);
        if (type instanceof ItemDefinitionType) {
            // Use constructor
            String interfaceName = this.transformer.toNativeType((ItemDefinitionType) type);
            String arguments = memberList.stream().map(Pair::getRight).collect(Collectors.joining(", "));
            return this.transformer.constructor(this.transformer.itemDefinitionNativeClassName(interfaceName), arguments);
        } else {
            // Use builder pattern in Context
            String builder = this.transformer.defaultConstructor(this.transformer.contextClassName());
            String parts = memberList.stream().map(a -> String.format("add(\"%s\", %s)", a.getLeft(), a.getRight())).collect(Collectors.joining("."));
            return String.format("%s.%s", builder, parts);
        }
    }

    private TItemDefinition findItemDefinition(TDRGElement element) {
        TInformationItem variable = this.repository.variable(element);
        return findItemDefinition(variable == null ? null : variable.getTypeRef());
    }

    private TItemDefinition findItemDefinition(QName typeRef) {
        if (typeRef == null) {
            return null;
        } else {
            return this.repository.lookupItemDefinition(typeRef.getLocalPart());
        }
    }

    private TItemDefinition elementItemDefinition(TItemDefinition itemDefinition) {
        if (itemDefinition == null) {
            return null;
        }
        if (itemDefinition.getTypeRef() != null) {
            return findItemDefinition(itemDefinition.getTypeRef());
        } else if (!itemDefinition.getItemComponent().isEmpty()) {
            return itemDefinition;
        }
        return null;
    }

    private TItemDefinition memberItemDefinition(TItemDefinition itemDefinition, String member) {
        if (itemDefinition == null) {
            return null;
        }
        for (TItemDefinition child : itemDefinition.getItemComponent()) {
            if (member.equals(child.getName())) {
                return child;
            }
        }
        return null;
    }

    private String makePath(String cleanText, TDRGElement element) {
        if (StringUtils.isBlank(cleanText)) {
            return null;
        }

        String[] parts = cleanText.split("\\.");
        String childName = parts[0];
        if (childName == null) {
            return null;
        }
        List> childRefs = this.repository.directDRGElements(element);
        Optional> childRef = childRefs.stream().filter(c -> childName.equals(repository.name(c.getElement()))).findFirst();
        if (childRef.isPresent()) {
            TDRGElement childElement = childRef.get().getElement();
            Type childType = this.transformer.drgElementOutputFEELType(childElement);
            String nativeType = this.transformer.toNativeType(childType);
            return makePath(cleanText, nativeType);
        }
        return null;
    }

    private String makePath(String text, String childType) {
        if (StringUtils.isBlank(text)) {
            return null;
        }

        String cleanText = removeWhiteSpaces(text);
        String[] parts = cleanText.split("\\.");
        StringBuilder result = new StringBuilder();
        String root = String.format("%s.%s", TCKUtil.mockContextVariable(), this.transformer.contextGetter(parts[0]));
        result.append(this.nativeFactory.makeNullCheck(root, childType));
        for (int i=1; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy