ch.agent.crnickl.mongodb.AccessMethodsForNumber Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of crnickl-mongodb Show documentation
Show all versions of crnickl-mongodb Show documentation
MongoDB implementation of the CrNiCKL database
/*
* Copyright 2012-2013 Hauser Olsson GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package ch.agent.crnickl.mongodb;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import ch.agent.crnickl.T2DBException;
import ch.agent.crnickl.T2DBMsg;
import ch.agent.crnickl.T2DBMsg.E;
import ch.agent.crnickl.api.Series;
import ch.agent.crnickl.api.Surrogate;
import ch.agent.crnickl.api.UpdatableSeries;
import ch.agent.crnickl.impl.ChronicleUpdatePolicy;
import ch.agent.crnickl.impl.Permission;
import ch.agent.crnickl.impl.ValueAccessMethods;
import ch.agent.t2.time.Range;
import ch.agent.t2.time.TimeDomain;
import ch.agent.t2.time.TimeIndex;
import ch.agent.t2.timeseries.Observation;
import ch.agent.t2.timeseries.TimeAddressable;
import ch.agent.t2.timeseries.TimeSeriesFactory;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* An implementation of {@link ValueAccessMethods} for numeric data using {@link java.lang.Double}.
*
* @author Jean-Paul Vetterli
*/
public class AccessMethodsForNumber extends MongoDatabaseMethods implements ValueAccessMethods {
/**
* Construct an access method object.
*/
public AccessMethodsForNumber() {
}
@Override
public Range getRange(Series series) throws T2DBException {
Range range = null;
try {
check(Permission.READ, series);
Surrogate s = series.getSurrogate();
BasicDBObject obj = (BasicDBObject) getObject(s, false);
if (obj != null) {
long first = obj.getLong(MongoDatabase.FLD_SER_FIRST);
long last = obj.getLong(MongoDatabase.FLD_SER_LAST);
range = new Range(series.getTimeDomain(), first, last);
}
} catch (Exception e) {
throw T2DBMsg.exception(e, E.E50122, series.getName(true));
}
if (range == null)
range = new Range(series.getTimeDomain());
return range;
}
@Override
public long getValues(Series series, Range range, TimeAddressable ts) throws T2DBException {
if (range != null && range.isEmpty())
return 0;
long count = 0;
try {
check(Permission.READ, series);
Surrogate s = series.getSurrogate();
DBObject obj = getObject(s, true);
count = extractValues(obj, range, ts);
} catch (Exception e) {
if (range == null)
throw T2DBMsg.exception(e, E.E50121, series.getName(true));
else
throw T2DBMsg.exception(e, E.E50120, series.getName(true), range.toString());
}
return count;
}
private long extractValues(DBObject obj, Range range, TimeAddressable ts) throws Exception {
if (range != null && range.isEmpty())
return 0;
long count = 0;
@SuppressWarnings("unchecked")
Map values = (Map) obj.get(MongoDatabase.FLD_SER_VALUES);
for (String k : values.keySet()) {
long t = Long.valueOf(k);
if (range == null || range.isInRange(t)) {
ts.put(t, values.get(k));
count++;
}
}
return count;
}
private Observation extractLastValue(BasicDBObject obj, TimeDomain domain, TimeIndex t) throws Exception {
long first = obj.getLong(MongoDatabase.FLD_SER_FIRST);
long last = obj.getLong(MongoDatabase.FLD_SER_LAST);
Observation obs = null;
long time = t == null ? last : t.asLong();
if (last >= first && time >= first) {
@SuppressWarnings("unchecked")
Map values = (Map) obj.get(MongoDatabase.FLD_SER_VALUES);
String key = null;
if (time >= last)
key = Long.toString(last);
else {
TreeMap sorted = new TreeMap(values);
key = sorted.headMap(Long.toString(time + 1)).lastKey();
}
obs = new Observation(domain.time(Long.valueOf(key)), values.get(key));
}
return obs;
}
private Observation extractFirstValue(BasicDBObject obj, TimeDomain domain, TimeIndex t) throws Exception {
long first = obj.getLong(MongoDatabase.FLD_SER_FIRST);
long last = obj.getLong(MongoDatabase.FLD_SER_LAST);
Observation obs = null;
long time = t == null ? first : t.asLong();
if (last >= first && time <= last) {
@SuppressWarnings("unchecked")
Map values = (Map) obj.get(MongoDatabase.FLD_SER_VALUES);
String key = null;
if (time <= first)
key = Long.toString(first);
else {
TreeMap sorted = new TreeMap(values);
key = sorted.tailMap(Long.toString(time)).firstKey();
}
obs = new Observation(domain.time(Long.valueOf(key)), values.get(key));
}
return obs;
}
@Override
public Observation getFirst(Series series, TimeIndex time) throws T2DBException {
try {
check(Permission.READ, series);
Surrogate s = series.getSurrogate();
DBObject obj = getObject(s, true);
return extractFirstValue((BasicDBObject) obj, series.getTimeDomain(), time);
} catch (Exception e) {
throw T2DBMsg.exception(e, E.E50123, series.getName(true), time.toString());
}
}
@Override
public Observation getLast(Series series, TimeIndex time) throws T2DBException {
try {
check(Permission.READ, series);
Surrogate s = series.getSurrogate();
DBObject obj = getObject(s, true);
return extractLastValue((BasicDBObject) obj, series.getTimeDomain(), time);
} catch (Exception e) {
throw T2DBMsg.exception(e, E.E50124, series.getName(true), time.toString());
}
}
@Override
public boolean deleteValue(UpdatableSeries series, TimeIndex t, ChronicleUpdatePolicy policy) throws T2DBException {
boolean done = false;
try {
check(Permission.MODIFY, series);
policy.willDelete(series, t);
policy.deleteValue(series, t);
Surrogate s = series.getSurrogate();
DBObject obj = getObject(s, true);
// force sparse, so it's always possible to repair when there are excessive gaps
TimeAddressable values = TimeSeriesFactory.make(series.getTimeDomain(), Double.class, true);
extractValues(obj, null, values);
if (values.getRange().isInRange(t)) {
values.put(t, values.getMissingValue());
done = true;
}
update(series, values);
} catch (Exception e) {
throw T2DBMsg.exception(e, E.E50113, series.getName(true), t.toString());
} finally {
}
return done;
}
@Override
public boolean updateSeries(UpdatableSeries series, Range range, ChronicleUpdatePolicy policy) throws T2DBException {
boolean done = false;
try {
check(Permission.MODIFY, series);
policy.willUpdate(series, range);
done = policy.update(series, range);
Surrogate s = series.getSurrogate();
DBObject obj = getObject(s, true);
// force sparse, so it's always possible to repair when there are excessive gaps
TimeAddressable values = TimeSeriesFactory.make(series.getTimeDomain(), Double.class, true);
extractValues(obj, null, values);
if (values.setRange(range))
done = true;
update(series, values);
} catch (Exception e) {
throw T2DBMsg.exception(e, E.E50109, series.getName(true));
} finally {
}
return done;
}
@Override
public long updateValues(UpdatableSeries series, TimeAddressable values, ChronicleUpdatePolicy policy) throws T2DBException {
long count = 0;
try {
check(Permission.MODIFY, series);
Surrogate s = series.getSurrogate();
DBObject obj = getObject(s, true);
// force sparse, so it's always possible to repair when there are excessive gaps
TimeAddressable current = TimeSeriesFactory.make(series.getTimeDomain(), Double.class, true);
extractValues(obj, null, current);
for(Observation obs : values) {
current.put(obs.getIndex(), obs.getValue());
count++;
}
update(series, current);
} catch (Exception e) {
throw T2DBMsg.exception(e, E.E50114, series.getName(true));
}
return count;
}
private void update(Series series, TimeAddressable values) throws T2DBException {
com.mongodb.DBObject operation = null;
Range range = values.getRange();
Map data = new HashMap();
for (Observation obs : values) {
data.put(Long.toString(obs.getIndex()), obs.getValue());
}
operation = operation(Operator.SET,
MongoDatabase.FLD_SER_FIRST, range.getFirstIndex(),
MongoDatabase.FLD_SER_LAST, range.getLastIndex(),
MongoDatabase.FLD_SER_VALUES, data);
Surrogate s = series.getSurrogate();
getMongoDB(s).getSeries().update(asQuery(s.getId()), operation);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy