/** Build the Map record from the Mongo DBObject. */
 public MongoRecord buildRecordFromDBObject(DBObject object) {
   MongoRecord record = new MongoRecord();
   for (Iterator iterator = object.toMap().entrySet().iterator(); iterator.hasNext(); ) {
     Map.Entry entry = (Map.Entry) iterator.next();
     if (entry.getValue() instanceof BasicDBList) {
       List values = new ArrayList();
       for (Iterator valuesIterator = ((BasicDBList) entry.getValue()).iterator();
           valuesIterator.hasNext(); ) {
         Object value = valuesIterator.next();
         if (value instanceof DBObject) {
           values.add(buildRecordFromDBObject((DBObject) value));
         } else {
           values.add(value);
         }
       }
       record.put((String) entry.getKey(), values);
     } else if (entry.getValue() instanceof DBObject) {
       MongoRecord nestedRecord = buildRecordFromDBObject((DBObject) entry.getValue());
       record.put((String) entry.getKey(), nestedRecord);
     } else {
       record.put((String) entry.getKey(), entry.getValue());
     }
   }
   return record;
 }
 /** Build the Mongo DBObject from the Map record. */
 public DBObject buildDBObject(MongoRecord record) {
   DBObject object = new BasicDBObject();
   for (Iterator iterator = record.entrySet().iterator(); iterator.hasNext(); ) {
     Map.Entry entry = (Map.Entry) iterator.next();
     if (entry.getValue() instanceof MongoRecord) {
       object.put((String) entry.getKey(), buildDBObject((MongoRecord) entry.getValue()));
     } else {
       object.put((String) entry.getKey(), entry.getValue());
     }
   }
   return object;
 }
  /**
   * Execute the interaction and return output record. The spec is either GET, PUT or DELETE
   * interaction.
   */
  public Record execute(InteractionSpec spec, Record record) throws ResourceException {
    if (!(spec instanceof MongoInteractionSpec)) {
      throw EISException.invalidInteractionSpecType();
    }
    if (!(record instanceof MongoRecord)) {
      throw EISException.invalidRecordType();
    }
    MongoInteractionSpec mongoSpec = (MongoInteractionSpec) spec;
    MongoRecord input = (MongoRecord) record;
    MongoOperation operation = mongoSpec.getOperation();
    String collectionName = mongoSpec.getCollection();
    if (operation == null) {
      ResourceException resourceException = new ResourceException("Mongo operation must be set");
      throw resourceException;
    }
    if (operation == MongoOperation.EVAL) {
      Object result = this.connection.getDB().eval(mongoSpec.getCode());
      return buildRecordFromDBObject((DBObject) result);
    }
    if (collectionName == null) {
      ResourceException resourceException = new ResourceException("DB Collection name must be set");
      throw resourceException;
    }
    try {
      DBCollection collection = this.connection.getDB().getCollection(collectionName);
      if (mongoSpec.getOptions() > 0) {
        collection.setOptions(mongoSpec.getOptions());
      }
      if (mongoSpec.getReadPreference() != null) {
        collection.setReadPreference(mongoSpec.getReadPreference());
      }
      if (mongoSpec.getWriteConcern() != null) {
        collection.setWriteConcern(mongoSpec.getWriteConcern());
      }
      if (operation == MongoOperation.INSERT) {
        DBObject object = buildDBObject(input);
        collection.insert(object);
      } else if (operation == MongoOperation.REMOVE) {
        DBObject object = buildDBObject(input);
        collection.remove(object);
      } else if (operation == MongoOperation.FIND) {
        DBObject sort = null;
        if (input.containsKey(MongoRecord.SORT)) {
          sort = buildDBObject((MongoRecord) input.get(MongoRecord.SORT));
          input.remove(MongoRecord.SORT);
        }
        DBObject select = null;
        if (input.containsKey("$select")) {
          select = buildDBObject((MongoRecord) input.get("$select"));
          input.remove("$select");
        }
        DBObject object = buildDBObject(input);
        DBCursor cursor = collection.find(object, select);
        if (sort != null) {
          cursor.sort(sort);
        }
        try {
          if (mongoSpec.getSkip() > 0) {
            cursor.skip(mongoSpec.getSkip());
          }
          if (mongoSpec.getLimit() != 0) {
            cursor.limit(mongoSpec.getLimit());
          }
          if (mongoSpec.getBatchSize() != 0) {
            cursor.batchSize(mongoSpec.getBatchSize());
          }
          if (!cursor.hasNext()) {
            return null;
          }
          MongoListRecord results = new MongoListRecord();
          while (cursor.hasNext()) {
            DBObject result = cursor.next();
            results.add(buildRecordFromDBObject(result));
          }
          return results;
        } finally {
          cursor.close();
        }

      } else {
        throw new ResourceException("Invalid operation: " + operation);
      }
    } catch (Exception exception) {
      ResourceException resourceException = new ResourceException(exception.toString());
      resourceException.initCause(exception);
      throw resourceException;
    }
    return null;
  }