
org.integratedmodelling.engine.modelling.TemporalSeries Maven / Gradle / Ivy
/*******************************************************************************
* 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;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.knowledge.IKnowledge;
import org.integratedmodelling.api.knowledge.IProperty;
import org.integratedmodelling.api.metadata.IMetadata;
import org.integratedmodelling.api.modelling.IDirectObservation;
import org.integratedmodelling.api.modelling.IExtent;
import org.integratedmodelling.api.modelling.IObservable;
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.storage.IStorage;
import org.integratedmodelling.api.space.ISpatialExtent;
import org.integratedmodelling.api.time.ITemporalExtent;
import org.integratedmodelling.api.time.ITemporalSeries;
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.engine.time.Time;
import org.integratedmodelling.engine.time.literals.PeriodValue;
import org.integratedmodelling.engine.time.literals.TimeValue;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabRuntimeException;
import org.integratedmodelling.exceptions.KlabValidationException;
import org.joda.time.Interval;
public class TemporalSeries implements ITemporalSeries {
// a wrapper for the typed object, which also stores start/end time for which it's valid
private class WrappedObject {
final ITimePeriod timePeriod;
final T item;
public WrappedObject(final ITimePeriod timePeriod, final T item) {
this.timePeriod = timePeriod;
this.item = item;
}
}
// a sorted collection which can query for "greatest prior"
private final TreeMap collection = new TreeMap();
@Override
public T getFirst() {
try {
return collection.firstEntry().getValue().item;
} catch (Exception e) {
return null;
}
}
@Override
public T getLast() {
try {
return collection.lastEntry().getValue().item;
} catch (Exception e) {
return null;
}
}
@Override
public T getAtTime(ITimeInstant time) {
return getWrappedObjectAtTime(time).item;
}
@Override
public IKnowledge getType() {
return getObservable().getType();
}
@Override
public T getPrior(ITimeInstant time) {
Entry entry = collection.lowerEntry(time);
if (entry == null) {
return null;
}
if (entry.getValue().timePeriod.contains(time)) {
entry = collection.lowerEntry(entry.getKey());
}
if (entry == null) {
return null;
}
return entry.getValue().item;
}
@Override
public T getFollowing(ITimeInstant time) {
Entry earliestNextEntry = collection.ceilingEntry(time);
// NOTE: by exclusive-inclusive semantics, key might equal time, which is OK.
if (earliestNextEntry == null) {
// no intervals exist which start after the query time.
return null;
}
return earliestNextEntry.getValue().item;
}
private WrappedObject getWrappedObjectAtTime(ITimeInstant time) {
Entry latestPriorEntry = collection.lowerEntry(time);
if (latestPriorEntry == null) {
// no intervals exist which start before the query time.
return null;
}
WrappedObject latestPrior = latestPriorEntry.getValue();
if (!latestPrior.timePeriod.contains(time)) {
// the latest-starting interval prior to the query time expires before the query time,
// so there is no matching interval for this query time.
return null;
}
// the interval contains the time, so return the enclosed value.
return latestPrior;
}
@Override
public void put(ITimeInstant start, ITimeInstant end, T item) throws KlabException {
Interval interval = new Interval(start.getMillis(), end.getMillis());
put(interval, item);
}
public void put(Interval interval, T item) throws KlabException {
PeriodValue timePeriod = new PeriodValue(interval);
put(timePeriod, item);
}
@Override
public void put(ITimePeriod timePeriod, T item) {
ITimeInstant endTime = new TimeValue(timePeriod.getEnd().getMillis());
WrappedObject wrapper = new WrappedObject(timePeriod, item);
// do any existing periods overlap with what is being written?
Entry latestPriorEntry = collection.floorEntry(endTime);
if (latestPriorEntry != null && latestPriorEntry.getValue().timePeriod.contains(endTime)) {
// latest prior entry overlaps the end time, so we can't write the interval.
throw new KlabRuntimeException("Cannot write the interval " + wrapper + " to TemporalScale "
+ this + " because it overlaps with interval " + latestPriorEntry + ".");
}
ITimeInstant startTime = new TimeValue(timePeriod.getStart().getMillis());
collection.put(startTime, wrapper);
}
@Override
public void remove(ITimeInstant time) {
WrappedObject wrappedObject = getWrappedObjectAtTime(time);
collection.remove(wrappedObject.timePeriod.getStart());
}
@Override
public ITimePeriod shorten(ITimeInstant spliceTime) throws KlabException {
WrappedObject originalWrappedObject = getWrappedObjectAtTime(spliceTime);
T item = originalWrappedObject.item;
ITimePeriod originalTimePeriod = originalWrappedObject.timePeriod;
// sanity check - new end time must be within original time period
if (!originalTimePeriod.contains(spliceTime)) {
throw new KlabValidationException("shorten() was called using the new end time "
+ spliceTime.toString() + ", which is outside the original time period "
+ originalTimePeriod.toString());
}
// create the new state. We don't have to validate for overlaps because we know we're shrinking the
// time period.
ITimePeriod newTimePeriod = new PeriodValue(originalTimePeriod.getStart().getMillis(), spliceTime
.getMillis());
WrappedObject newWrappedObject = new WrappedObject(newTimePeriod, item);
collection.remove(originalTimePeriod.getStart());
collection.put(originalTimePeriod.getStart(), newWrappedObject);
return newTimePeriod;
}
@Override
public ITimePeriod bisect(ITimeInstant spliceTime, T object) throws KlabException {
ITimeInstant endTime = getWrappedObjectAtTime(spliceTime).timePeriod.getEnd();
shorten(spliceTime);
PeriodValue newTimePeriod = new PeriodValue(spliceTime.getMillis(), endTime.getMillis());
put(newTimePeriod, object);
return newTimePeriod;
}
@Override
public Collection getOverlapping(ITimePeriod timePeriod) {
Collection result = new LinkedList();
// step forward through time finding all overlapping time periods
Entry currentEntry = collection.floorEntry(timePeriod.getStart());
WrappedObject wrappedObject;
while (currentEntry != null) {
// does the next wrappedObject time period overlap the one requested?
wrappedObject = currentEntry.getValue();
if (!wrappedObject.timePeriod.overlaps(timePeriod)) {
break;
}
result.add(wrappedObject.item);
currentEntry = collection.higherEntry(currentEntry.getKey());
}
return result;
}
/* THE ITemporalExtent METHODS */
@Override
public ITemporalExtent getExtent(int stateIndex) {
Entry result = collection.firstEntry();
ITimeInstant currentPosition = result.getKey();
for (int i = 0; i < stateIndex && result != null; i++) {
result = collection.higherEntry(currentPosition);
currentPosition = result.getKey();
}
return result == null ? null : result.getValue().timePeriod;
}
@Override
public ITimePeriod collapse() {
ITimeInstant start = getStart();
ITimeInstant end = getEnd();
if (start == null || end == null) {
return null;
}
return new PeriodValue(start.getMillis(), end.getMillis());
}
@Override
public ITemporalExtent intersection(IExtent other) throws KlabException {
// TODO Auto-generated method stub
return null;
}
@Override
public ITimeInstant getStart() {
return collection.firstKey();
}
@Override
public ITimeInstant getEnd() {
Entry lastEntry = collection.lastEntry();
if (lastEntry == null) {
return null;
}
return lastEntry.getValue().timePeriod.getEnd();
}
@Override
public IConcept getDomainConcept() {
return Time.TIME_DOMAIN;
}
@Override
public IProperty getCoverageProperty() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isCovered(int stateIndex) {
// TODO Auto-generated method stub
return true;
}
@Override
public IExtent merge(IExtent extent, boolean force) throws KlabException {
// TODO Auto-generated method stub
return null;
}
@Override
public Pair, Double> checkCoverage(ITopologicallyComparable> obj)
throws KlabException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isConsistent() {
return true;
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}
@Override
public long getValueCount() {
return collection.size();
}
@Override
public IObserver getObserver() {
return null;
}
@Override
public boolean isSpatiallyDistributed() {
return false;
}
@Override
public boolean isTemporallyDistributed() {
return getValueCount() > 1;
}
@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 double getCoveredExtent() {
// TODO a double that can be used to compare objects
return 0;
}
//
// @Override
// public INamespace getNamespace() {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public IConcept getDirectType() {
// return Time.TIME_DOMAIN;
// }
//
// @Override
// public boolean is(Object other) {
// // TODO Auto-generated method stub
// return false;
// }
@Override
public IMetadata getMetadata() {
return null;
}
@Override
public IObservable getObservable() {
return null;
}
@Override
public long getMultiplicity() {
return getValueCount();
}
@Override
public IExtent union(IExtent other) throws KlabException {
// 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 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 IScale getScale() {
// TODO Auto-generated method stub
return null;
}
@Override
public Object getValue(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public Iterator
© 2015 - 2025 Weber Informatics LLC | Privacy Policy