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

org.integratedmodelling.engine.modelling.datasources.DatatableContextualizer Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (C) 2007, 2015:
 * 
 * - Ferdinando Villa  - integratedmodelling.org - any
 * other authors listed in @author annotations
 *
 * All rights reserved. This file is part of the k.LAB software suite, meant to enable
 * modular, collaborative, integrated development of interoperable data and model
 * components. For details, see http://integratedmodelling.org.
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms
 * of the Affero General Public License Version 3 or any later version.
 *
 * This program is distributed in the hope that it will be useful, but without any
 * warranty; without even the implied warranty of merchantability or fitness for a
 * particular purpose. See the Affero General Public License for more details.
 * 
 * You should have received a copy of the Affero General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite
 * 330, Boston, MA 02111-1307, USA. The license is also available at:
 * https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.modelling.datasources;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.integratedmodelling.api.data.IAggregator;
import org.integratedmodelling.api.data.IColumn;
import org.integratedmodelling.api.data.ITable;
import org.integratedmodelling.api.data.ITableSet;
import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.knowledge.IExpression;
import org.integratedmodelling.api.modelling.IModel;
import org.integratedmodelling.api.modelling.IValueResolver;
import org.integratedmodelling.api.modelling.scheduling.ITransition;
import org.integratedmodelling.api.monitoring.IMonitor;
import org.integratedmodelling.api.project.IProject;
import org.integratedmodelling.api.services.annotations.Prototype;
import org.integratedmodelling.common.data.TableFactory;
import org.integratedmodelling.common.kim.expr.GroovyExpression;
import org.integratedmodelling.common.model.runtime.AbstractStateContextualizer;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabValidationException;

@Prototype(
        id = "data.tabular",
        args = {
                "file",
                Prototype.TEXT,
                "# sheet",
                Prototype.TEXT,
                "# column",
                Prototype.TEXT,
                "# row-selector",
                Prototype.TEXT,
                "# aggregation",
                Prototype.TEXT },
        returnTypes = { NS.STATE_CONTEXTUALIZER })
public class DatatableContextualizer extends AbstractStateContextualizer implements IValueResolver {

    ITable      table;
    IExpression rowSelector;
    IAggregator operation;
    IColumn     column;

    private Map cachedValues = new HashMap<>();

    public DatatableContextualizer(ITable table, IExpression rowSelector,
            IAggregator operation, String column, IMonitor monitor) throws KlabValidationException {

        super(monitor);
        this.table = table;
        this.column = table.getColumn(column);
        this.rowSelector = rowSelector;
        this.operation = operation;
        if (this.column == null) {
            throw new KlabValidationException("table column " + column + " does not exist");
        }
    }

    /*
     * for the instantiator
     */
    public DatatableContextualizer() {
        super(null);
    }

    @Override
    public void setContext(Map parameters, IModel model, IProject project)
            throws KlabValidationException {

        ITable table = null;
        IExpression rowSelector = null;
        IAggregator operation = null;
        String column = null;

        if (parameters.containsKey("file")) {
            File file = new File((project == null ? "" : (project.getLoadPath() + File.separator))
                    + parameters.get("file"));
            ITableSet tableSet = TableFactory.open(file);

            if (tableSet != null) {
                String sheet = null;
                if (parameters.containsKey("table-name")) {
                    sheet = parameters.get("table-name").toString();
                }
                if (sheet != null) {
                    table = tableSet.getTable(sheet);
                } else {
                    Collection tables = tableSet.getTables();
                    if (tables.size() > 0) {
                        table = tables.iterator().next();
                    }
                }

                if (table == null) {
                    throw new KlabValidationException("data.tabular: cannot find "
                            + (sheet == null ? "default" : sheet) + " table");
                }
            }
        }
        if (parameters.containsKey("column")) {
            column = parameters.get("column").toString();
        }
        if (parameters.containsKey("row-selector")) {
            rowSelector = new GroovyExpression(parameters.get("row-selector").toString());
        }
        if (parameters.containsKey("aggregation")) {
            String op = parameters.get("aggregation").toString();
            operation = TableFactory.getAggregator(op);
            if (operation == null) {
                throw new KlabValidationException("data.tabular: cannot find operation " + op);
            }
        }

        // average is the default aggregation
        if (operation == null) {
            operation = TableFactory.getAggregator("mean");
        }

        this.table = table;
        this.column = table.getColumn(column);
        this.rowSelector = rowSelector;
        this.operation = operation;
        if (this.column == null) {
            throw new KlabValidationException("table column " + column + " does not exist");
        }

    }

    public Map processState(int stateIndex, Map inputs, ITransition transition)
            throws KlabException {

        Map ret = new HashMap<>();
        Object value = null;

        String is = getInputSignature(inputs);
        if (!cachedValues.containsKey(is)) {

            /*
             * scan rows; if there is a selector, filter them through it; keep IDs of
             * valid rows. Use copy of _parameters plus all values of columns at each
             * point.
             */
            if (this.rowSelector == null) {
                // aggregation of all rows. Table is read-only so we only need to do this
                // once.
                if (value == null) {
                    value = this.operation.aggregate(this.column.getValues());
                }
            } else {
                /*
                 * apply aggregator to rows that match the filter.
                 */
                if (value == null || inputs.size() > 0) {
                    value = this.operation
                            .aggregate(this.table
                                    .lookup(this.column.getName(), this.rowSelector, inputs, monitor));
                }
            }
            cachedValues.put(is, value);
        } else {
            value = cachedValues.get(is);
        }
        
        /*
         * set value to resulting aggregation
         */
        for (String s : getOutputKeys()) {
            ret.put(s, value);
        }

        return ret;
    }

    private String getInputSignature(Map inputs) {
        
        List keys = new ArrayList<>(inputs.keySet());
        Collections.sort(keys);
        String ret = "";
        for (String key : keys) {
            Object o = inputs.get(key);
            if (o instanceof String || o instanceof Number || o instanceof Boolean || o == null || o instanceof IConcept) {
                ret += key + "=" + (o == null ? "_n_" : o.toString()); 
            }
        }
        return ret;
    }

    @Override
    public Map initialize(int index, Map inputs) throws KlabException {
        return processState(index, inputs, ITransition.INITIALIZATION);
    }

    @Override
    public Map compute(int index, ITransition transition, Map inputs)
            throws KlabException {
        return processState(index, inputs, transition);
    }

    @Override
    public boolean isProbabilistic() {
        // for now and likely more
        return false;
    }

    @Override
    public String getLabel() {
        return "table lookup";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy