de.dfki.iui.mmds.dialogue.SiamContext.java Source code

Java tutorial

Introduction

Here is the source code for de.dfki.iui.mmds.dialogue.SiamContext.java

Source

/*******************************************************************************
 * The Creative Commons CC-BY-NC 4.0 License
 * http://creativecommons.org/licenses/by-nc/4.0/legalcode
 *
 * Creative Commons (CC) by DFKI GmbH
 * - Vanessa Hahn <Vanessa.Hahn@dfki.de>
 * - Robert Nesselrath <rnesselrath@gmail.com>
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 *******************************************************************************/
package de.dfki.iui.mmds.dialogue;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.scxml.Context;
import org.apache.commons.scxml.SCXMLExpressionException;
import org.apache.commons.scxml.env.jexl.JexlContext;
import org.apache.log4j.Logger;
import org.eclipse.emf.ecore.EDataType;

import de.dfki.iui.mmds.core.emf.datatypes.BDataType;
import de.dfki.iui.mmds.core.model.dialogue.Variable;
import de.dfki.iui.mmds.scxml.Data;
import de.dfki.iui.mmds.scxml.State;
import de.dfki.iui.mmds.scxml.TransitionTarget;
import de.dfki.iui.mmds.scxml.XData;

class SiamContext extends JexlContext {

    static SiamStateMachine siamStateMachine;

    public SiamContext(SiamStateMachine _siamStateMachine) {
        super();
        siamStateMachine = _siamStateMachine;
    }

    SiamContext(Context parent) {
        super(parent);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public void setLocal(String name, Object value) {
        if (value != null && value.toString().equals("[data: null]") && has("stateID")) {
            // value is variable from scxml model
            String stateID = (String) get("stateID");
            value = null;
            if (DialogueComponent.INSTANCE.idToScxmlState.containsKey(stateID)) {
                TransitionTarget tt = DialogueComponent.INSTANCE.idToScxmlState.get(stateID);
                State state = null;
                if (tt instanceof State) {
                    state = (State) tt;
                }
                while (value == null && state != null) {
                    // search for variable in scxml-model and set variable with
                    // default value in context.
                    for (Data data : state.getDatamodel().getData()) {
                        if (data instanceof XData && ((XData) data).getId().equals(name)) {
                            value = ((XData) data).getObject();
                            if (name.startsWith("_variable$")) {
                                Object defaultValue = null;
                                String variableName = name.split("\\$")[1];
                                Variable variable = (Variable) value;
                                if (variable.getDefault() != null && !variable.getDefault().isEmpty()) {
                                    if (variable.getEmfType() != null
                                            && variable.getEmfType() instanceof EDataType) {
                                        defaultValue = variable.getEmfType().getEPackage().getEFactoryInstance()
                                                .createFromString((EDataType) variable.getEmfType(),
                                                        variable.getDefault());
                                    } else if (variable.getType() != null && !variable.getType().isEmpty()) {
                                        try {
                                            defaultValue = siamStateMachine.siamEvaluator.eval(this,
                                                    variable.getDefault());
                                        } catch (IllegalArgumentException | SecurityException
                                                | SCXMLExpressionException e) {
                                            final Writer result = new StringWriter();
                                            final PrintWriter printWriter = new PrintWriter(result);
                                            e.printStackTrace(printWriter);
                                            Logger.getLogger(this.getClass()).warn(String.format(
                                                    "Cannot create default variable value \"%s\" for variable \"%s\" of type %s!\n%s",
                                                    variable.getDefault(), variable.getName(), variable.getType(),
                                                    result.toString()));
                                        }
                                        if (defaultValue == null) {
                                            Logger.getLogger(this.getClass()).warn(String.format(
                                                    "Cannot create default variable value \"%s\" for variable \"%s\" of type %s!",
                                                    variable.getDefault(), variable.getName(), variable.getType()));
                                        }
                                    } else {
                                        Logger.getLogger(this.getClass()).warn(String.format(
                                                "Cannot create default value for variable \"%s\". The type %s is not serializable.",
                                                variable.getName(), variable.getEmfType()));
                                    }
                                }
                                super.setLocal(variableName, defaultValue);
                            }
                            break;
                        }
                    }
                    // go up to containing state and search for variable here
                    if (state.eContainer() instanceof State) {
                        state = (State) state.eContainer();
                    } else {
                        state = null;
                    }
                }
            }
        } else {
            // type check. Convert BDataType to DataType or vice versa if
            // necessary.
            Variable variable = (Variable) get("_variable$" + name);

            if (variable != null && value != null) {
                Class variableInstanceClass;
                if (variable.getEmfType() != null) {
                    variableInstanceClass = variable.getEmfType().getInstanceClass();
                } else if (variable.getType() != null && !variable.getType().isEmpty()) {
                    try {
                        variableInstanceClass = DialogueComponent.INSTANCE.projectContext.getBundleContext()
                                .getBundle().loadClass(variable.getType());
                    } catch (ClassNotFoundException e) {
                        throw new IllegalArgumentException(String.format(
                                "Cannot assign value to variable \"%s\" of type %s. Class \'%s\' does not exist",
                                name, variable.getType(), variable.getType()));
                    }
                } else
                    throw new IllegalArgumentException(
                            String.format("No type defined for variable \"%s\" in scope of state \"%s\".",
                                    variable.getName(), get("stateID")));
                if (!(variableInstanceClass.isInstance(value))
                        && !areMatchingClassTypes(variableInstanceClass, value.getClass())) {
                    boolean success = false;
                    if (value instanceof BDataType) {
                        ParameterizedType type = (ParameterizedType) value.getClass().getGenericSuperclass();
                        if (((Class) type.getActualTypeArguments()[0]).getName()
                                .equals(variableInstanceClass.getName())) {
                            if (!((BDataType) value).isResolved()
                                    && ((BDataType) value).getExpression().isEmpty()) {
                                value = "";
                            } else {
                                value = ((BDataType) value).getValue();
                            }
                            success = true;
                        } else if (((Class) type.getActualTypeArguments()[0]).getName()
                                .equals(String.class.getName())) {
                            if (BDataType.class.isAssignableFrom(variableInstanceClass)) {
                                try {
                                    value = variableInstanceClass.getMethod("valueOf", String.class).invoke(null,
                                            value.toString());
                                    success = true;
                                } catch (IllegalAccessException | IllegalArgumentException
                                        | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }
                    } else if (variableInstanceClass.getSuperclass() == BDataType.class) {
                        BDataType newValue;
                        try {
                            newValue = (BDataType) variableInstanceClass.newInstance();
                            newValue.setValue(value);
                            value = newValue;
                            success = true;
                        } catch (InstantiationException | IllegalAccessException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (ClassCastException e) {
                            success = false;
                        }
                    }
                    if (!success) {
                        String message = String.format(
                                "Cannot assign value of type %s to variable \"%s\" of type %s: Wrong type.",
                                value.getClass().getName(), name, variableInstanceClass.getName());
                        Logger.getLogger(this.getClass()).error(message);
                        throw new IllegalArgumentException(message);
                    }
                }
            }
        }
        super.setLocal(name, value);
    }

    static boolean areMatchingClassTypes(Class clazz1, Class clazz2) {
        clazz1 = wrap(clazz1);
        clazz2 = wrap(clazz2);
        return clazz1.equals(clazz2);
    }

    private static final Map<Class<?>, Class<?>> PRIMITIVES_TO_WRAPPERS = new HashMap<Class<?>, Class<?>>();

    private static <T> Class<T> wrap(Class<T> c) {
        if (PRIMITIVES_TO_WRAPPERS.isEmpty()) {
            PRIMITIVES_TO_WRAPPERS.put(boolean.class, Boolean.class);
            PRIMITIVES_TO_WRAPPERS.put(byte.class, Byte.class);
            PRIMITIVES_TO_WRAPPERS.put(char.class, Character.class);
            PRIMITIVES_TO_WRAPPERS.put(double.class, Double.class);
            PRIMITIVES_TO_WRAPPERS.put(float.class, Float.class);
            PRIMITIVES_TO_WRAPPERS.put(int.class, Integer.class);
            PRIMITIVES_TO_WRAPPERS.put(long.class, Long.class);
            PRIMITIVES_TO_WRAPPERS.put(short.class, Short.class);
            PRIMITIVES_TO_WRAPPERS.put(void.class, Void.class);
        }
        return c.isPrimitive() ? (Class<T>) PRIMITIVES_TO_WRAPPERS.get(c) : c;
    }

    private static final long serialVersionUID = 3244867294078681578L;

}