it.unibo.alchemist.model.implementations.actions.LsaAbstractAction.java Source code

Java tutorial

Introduction

Here is the source code for it.unibo.alchemist.model.implementations.actions.LsaAbstractAction.java

Source

/*
 * Copyright (C) 2010-2014, Danilo Pianini and contributors
 * listed in the project's pom.xml file.
 * 
 * This file is part of Alchemist, and is distributed under the terms of
 * the GNU General Public License, with a linking exception, as described
 * in the file LICENSE in the Alchemist distribution's top directory.
 */
package it.unibo.alchemist.model.implementations.actions;

import it.unibo.alchemist.expressions.implementations.Expression;
import it.unibo.alchemist.expressions.implementations.ListTreeNode;
import it.unibo.alchemist.expressions.implementations.NumTreeNode;
import it.unibo.alchemist.expressions.implementations.Type;
import it.unibo.alchemist.expressions.interfaces.IExpression;
import it.unibo.alchemist.expressions.interfaces.ITreeNode;
import it.unibo.alchemist.model.implementations.molecules.LsaMolecule;
import it.unibo.alchemist.model.interfaces.ILsaAction;
import it.unibo.alchemist.model.interfaces.ILsaMolecule;
import it.unibo.alchemist.model.interfaces.ILsaNode;
import it.unibo.alchemist.model.interfaces.Node;
import it.unibo.alchemist.model.interfaces.Reaction;
import org.danilopianini.lang.HashString;
import org.danilopianini.util.ListSet;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Sets;

/**
 *
 */
public abstract class LsaAbstractAction extends AbstractAction<List<ILsaMolecule>> implements ILsaAction {
    private static final long serialVersionUID = 4158296120349274343L;
    private Map<HashString, ITreeNode<?>> matches;
    private List<ILsaNode> nodes;

    /**
     * @param node
     *            the node
     * @param m
     *            the modified molecule
     */
    public LsaAbstractAction(final ILsaNode node, final List<ILsaMolecule> m) {
        super(node);
        for (final ILsaMolecule mol : m) {
            addModifiedMolecule(mol);
        }
    }

    /**
     * Used to add a new match to the matches map.
     * 
     * @param key
     *            the variable
     * @param value
     *            the associated value
     */
    protected final void addMatch(final HashString key, final double value) {
        addMatch(key, new NumTreeNode(value));
    }

    /**
     * Used to add a new match to the matches map.
     * 
     * @param key
     *            the variable
     * @param value
     *            the associated value
     */
    protected final void addMatch(final ITreeNode<?> key, final ITreeNode<?> value) {
        if (key.getType() != Type.VAR) {
            throw new IllegalArgumentException("Only variables can be used as keys when inserting matches.");
        }
        switch (value.getType()) {
        case COMPARATOR:
        case LISTCOMPARATOR:
        case OPERATOR:
        case VAR:
            throw new IllegalArgumentException(
                    "Only instanced elements can be used as values when inserting matches.");
        default:
            addMatch(key.toHashString(), value);
        }
    }

    /**
     * Used to add a new match to the matches map.
     * 
     * @param key
     *            the variable
     * @param value
     *            the associated value
     */
    protected final void addMatch(final IExpression key, final ITreeNode<?> value) {
        addMatch(key.getRootNode(), value);
    }

    /**
     * Used to add a new match to the matches map.
     * 
     * @param key
     *            the variable
     * @param value
     *            the associated value
     */
    protected final void addMatch(final IExpression key, final IExpression value) {
        addMatch(key.getRootNode(), value.getRootNode());
    }

    /**
     * Used to add a new match to the matches map.
     * 
     * @param key
     *            the variable
     * @param value
     *            the associated value
     */
    protected final void addMatch(final HashString key, final ITreeNode<?> value) {
        if (matches == null) {
            matches = new HashMap<>();
        }
        matches.put(key, value);
    }

    /**
     * Used to add a new match to the matches map.
     * 
     * @param key
     *            the variable
     * @param value
     *            the associated value
     */
    protected final void addMatch(final String key, final double value) {
        addMatch(new HashString(key), new NumTreeNode(value));
    }

    /**
     * Used to add a new match to the matches map.
     * 
     * @param key
     *            the variable
     * @param value
     *            the associated value
     */
    protected final void addMatch(final String key, final ITreeNode<?> value) {
        addMatch(new HashString(key), value);
    }

    /**
     * Given an LSA template, allocates all the variables using the current
     * matches. The allocations may or not produce an instance: it does only if
     * all the variable within the LSA have a corresponding entry in the matches
     * map.
     * 
     * @param template
     *            the LSA template
     * @return the template with all the the variables instanced
     */
    protected List<IExpression> allocateVars(final ILsaMolecule template) {
        return template.allocateVar(getMatches());
    }

    /**
     * Same of {@link #allocateVars(ILsaMolecule)}, but also builds an
     * ILsaMolecule.
     * 
     * @param template
     *            the LSA template
     * @return the template with all the the variables instanced
     */
    protected ILsaMolecule allocateVarsAndBuildLSA(final ILsaMolecule template) {
        return new LsaMolecule(template.allocateVar(getMatches()));
    }

    @Override
    public abstract LsaAbstractAction cloneAction(Node<List<ILsaMolecule>> n, Reaction<List<ILsaMolecule>> r);

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as Double.
     * Hides some low-level details. If a molecule template is passed, it will
     * be istanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as Double, or NaN if you use this method not properly
     */
    protected Double getLSAArgumentAsDouble(final ILsaMolecule mol, final int argNumber) {
        return (Double) getLSAArgumentAsObject(mol, argNumber);
    }

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as Double.
     * Hides some low-level details. If a molecule template is passed, it will
     * be instanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as Double, or NaN if you use this method not properly
     */
    protected Double getLSAArgumentAsDouble(final List<IExpression> mol, final int argNumber) {
        return (Double) getLSAArgumentAsObject(mol, argNumber);
    }

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as Double.
     * Hides some low-level details. If a molecule template is passed, it will
     * be instanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as Integer, or 0 if you use this method not properly
     */
    protected int getLSAArgumentAsInt(final ILsaMolecule mol, final int argNumber) {
        return getLSAArgumentAsDouble(mol, argNumber).intValue();
    }

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as Double.
     * Hides some low-level details. If a molecule template is passed, it will
     * be instanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as Integer, or 0 if you use this method not properly
     */
    protected int getLSAArgumentAsInt(final List<IExpression> mol, final int argNumber) {
        return getLSAArgumentAsDouble(mol, argNumber).intValue();
    }

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as Integer.
     * Hides some low-level details. If a molecule template is passed, it will
     * be instanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as Object
     */
    protected Object getLSAArgumentAsObject(final ILsaMolecule mol, final int argNumber) {
        return mol.getArg(argNumber).calculate(matches).getValue(matches);
    }

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as Object.
     * Hides some low-level details. If a molecule template is passed, it will
     * be instanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as Object
     */
    protected Object getLSAArgumentAsObject(final List<IExpression> mol, final int argNumber) {
        return mol.get(argNumber).calculate(matches).getValue(matches);
    }

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as String.
     * Hides some low-level details. If a molecule template is passed, it will
     * be instanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as String
     */
    protected String getLSAArgumentAsString(final ILsaMolecule mol, final int argNumber) {
        return getLSAArgumentAsObject(mol, argNumber).toString();
    }

    /**
     * This method allows subclasses to access a field of an LSA (supposed to be
     * a computable expression or a number) and have back its VALUE as String.
     * Hides some low-level details. If a molecule template is passed, it will
     * be instanced using the current matches.
     * 
     * @param mol
     *            the molecule (or molecule template)
     * @param argNumber
     *            the position of the argument
     * @return the value as String
     */
    protected String getLSAArgumentAsString(final List<IExpression> mol, final int argNumber) {
        return getLSAArgumentAsObject(mol, argNumber).toString();
    }

