Package ch.agent.crnickl.mongodb

Source Code of ch.agent.crnickl.mongodb.MongoDB$Singleton

/*
*   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 ch.agent.crnickl.T2DBException;
import ch.agent.crnickl.T2DBMsg;
import ch.agent.crnickl.T2DBMsg.E;
import ch.agent.crnickl.api.Database;
import ch.agent.crnickl.api.DatabaseConfiguration;
import ch.agent.crnickl.api.Surrogate;
import ch.agent.crnickl.api.UpdatableProperty;
import ch.agent.crnickl.api.UpdatableValueType;
import ch.agent.crnickl.api.ValueType;
import ch.agent.crnickl.mongodb.T2DBMMsg.J;
import ch.agent.t2.time.DateTime;
import ch.agent.t2.time.Day;
import ch.agent.t2.time.Month;
import ch.agent.t2.time.TimeDomain;
import ch.agent.t2.time.Workday;
import ch.agent.t2.time.Year;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.WriteConcern;

/**
* MongoDB is a singleton encapsulating the MongoDB connection and the
* base collections used by CrNiCKL.
*
* @author Jean-Paul Vetterli
*/
public class MongoDB {

  private static class Singleton {
    private static MongoDB mongo_connection;
    static {
      mongo_connection = new MongoDB();
    };
  }

  private enum WriteConcernKeyword {
    NONE, NORMAL, SAFE, MAJORITY, FSYNC_SAFE, JOURNAL_SAFE, REPLICAS_SAFE
  }
 
  private DatabaseConfiguration configuration;
  private Mongo connection = null;
  private DBCollection properties;
  private DBCollection valueTypes;
  private DBCollection schemas;
  private DBCollection chronicles;
  private DBCollection series;
  private DBCollection attributes;
  private String user;
 
  public static final String MONGODB_HOST = "mongodb.host";
  public static final String MONGODB_PORT = "mongodb.port";
  public static final String MONGODB_DB = "mongodb.db";
  public static final String MONGODB_WRITE_CONCERN = "mongodb.writeConcern";
  public static final String MONGODB_USER = "mongodb.user";
  public static final String MONGODB_PASSWORD = "mongodb.password";

  private MongoDB() {
  }

  /**
   * Construct a MongoDB session. This constructor can be invoked only once.
   *
   * @param configuration a database configuration
   */
  public MongoDB(Database database, DatabaseConfiguration configuration) throws T2DBException {
    if (Singleton.mongo_connection.configuration != null)
      throw new IllegalStateException("already initialized");
    Singleton.mongo_connection.configuration = configuration;
    Singleton.mongo_connection.open(database);
  }
 
  /**
   * Return the MongoDB connection.
   *
   * @return the MongoDB connection
   */
  public static MongoDB getInstance() {
    if (Singleton.mongo_connection.configuration == null)
      throw new IllegalStateException("not initialized");
    return Singleton.mongo_connection;
  }
 
  private void open(Database database) throws T2DBException {
    try {
      String host = configuration.getParameter(MONGODB_HOST, false);
      String port = configuration.getParameter(MONGODB_PORT, false);
     
      if (host != null) {
        if (port != null) {
          connection = new Mongo(host, Integer.parseInt(port));
        } else {
          connection = new Mongo(host);
        }
      } else {
        connection = new Mongo();
      }
     
      initialize(connection, database);
     
      // TODO: implement secure mode
      user = configuration.getParameter(MONGODB_USER, true);
      configuration.getParameter(MONGODB_PASSWORD, true);
      configuration.setParameter(MONGODB_USER, "zzzzz");
      configuration.setParameter(MONGODB_PASSWORD, "zzzzz");
    } catch (Exception e) {
      throw T2DBMMsg.exception(e, J.J80050, toString());
    }
  }
 
  private WriteConcern getWriteConcernFromKeyword(String keyword) throws T2DBException  {
    WriteConcern wc = null;
    if (keyword == null)
      keyword = "SAFE";
    WriteConcernKeyword k = null;
    try {
      k = WriteConcernKeyword.valueOf(keyword);
    } catch (IllegalArgumentException e) {
      throw T2DBMMsg.exception(e, J.J81020, keyword);
    }
    switch (k) {
    case NONE:
      wc = WriteConcern.NONE;
      break;
    case NORMAL:
      wc =  WriteConcern.NORMAL;
      break;
    case SAFE:
      wc =  WriteConcern.SAFE;
      break;
    case MAJORITY:
      wc =  WriteConcern.MAJORITY;
      break;
    case FSYNC_SAFE:
      wc =  WriteConcern.FSYNC_SAFE;
      break;
    case JOURNAL_SAFE:
      wc =  WriteConcern.JOURNAL_SAFE;
      break;
    case REPLICAS_SAFE:
      wc =  WriteConcern.REPLICAS_SAFE;
      break;
    default:
      throw new RuntimeException("bug: " + k.name());
    }
    if (wc != WriteConcern.SAFE)
      throw T2DBMMsg.exception(J.J81021, keyword);
    return wc;
  }
 
