Package ch.agent.crnickl.mongodb

Source Code of ch.agent.crnickl.mongodb.AccessMethodsForNumber

/*
*   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<Double> {
 
  /**
   * Construct an access method object.
   */
  public AccessMethodsForNumber() {
  }

  @Override
  public Range getRange(Series<Double> 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<Double> series, Range range, TimeAddressable<Double> 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<Double> ts) throws Exception {
    if (range != null && range.isEmpty())
      return 0;
    long count = 0;
    @SuppressWarnings("unchecked")
    Map<String, Double> values = (Map<String, Double>) 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<Double> 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<Double> obs = null;
    long time = t == null ? last : t.asLong();
    if (last >= first && time >= first) {
      @SuppressWarnings("unchecked")
      Map<String, Double> values = (Map<String, Double>) obj.get(MongoDatabase.FLD_SER_VALUES);
      String key = null;
      if (time  >= last)
        key = Long.toString(last);
      else {
        TreeMap<String, Double> sorted = new TreeMap<String, Double>(values);
        key = sorted.headMap(Long.toString(time + 1)).lastKey();
      }
      obs = new Observation<Double>(domain.time(Long.valueOf(key)), values.get(key));
    }
    return obs;
  }
 
  private Observation<Double> 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<Double> obs = null;
    long time = t == null ? first : t.asLong();
    if (last >= first && time <= last) {
      @SuppressWarnings("unchecked")
      Map<String, Double> values = (Map<String, Double>) obj.get(MongoDatabase.FLD_SER_VALUES);
      String key = null;
      if (time  <= first)
        key = Long.toString(first);
      else {
        TreeMap<String, Double> sorted = new TreeMap<String, Double>(values);
        key = sorted.tailMap(Long.toString(time)).firstKey();
      }
      obs = new Observation<Double>(domain.time(Long.valueOf(key)), values.get(key));
    }
    return obs;
  }
 
  @Override
  public Observation<Double> getFirst(Series<Double> 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<Double> getLast(Series<Double> 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<Double> 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<Double> 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<Double> 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<Double> 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<Double> series, TimeAddressable<Double> 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<Double> current = TimeSeriesFactory.make(series.getTimeDomain(), Double.class, true);
      extractValues(obj, null, current);
      for(Observation<Double> 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 <T>void update(Series<T> series, TimeAddressable<Double> values) throws T2DBException {
    com.mongodb.DBObject operation = null;
    Range range = values.getRange();
    Map<String, Double> data = new HashMap<String, Double>();
    for (Observation<Double> 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);
  }

 
}
TOP

Related Classes of ch.agent.crnickl.mongodb.AccessMethodsForNumber

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.