Example usage for com.mongodb BasicDBObject containsField

List of usage examples for com.mongodb BasicDBObject containsField

Introduction

In this page you can find the example usage for com.mongodb BasicDBObject containsField.

Prototype

public boolean containsField(final String field) 

Source Link

Document

Checks if this object contains a given field

Usage

From source file:com.edgytech.umongo.EditAggGeoNearDialog.java

License:Apache License

@Override
public void setParameters(Object value) {
    BasicDBObject cmd = (BasicDBObject) value;
    ((DocBuilderField) getBoundUnit(Item.near)).setDBObject((DBObject) cmd.get("near"));
    setStringFieldValue(Item.distanceField, cmd.getString("distanceField"));
    setDoubleFieldValue(Item.maxDistance, cmd.getDouble("maxDistance"));
    if (cmd.containsField("distanceMultiplier")) {
        setDoubleFieldValue(Item.distanceMultiplier, cmd.getDouble("distanceMultiplier"));
    }// w  w  w . ja v  a 2 s.co m
    if (cmd.containsField("query")) {
        ((DocBuilderField) getBoundUnit(Item.query)).setDBObject((DBObject) cmd.get("query"));
    }
    if (cmd.containsField("spherical")) {
        setBooleanFieldValue(Item.spherical, cmd.getBoolean("spherical"));
    }

    if (cmd.containsField("query")) {
        ((DocBuilderField) getBoundUnit(Item.query)).setDBObject((DBObject) cmd.get("query"));
    }

    if (cmd.containsField("includeLocs")) {
        setStringFieldValue(Item.includeLocs, cmd.getString("includeLocs"));
    }

    if (cmd.containsField("uniqueDocs")) {
        setBooleanFieldValue(Item.uniqueDocs, cmd.getBoolean("uniqueDocs"));
    }
}

From source file:com.edgytech.umongo.IndexPanel.java

License:Apache License

public void settings(ButtonBase button) {
    FormDialog dialog = (FormDialog) ((MenuItem) getBoundUnit(Item.settings)).getDialog();
    BasicDBObject index = (BasicDBObject) getIndexInfo();
    boolean isTTL = false;
    long ttl = 0;
    if (index.containsField("expireAfterSeconds")) {
        isTTL = true;/*from   w  w  w. java 2s. c  o m*/
        ttl = index.getLong("expireAfterSeconds");
    }
    setLongFieldValue(Item.expireAfterSeconds, ttl);
    if (!dialog.show())
        return;

    long newTTL = getLongFieldValue(Item.expireAfterSeconds);
    if (newTTL != ttl) {
        BasicDBObject cmd = new BasicDBObject("collMod",
                getIndexNode().getCollectionNode().getCollection().getName());
        BasicDBObject param = new BasicDBObject();
        param.put("keyPattern", (DBObject) index.get("key"));
        param.put("expireAfterSeconds", newTTL);
        cmd.put("index", param);
        new DbJobCmd(getIndexNode().getCollectionNode().getCollection().getDB(), cmd).addJob();
    }
}

From source file:com.edgytech.umongo.MongoUtils.java

License:Apache License

public static boolean isBalancerOn(MongoClient mongo) {
    final DB config = mongo.getDB("config");
    final DBCollection settings = config.getCollection("settings");
    BasicDBObject res = (BasicDBObject) settings.findOne(new BasicDBObject("_id", "balancer"));
    if (res == null || !res.containsField("stopped"))
        return true;
    return !res.getBoolean("stopped");
}

From source file:com.edgytech.umongo.ReplicaDialog.java

License:Apache License

public void updateFromReplicaConfig(BasicDBObject member) {
    // reset//from  www .ja v a  2 s . com
    xmlLoadCheckpoint();
    ((TextField) getBoundUnit(Item.host)).editable = false;

    setStringFieldValue(Item.host, member.getString("host"));
    setBooleanFieldValue(Item.arbiterOnly, member.getBoolean("arbiterOnly", false));
    setBooleanFieldValue(Item.hidden, member.getBoolean("hidden", false));
    setBooleanFieldValue(Item.ignoreIndexes, !member.getBoolean("buildIndexes", true));

    if (member.containsField("priority")) {
        setDoubleFieldValue(Item.priority, member.getDouble("priority"));
    }
    if (member.containsField("slaveDelay")) {
        setIntFieldValue(Item.slaveDelay, member.getInt("slaveDelay"));
    }
    if (member.containsField("votes")) {
        setIntFieldValue(Item.votes, member.getInt("votes"));
    }
    if (member.containsField("tags")) {
        ((DocBuilderField) getBoundUnit(Item.tags)).setDBObject((DBObject) member.get("tags"));
    }
}

From source file:com.edgytech.umongo.RouterPanel.java

License:Apache License

public void balancer(ButtonBase button) {
    final MongoClient mongo = getRouterNode().getMongoClient();
    final DB config = mongo.getDB("config");
    final DBCollection settings = config.getCollection("settings");

    FormDialog diag = (FormDialog) ((MenuItem) getBoundUnit(Item.balancer)).getDialog();
    diag.xmlLoadCheckpoint();/*w  w  w  . j  ava2s  .c  o m*/

    final BasicDBObject query = new BasicDBObject("_id", "balancer");
    BasicDBObject balDoc = (BasicDBObject) settings.findOne(query);
    if (balDoc != null) {
        if (balDoc.containsField("stopped"))
            setIntFieldValue(Item.balStopped, balDoc.getBoolean("stopped") ? 1 : 2);
        if (balDoc.containsField("_secondaryThrottle"))
            setIntFieldValue(Item.balSecThrottle, balDoc.getBoolean("_secondaryThrottle") ? 1 : 2);
        BasicDBObject window = (BasicDBObject) balDoc.get("activeWindow");
        if (window != null) {
            setStringFieldValue(Item.balStartTime, window.getString("start"));
            setStringFieldValue(Item.balStopTime, window.getString("stop"));
        }
    }

    if (!diag.show())
        return;

    if (balDoc == null)
        balDoc = new BasicDBObject("_id", "balancer");
    int stopped = getIntFieldValue(Item.balStopped);
    if (stopped > 0)
        balDoc.put("stopped", stopped == 1 ? true : false);
    else
        balDoc.removeField("stopped");
    int throttle = getIntFieldValue(Item.balSecThrottle);
    if (throttle > 0)
        balDoc.put("_secondaryThrottle", throttle == 1 ? true : false);
    else
        balDoc.removeField("_secondaryThrottle");

    if (!getStringFieldValue(Item.balStartTime).trim().isEmpty()) {
        BasicDBObject aw = new BasicDBObject();
        aw.put("start", getStringFieldValue(Item.balStartTime).trim());
        aw.put("stop", getStringFieldValue(Item.balStopTime).trim());
        balDoc.put("activeWindow", aw);
    }
    final BasicDBObject newDoc = balDoc;

    new DbJob() {

        @Override
        public Object doRun() throws IOException {
            return settings.update(query, newDoc, true, false);
        }

        @Override
        public String getNS() {
            return settings.getFullName();
        }

        @Override
        public String getShortName() {
            return "Balancer";
        }

        @Override
        public void wrapUp(Object res) {
            updateComponent();
            super.wrapUp(res);
        }
    }.addJob();
}

From source file:com.edgytech.umongo.RouterPanel.java

License:Apache License

public void regenConfigDB(ButtonBase button) throws UnknownHostException {
    MongoClient cmongo = getRouterNode().getMongoClient();
    String servers = getStringFieldValue(Item.regenServers);
    final String db = getStringFieldValue(Item.regenDB);
    final String col = getStringFieldValue(Item.regenCollection);
    final String ns = db + "." + col;
    final DBObject shardKey = ((DocBuilderField) getBoundUnit(Item.regenShardKey)).getDBObject();
    final boolean unique = getBooleanFieldValue(Item.regenKeyUnique);
    final BasicDBObject result = new BasicDBObject();
    result.put("ns", ns);
    result.put("shardKey", shardKey);
    result.put("unique", unique);

    // create direct mongo for each replica set
    String[] serverList = servers.split("\n");
    List<ServerAddress> list = new ArrayList<ServerAddress>();
    String txt = "";
    String primaryShard = null;//from w  w  w  .  jav a 2s .c  o m
    final BasicDBObject shardList = new BasicDBObject();
    HashMap<MongoClient, String> mongoToShard = new HashMap<MongoClient, String>();
    sLoop: for (String server : serverList) {
        server = server.trim();
        String[] tokens = server.split("/");
        if (tokens.length != 2) {
            new InfoDialog(null, "Error", null, "Server format must be like 'hostname:port/shard', one by line")
                    .show();
            return;
        }
        server = tokens[0];
        String shard = tokens[1];
        if (primaryShard == null) {
            primaryShard = shard;
        }
        ServerAddress addr = new ServerAddress(server);

        // filter out if replset already exists
        for (MongoClient replset : mongoToShard.keySet()) {
            if (replset.getServerAddressList().contains(addr)) {
                continue sLoop;
            }
        }

        list.clear();
        list.add(addr);
        MongoClient mongo = new MongoClient(list);
        //            UMongo.instance.addMongoClient(mongo, null);
        // make request to force server detection
        mongo.getDatabaseNames();
        mongoToShard.put(mongo, shard);

        String desc = null;
        if (!mongo.getDatabaseNames().contains(db) || !mongo.getDB(db).getCollectionNames().contains(col)) {
            desc = "Collection not present!";
        } else {
            // try to see if shard key has index
            DBObject index = mongo.getDB(db).getCollection("system.indexes")
                    .findOne(new BasicDBObject("key", shardKey));
            if (index != null) {
                desc = "shard key found";
            } else {
                desc = "shard key NOT found!";
            }
        }
        txt += mongo.toString() + " shard=" + shard + " - " + desc + "\n";
        BasicDBObject shardObj = new BasicDBObject("servers", mongo.toString());
        shardObj.put("status", desc);
        if (shardList.containsField(shard)) {
            new InfoDialog(null, "Error", null, "Duplicate Shard name " + shard).show();
            return;
        }
        shardList.put(shard, shardObj);
    }
    result.put("shards", shardList);

    FormDialog dia = (FormDialog) getBoundUnit(Item.regenRSList);
    dia.setStringFieldValue(Item.regenRSListArea, txt);
    if (!dia.show()) {
        return;
    }

    DB config = cmongo.getDB("config");

    // add database record
    BasicDBObject doc = new BasicDBObject("_id", db);
    doc.put("partitioned", true);
    doc.put("primary", primaryShard);
    config.getCollection("databases").save(doc);

    // add collection record
    doc = new BasicDBObject("_id", ns);
    doc.put("lastmod", new Date());
    doc.put("dropped", false);
    doc.put("key", shardKey);
    doc.put("unique", unique);
    config.getCollection("collections").save(doc);

    final DBCollection chunks = config.getCollection("chunks");
    long count = chunks.count(new BasicDBObject("ns", ns));
    if (count > 0) {
        dia = (FormDialog) getBoundUnit(Item.regenDeleteChunks);
        if (dia.show()) {
            chunks.remove(new BasicDBObject("ns", ns));
        } else {
            return;
        }
    }

    // add temp collection to sort chunks with shard key
    final DBCollection tmpchunks = config.getCollection("_tmpchunks_" + col);
    tmpchunks.drop();
    // should be safe environment, and dup keys should be ignored
    tmpchunks.setWriteConcern(WriteConcern.NORMAL);
    // can use shardKey as unique _id
    //        tmpchunks.ensureIndex(shardKey, "shardKey", true);

    // create filter for shard fields
    final DBObject shardKeyFilter = new BasicDBObject();
    //        final DBObject shardKeyDescend = new BasicDBObject();
    boolean hasId = false;
    for (String key : shardKey.keySet()) {
        shardKeyFilter.put(key, 1);
        if (key.equals("_id")) {
            hasId = true;
        }
    }
    if (!hasId) {
        shardKeyFilter.put("_id", 0);
    }

    dia = (FormDialog) getBoundUnit(Item.regenConfirm);
    if (!dia.show()) {
        return;
    }

    // now fetch all records from each shard
    final AtomicInteger todo = new AtomicInteger(mongoToShard.size());
    for (Map.Entry<MongoClient, String> entry : mongoToShard.entrySet()) {
        final MongoClient mongo = entry.getKey();
        final String shard = entry.getValue();
        new DbJob() {

            @Override
            public Object doRun() throws Exception {
                BasicDBObject shardObj = (BasicDBObject) shardList.get(shard);
                long count = mongo.getDB(db).getCollection(col).count();
                shardObj.put("count", count);
                DBCursor cur = mongo.getDB(db).getCollection(col).find(new BasicDBObject(), shardKeyFilter);
                long i = 0;
                int inserted = 0;
                long start = System.currentTimeMillis();
                while (cur.hasNext() && !isCancelled()) {
                    BasicDBObject key = (BasicDBObject) cur.next();
                    setProgress((int) ((++i * 100.0f) / count));
                    try {
                        BasicDBObject entry = new BasicDBObject("_id", key);
                        entry.put("_shard", shard);
                        tmpchunks.insert(entry);
                        ++inserted;
                    } catch (Exception e) {
                        getLogger().log(Level.WARNING, e.getMessage(), e);
                    }
                }

                if (isCancelled()) {
                    shardObj.put("cancelled", true);
                }
                shardObj.put("inserted", inserted);
                shardObj.put("scanTime", System.currentTimeMillis() - start);
                todo.decrementAndGet();
                return null;
            }

            @Override
            public String getNS() {
                return tmpchunks.getFullName();
            }

            @Override
            public String getShortName() {
                return "Scanning " + shard;
            }

            @Override
            public boolean isDeterminate() {
                return true;
            }
        }.addJob();

    }

    new DbJob() {

        @Override
        public Object doRun() throws Exception {
            // wait for all shards to be done
            long start = System.currentTimeMillis();
            while (todo.get() > 0 && !isCancelled()) {
                Thread.sleep(2000);
            }

            if (isCancelled()) {
                result.put("cancelled", true);
                return result;
            }

            // find highest current timestamp
            DBCursor cur = chunks.find().sort(new BasicDBObject("lastmod", -1)).batchSize(-1);
            BasicDBObject chunk = (BasicDBObject) (cur.hasNext() ? cur.next() : null);
            BSONTimestamp ts = (BSONTimestamp) (chunk != null ? chunk.get("lastmod") : null);

            // now infer chunk ranges
            long count = tmpchunks.count();
            result.put("uniqueKeys", count);
            int numChunks = 0;
            cur = tmpchunks.find().sort(new BasicDBObject("_id", 1));
            BasicDBObject prev = (BasicDBObject) cur.next();
            BasicDBObject next = null;
            // snap prev to minkey
            BasicDBObject theid = (BasicDBObject) prev.get("_id");
            for (String key : shardKey.keySet()) {
                theid.put(key, new MinKey());
            }
            String currentShard = prev.getString("_shard");

            int i = 1;
            while (cur.hasNext()) {
                next = (BasicDBObject) cur.next();
                setProgress((int) ((++i * 100.0f) / count));
                String newShard = next.getString("_shard");
                if (newShard.equals(currentShard))
                    continue;

                // add chunk
                ts = getNextTimestamp(ts);
                chunk = getChunk(ns, shardKey, prev, next, ts);
                chunks.insert(chunk);
                prev = next;
                currentShard = prev.getString("_shard");
                ++numChunks;
            }

            // build max
            next = new BasicDBObject();
            for (String key : shardKey.keySet()) {
                next.put(key, new MaxKey());
            }
            next = new BasicDBObject("_id", next);
            ts = getNextTimestamp(ts);
            chunk = getChunk(ns, shardKey, prev, next, ts);
            chunks.insert(chunk);
            ++numChunks;
            result.put("numChunks", numChunks);
            result.put("totalTime", System.currentTimeMillis() - start);
            return result;
        }

        @Override
        public String getNS() {
            return chunks.getFullName();
        }

        @Override
        public String getShortName() {
            return "Creating Chunks";
        }

        @Override
        public boolean isDeterminate() {
            return true;
        }
    }.addJob();
}

