ch.agent.crnickl.mongodb.MongoDatabaseMethods Maven / Gradle / Ivy
Show all versions of crnickl-mongodb Show documentation
/*
* 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.regex.Matcher;
import java.util.regex.Pattern;
import org.bson.types.ObjectId;
import ch.agent.crnickl.T2DBException;
import ch.agent.crnickl.api.DBObject;
import ch.agent.crnickl.api.DBObjectId;
import ch.agent.crnickl.api.DBObjectType;
import ch.agent.crnickl.api.Database;
import ch.agent.crnickl.api.Surrogate;
import ch.agent.crnickl.impl.DatabaseMethodsImpl;
import ch.agent.crnickl.mongodb.T2DBMMsg.J;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
/**
* A MongoDatabaseMethods object provides implementation support. It is
* meant as base class for actual access methods.
*
* @author Jean-Paul Vetterli
*/
/**
* @author jp
*
*/
public class MongoDatabaseMethods extends DatabaseMethodsImpl {
public enum Operator {
AND("$and"),
OR("$or"),
IN("$in"),
INC("$inc"),
SET("$set"),
PUSH("$push");
private String op;
private Operator(String op) {
this.op = op;
}
public String op() {
return op;
}
}
private static Matcher regex;
public MongoDB getMongoDB(Database db) {
return ((MongoDatabase) db).getMongoDB();
}
public MongoDB getMongoDB(DBObject dbObj) {
return ((MongoDatabase) dbObj.getSurrogate().getDatabase()).getMongoDB();
}
public MongoDB getMongoDB(Surrogate surr) {
return ((MongoDatabase) surr.getDatabase()).getMongoDB();
}
/**
* Return the MongoDB database object corresponding to a surrogate.
* When mustExist
is false the method returns null if the object cannot be found,
* else an exception is thrown.
*
* @param s a surrogate
* @param mustExist if true throw an exception when the object cannot be found
* @return a DBObject object or null
* @throws T2DBException
*/
public com.mongodb.DBObject getObject(Surrogate s, boolean mustExist) throws T2DBException {
DBCollection coll = getMongoDB(s).getCollection(s);
Throwable cause = null;
com.mongodb.DBObject obj = null;
try {
obj = coll.findOne(asQuery(s.getId()));
} catch (Exception e) {
cause = e;
}
if (cause != null || (obj == null && mustExist))
throw T2DBMMsg.exception(cause, J.J80020, s.toString());
return obj;
}
/**
* @param bdo a {@link BasicDBObject}
* @return the argument's {@link ObjectId}
*/
public ObjectId getObjectId(BasicDBObject bdo) {
return bdo.getObjectId(MongoDatabase.FLD_ID);
}
/**
* Return the internal ID of a database object or 0 if the object is null or
* is in construction.
* The internal ID is not exposed to clients.
*
* This method is for use inside the MongoDB implementation
* and its argument must have a {@link DBObjectId} implemented
* by {@link MongoDBObjectId}.
*
* @param dBObject a database object or null
* @return an id or null
*/
public ObjectId getIdOrZero(DBObject dBObject) {
try {
if (dBObject != null && !dBObject.inConstruction())
return ((MongoDBObjectId) dBObject.getId()).value();
else
return null;
} catch(ClassCastException e) {
throw new RuntimeException("bug: " + dBObject.toString(), e);
}
}
/**
* Return the internal ID of a database object.
* The internal ID is not exposed to clients.
*
* This method is for use inside the MongoDB implementation
* and its argument must have a {@link DBObjectId} implemented
* by {@link MongoDBObjectId}.
*
* @param dBObject a non-null database object
* @return a non-null id
*/
protected ObjectId getId(DBObject dBObject) {
if (dBObject == null)
throw new IllegalArgumentException();
ObjectId id = getIdOrZero(dBObject);
if (id == null)
throw new RuntimeException("bug (database integrity violation)");
return id;
}
/**
* Extract the internal ID of a database object from its surrogate.
* The internal ID is not exposed to clients.
*
* This method is for use inside the MongoDB implementation
* and its argument must have a {@link DBObjectId} implemented
* by {@link MongoDBObjectId}.
*
* @param surrogate the surrogate of a database object
* @return a non-null id
*/
public ObjectId getId(Surrogate surrogate) {
return getId(surrogate.getObject());
}
/**
* Create a surrogate for a database object.
*
* @param db the database of the object
* @param dot the type of the object
* @param id the internal ID of the database object
* @return a surrogate
*/
public Surrogate makeSurrogate(Database db, DBObjectType dot, ObjectId id) {
return super.makeSurrogate(db, dot, new MongoDBObjectId(id));
}
protected com.mongodb.DBObject asQuery(DBObjectId id) throws T2DBException {
com.mongodb.DBObject bo = new BasicDBObject(1);
try {
bo.put(MongoDatabase.FLD_ID, ((MongoDBObjectId)id).value());
} catch (ClassCastException e) {
throw T2DBMMsg.exception(e, J.J81012, id.toString());
}
return bo;
}
/**
* Remove enclosing slashes from the input pattern. If there are leading and
* trailing slashes, the method returns the enclosed string, else it returns
* null.
*
* @param pattern
* @return the pattern without the leading and trailing slashes or null
*/
protected String extractRegexp(String pattern) {
if (regex == null)
regex = Pattern.compile("^/(.*)/$").matcher("");
regex.reset(pattern);
if (regex.matches())
return regex.group(1);
else
return null;
}
/**
* Add an update operation to a DBObject.
* The operation is defined by an operator and a list of arguments.
* See {@link #mongoObject(Object...)} for restrictions on the list of arguments.
*
* @param operation the operation object
* @param op the operator
* @param arg the list of arguments
* @throws IllegalArgumentException
*/
protected void addOperation(com.mongodb.DBObject operation, Operator op, Object ... arg) {
operation.put(op.op(), mongoObject(arg));
}
/**
* Return a com.mongodb.DbObject representing an operation object for an
* operator and list of arguments. See {@link #mongoObject(Object...)} for
* restrictions on the list of arguments.
*
* @param op
* the operator
* @param arg
* the list of arguments
* @return an operation
* @throws IllegalArgumentException
*/
protected com.mongodb.DBObject operation(Operator op, Object ... arg) {
com.mongodb.DBObject operation = new BasicDBObject();
addOperation(operation, op, arg);
return operation;
}
/**
* Return an array of key-value pairs as a DBObject. The array must be
* non-empty and its length must be even. Non-even elements (the keys) must
* be non-null Strings. Even elements must be BSON compatible (this is not
* enforced by this method but violations are detected later).
*
* @param arg
* an non-empty array of arguments of even length
* @return a DBObject
* @throws IllegalArgumentException
*/
protected com.mongodb.DBObject mongoObject(Object ... arg) {
if (arg.length == 0 || arg.length % 2 != 0)
throw new IllegalArgumentException(new T2DBMMsg(J.J81014, arg.length).toString());
com.mongodb.DBObject operand = new BasicDBObject(arg.length / 2);
for (int i = 0; i < arg.length; i++) {
if (arg[i] == null)
throw new IllegalArgumentException(new T2DBMMsg(J.J81016, i).toString());
try {
operand.put((String) arg[i], arg[++i]);
} catch (ClassCastException e) {
throw new IllegalArgumentException(new T2DBMMsg(J.J81016, i).toString(), e);
}
}
return operand;
}
/**
* Return a composite mongodb identifier.
* @param names series of zero or more names
* @return a composite name
*/
protected String compositeName(String... names) {
StringBuffer b = new StringBuffer();
for (int i = 0; i < names.length; i++) {
if (i > 0)
b.append('.');
b.append(names[i]);
}
return b.toString();
}
}