  private void initialize(Mongo mongo, Database database) throws T2DBException {
    DB db = mongo.getDB(configuration.getParameter(MONGODB_DB, true));
    db.setWriteConcern(getWriteConcernFromKeyword(
        configuration.getParameter(MONGODB_WRITE_CONCERN, false)));
    if (!db.collectionExists(MongoDatabase.COLL_VT)) {
      valueTypes = createCollection(db, MongoDatabase.COLL_VT, MongoDatabase.FLD_VT_NAME);
      properties = createCollection(db, MongoDatabase.COLL_PROP, MongoDatabase.FLD_PROP_NAME);
      schemas = createCollection(db, MongoDatabase.COLL_SCHEMA, MongoDatabase.FLD_SCHEMA_NAME);
      chronicles = createCollection(db, MongoDatabase.COLL_CHRON,
          MongoDatabase.FLD_CHRON_PARENT, MongoDatabase.FLD_CHRON_NAME);
      series = createCollection(db, MongoDatabase.COLL_SER,
          MongoDatabase.FLD_SER_CHRON, MongoDatabase.FLD_SER_NUM);
      /* can't index on variable keys ... this is yet another NO GO for MONGO)
      createIndex(series, MongoDatabase.FLD_SER_CHRON, MongoDatabase.FLD_SER_NUM,
          MongoDatabase.FLD_SER_VALUES ... errr); */
      attributes = createCollection(db, MongoDatabase.COLL_ATTR,
          MongoDatabase.FLD_ATTR_CHRON, MongoDatabase.FLD_ATTR_PROP);
      createIndex(attributes, MongoDatabase.FLD_ATTR_PROP, MongoDatabase.FLD_ATTR_VALUE);
      createBuiltInValueTypes(database);
    } else {
      valueTypes = db.getCollection(MongoDatabase.COLL_VT);
      properties = db.getCollection(MongoDatabase.COLL_PROP);
      schemas = db.getCollection(MongoDatabase.COLL_SCHEMA);
      chronicles = db.getCollection(MongoDatabase.COLL_CHRON);
      series = db.getCollection(MongoDatabase.COLL_SER);
      attributes = db.getCollection(MongoDatabase.COLL_ATTR);
    }
  }
  private void createBuiltInValueTypes(Database db) throws T2DBException {
    UpdatableValueType<String> nameVT = db.createValueType("name", false, "NAME");
    nameVT.applyUpdates();
    UpdatableValueType<ValueType<?>> typeVT = db.createValueType("type", true, "TYPE");
    typeVT.applyUpdates();
    UpdatableValueType<TimeDomain> tdVT = db.createValueType("timedomain", true, "TIMEDOMAIN");
    tdVT.addValue(Day.DOMAIN, "daily");
    tdVT.addValue(DateTime.DOMAIN, "date and time with second precision");
    tdVT.addValue(Month.DOMAIN, "monthly");
    tdVT.addValue(Workday.DOMAIN, "working days Monday-Friday");
    tdVT.addValue(Year.DOMAIN, "yearly");
    tdVT.applyUpdates();
    UpdatableValueType<Boolean> binaryVT = db.createValueType("binary", false, "BOOLEAN");
    binaryVT.applyUpdates();
   
    UpdatableProperty<String> symbolProp = db.createProperty("Symbol", nameVT, false);
    symbolProp.applyUpdates();
    UpdatableProperty<ValueType<?>> typeProp = db.createProperty("Type", typeVT, false);
    typeProp.applyUpdates();
    UpdatableProperty<TimeDomain> calendarProp = db.createProperty("Calendar", tdVT, false);
    calendarProp.applyUpdates();
    UpdatableProperty<Boolean> sparseProp = db.createProperty("Sparsity", binaryVT, false);
    sparseProp.applyUpdates();
  }
 
  private DBCollection createCollection(DB db, String name, String... keys) throws T2DBException {
    DBCollection coll = db.getCollection(name);
    if (keys.length > 0) {
      DBObject index = new BasicDBObject();
      DBObject options = new BasicDBObject();
      for (String key : keys) {
        index.put(key, 1);
      }
      options.put("unique", 1);
      coll.ensureIndex(index, options);
    }
    return coll;
  }
 
  private void createIndex(DBCollection coll, String... keys) throws T2DBException {
    if (keys.length > 0) {
      DBObject index = new BasicDBObject();
      for (String key : keys)
        index.put(key, 1);
      coll.ensureIndex(index);
    }
  }

  /**
   * Close the MongoDB connection if it is open.
   */
  public void close(boolean ignoreException) throws T2DBException {
    try {
      if (connection != null)
        connection.close();
      connection = null;
    } catch (Exception e) {
      if (!ignoreException)
        throw T2DBMsg.exception(E.E00110, toString());
    }
  }

  /**
   * Operation not supported by MongoDB.
   * Always throws an exception.
   *
   * @throws T2DBException
   */
  public void commit() throws T2DBException {
    throw T2DBMMsg.exception(J.J80100);
  }
 
  /**
   * Operation not supported by MongoDB.
   * Always throws an exception.
   *
   * @throws T2DBException
   */
  public void rollback() throws T2DBException {
    throw T2DBMMsg.exception(J.J80100);
  }
 
  public String getUser() {
    return user;
  }

  public DBCollection getValueTypes() {
    return valueTypes;
  }
 
  public DBCollection getProperties() {
    return properties;
  }
 
  public DBCollection getSchemas() {
    return schemas;
  }
 
  public DBCollection getChronicles() {
    return chronicles;
  }
 
  public DBCollection getSeries() {
    return series;
  }
 
  public DBCollection getAttributes() {
    return attributes;
  }
 
  public DBCollection getCollection(Surrogate s) throws T2DBException {
    switch (s.getDBObjectType()) {
    case CHRONICLE:
      return chronicles;
    case SERIES:
      return series;
    case SCHEMA:
      return schemas;
    case PROPERTY:
      return properties;
    case VALUE_TYPE:
      return valueTypes;
    default:
      throw new RuntimeException("bug " + s.getDBObjectType());
    }
  }
 
  /**
   * Return a string displaying the session with the connection and the user id.
   *
   * @return a string displaying the session
   */
  @Override
  public String toString() {
    return String.format("%s@%s", user, connection.toString());
  }
 
}
TOP

Related Classes of ch.agent.crnickl.mongodb.MongoDB$Singleton

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.