Java tutorial
/* * Copyright (C) 2005 - 2012 Jaspersoft Corporation. All rights reserved. * http://www.jaspersoft.com. * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jaspersoft.mongodb.query; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import net.sf.jasperreports.engine.JRException; import org.apache.log4j.Logger; import com.jaspersoft.mongodb.ReportTest; import com.jaspersoft.mongodb.connection.MongoDbConnection; import com.mongodb.BasicDBObject; import com.mongodb.CommandResult; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MapReduceCommand; import com.mongodb.MapReduceCommand.OutputType; import com.mongodb.MapReduceOutput; import com.mongodb.util.JSON; /** * * @author Eric Diaz * */ public class MongoDbQueryWrapper { private final static Logger logger = Logger.getLogger(MongoDbQueryWrapper.class); public static final String FIND_QUERY_KEY = "findQuery"; public static final String FIND_QUERY_REGEXP_KEY = "findQueryRegEx"; public static final String FIND_FIELDS_KEY = "findFields"; public static final String SORT_KEY = "sort"; public static final String LIMIT_KEY = "limit"; public static final String COLLECTION_NAME_KEY = "collectionName"; public static final String ROWS_TO_PROCESS_KEY = "rowsToProcess"; public static final String MAP_REDUCE_KEY = "mapReduce"; public static final String MAP_KEY = "map"; public static final String REDUCE_KEY = "reduce"; public static final String OUT_KEY = "out"; private static final String OUT_DB_KEY = "db"; private static final String FINALIZE_KEY = "finalize"; private static final String RUN_COMMAND_KEY = "runCommand"; private static final String RESULT_KEY = "result"; public DBCursor iterator; public DBObject queryObject; public int rowsToProcess = 5; private MongoDbConnection connection; private Map<String, Object> parameters; public List<?> commandResults; public MongoDbQueryWrapper(String queryString, MongoDbConnection connection, Map<String, Object> parameters) throws JRException { this.connection = connection; this.parameters = parameters; processQuery(queryString); } public void processQuery(String queryString) throws JRException { logger.info("Processing mongoDB query"); if (queryString.startsWith("\"")) { queryString = queryString.substring(1, queryString.length()); } if (queryString.endsWith("\"")) { queryString = queryString.substring(0, queryString.length() - 1); } Object parseResult = JSON.parse(queryString); if (logger.isDebugEnabled()) { logger.debug("Query: " + queryString); } if (!(parseResult instanceof DBObject)) { throw new JRException("Unsupported type: " + parseResult.getClass().getName()); } queryObject = (DBObject) parseResult; fixQueryObject(queryObject, parameters); if (queryObject.containsField(RUN_COMMAND_KEY)) { runCommand(queryObject.removeField(RUN_COMMAND_KEY)); } else { createIterator(); } if (queryObject.containsField(ROWS_TO_PROCESS_KEY)) { Integer value = processInteger(queryObject.get(ROWS_TO_PROCESS_KEY)); if (value != null) { rowsToProcess = value.intValue(); } } if (rowsToProcess == 0) { rowsToProcess = Integer.MAX_VALUE; } } private Object fixQueryObject(DBObject queryObjectToFix, Map<String, Object> reportParameters) { Set<String> keySet = queryObjectToFix.keySet(); if (keySet.size() == 1) { String key = keySet.iterator().next(); if (reportParameters.containsKey(key) && queryObjectToFix.get(key) == null) { return reportParameters.get(key); } } for (String key : queryObjectToFix.keySet()) { Object value = queryObjectToFix.get(key); if (value instanceof DBObject) { queryObjectToFix.put(key, fixQueryObject((DBObject) value, reportParameters)); } } return queryObjectToFix; } private void runCommand(Object commandValue) throws JRException { if (!(commandValue instanceof DBObject)) { throw new JRException("Command must be a valid BSON object"); } DBObject commandObject = (DBObject) commandValue; if (logger.isDebugEnabled()) { logger.debug("Command object: " + commandObject); } CommandResult commandResult = connection.getMongoDatabase().command(commandObject); if (!commandResult.ok()) { throw new JRException(commandResult.getErrorMessage()); } Object resultObject = commandResult.get(RESULT_KEY); if (resultObject == null) { throw new JRException("No results"); } commandResults = (List<?>) resultObject; } private void createIterator() throws JRException { if (!queryObject.containsField(COLLECTION_NAME_KEY)) { throw new JRException("\"" + COLLECTION_NAME_KEY + "\" must be part of the query object"); } DBObject findQueryObject = (DBObject) queryObject.get(FIND_QUERY_KEY); if (findQueryObject == null) { findQueryObject = new BasicDBObject(); } if (queryObject.containsField(FIND_QUERY_REGEXP_KEY)) { DBObject regExpObject = (DBObject) queryObject.get(FIND_QUERY_REGEXP_KEY); String value, flags; int index; for (String key : regExpObject.keySet()) { value = (String) regExpObject.get(key); if (value.startsWith("/")) { value = value.substring(1, value.length()); } else { throw new JRException("Regular expressions must start with: /"); } if (!value.contains("/")) { throw new JRException("No ending symbol found: /"); } index = value.lastIndexOf("/"); flags = null; if (index == value.length() - 1) { value = value.substring(0, index); } else { flags = value.substring(index + 1, value.length()); value = value.substring(0, index); } findQueryObject.put(key, Pattern.compile((flags != null ? "(?" + flags + ")" : "") + value)); } } DBCollection collection = connection.getMongoDatabase() .getCollectionFromString((String) queryObject.removeField(COLLECTION_NAME_KEY)); if (queryObject.containsField(MAP_REDUCE_KEY)) { Object value = queryObject.removeField(MAP_REDUCE_KEY); if (!(value instanceof DBObject)) { logger.error("MapReduce value must be a valid JSON object"); } else { DBObject mapReduceObject = (DBObject) value; String map = validateProperty(mapReduceObject, MAP_KEY); String reduce = validateProperty(mapReduceObject, REDUCE_KEY); Object outObject = mapReduceObject.get(OUT_KEY); if (outObject == null) { throw new JRException("\"out\" cannot be null"); } String collectionName = null; Object outDb = null; OutputType outputType = null; boolean hasOutputType = false; if (logger.isDebugEnabled()) { logger.debug("Out object: " + outObject + ". Type: " + outObject.getClass().getName()); } if (outObject instanceof String) { collectionName = String.valueOf(outObject); } else if (outObject instanceof DBObject) { DBObject outDbObject = (DBObject) outObject; outDb = outDbObject.removeField(OUT_DB_KEY); Iterator<String> keysIterator = outDbObject.keySet().iterator(); String type = null; if (keysIterator.hasNext()) { type = keysIterator.next(); collectionName = String.valueOf(outDbObject.get(type)); } else { throw new JRException("\"out\" object cannot be empty"); } type = type.toUpperCase(); outputType = OutputType.valueOf(type); if (outputType == null) { throw new JRException("Unknow output type: " + type); } hasOutputType = true; if (logger.isDebugEnabled()) { logger.debug("outobject: " + outDbObject); logger.debug("collectionName: " + collectionName); logger.debug("outputType: " + outputType); } } else { throw new JRException("Unsupported type for \"out\": " + outObject.getClass().getName()); } MapReduceCommand mapReduceCommand = new MapReduceCommand(collection, map, reduce, collectionName, hasOutputType ? outputType : OutputType.REPLACE, null); if (outDb != null) { mapReduceCommand.setOutputDB(String.valueOf(outDb)); } Object finalizeObject = mapReduceObject.removeField(FINALIZE_KEY); if (finalizeObject != null) { mapReduceCommand.setFinalize(String.valueOf(finalizeObject)); } MapReduceOutput mapReduceOutput = collection.mapReduce(mapReduceCommand); DBCollection mapReduceCollection = mapReduceOutput.getOutputCollection(); if (mapReduceCollection != null) { collection = mapReduceCollection; } } } iterator = collection.find(findQueryObject, (DBObject) queryObject.get(FIND_FIELDS_KEY)); if (queryObject.containsField(SORT_KEY)) { iterator = iterator.sort((DBObject) queryObject.get(SORT_KEY)); } if (queryObject.containsField(LIMIT_KEY)) { Integer value = processInteger(queryObject.get(LIMIT_KEY)); if (value != null) { iterator = iterator.limit(value.intValue()); } } } private Integer processInteger(Object value) { try { if (value instanceof Integer) { return (Integer) value; } else { return Integer.parseInt((String) value); } } catch (Exception e) { logger.error(e); } return null; } public String validateProperty(DBObject object, String name) throws JRException { Object value = object.get(name); if (value == null) { throw new JRException(name + " can't be null"); } return String.valueOf(value); } public static void main(String[] args) { MongoDbConnection c = null; ReportTest reports = new ReportTest(); try { c = new MongoDbConnection("mongodb://localhost:27017/test", null, null); reports.test(); Object cmd = JSON.parse("{\n" + " aggregate : \"accounts\",\n" + " pipeline : [\n" + " {\n" + " $project : {\n" + " billing_address_street : 1,\n" + " billing_address_country : 1\n" + " }\n" + " }\n" + " ]\n" + " }"); CommandResult result = c.getMongoDatabase().command((DBObject) cmd); System.out.println(result.keySet()); System.out.println(result.get("ok") + " - " + result.ok()); System.out.println(result.get("result").getClass().getName()); } catch (Exception e) { logger.error(e); } finally { if (c != null) { c.close(); } } } }