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

de.tsl2.nano.incubation.specification.rules.RuleScript Maven / Gradle / Ivy

Go to download

TSL2 Framework Specification (Pools of descripted and runnable Actions and Rules, Generic Tree)

There is a newer version: 2.5.1
Show newest version
/*
 * File: $HeadURL$
 * Id  : $Id$
 * 
 * created by: Tom, Thomas Schneider
 * created on: 04.11.2015
 * 
 * Copyright: (c) Thomas Schneider 2015, all rights reserved
 */
package de.tsl2.nano.incubation.specification.rules;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.script.Bindings;
import javax.script.ScriptEngine;

import org.apache.commons.logging.Log;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.core.Commit;

import de.tsl2.nano.core.ENV;
import de.tsl2.nano.core.ManagedException;
import de.tsl2.nano.core.log.LogFactory;
import de.tsl2.nano.incubation.specification.ParType;
import de.tsl2.nano.util.operation.Operator;

/**
 * Uses javascript engine (java6+7: rhino, java8: nashorn) to evaluate an operation.
 * 
 * @author Tom, Thomas Schneider
 * @version $Revision$
 */
public class RuleScript extends AbstractRule {
    /** serialVersionUID */
    private static final long serialVersionUID = -6479357867492017791L;

    private static final Log LOG = LogFactory.getLog(RuleScript.class);

    @Attribute(required=false)
    String language;
    
    transient ScriptEngine engine;

    public static final char PREFIX = '%';

    /**
     * constructor
     */
    protected RuleScript() {
        super();
    }

    public RuleScript(String name, String operation, LinkedHashMap parameter) {
        this(null, name, operation, parameter);
    }
    
    /**
     * constructor
     * 
     * @param name
     * @param operation
     * @param parameter
     */
    public RuleScript(String language, String name, String operation, LinkedHashMap parameter) {
        super(name, operation, parameter);
        init(language);
    }

    void init(String engineName) {
        this.language = engineName;
    }

    protected ScriptEngine engine() {
        if (engine == null)
            engine = ActionScript.createEngine(language);
        return engine;
    }
    
    @Override
    public String prefix() {
        return String.valueOf(PREFIX);
    }

    @Override
    public T run(Map arguments, Object... extArgs) {
        if (!initialized) {
            importSubRules();
        }
        arguments = checkedArguments(arguments, ENV.get("app.mode.strict", false));
        //in generics it is not possible to cast from Map(String,?) to Map(CharSequence, ?)

        try {
            LOG.debug("running rule <" + toString() + "> on arguments: " + arguments);
            Object obj = engine().eval(getOperation(), bind(arguments));
            T result = (T) transform(obj);
            checkConstraint(Operator.KEY_RESULT, result);
            return result;
        } catch (Exception e) {
            ManagedException.forward(e);
            return null;
        }
    }

    /**
     * some java script objects like 'java.util.HashMap' must be transformed to real java objects. E.g. the javascript
     * 'java.util.HashMap' seems not to implement Serializable!
     * 
     * @param jsValue
     * @return real java class object
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private T transform(Object jsValue) {
        if (jsValue instanceof Map)
            return (T) new LinkedHashMap((Map) jsValue);
        else if (jsValue instanceof Collection)
            return (T) new ArrayList((Collection) jsValue);
        else
            return (T) jsValue;
    }

    private Bindings bind(Map arguments) {
        return ActionScript.bind(engine(), arguments);
    }

    @Override
    @Commit
    protected void initDeserializing() {
        init(language);
        super.initDeserializing();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy