
org.integratedmodelling.engine.time.functions.TIME 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.time.functions;
import java.util.Map;
import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.knowledge.IExpression;
import org.integratedmodelling.api.monitoring.IMonitor;
import org.integratedmodelling.api.services.annotations.Prototype;
import org.integratedmodelling.api.time.ITemporalExtent;
import org.integratedmodelling.common.kim.expr.CodeExpression;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.engine.time.extents.InfiniteTemporalGrid;
import org.integratedmodelling.engine.time.extents.InfiniteTemporalGridBoundedStart;
import org.integratedmodelling.engine.time.extents.RegularTemporalGrid;
import org.integratedmodelling.engine.time.literals.DurationValue;
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.DateTime;
@Prototype(
id = "time",
args = {
"# start",
// int allowed to mean a year
Prototype.TEXT + "," + Prototype.INT,
"# end",
// int allowed to mean a year
Prototype.TEXT + "," + Prototype.INT,
"# step",
Prototype.TEXT,
"# duration",
Prototype.TEXT,
"# year",
Prototype.INT },
returnTypes = { NS.TIME_DOMAIN })
public class TIME extends CodeExpression implements IExpression {
/*
* example: observe ... over time( start=2013-01-01, end=2014-01-01, resolution="1 d"
* );
*/
@Override
public ITemporalExtent eval(Map parameters, IMonitor monitor, IConcept... context)
throws KlabException {
ITemporalExtent result = null;
TimeValue start = null;
TimeValue end = null;
/*
* support simple year specification without start/end
*/
if (parameters.containsKey("year")) {
int year = (int) Double.parseDouble(parameters.get("year").toString());
start = new TimeValue(new DateTime(year + "-01-01"));
end = new TimeValue(new DateTime((year + 1) + "-01-01"));
} else {
start = getInstant("start", parameters);
end = getInstant("end", parameters);
}
DurationValue duration = getDuration("duration", parameters);
DurationValue resolution = getDuration("step", parameters);
if (end == null && duration == null && resolution == null) {
// just a placeholder for the notion of time. Return an undescript time
// extent.
return new RegularTemporalGrid();
}
if (end == null && duration == null && resolution != null) {
// unbounded time period (simulation will have to set the limits)
if (start == null) {
// unbounded start & end
result = new InfiniteTemporalGrid(resolution.getMilliseconds());
} else {
// unbounded end
result = new InfiniteTemporalGridBoundedStart(start.getMillis(), resolution
.getMilliseconds());
}
} else {
// guaranteed either end != null or duration != null
if (start == null && (end == null || duration == null)) {
// not anchored in time. Default to "starting right now"
// TODO this doesn't make sense - most raw data will be in the past,
// meaning this assumption
// forces coverage == 0.
start = new TimeValue();
}
// guaranteed at most one of start, end, duration are null
if (start == null && duration != null) {
start = new TimeValue(end.getMillis() - duration.getMilliseconds());
} else if (end == null && duration != null) {
end = new TimeValue(start.getMillis() + duration.getMilliseconds());
} else if (duration == null && start != null && end != null) {
duration = new DurationValue(end.getMillis() - start.getMillis());
}
// guaranteed start, end, duration are all non-null
if (duration.getMilliseconds() != end.getMillis() - start.getMillis()) {
throw new KlabValidationException("'start', 'end', and 'duration' were all given for time(), and their values were not compatible.");
}
if (start.compareTo(end) > 0) {
throw new KlabValidationException("'start' must be before 'end' (got a negative duration) for time().");
}
if (resolution == null || resolution.getMilliseconds() >= duration.getMilliseconds()) {
// only 1 period to generate, so create a PeriodValue
result = new PeriodValue(start.getMillis(), end.getMillis());
} else {
// multiple periods to generate
result = new RegularTemporalGrid(start, end, resolution.getMilliseconds());
}
}
return result;
}
private DurationValue getDuration(String key, Map parameters) {
DurationValue result = null;
if (parameters.get(key) != null) {
Object param = parameters.get(key);
if (param instanceof Long) {
result = new DurationValue((Long) param);
} else if (param instanceof Double) {
result = new DurationValue(((Double) param).longValue());
} else {
try {
result = new DurationValue(param.toString());
} catch (KlabValidationException e) {
throw new KlabRuntimeException(e);
}
}
}
// String parameter = getParameterOrNull(key, parameters);
// if (parameter != null) {
// try {
// result = new DurationValue(parameter);
// } catch (KlabValidationException e) {
// // bad formatting. leave result null.
// /*
// * FIXME actually this should throw an exception (but in the client, which
// * is not using actual function implementations at the moment).
// */
// e.printStackTrace();
// }
// }
return result;
}
private TimeValue getInstant(String key, Map parameters)
throws KlabValidationException {
TimeValue result = null;
if (parameters.get(key) != null) {
Object param = parameters.get(key);
if (param instanceof Long) {
result = new TimeValue((Long) param);
} else if (param instanceof Double) {
result = new TimeValue(((Double) param).intValue());
} else {
result = new TimeValue(param.toString());
}
}
return result;
}
// private String getParameterOrNull(String key, Map parameters) {
// Object ret = parameters.containsKey(key) ? parameters.get(key) : null;
// if (ret instanceof Double) {
// // we don't need doubles anywhere, but if we have numbers (e.g. for years), we
// // want them in int
// // format.
// ret = ((Double) ret).intValue();
// }
// return ret == null ? null : ret.toString();
// }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy