<commit_before>/*
 * Wegas
 * http://wegas.albasim.ch
 *
 * Copyright (c) 2013 School of Business and Engineering Vaud, Comem
 * Licensed under the MIT License
 */
package com.wegas.core.ejb;

import com.wegas.core.event.internal.EngineInvocationEvent;
import com.wegas.core.exception.WegasException;
import com.wegas.core.persistence.AbstractEntity;
import com.wegas.core.persistence.game.GameModelContent;
import com.wegas.core.persistence.game.Player;
import com.wegas.core.persistence.game.Script;
import com.wegas.core.persistence.variable.VariableDescriptor;
import com.wegas.core.persistence.variable.VariableInstance;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.enterprise.event.ObserverException;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author <NAME> <<EMAIL>>
 */
@Stateless
@LocalBean
public class ScriptFacade implements Serializable {

    private static final Logger logger = LoggerFactory.getLogger(ScriptFacade.class);
    /**
     *
     */
    @PersistenceContext(unitName = "wegasPU")
    private EntityManager em;
    /**
     *
     */
    @EJB
    private PlayerFacade playerEntityFacade;
    /**
     *
     */
    @EJB
    private VariableDescriptorFacade variableDescriptorFacade;
    /**
     *
     */
    @Inject
    private RequestManager requestManager;
    /**
     *
     */
    @Inject
    Event<EngineInvocationEvent> engineInvocationEvent;

    /**
     *
     */
    //@PostConstruct
    //public void onConstruct() {
    //}
    /**
     *
     * Fires an engineInvocationEvent, which should be intercepted to customize
     * engine scope.
     *
     * @param scripts A list of ScriptEntities to evaluate, all programming
     * language should be the same
     * @param arguments
     * @return
     * @throws ScriptException
     * @throws WegasException
     */
    public Object eval(Script script, Map<String, AbstractEntity> arguments) throws ScriptException, WegasException {
        ScriptEngineManager mgr = new ScriptEngineManager();                    // Instantiate the corresponding script engine
        ScriptEngine engine;
        try {
            engine = mgr.getEngineByName(script.getLanguage());
        } catch (NullPointerException ex) {
            logger.error("Could not find language", ex.getMessage(), ex.getStackTrace());
            throw new WegasException("Could not instantiate script engine for script" + script);
        }
        // Invocable invocableEngine = (Invocable) engine;

        try {
            engineInvocationEvent.fire(new EngineInvocationEvent(requestManager.getPlayer(), engine));// Fires the engine invocation event, to allow extensions

        } catch (ObserverException ex) {
            throw (WegasException) ex.getCause();
        } finally {                                                             //Try finishing evaluation
            for (Entry<String, AbstractEntity> arg : arguments.entrySet()) {    // Inject the arguments
                engine.put(arg.getKey(), arg.getValue());
            }

            try {
                return engine.eval(script.getContent());
            } catch (ScriptException ex) {
                logger.warn("{} in\n{}", ex.getMessage(), script.getContent());
                requestManager.addException(
                        new com.wegas.core.exception.ScriptException(script.getContent(), ex.getLineNumber(), ex.getMessage()));
                throw new ScriptException(ex.getMessage(), script.getContent(), ex.getLineNumber());
            }
        }
    }

    public Object eval(List<Script> scripts, Map<String, AbstractEntity> arguments) throws ScriptException, WegasException {
        if (scripts.isEmpty()) {
            return null;
        }
        while (scripts.remove(null)) {
        }                                                                        //remove null scripts
        // @fixme test the most performant version
        StringBuilder buf = new StringBuilder();
        for (Script s : scripts) {                                              // Evaluate each script
            try {
                buf.append(s.getContent());
                buf.append(";");
            } catch (NullPointerException ex) {
                //script does not exist
            }
            //result = engine.eval(s.getContent());
        }
        return this.eval(new Script(buf.toString()));
    }