From source file:com.flyingdonut.implementation.helpers.MongoDbConsumerAssociationStore.java

License:Apache License

private void mongoEnsureIndex(BasicDBObject query, BasicDBObject sort) {
    if (query.containsField(id) || query.keySet().isEmpty()) {
        return;//from   w w w  .  j  a  v  a2  s .c o  m
    }

    DBObject indexDoc = new BasicDBObject();
    for (String k : query.keySet()) {
        if (k.startsWith("$")) {
            mongoEnsureIndexAddAll(indexDoc, (BasicDBList) query.get(k));
        } else {
            indexDoc.put(k, 1);
        }
    }

    if (sort != null) {
        for (String k : sort.keySet()) {
            indexDoc.put(k, sort.get(k));
        }
    }

    getMongoDBConnection().getCollection(getCollectionName()).ensureIndex(indexDoc);
}

From source file:com.github.camellabs.iot.cloudlet.document.driver.mongodb.MongoQueryBuilder.java

License:Apache License

private void addRestriction(BasicDBObject query, String propertyWithOperator, String propertyOperator,
        String operator, Object value) {
    String property = propertyWithOperator.replaceAll(propertyOperator + "$", "");
    if (query.containsField(property)) {
        BasicDBObject existingRestriction = (BasicDBObject) query.get(property);
        existingRestriction.put(operator, value);
    } else {/*from  ww w  . jav  a2  s .co m*/
        query.put(property, new BasicDBObject(operator, value));
    }
}

