/* * 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; } }