    /**
     * Default customization of our engine: inject the script library, the root
     * variable instances and some libraries.
     *
     * @param evt
     * @throws ScriptException
     * @throws WegasException
     */
    public void onEngineInstantiation(@Observes EngineInvocationEvent evt) throws ScriptException {
        evt.getEngine().put("self", evt.getPlayer());                           // Inject current player
        evt.getEngine().put("gameModel", evt.getPlayer().getGameModel());       // Inject current gameModel
        evt.getEngine().put("VariableDescriptorFacade", variableDescriptorFacade); // Inject the variabledescriptor facade
        evt.getEngine().put("RequestManager", requestManager);                  // Inject the request manager

        List<String> errorVariable = new ArrayList<>();

        for (Entry<String, GameModelContent> arg
                : evt.getPlayer().getGameModel().getScriptLibrary().entrySet()) { // Inject the script library
            try {
                evt.getEngine().eval(arg.getValue().getContent());
            } catch (ScriptException ex) {
                logger.warn("Error injecting script library: {} in\n{}", ex.getMessage(), arg.getValue());
                throw new ScriptException(ex.getMessage(), arg.getValue().getContent(), ex.getLineNumber());
            }
        }

        for (VariableDescriptor vd
                : evt.getPlayer().getGameModel().getChildVariableDescriptors()) { // Inject the variable instances in the script
            VariableInstance vi = vd.getInstance(evt.getPlayer());
            try {
                evt.getEngine().put(vd.getName(), vi);
            } catch (IllegalArgumentException ex) {
                errorVariable.add(vd.getLabel());

            }
        }
        if (errorVariable.size() > 0) {
            StringBuilder allVars = new StringBuilder();<commit_msg>Adapt script after merge<commit_after>/*
 * Wegas
 * http://wegas.albasim.ch
 *
 * Copyright (c) 2013 School of Business and Engineering Vaud, Comem
 * Licensed under the MIT License
 */
package com.wegas.core.ejb;

import com.wegas.core.event.internal.EngineInvocationEvent;
import com.wegas.core.exception.WegasException;
import com.wegas.core.persistence.AbstractEntity;
import com.wegas.core.persistence.game.GameModelContent;
import com.wegas.core.persistence.game.Player;
import com.wegas.core.persistence.game.Script;
import com.wegas.core.persistence.variable.VariableDescriptor;
import com.wegas.core.persistence.variable.VariableInstance;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.enterprise.event.ObserverException;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author <NAME> <<EMAIL>>
 */
@Stateless
@LocalBean
public class ScriptFacade implements Serializable {

    private static final Logger logger = LoggerFactory.getLogger(ScriptFacade.class);
    /**
     *
     */
    @PersistenceContext(unitName = "wegasPU")
    private EntityManager em;
    /**
     *
     */
    @EJB
    private PlayerFacade playerEntityFacade;
    /**
     *
     */
    @EJB
    private VariableDescriptorFacade variableDescriptorFacade;
    /**
     *
     */
    @Inject
    private ScriptEvent event;
    /**
     *
     */
    @Inject
    private RequestManager requestManager;
    /**
     *
     */
    @Inject
    Event<EngineInvocationEvent> engineInvocationEvent;

    /**
     *
     */
    //@PostConstruct
    //public void onConstruct() {
    //}
    /**
     *
     * Fires an engineInvocationEvent, which should be intercepted to customize
     * engine scope.
     *
     * @param scripts A list of ScriptEntities to evaluate, all programming
     * language should be the same
     * @param arguments
     * @return
     * @throws ScriptException
     * @throws WegasException
     */
    public Object eval(Script script, Map<String, AbstractEntity> arguments) throws ScriptException, WegasException {

        ScriptEngine engine = requestManager.getCurrentEngine();
        if (engine == null) {
            ScriptEngineManager mgr = new ScriptEngineManager();                    // Instantiate the corresponding script engine

            try {
                engine = mgr.getEngineByName(script.getLanguage());
            } catch (NullPointerException ex) {
                logger.error("Could not find language", ex.getMessage(), ex.getStackTrace());
                throw new WegasException("Could not instantiate script engine for script" + script);
            }

            // Invocable invocableEngine = (Invocable) engine;
            engine.put("self", requestManager.getPlayer());                         // Inject current player
            engine.put("gameModel", requestManager.getPlayer().getGameModel());     // Inject current gameModel
            try {
                engineInvocationEvent.fire(
                        new EngineInvocationEvent(requestManager.getPlayer(), engine));// Fires the engine invocation event, to allow extensions

            } catch (ObserverException ex) {
                throw (WegasException) ex.getCause();
            }
            requestManager.setCurrentEngine(engine);
        }
        // Invocable invocableEngine = (Invocable) engine;

        for (Entry<String, AbstractEntity> arg : arguments.entrySet()) {    // Inject the arguments
            engine.put(arg.getKey(), arg.getValue());
        }

        try {
            return engine.eval(script.getContent());
        } catch (ScriptException ex) {
            logger.warn("{} in\n{}", ex.getMessage(), script.getContent());
            requestManager.addException(
                    new com.wegas.core.exception.ScriptException(script.getContent(), ex.getLineNumber(), ex.getMessage()));
            throw new ScriptException(ex.getMessage(), script.getContent(), ex.getLineNumber());
        }

    }

    public Object eval(List<Script> scripts, Map<String, AbstractEntity> arguments) throws ScriptException, WegasException {
        if (scripts.isEmpty()) {
            return null;
        }
        while (scripts.remove(null)) {
        }                                                                        //remove null scripts
        // @fixme test the most performant version
        StringBuilder buf = new StringBuilder();
        for (Script s : scripts) {                                              // Evaluate each script
            try {
                buf.append(s.getContent());
                buf.append(";");
            } catch (NullPointerException ex) {
                //script does not exist
            }
            //result = engine.eval(s.getContent());
        }
        return this.eval(new Script(buf.toString()));
    }

    /**
     * Default customization of our engine: inject the script library, the root
     * variable instances and some libraries.
     *
     * @param evt
     * @throws ScriptException
     * @throws WegasException
     */
    public void onEngineInstantiation(@Observes EngineInvocationEvent evt) throws ScriptException {
        evt.getEngine().put("self", evt.getPlayer());                           // Inject current player
        evt.getEngine().put("gameModel", evt.getPlayer().getGameModel());       // Inject current gameModel
        evt.getEngine().put("VariableDescriptorFacade", variableDescriptorFacade); // Inject the variabledescriptor facade
        evt.getEngine().put("RequestManager", requestManager);                  // Inject the request manager
        evt.getEngine().put("Event", event);                                    // Inject the Event manager
        event.detachAll();

        List<String> errorVariable = new ArrayList<>();

        for (Entry<String, GameModelContent> arg
                : evt.getPlayer().getGameModel().getScriptLibrary().entrySet()) { // Inject the script library
            try {
                evt.getEngine().eval(arg.getValue().getContent());
            } catch (ScriptException ex) {
                logger.warn("Error injecting script library: {} in\n{}", ex.getMessage(), arg.getValue());
                throw new ScriptException(ex.getMessage(), arg.getValue().getContent(), ex.getLineNumber());
            }
        }

        for (VariableDescriptor vd
                : evt.getPlayer().getGameModel().getChildVariableDescriptors()) { // Inject the variable instances in the script
            VariableInstance vi = vd.getInstance(evt.getPlayer());
            try {
                evt.getEngine().put(vd.getName(), vi);
            } catch (IllegalArgumentException ex) {
                errorVariable.add(vd.getLabel());

            }
        }
        if (errorVariable.size() > 0) {
            StringBuilder allVars = new StringBuilder();
{'fraction_non_alphanumeric': 0.10734947503749732, 'fraction_numerical': 0.0009999285765302478, 'mean_word_length': 2.274555659494855, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 13, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '827158', 'n_tokens_mistral': 3551, 'n_tokens_neox': 3514, 'n_words': 833}