    /**
     * Accesses an LSA space and retrieves a molecule matching template. It
     * instances its variables with the current matches before accessing the
     * space. Equivalent to getLSAs(n, template, true)
     * 
     * 
     * @param n
     *            the node to access
     * @param template
     *            the template molecule to retrieve
     * @return a list of ILsaMolecules matching the (possibly partly instanced)
     *         template
     */
    protected List<ILsaMolecule> getLSAs(final ILsaNode n, final ILsaMolecule template) {
        return getLSAs(n, template, true);
    }

    /**
     * Accesses an LSA space and retrieves a molecule matching template. It can
     * use the template as-is or instance its variables with the current matches
     * before accessing the space.
     * 
     * @param n
     *            the node to access
     * @param template
     *            the template molecule to retrieve
     * @param useMatches
     *            if true, the template will have its variables (possibly
     *            partly) instantiated using the values in the matches map
     * @return a list of ILsaMolecules matching the (possibly partly instanced)
     *         template
     */
    protected List<ILsaMolecule> getLSAs(final ILsaNode n, final ILsaMolecule template, final boolean useMatches) {
        if (useMatches) {
            return n.getConcentration(new LsaMolecule(allocateVars(template)));
        }
        return n.getConcentration(template);
    }

    /**
     * Accesses the local tuple space and retrieves a molecule matching
     * template. It instances its variables with the current matches before
     * accessing the space. Equivalent to getLSAsFromLocalSpace(template, true)
     * 
     * @param template
     *            the template molecule to retrieve
     * @return a list of ILsaMolecules matching the (possibly partly instanced)
     *         template
     */
    protected List<ILsaMolecule> getLSAsFromLocalSpace(final ILsaMolecule template) {
        return getLSAsFromLocalSpace(template, true);
    }

    /**
     * Accesses the local tuple space and retrieves a molecule matching
     * template. It can use the template as-is or instance its variables with
     * the current matches before accessing the space.
     * 
     * @param template
     *            the template molecule to retrieve
     * @param useMatches
     *            if true, the template will have its variables (possibly
     *            partly) instantiated using the values in the matches map
     * @return a list of ILsaMolecules matching the (possibly partly instanced)
     *         template
     */
    protected List<ILsaMolecule> getLSAsFromLocalSpace(final ILsaMolecule template, final boolean useMatches) {
        return getLSAs(getNode(), template, useMatches);
    }

    /**
     * Given a variable, allows to access to its associated value.
     * 
     * @param var
     *            the variable
     * @return the value associated to the variable
     */
    protected ITreeNode<?> getMatch(final HashString var) {
        return matches.get(var);
    }

    /**
     * Given a variable, allows to access to its associated value.
     * 
     * @param s
     *            the variable
     * @return the value associated to the variable
     */
    protected ITreeNode<?> getMatch(final String s) {
        return getMatch(new HashString(s));
    }

    /**
     * Given a variable, allows to access to its associated value as double.
     * Note that this might fail if you try to access a value which is not
     * numeric through this method.
     * 
     * @param s
     *            the variable
     * @return the double value associated to the variable
     */
    protected double getMatchAsDouble(final HashString s) {
        return ((NumTreeNode) getMatch(s)).getData();
    }

    /**
     * Given a variable, allows to access to its associated value as double.
     * Note that this might fail if you try to access a value which is not
     * numeric through this method.
     * 
     * @param s
     *            the variable
     * @return the double value associated to the variable
     */
    protected double getMatchAsDouble(final String s) {
        return ((NumTreeNode) getMatch(s)).getData();
    }

    /**
     * Given a variable, allows to access to its associated value as String.
     * 
     * @param s
     *            the variable
     * @return its String representation
     */
    protected String getMatchAsString(final HashString s) {
        return getMatch(s).toString();
    }