From source file:com.ikanow.aleph2.v1.document_db.utils.LegacyV1HadoopUtils.java

License:Open Source License

/** parse the V1 query string 
 * @param query/*from  w ww.  j  a  v  a 2s  . c  om*/
 * @return the required objects embedded in various tuples
 */
public static Tuple4<String, Tuple2<Integer, Integer>, BasicDBObject, DBObject> parseQueryObject(
        final String query, final List<String> community_ids) {
    // Some fixed variables just to avoid changing the guts of the (tested in v1) code
    final boolean isCustomTable = false;
    @SuppressWarnings("unused")
    Integer nDebugLimit = null;
    final boolean bLocalMode = false;
    @SuppressWarnings("unused")
    final Boolean incrementalMode = null;
    final String input = "doc_metadata.metadata";

    // Output objects
    final String out_query;
    int nSplits = 8;
    int nDocsPerSplit = 12500;

    List<ObjectId> communityIds = community_ids.stream().map(s -> new ObjectId(s)).collect(Collectors.toList());

    //C/P code:

    //add communities to query if this is not a custom table
    BasicDBObject oldQueryObj = null;
    BasicDBObject srcTags = null;
    // Start with the old query:
    if (query.startsWith("{")) {
        oldQueryObj = (BasicDBObject) com.mongodb.util.JSON.parse(query);
    } else {
        oldQueryObj = new BasicDBObject();
    }
    boolean elasticsearchQuery = oldQueryObj.containsField("qt") && !isCustomTable;
    @SuppressWarnings("unused")
    int nLimit = 0;
    if (oldQueryObj.containsField(":limit")) {
        nLimit = oldQueryObj.getInt(":limit");
        oldQueryObj.remove(":limit");
    }
    if (oldQueryObj.containsField(":splits")) {
        nSplits = oldQueryObj.getInt(":splits");
        oldQueryObj.remove(":splits");
    }
    if (oldQueryObj.containsField(":srctags")) {
        srcTags = new BasicDBObject(SourcePojo.tags_, oldQueryObj.get(":srctags"));
        oldQueryObj.remove(":srctags");
    }
    if (bLocalMode) { // If in local mode, then set this to a large number so we always run inside our limit/split version
        // (since for some reason MongoInputFormat seems to fail on large collections)
        nSplits = InfiniteMongoSplitter.MAX_SPLITS;
    }
    if (oldQueryObj.containsField(":docsPerSplit")) {
        nDocsPerSplit = oldQueryObj.getInt(":docsPerSplit");
        oldQueryObj.remove(":docsPerSplit");
    }
    final DBObject fields = (DBObject) oldQueryObj.remove(":fields");
    oldQueryObj.remove(":output");
    oldQueryObj.remove(":reducers");
    @SuppressWarnings("unused")
    String mapperKeyClass = oldQueryObj.getString(":mapper_key_class", "");
    @SuppressWarnings("unused")
    String mapperValueClass = oldQueryObj.getString(":mapper_value_class", "");
    oldQueryObj.remove(":mapper_key_class");
    oldQueryObj.remove(":mapper_value_class");
    String cacheList = null;
    Object cacheObj = oldQueryObj.get(":caches");
    if (null != cacheObj) {
        cacheList = cacheObj.toString(); // (either array of strings, or single string)
        if (!cacheList.startsWith("[")) {
            cacheList = "[" + cacheList + "]"; // ("must" now be valid array)
        }
        oldQueryObj.remove(":caches");
    } //TESTED

    //      if (null != nDebugLimit) { // (debug mode override)
    //         nLimit = nDebugLimit;
    //      }
    //      boolean tmpIncMode = ( null != incrementalMode) && incrementalMode; 

    @SuppressWarnings("unused")
    String otherCollections = null;
    Date fromOverride = null;
    Date toOverride = null;
    Object fromOverrideObj = oldQueryObj.remove(":tmin");
    Object toOverrideObj = oldQueryObj.remove(":tmax");
    if (null != fromOverrideObj) {
        fromOverride = dateStringFromObject(fromOverrideObj, true);
    }
    if (null != toOverrideObj) {
        toOverride = dateStringFromObject(toOverrideObj, false);
    }

    if (!isCustomTable) {
        if (elasticsearchQuery) {
            oldQueryObj.put("communityIds", communityIds);
            //tmin/tmax not supported - already have that capability as part of the query
        } else {
            if (input.equals("feature.temporal")) {
                if ((null != fromOverride) || (null != toOverride)) {
                    oldQueryObj.put("value.maxTime", createDateRange(fromOverride, toOverride, true));
                } //TESTED
                oldQueryObj.put("_id.c", new BasicDBObject(DbManager.in_, communityIds));
            } else {
                oldQueryObj.put(DocumentPojo.communityId_, new BasicDBObject(DbManager.in_, communityIds));
                if ((null != fromOverride) || (null != toOverride)) {
                    oldQueryObj.put(JsonUtils._ID, createDateRange(fromOverride, toOverride, false));
                } //TESTED         
                if (input.equals("doc_metadata.metadata")) {
                    oldQueryObj.put(DocumentPojo.index_, new BasicDBObject(DbManager.ne_, "?DEL?")); // (ensures not soft-deleted)
                }
            }
        }
    } else {
        throw new RuntimeException("Custom Tables not currently supported (no plans to)");
        //         if ((null != fromOverride) || (null != toOverride)) {
        //            oldQueryObj.put(JsonUtils._ID, createDateRange(fromOverride, toOverride, false));
        //         }//TESTED
        //         //get the custom table (and database)
        //
        //         String[] candidateInputs = input.split("\\s*,\\s*");
        //         input = CustomOutputManager.getCustomDbAndCollection(candidateInputs[0]);
        //         if (candidateInputs.length > 1) {            
        //            otherCollections = Arrays.stream(candidateInputs)
        //                  .skip(1L)
        //                  .map(i -> CustomOutputManager.getCustomDbAndCollection(i))
        //                  .map(i -> "mongodb://"+dbserver+"/"+i).collect(Collectors.joining("|"));
        //         }
    }
    out_query = oldQueryObj.toString();

    return Tuples._4T(out_query, Tuples._2T(nSplits, nDocsPerSplit), srcTags, fields);
}

