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

org.integratedmodelling.engine.time.extents.RegularTemporalGrid 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.time.extents;

import java.util.Iterator;

import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.metadata.IMetadata;
import org.integratedmodelling.api.modelling.IExtent;
import org.integratedmodelling.api.modelling.IModelBean;
import org.integratedmodelling.api.modelling.IObservableSemantics;
import org.integratedmodelling.api.modelling.IObserver;
import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.api.modelling.IScale.Index;
import org.integratedmodelling.api.modelling.IScale.Locator;
import org.integratedmodelling.api.modelling.ITopologicallyComparable;
import org.integratedmodelling.api.modelling.scheduling.ITransition;
import org.integratedmodelling.api.modelling.storage.IStorage;
import org.integratedmodelling.api.space.ISpatialExtent;
import org.integratedmodelling.api.time.ITemporalExtent;
import org.integratedmodelling.api.time.ITimeDuration;
import org.integratedmodelling.api.time.ITimeInstant;
import org.integratedmodelling.api.time.ITimePeriod;
import org.integratedmodelling.collections.Pair;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.interfaces.NetworkDeserializable;
import org.integratedmodelling.common.interfaces.NetworkSerializable;
import org.integratedmodelling.common.knowledge.Observation;
import org.integratedmodelling.common.model.runtime.TimeInstant;
import org.integratedmodelling.common.time.TimeLocator;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.engine.modelling.runtime.mediators.TimeIdentityMediator;
import org.integratedmodelling.engine.modelling.runtime.mediators.TimeResampler;
import org.integratedmodelling.engine.time.literals.DurationValue;
import org.integratedmodelling.engine.time.literals.PeriodValue;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabInternalRuntimeException;

/**
 * A regular grid extent represents a fixed number of milliseconds from time x to y. We represent it
 * internally as a line segment, so we can use topological operations on it through JTS.
 *
 * This class only handles continuous grid segments - it's easy, although cumbersome, to represent
 * discontinuous time extents, but the questions becomes one of semantics. It should be bound to its own time
 * concept, as in the standard one there can be no discontinuities.
 * 
 * NOTE that temporal grids always have a minimum multiplicity of 2. This is because the grid represents
 * the transition between the start and the end, implying distinct initial and final states. The time() 
 * function in Thinklab will build a TemporalLocation if not passed a step parameter, which has multiplicity
 * 1. In a grid, number of periods = number of transitions generated = (multiplicity - 1). 
 *
 * @author Ferdinando Villa
 *
 */
public class RegularTemporalGrid extends Observation
        implements ITemporalExtent, NetworkSerializable, NetworkDeserializable {

    Object              value;
    long                stepMs;
    private PeriodValue overallPeriodValue = null;

    /**
     * build a series of consecutive time periods
     *
     * @param start
     * @param end
     * @param stepMs
     */
    public RegularTemporalGrid(ITimeInstant start, ITimeInstant end, long stepMs) {
        // super(1); // 1 = dummy value.length; value is replaced below.

        setup(start, end, stepMs);

    }

    private void setup(ITimeInstant start, ITimeInstant end, long stepMs) {

        this.stepMs = stepMs;
        // generate the sub-extents
        long currentPosition = start.getMillis();
        long endMs = end.getMillis();
        double predictedNumExtents = Math.ceil(((double) (endMs - currentPosition)) / stepMs);
        PeriodValue[] extents = new PeriodValue[(int) predictedNumExtents];

        int i = 0; // should end up the same as (int)predictedNumExtents
        while (currentPosition < endMs) {
            PeriodValue period = new PeriodValue(currentPosition, currentPosition + stepMs);
            extents[i++] = period;
            currentPosition += stepMs;
        }

        value = extents;
        overallPeriodValue = new PeriodValue(start.getMillis(), endMs);

    }

    // @Override
    // protected PeriodValue[] getValue() {
    // return (PeriodValue[]) value;
    // }

    public RegularTemporalGrid() {
        // a completely undescript temporal grid, meant to represent the time notion without
        // any specification.
    }

    @Override
    public int[] getDimensionSizes() {
        return new int[] { (int) getMultiplicity() };
    }

    @Override
    public int[] getDimensionOffsets(int linearOffset, boolean rowFirst) {
        return new int[] { linearOffset };
    }

    @Override
    public boolean isSpatiallyDistributed() {
        return false;
    }

    @Override
    public boolean isTemporallyDistributed() {
        return getValueCount() > 1;
    }

    @Override
    public ITemporalExtent intersection(IExtent other) throws KlabException {
        if (!(other instanceof ITemporalExtent)) {
            return null;
        }
        // TODO
        return null;
    }

    @Override
    public IExtent union(IExtent other) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean contains(IExtent o) throws KlabException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean overlaps(IExtent o) throws KlabException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean intersects(IExtent o) throws KlabException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public ITimePeriod collapse() {
        return overallPeriodValue;
    }

    @Override
    public ITemporalExtent getExtent(int index) {
        return (ITemporalExtent) getValue(index);
    }

    @Override
    public boolean isCovered(int stateIndex) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public IConcept getDomainConcept() {
        return KLAB.c(NS.TIME_DOMAIN);
    }

    @Override
    public IObserver getObserver() {
        return null;
    }

    @Override
    public boolean isTemporal() {
        return true;
    }

    @Override
    public boolean isSpatial() {
        return false;
    }

    @Override
    public ISpatialExtent getSpace() {
        return null;
    }

    @Override
    public ITemporalExtent getTime() {
        return this;
    }

    @Override
    public boolean isConsistent() {
        return true;
    }

//    @Override
//    public IProperty getCoverageProperty() {
//        return KLAB.p(NS.TEMPORAL_EXTENT_PROPERTY);
//    }

    @Override
    public ITemporalExtent merge(IExtent extent, boolean force) throws KlabException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Pair, Double> checkCoverage(ITopologicallyComparable obj) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public ITopologicallyComparable union(ITopologicallyComparable other)
            throws KlabException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public ITopologicallyComparable intersection(ITopologicallyComparable other)
            throws KlabException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public double getCoveredExtent() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public long getMultiplicity() {
        // this is inherited from ITopology, but in this context it means the same thing as 'value count'
        return getValueCount();
    }

    @Override
    public ITimeInstant getStart() {
        return overallPeriodValue.getStart();
    }

    @Override
    public ITimeInstant getEnd() {
        return overallPeriodValue.getEnd();
    }

    @Override
    public IScale getScale() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public ITemporalExtent getExtent() {
        return overallPeriodValue == null ? null : overallPeriodValue.getExtent();
    }

    @Override
    public ITimeDuration getStep() {
        // TODO Auto-generated method stub
        return new DurationValue((getEnd().getMillis() - getStart().getMillis()) / getMultiplicity());
    }

    @Override
    public IStorage getStorage() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getValueCount() {
        return value == null ? 0 : ((PeriodValue[]) value).length + 1;
    }

    @Override
    public Object getValue(int index) {
        if (value == null)
            return null;
        // if (index == 0) {
        // return new TemporalLocation(getStart(), stepMs);
        // }
        return ((PeriodValue[]) value)[index];
    }

    @Override
    public Iterator iterator(Index index) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public IMetadata getMetadata() {
        // TODO Auto-generated method stub
        return null;
    }


    @Override
    public int locate(Locator locator) {

        if (locator == null)
            return 0;

        ITemporalExtent ext = null;
        if (locator instanceof ITransition) {

            long mul = getMultiplicity();
            int trind = ((ITransition) locator).getTimeIndex();

            if (trind < mul) {

                ext = getExtent(trind);
                ITemporalExtent ttime = ((ITransition) locator).getTime();

                // System.out.println("TR " + trind + " [" + ttime.getStart().getMillis() + " -> "
                // + ttime.getEnd().getMillis());

                int ret = -1;
                if (ttime.equals(ext)) {
                    ret = trind;
                }

                return ret;

            }
        } else if (locator instanceof TimeLocator) {
            return ((TimeLocator) locator).isAll() ? GENERIC_LOCATOR : ((TimeLocator) locator).getSlice();
        }
        return INAPPROPRIATE_LOCATOR;
    }

    public static IExtent sanitize(ITemporalExtent e) {

        if (e instanceof RegularTemporalGrid || e instanceof PeriodValue) {
            return e;
        }

        if (e.getStep() == null || e.getStep().getMilliseconds() <= 0) {
            return new PeriodValue(e.getStart() == null ? 0 : e.getStart().getMillis(), e.getEnd() == null ? 0
                    : e.getEnd().getMillis());
        }
        return new RegularTemporalGrid(e.getStart(), e.getEnd(), (e.getStep() == null ? 0 : e.getStep()
                .getMilliseconds()));
    }

    @Override
    public Mediator getMediator(IExtent extent, IObservableSemantics observable, IConcept trait) {

        if (extent instanceof RegularTemporalGrid) {
            RegularTemporalGrid tg = (RegularTemporalGrid) extent;
            if (tg.overallPeriodValue.equals(overallPeriodValue) && tg.stepMs == stepMs) {
                return new TimeIdentityMediator();
            } else {
                return new TimeResampler(this, extent);
            }
        }
        return null;
    }

    @Override
    public boolean isConstant() {
        return getMultiplicity() == 1;
    }

    // @Override
    // public Object adapt() {
    //
    // Map ret = new HashMap();
    // ret.put("multiplicity", getValueCount());
    // ret.put("domain", getDomainConcept().toString());
    // ret.put("start", overallPeriodValue.getStart().getMillis());
    // ret.put("end", overallPeriodValue.getEnd().getMillis());
    // /*
    // * TODO the rest
    // */
    // return ret;
    // }

    @Override
    public void deserialize(IModelBean object) {
        if (!(object instanceof org.integratedmodelling.common.beans.Time)) {
            throw new KlabInternalRuntimeException("cannot adapt a "
                    + object.getClass().getCanonicalName() + " to a temporal extent");
        }
        org.integratedmodelling.common.beans.Time bean = (org.integratedmodelling.common.beans.Time) object;
        setup(new TimeInstant(bean.getStart()), new TimeInstant(bean.getEnd()), bean.getStep());
    }

    @Override
    public  T serialize(Class desiredClass) {

        if (!desiredClass.isAssignableFrom(org.integratedmodelling.common.beans.Time.class)) {
            throw new KlabInternalRuntimeException("cannot adapt a space extent to "
                    + desiredClass.getCanonicalName());
        }

        org.integratedmodelling.common.beans.Time ret = new org.integratedmodelling.common.beans.Time();
        ret.setDomain(getDomainConcept().toString());
        ret.setStart(this.getStart().getMillis());
        ret.setEnd(this.getEnd().getMillis());
        ret.setStep(this.getStep().getMilliseconds());

        return (T) ret;
    }

    @Override
    public boolean isDynamic() {
        return getMultiplicity() > 1;
    }

    @Override
    public void addChangeListener(ChangeListener listener) {
        // TODO Auto-generated method stub
        
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy