/*
* The MIT License (MIT)
*
* Copyright (c) 2014 México Abierto
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* For more information visit https://github.com/mxabierto/avisos.
*/
package mx.org.cedn.avisosconagua.mongo;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.gridfs.GridFS;
import java.net.UnknownHostException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Date;
import java.util.Deque;
import java.util.HashMap;
import java.util.Set;
import mx.org.cedn.avisosconagua.util.Utils;
/**
* Class to manage communication with MongoDB to persist and retrieve advice information.
* @author serch
*/
public class MongoInterface {
private final MongoClient mongoClient;
private final MongoClientURI mongoClientURI;
private final DB mongoDB;
private static MongoInterface instance = null;
private static final String CAPTURA_COL = "AdviceDataForms";
public static final String INTERNAL_FORM_ID = "internalId";
private static final String IMAGES_COL = "AdviceDataImages";
private static final String IMAGES_FILES_COL = "AdviceDataImages.files";
public static final String ADVICE_TYPE = "adviceType";
public static final String UPDATE_TS = "updatedAt";
private static final String PUBLISHED_COL = "GeneratedAdvices";
private static final String GENERATED_COL = "GeneratedFiles";
private static final String GENERATED_FILES_COL = "GeneratedFiles.files";
private static final String GENERATED_TITLE = "generatedTitle";
//public static final String LOCAL_MONGO_URL = "mongodb://heroku:DnZ2AYC8nmtWR3p1Dccs4N9WSLUIrQQTrjcvfLrDlLo8V8yD4Pz6yV5mR5HPuTdEDx2b34v2W0qfufBHUBZlQg@oceanic.mongohq.com:10080/app23903821";
//public static final String LOCAL_MONGO_URL = "mongodb://conagua:C0n4gu4@192.168.204.147/conagua";
public static final String LOCAL_MONGO_URL = "mongodb://localhost:25000/conagua";
/**
* Gets an instance of a MongoInterface.
* @return current MongoInterface object
*/
public static synchronized MongoInterface getInstance() {
if (null == instance) {
try {
instance = new MongoInterface();
} catch (UnknownHostException uhe) {
System.out.println("Can't connect to MongoDB" + uhe.getLocalizedMessage());
}
}
return instance;
}
/**
* Constructor. Creates a new instance of a MongoInterface object.
* @throws UnknownHostException
*/
private MongoInterface() throws UnknownHostException {
boolean running = true;
for (String key : System.getenv().keySet()) {
if (key.startsWith("JAVA_MAIN")) {
if (System.getenv(key).startsWith("org.apache.maven")) {
running = false;
}
}
}
if (null != System.getenv("MONGOHQ_URL") && running) {
mongoClientURI = new MongoClientURI(System.getenv("MONGOHQ_URL"));
} else {
//mongodb://conagua:C0n4gu4@192.168.204.147/conagua
//MONGOHQ_URL=mongodb://heroku:DnZ2AYC8nmtWR3p1Dccs4N9WSLUIrQQTrjcvfLrDlLo8V8yD4Pz6yV5mR5HPuTdEDx2b34v2W0qfufBHUBZlQg@oceanic.mongohq.com:10080/app23903821
//mongoClientURI = new MongoClientURI("mongodb://heroku:DnZ2AYC8nmtWR3p1Dccs4N9WSLUIrQQTrjcvfLrDlLo8V8yD4Pz6yV5mR5HPuTdEDx2b34v2W0qfufBHUBZlQg@oceanic.mongohq.com:10080/app23903821");
//mongoClientURI = new MongoClientURI("mongodb://conagua:C0n4gu4@192.168.204.147/conagua");
mongoClientURI = new MongoClientURI(LOCAL_MONGO_URL);
}
mongoClient = new MongoClient(mongoClientURI);
mongoDB = mongoClient.getDB(mongoClientURI.getDatabase());
if (null != mongoClientURI.getUsername()) {
mongoDB.authenticate(mongoClientURI.getUsername(), mongoClientURI.getPassword());
}
}
/**
* Gets an array of the collection names in the current Mongo database.
* @return array of the collection names
*/
public String[] getCollections() {
Set<String> names = mongoDB.getCollectionNames();
return names.toArray(new String[0]);
}
/**
* Creates a new advice object
* @param currentId ID for the advice object
* @param tipo type of the advice. One of pacdp|atldp|pacht|atlht.
* @return BasicDBObject for the advice
*/
public BasicDBObject createNewAdvice(String currentId, String tipo) {
//System.out.println("new advice:" + currentId);
BasicDBObject newdata = new BasicDBObject(INTERNAL_FORM_ID, currentId)
.append(ADVICE_TYPE, tipo).append(UPDATE_TS, new Date());
mongoDB.getCollection(CAPTURA_COL).insert(newdata);
return newdata;
}
/**
* Gets the BasicDBObject with the advice information.
* @param currentId ID for the current advice
* @return BasicDBObject with the advice information
*/
public BasicDBObject getAdvice(String currentId) {
//System.out.println("getAdvice: " + currentId);
BasicDBObject newdata = new BasicDBObject(INTERNAL_FORM_ID, currentId);
return (BasicDBObject) mongoDB.getCollection(CAPTURA_COL).findOne(newdata);
}
/**
* Stores a set of key-value pairs in a BasicDBObject.
* @param currentId ID for the current advice
* @param formId form ID
* @param parametros key-value pairs to store
*/
public void savePlainData(String currentId, String formId, HashMap<String, String> parametros) {
//System.out.println("saveAdvice: " + currentId + " screen:" + formId);
BasicDBObject actual = getAdvice(currentId);
BasicDBObject interno = new BasicDBObject(parametros);
actual.append(formId, interno);
actual.append(UPDATE_TS, new Date());
mongoDB.getCollection(CAPTURA_COL).update(getAdvice(currentId), actual);
}
/**
* Gets a GridFS object to retrieve an image from.
* @return GridFS object
*/
public GridFS getImagesFS() {
return new GridFS(mongoDB, IMAGES_COL);
}
/**
* Gets a GridFS object to store an image.
* @return GridFS object
*/
public GridFS getGeneratedFS() {
return new GridFS(mongoDB, GENERATED_COL);
}
/**
* Gets a GridFS object for the provided type of operation.
* @param type type of operation (get or store the image)
* @return GridFS object
*/
public GridFS getGridFS(String type) {
String collection = GENERATED_COL;
if ("getImage".equals(type)) {
collection = IMAGES_COL;
}
return new GridFS(mongoDB, collection);
}
/**
* Gets a list of the last 10 generated advices from the Mongo database.
* @return list conitaining the last 10 generated advices
*/
public ArrayList<String> getPublisedAdvicesList() {
return getPublisedAdvicesList(null);
}
/**
* Gets the count of all generated advices in the Mongo database.
* @return Count of generated advices.
*/
public long countPublishedAdvices() {
DBCollection col = mongoDB.getCollection(GENERATED_COL);
return col.count();
}
/**
* Gets a list with the last 10 generated (complete) advices in the Mongo database.
* @param type type of the advice. One of pacdp|atldp|pacht|atlht
* @return list with the last 10 generated (complete) advices
*/
public ArrayList<String> getPublisedAdvicesList(String type) {
DBCollection col = mongoDB.getCollection(GENERATED_COL);
ArrayList<String> ret = null;
DBCursor cursor = null;
if (null == type) {
cursor = col.find().sort(new BasicDBObject("issueDate", -1)).limit(10);
} else {
cursor = col.find(new BasicDBObject("adviceType", type)).sort(new BasicDBObject("issueDate", -1)).limit(10);
}
if (null != cursor) {
ret = new ArrayList<>();
for (DBObject object : cursor) {
String advice = object.get(INTERNAL_FORM_ID) + "|" + object.get(GENERATED_TITLE);
ret.add(advice);
}
}
return ret;
}
/**
* Gets a list of the files stored in an advice.
* @param adviceID ID for the current advice
* @return list of the files stored in an advice
*/
ArrayList<String> listFilesFromAdvice(String adviceID) {
ArrayList<String> ret = new ArrayList<>();
DBCollection col = mongoDB.getCollection(IMAGES_FILES_COL);
DBCursor cursor = col.find(new BasicDBObject("filename", new BasicDBObject("$regex", adviceID)));
if (null != cursor) {
ret = new ArrayList<>();
for (DBObject obj : cursor) {
ret.add((String) obj.get("filename"));
}
}
return ret;
}
/**
* Flags te advice as succesfully generated (completed)
* @param adviceID ID for the current advice
* @param previous ID for the previous advice (if any)
* @param title title of the advice
* @param type type of the advice. One of pacdp|atldp|pacht|atlht.
* @param date issue date of the advice
*/
public void setGenerated(String adviceID, String previous, String title, String type, String date) {
DBCollection col = mongoDB.getCollection(GENERATED_COL);
String isodate = Utils.getOrderDate(date);
BasicDBObject nuevo = new BasicDBObject(INTERNAL_FORM_ID, adviceID)
.append(GENERATED_TITLE, title)
.append("previousIssue", previous)
.append("generationTime", Utils.sdf.format(new Date()))
.append("adviceType", type)
.append("issueDate", isodate);
BasicDBObject query = new BasicDBObject(INTERNAL_FORM_ID, adviceID);
BasicDBObject old = (BasicDBObject) col.findOne(query);
if (null == old) {
col.insert(nuevo);
} else {
col.update(old, nuevo);
}
}
/**
* Gets the chain of tracking advices (from newest to oldest)
* @param currentId ID for the current advice
* @return list of previous advices starting from the current advice
*/
public ArrayList<Statistics> getAdviceChain(String currentId) {
String searchId = currentId;
DBCollection col = mongoDB.getCollection(CAPTURA_COL);
Deque<String> deque = new ArrayDeque<>();
while (searchId != null && !searchId.trim().equals("")) {
deque.push(searchId);
BasicDBObject current = (BasicDBObject) col.findOne(new BasicDBObject(INTERNAL_FORM_ID, searchId));
if (null != current) {
current = (BasicDBObject) current.get("precapture");
}
if (null != current) {
searchId = current.getString("previousIssue");
} else {
searchId = null;
}
}
ArrayList<Statistics> ret = new ArrayList<>();
while (!deque.isEmpty()) {
String curr = deque.pop();
BasicDBObject lobj = (BasicDBObject) col.findOne(new BasicDBObject(INTERNAL_FORM_ID, curr));
if (null != lobj) {
ret.add(new Statistics(lobj));
}
}
return ret;
}
/**
* Gets a list of the last 10 published (complete) advices.
* @return list of the published (complete) advices
*/
public ArrayList<String> listPublishedAdvices() {
return listPublishedAdvices(10);
}
/**
* Gets a paged list of generated advices in the Mongo database.
* @param pNumber Page number to retrieve.
* @param nPerPage Items per page to retrieve.
* @return List of the nPerPage published (complete) advices in the page pNumber
*/
public ArrayList<String> listPagedPublishedAdvices(int pNumber, int nPerPage) {
DBCollection col = mongoDB.getCollection(GENERATED_COL);
ArrayList<String> ret = null;
DBCursor cursor;
cursor = col.find().skip(pNumber > 0 ? ((pNumber-1)*nPerPage) : 0).sort(new BasicDBObject("issueDate", -1)).limit(nPerPage);
if (null != cursor) {
ret = new ArrayList<>();
for (DBObject obj : cursor) {
ret.add((String) obj.get(INTERNAL_FORM_ID));
}
}
return ret;
}
/**
* Gets a list of the n last published advices.
* @param limit number of advices to get
* @return list of the n last published advices
*/
public ArrayList<String> listPublishedAdvices(int limit) {
DBCollection col = mongoDB.getCollection(GENERATED_COL);
ArrayList<String> ret = null;
DBCursor cursor;
if (limit > 0) {
cursor = col.find().sort(new BasicDBObject("issueDate", -1)).limit(limit);
} else {
cursor = col.find().sort(new BasicDBObject("issueDate", -1));
}
if (null != cursor) {
ret = new ArrayList<>();
for (DBObject obj : cursor) {
ret.add((String) obj.get(INTERNAL_FORM_ID));
}
}
return ret;
}
/**
* Gets a list of the last n published hurricane advices.
* @param limit number of advices to get
* @return list of the last n published hurricane advices
*/
public ArrayList<String> listPublishedHurricanes(int limit) {
DBCollection col = mongoDB.getCollection(GENERATED_COL);
ArrayList<String> ret = null;
DBCursor cursor;
if (limit > 0) {
cursor = col.find().sort(new BasicDBObject("issueDate", -1).append("adviceType", new BasicDBObject("$regex", "ht$"))).limit(limit);
} else {
cursor = col.find().sort(new BasicDBObject("issueDate", -1).append("adviceType", new BasicDBObject("$regex", "ht$")));
}
if (null != cursor) {
ret = new ArrayList<>();
for (DBObject obj : cursor) {
ret.add((String) obj.get(INTERNAL_FORM_ID));
}
}
return ret;
}
/**
* Gets the DBObject for the given advice ID.
* @param adviceId ID for the current advice
* @return DBObject for the given advice ID
*/
public DBObject getPublishedAdvice(String adviceId) {
return mongoDB.getCollection(GENERATED_COL).findOne(new BasicDBObject(INTERNAL_FORM_ID, adviceId));
}
/**
* Makes a deep clone of an existing advice object.
* @param originAdviceID source object
* @param currentAdviceId ID for the cloned advice object
*/
public void copyFromAdvice(String originAdviceID, String currentAdviceId) {
BasicDBObject origen = getAdvice(originAdviceID);
BasicDBObject destino = getAdvice(currentAdviceId);
destino.putAll(origen.toMap());
destino.put(INTERNAL_FORM_ID, currentAdviceId);
origen = getAdvice(currentAdviceId);
mongoDB.getCollection(CAPTURA_COL).update(origen, destino);
}
/**
* Gets the prefix of the HTML file name for the advice, depending on its type.
* @param adviceID ID for the current advice
* @return prefix for the file name. One of pacifico|atlantico.
*/
public String getHTMLFileNamePrefix(String adviceID){
BasicDBObject newdata = new BasicDBObject(INTERNAL_FORM_ID, adviceID);
newdata = (BasicDBObject) mongoDB.getCollection(CAPTURA_COL).findOne(newdata);
String type = newdata.getString("adviceType");
String ret = null;
if (type.indexOf("pac")>-1){
ret = "pacifico";
}
if (type.indexOf("atl")>-1){
ret = "atlantico";
}
return ret;
}
}