From source file:com.ikanow.infinit.e.application.utils.LogstashConfigUtils.java

License:Open Source License

public static BasicDBObject parseLogstashConfig(String configFile, StringBuffer error) {

    BasicDBObject tree = new BasicDBObject();

    // Stage 0: remove escaped "s and 's (for the purpose of the validation):
    // (prevents tricksies with escaped "s and then #s)
    // (http://stackoverflow.com/questions/5082398/regex-to-replace-single-backslashes-excluding-those-followed-by-certain-chars)
    configFile = configFile.replaceAll("(?<!\\\\)(?:((\\\\\\\\)*)\\\\)[\"']", "X");
    //TESTED (by hand - using last 2 fields of success_2_1)

    // Stage 1: remove #s, and anything in quotes (for the purpose of the validation)
    configFile = configFile.replaceAll("(?m)(?:([\"'])(?:(?!\\1).)*\\1)", "VALUE").replaceAll("(?m)(?:#.*$)",
            "");/*from   ww  w.  j a  va  2 s.  com*/
    //TESTED (2_1 - including with a # inside the ""s - Event_Date -> Event_#Date)
    //TESTED (2_2 - various combinations of "s nested inside 's) ... yes that is a negative lookahead up there - yikes!

    // Stage 2: get a nested list of objects
    int depth = 0;
    int ifdepth = -1;
    Stack<Integer> ifStack = new Stack<Integer>();
    BasicDBObject inputOrFilter = null;
    Matcher m = _navigateLogstash.matcher(configFile);
    // State:
    String currTopLevelBlockName = null;
    String currSecondLevelBlockName = null;
    BasicDBObject currSecondLevelBlock = null;
    while (m.find()) {
        boolean simpleField = false;

        //DEBUG
        //System.out.println("--DEPTH="+depth + " GROUP=" + m.group() + " IFS" + Arrays.toString(ifStack.toArray()));
        //System.out.println("STATES: " + currTopLevelBlockName + " AND " + currSecondLevelBlockName);

        if (m.group().equals("}")) {

            if (ifdepth == depth) { // closing an if statement
                ifStack.pop();
                if (ifStack.isEmpty()) {
                    ifdepth = -1;
                } else {
                    ifdepth = ifStack.peek();
                }
            } //TESTED (1_1bc, 2_1)
            else { // closing a processing block

                depth--;
                if (depth < 0) { // {} Mismatch
                    error.append("{} Mismatch (})");
                    return null;
                } //TESTED (1_1abc)
            }
        } else { // new attribute!

            String typeName = m.group(1);
            if (null == typeName) { // it's an if statement or a string value
                typeName = m.group(4);
                if (null != typeName) {
                    simpleField = true;
                }
            } else if (typeName.equalsIgnoreCase("else")) { // It's an if statement..
                typeName = null;
            }
            if (null == typeName) { // if statement after all
                // Just keep track of ifs so we can ignore them
                ifStack.push(depth);
                ifdepth = depth;
                // (don't increment depth)
            } //TESTED (1_1bc, 2_1)
            else { // processing block
                String subTypeName = m.group(3);
                if (null != subTypeName) { // eg codec.multiline
                    typeName = typeName + "." + subTypeName;
                } //TESTED (2_1, 2_3)

                if (depth == 0) { // has to be one of input/output/filter)
                    String topLevelType = typeName.toLowerCase();
                    if (topLevelType.equalsIgnoreCase("input") || topLevelType.equalsIgnoreCase("filter")) {
                        if (tree.containsField(topLevelType)) {
                            error.append("Multiple input or filter blocks: " + topLevelType);
                            return null;
                        } //TESTED (1_3ab)
                        else {
                            inputOrFilter = new BasicDBObject();
                            tree.put(topLevelType, inputOrFilter);

                            // Store state:
                            currTopLevelBlockName = topLevelType;
                        } //TESTED (*)
                    } else {
                        if (topLevelType.equalsIgnoreCase("output")) {
                            error.append(
                                    "Not allowed output blocks - these are appended automatically by the logstash harvester");
                        } else {
                            error.append("Unrecognized processing block: " + topLevelType);
                        }
                        return null;
                    } //TESTED (1_4a)
                } else if (depth == 1) { // processing blocks
                    String subElType = typeName.toLowerCase();

                    // Some validation: can't include a type called "filter" anywhere
                    if ((null != currTopLevelBlockName) && currTopLevelBlockName.equals("input")) {
                        if (subElType.equals("filter") || subElType.endsWith(".filter")) {
                            error.append("Not allowed sub-elements of input called 'filter' (1)");
                            return null;
                        }
                    } //TESTED (1_5b)

                    BasicDBList subElements = (BasicDBList) inputOrFilter.get(subElType);
                    if (null == subElements) {
                        subElements = new BasicDBList();
                        inputOrFilter.put(subElType, subElements);
                    }
                    BasicDBObject newEl = new BasicDBObject();
                    subElements.add(newEl);

                    // Store state:
                    currSecondLevelBlockName = subElType;
                    currSecondLevelBlock = newEl;
                } //TESTED (*)
                else if (depth == 2) { // attributes of processing blocks
                    // we'll just store the field names for these and do any simple validation that was too complicated for the regexes
                    String subSubElType = typeName.toLowerCase();

                    // Validation:
                    if (null != currTopLevelBlockName) {
                        // 1] sincedb path
                        if (currTopLevelBlockName.equals("input") && (null != currSecondLevelBlockName)) {
                            // (don't care what the second level block name is - no sincedb allowed)
                            if (subSubElType.equalsIgnoreCase("sincedb_path")) {
                                error.append("Not allowed sincedb_path in input.* block");
                                return null;
                            } //TESTED (1_5a)
                              // 2] no sub-(-sub etc)-elements of input called filter
                            if (subSubElType.equals("filter") || subSubElType.endsWith(".filter")) {
                                error.append("Not allowed sub-elements of input called 'filter' (2)");
                                return null;
                            } //TESTED (1_5c)
                        }
                    }

                    // Store in map:
                    if (null != currSecondLevelBlock) {
                        currSecondLevelBlock.put(subSubElType, new BasicDBObject());
                    }
                }
                // (won't go any deeper than this)
                if (!simpleField) {
                    depth++;
                }
            }

        }
    }
    if (0 != depth) {
        error.append("{} Mismatch ({)");
        return null;
    } //TESTED (1_2a)

    return tree;
}