    /**
     * Given a variable, allows to access to its associated value as String.
     * 
     * @param s
     *            the variable
     * @return its String representation
     */
    protected String getMatchAsString(final String s) {
        return getMatch(s).toString();
    }

    /**
     * @return the map containing the variable / value associations
     */
    protected final Map<HashString, ITreeNode<?>> getMatches() {
        return matches;
    }

    @Override
    @SuppressWarnings("unchecked")
    public ListSet<ILsaMolecule> getModifiedMolecules() {
        return (ListSet<ILsaMolecule>) super.getModifiedMolecules();
    }

    @Override
    public ILsaNode getNode() {
        return (ILsaNode) super.getNode();
    }

    /**
     * @return a list of the nodes in the current execution context. This backs
     *         the internal representation: handle with care.
     */
    protected final List<ILsaNode> getNodes() {
        return nodes;
    }

    /**
     * Injects an LSA in a node.
     * 
     * @param n
     *            the destination
     * @param m
     *            the LSA to inject
     */
    protected void inject(final ILsaNode n, final ILsaMolecule m) {
        n.setConcentration(new LsaMolecule(m.allocateVar(getMatches())));
    }

    /**
     * Injects an ILsaMolecule locally.
     * 
     * @param m
     *            the molecule to inject. Must be instanced: no variables, no
     *            comparators, no operations of any kind.
     */
    protected void injectLocally(final ILsaMolecule m) {
        inject(getNode(), m);
    }

    @Override
    public void setExecutionContext(final Map<HashString, ITreeNode<?>> m, final List<ILsaNode> n) {
        matches = m;
        nodes = n;
    }

    /**
     * Given an an LSA template, an argument number and some new data, sets the
     * argument in the given position as the passed value.
     * 
     * @param template
     *            the original LSA template
     * @param data
     *            the data to insert
     * @param argNumber
     *            the argument to substitute with the new one
     * @return the template modified, with the insertion of data where required
     *         in place of the old value
     */
    protected ILsaMolecule setLSAArgument(final ILsaMolecule template, final double data, final int argNumber) {
        return setLSAArgument(template, new NumTreeNode(data), argNumber);
    }

    /**
     * Given an an LSA template, an argument number and some new data, sets the
     * argument in the given position as the passed value.
     * 
     * @param template
     *            the original LSA template
     * @param data
     *            the data to insert
     * @param argNumber
     *            the argument to substitute with the new one
     * @return the template modified, with the insertion of data where required
     *         in place of the old value
     */
    protected ILsaMolecule setLSAArgument(final ILsaMolecule template, final ITreeNode<?> data,
            final int argNumber) {
        final List<IExpression> l = template.allocateVar(null);
        l.remove(argNumber);
        l.add(argNumber, new Expression(data));
        return new LsaMolecule(l);
    }

    /**
     * Sets #D.
     * 
     * @param d
     *            the value associated to #D
     */
    protected void setSyntheticD(final double d) {
        matches.put(LsaMolecule.SYN_D, new NumTreeNode(d));
    }

    /**
     * Sets #ROUTE.
     * 
     * @param d
     *            the value associated to #ROUTE
     */
    protected void setSyntheticRoute(final double d) {
        matches.put(LsaMolecule.SYN_ROUTE, new NumTreeNode(d));
    }

    /**
     * Sets #NEIGH equal to the passed node list.
     * 
     * @param list
     *            the list of nodes to use
     */
    protected void setSyntheticNeigh(final Collection<Node<List<ILsaMolecule>>> list) {
        final Set<ITreeNode<?>> l = Sets.newHashSetWithExpectedSize(list.size());
        for (final Node<List<ILsaMolecule>> n : list) {
            l.add(new NumTreeNode(n.getId()));
        }
        matches.put(LsaMolecule.SYN_NEIGH, new ListTreeNode(l));
    }

    /**
     * Sets #O to the local node.
     */
    protected void setSyntheticO() {
        matches.put(LsaMolecule.SYN_O, new NumTreeNode(getNode().getId()));
    }

    @Override
    public abstract String toString();

}