ch.agent.crnickl.mongodb.MongoDB 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 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 nameVT = db.createValueType("name", false, "NAME");
nameVT.applyUpdates();
UpdatableValueType> typeVT = db.createValueType("type", true, "TYPE");
typeVT.applyUpdates();
UpdatableValueType 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 binaryVT = db.createValueType("binary", false, "BOOLEAN");
binaryVT.applyUpdates();
UpdatableProperty symbolProp = db.createProperty("Symbol", nameVT, false);
symbolProp.applyUpdates();
UpdatableProperty> typeProp = db.createProperty("Type", typeVT, false);
typeProp.applyUpdates();
UpdatableProperty calendarProp = db.createProperty("Calendar", tdVT, false);
calendarProp.applyUpdates();
UpdatableProperty 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());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy