calliope.core.database.MongoConnection.java Source code

Java tutorial

Introduction

Here is the source code for calliope.core.database.MongoConnection.java

Source

/* This file is part of calliope.
 *
 *  calliope is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  calliope is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with calliope.  If not, see <http://www.gnu.org/licenses/>.
 */
package calliope.core.database;

import calliope.core.exception.*;
import calliope.core.constants.Database;
import calliope.core.constants.JSONKeys;
import java.util.Iterator;
import java.util.ArrayList;
import com.mongodb.MongoClient;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.util.JSON;
import com.mongodb.BasicDBObject;
import org.bson.types.ObjectId;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
import com.mongodb.DBCursor;
import org.json.simple.*;
import com.mongodb.WriteResult;

import java.util.regex.Pattern;

/**
 * Database interface for MongoDB
 * @author desmond
 */
public class MongoConnection extends Connection {
    MongoClient client;
    static int MONGO_PORT = 27017;
    /** connection to database */
    DB db;

    public MongoConnection(String user, String password, String host, String dbName, int dbPort, int wsPort,
            String webRoot) {
        super(user, password, host, dbName, dbPort, wsPort, webRoot);
    }

    /**
     * Connect to the database
     * @throws Exception 
     */
    private void connect() throws Exception {
        if (db == null) {
            MongoClient mongoClient = new MongoClient(host, MONGO_PORT);
            db = mongoClient.getDB(this.databaseName);
            //boolean auth = db.authenticate( user, password.toCharArray() );
            //if ( !auth )
            //    throw new DbException( "MongoDB authentication failed");
        }
    }

    /**
     * Get the Mongo db collection object from its name
     * @param collName the collection name
     * @return a DBCollection object
     * @throws DbException 
     */
    private DBCollection getCollectionFromName(String collName) throws DbException {
        DBCollection coll = db.getCollection(collName);
        if (coll == null)
            coll = db.createCollection(collName, null);
        if (coll != null)
            return coll;
        else
            throw new DbException("Unknown collection " + collName);
    }

    /**
     * Fetch a resource from the server via a given field value
     * @param collName the collection or database name
     * @param value the value of the field
     * @param field the field name
     * @return the response as a string or null if not found
     */
    @Override
    public String getFromDbByField(String collName, String value, String field) throws DbException {
        try {
            connect();
            DBCollection coll = getCollectionFromName(collName);
            DBObject query;
            if (field.equals(JSONKeys._ID)) {
                ObjectId objId = new ObjectId(value);
                query = new BasicDBObject(field, objId);
            } else
                query = new BasicDBObject(field, value);
            DBObject obj = coll.findOne(query);
            if (obj != null)
                return obj.toString();
            else
                return null;
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    DBObject getThreeFieldQuery(String field1, String value1, String field2, String value2, String field3,
            String value3) {
        DBObject query;
        if (field1.equals(JSONKeys._ID)) {
            ObjectId objId = new ObjectId(value1);
            query = new BasicDBObject(field1, objId);
        } else
            query = new BasicDBObject(field1, value1);
        if (field2.equals(JSONKeys._ID)) {
            ObjectId objId = new ObjectId(value2);
            query.put(field2, objId);
        } else
            query.put(field2, value2);
        if (field3.equals(JSONKeys._ID)) {
            ObjectId objId = new ObjectId(value3);
            query.put(field3, objId);
        } else
            query.put(field3, value3);
        return query;
    }

    /**
     * Fetch a resource from the server via a given field value
     * @param collName the collection or database name
     * @param field1 the first field name
     * @param value1 the value of the first field
     * @param field2 the second field name
     * @param value2 the value of the second field
     * @param field3 its field name
     * @param value3 the third value
     * @return the response as a string or null if not found
     */
    private String getFromDbByThreeFields(String collName, String field1, String value1, String field2,
            String value2, String field3, String value3) throws DbException {
        try {
            connect();
            DBCollection coll = getCollectionFromName(collName);
            DBObject query = getThreeFieldQuery(field1, value1, field2, value2, field3, value3);
            DBObject obj = coll.findOne(query);
            if (obj != null)
                return obj.toString();
            else
                return null;
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * Fetch a resource from the server, or try to.
     * @param collName the collection or database name
     * @param docID the path to the resource in the collection
     * @return the response as a string or null if not found
     */
    @Override
    public String getFromDb(String collName, String docID) throws DbException {
        return getFromDbByField(collName, docID, JSONKeys.DOCID);
    }

    /**
     * Fetch a resource from the server, or try to.
     * @param collName the collection or database name
     * @param dbase the database to which this record ultimately belongs
     * @param docID the path to the resource in the collection
     * @param version the version of the scratch resource
     * @return the response as a string or null if not found
     */
    @Override
    public String getFromDb(String collName, String dbase, String docID, String version) throws DbException {
        return getFromDbByThreeFields(collName, JSONKeys.DBASE, dbase, JSONKeys.DOCID, docID, JSONKeys.VERSION1,
                version);
    }

    /**
     * PUT a json file to the database
     * @param collName the name of the collection
     * @param docID the docid of the resource 
     * @param json the json to put there
     * @return the server response
     */
    @Override
    public String putToDb(String collName, String docID, String json) throws DbException {
        try {
            DBObject doc = (DBObject) JSON.parse(json);
            doc.put(JSONKeys.DOCID, docID);
            connect();
            DBCollection coll = getCollectionFromName(collName);
            DBObject query = new BasicDBObject(JSONKeys.DOCID, docID);
            WriteResult result = coll.update(query, doc, true, false);
            //return removeFromDb( path );
            return result.toString();
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * PUT a json file to the database using dbase, docid and version
     * @param collName the name of the collection
     * @param dbase the name of the database 
     * @param docid the document identifier
     * @param version the version of the document
     * @param json the json to put there
     * @return the server response
     */
    @Override
    public String putToDb(String collName, String dbase, String docid, String version, String json)
            throws DbException {
        try {
            DBObject doc = (DBObject) JSON.parse(json);
            doc.put(JSONKeys.DOCID, docid);
            connect();
            DBObject query = getThreeFieldQuery(JSONKeys.DBASE, dbase, JSONKeys.DOCID, docid, JSONKeys.VERSION1,
                    version);
            DBCollection coll = getCollectionFromName(collName);
            WriteResult result = coll.update(query, doc, true, false);
            //return removeFromDb( path );
            return result.toString();
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * PUT a new json file to the database
     * @param collName the name of the collection
     * @param json the json to put there
     * @return the server response
     */
    @Override
    public String addToDb(String collName, String json) throws DbException {
        try {
            DBObject doc = (DBObject) JSON.parse(json);
            connect();
            DBCollection coll = getCollectionFromName(collName);
            if (doc.containsField(JSONKeys._ID)) {
                Object id = doc.get(JSONKeys._ID);
                DBObject query = new BasicDBObject(JSONKeys._ID, id);
                if (query != null) {
                    WriteResult result = coll.update(query, doc, true, false);
                    return result.toString();
                } else
                    throw new Exception("Failed to update object " + id);
            } else {
                WriteResult result = coll.insert(doc, WriteConcern.ACKNOWLEDGED);
                // return the new document's id
                ObjectId id = (ObjectId) doc.get("_id");
                JSONObject jDoc = (JSONObject) JSONValue.parse(result.toString());
                jDoc.put("_id", id.toString());
                return jDoc.toJSONString();
            }
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * Remove a document from the database
     * @param collName name of the collection
     * @param docID the docid of the resource 
     * @param json the json to put there
     * @return the server response
     */
    @Override
    public String removeFromDb(String collName, String docID) throws DbException {
        return removeFromDbByField(collName, JSONKeys.DOCID, docID);
    }

    private String removeFromDbByThreeFields(String collName, String field1, String value1, String field2,
            String value2, String field3, String value3) throws DbException {
        try {
            connect();
            DBCollection coll = getCollectionFromName(collName);
            DBObject query = getThreeFieldQuery(field1, value1, field2, value2, field3, value3);
            WriteResult result = coll.remove(query);
            if (result != null)
                return result.toString();
            else
                return null;
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * Remove a document from the database
     * @param collName name of the collection
     * @param docID the docid of the resource 
     * @param json the json to put there
     * @return the server response
     */
    @Override
    public String removeFromDb(String collName, String dbase, String docID, String version) throws DbException {
        return removeFromDbByThreeFields(collName, JSONKeys.DBASE, dbase, JSONKeys.DOCID, docID, JSONKeys.VERSION1,
                version);
    }

    /**
     * Remove a document from the database by a unique field value
     * @param collName name of the collection
     * @param field the name of the field 
     * @param value the value of the field
     * @return the server response
     */
    @Override
    public String removeFromDbByField(String collName, String field, String value) throws DbException {
        try {
            connect();
            DBCollection coll = getCollectionFromName(collName);
            //new BasicDBObject("_id", new ObjectId(idString));
            Object obj = value;
            if (field.equals(JSONKeys._ID))
                obj = new ObjectId(value);
            DBObject query = new BasicDBObject(field, obj);
            WriteResult result = coll.remove(query);
            return result.toString();
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * Remove an entire set of documents that match a regular expression.
     * @param collName the collection to remove from
     * @param key the key field to match
     * @param expr the regular expression for key's values
     * @return the result
     * @throws DbException 
     */
    public String removeFromDbByExpr(String collName, String key, String expr) throws DbException {
        try {
            DBCollection coll = getCollectionFromName(collName);
            if (coll != null) {
                BasicDBObject q = new BasicDBObject();
                q.put(key, Pattern.compile(expr));
                WriteResult result = coll.remove(q);
                return result.toString();
            } else
                throw new Exception("Collection " + collName + " not found");
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * Get a list of docIDs or file names corresponding to the regex expr
     * @param collName the collection to query
     * @param expr the regular expression to match against docid
     * @param key the key to retrieve for each matching document
     * @return an array of matching docids, which may be empty
     */
    @Override
    public String[] listDocuments(String collName, String expr, String key) throws DbException {
        try {
            try {
                connect();
            } catch (Exception e) {
                throw new DbException(e);
            }
            DBCollection coll = getCollectionFromName(collName);
            if (coll != null) {
                BasicDBObject q = new BasicDBObject();
                q.put(JSONKeys.DOCID, Pattern.compile(expr));
                DBCursor curs = coll.find(q);
                ArrayList<String> docids = new ArrayList<String>();
                Iterator<DBObject> iter = curs.iterator();
                int i = 0;
                while (iter.hasNext()) {
                    Object kId = iter.next().get(key);
                    if (kId != null)
                        docids.add(kId.toString());
                }
                String[] array = new String[docids.size()];
                docids.toArray(array);
                return array;
            } else
                throw new DbException("collection " + collName + " not found");
        } catch (Exception e) {
            throw new DbException(e);
        }
    }

    /**
     * List all the documents in a Mongo collection
     * @param collName the name of the collection
     * @param key the document key to retrieve by
     * @return a String array of document keys
     * @throws DbException 
     */
    @Override
    public String[] listCollectionByKey(String collName, String key) throws DbException {
        try {
            connect();
        } catch (Exception e) {
            throw new DbException(e);
        }
        DBCollection coll = getCollectionFromName(collName);
        BasicDBObject keys = new BasicDBObject();
        keys.put(key, 1);
        DBCursor cursor = coll.find(new BasicDBObject(), keys);
        if (cursor.length() > 0) {
            String[] docs = new String[cursor.length()];
            Iterator<DBObject> iter = cursor.iterator();
            int i = 0;
            while (iter.hasNext()) {
                DBObject dbObj = iter.next();
                Object obj = dbObj.get(key);
                if (key.equals(JSONKeys._ID)) {
                    ObjectId id = (ObjectId) dbObj.get(JSONKeys._ID);
                    obj = id.toStringMongod();
                    docs[i++] = (String) obj;
                } else
                    docs[i++] = obj.toString();
            }
            return docs;
        } else
            return new String[0];
    }

    /**
     * List all the documents in a Mongo collection
     * @param collName the name of the collection
     * @return a String array of document keys
     * @throws DbException 
     */
    @Override
    public String[] listCollection(String collName) throws DbException {
        try {
            connect();
        } catch (Exception e) {
            throw new DbException(e);
        }
        DBCollection coll = getCollectionFromName(collName);
        BasicDBObject keys = new BasicDBObject();
        keys.put(JSONKeys.DOCID, 1);
        DBCursor cursor = coll.find(new BasicDBObject(), keys);
        if (cursor.length() > 0) {
            String[] docs = new String[cursor.length()];
            Iterator<DBObject> iter = cursor.iterator();
            int i = 0;
            while (iter.hasNext())
                docs[i++] = (String) iter.next().get(JSONKeys.DOCID);
            return docs;
        } else
            return new String[0];
    }

    /**
     * Get the metadata as a string
     * @param docid its filename or docid
     * @return the metadata of the document as a string
     */
    public String getMetadata(String docid) {
        try {
            connect();
            DBCollection collection = getCollectionFromName(Database.METADATA);
            DBObject query;
            query = new BasicDBObject(JSONKeys.DOCID, docid);
            DBObject obj = collection.findOne(query);
            if (obj != null) {
                obj.removeField(JSONKeys._ID);
                return obj.toString();
            } else
                return null;
        } catch (Exception e) {
            e.printStackTrace(System.out);
            return null;
        }
    }

    /**
     * Update one field of a database document
     * @param coll the collection the document is in
     * @param findField the field to look for
     * @param findValue the field value to search for
     * @param setField the field to set
     * @param setValue the new field value
     * @throws DbException 
     */
    public void updateByField(String coll, String findField, Object findValue, String setField, Object setValue)
            throws DbException {
        try {
            connect();
            DBCollection collection = getCollectionFromName(coll);
            if (findField.equals(JSONKeys._ID))
                findValue = new ObjectId((String) findValue);
            BasicDBObject update = new BasicDBObject("$set", new BasicDBObject(setField, setValue));
            BasicDBObject query = new BasicDBObject();
            query.put(findField, findValue);
            WriteResult res = collection.update(query, update);
        } catch (Exception e) {
            throw new DbException(e);
        }
    }
}