@Test
 public void constructor_map_correctObjectShouldBeCreated() {
   DocumentBody body = new BasicDocumentBody(JSONUtils.deserialize(jsonData));
   Map<String, Object> map = JSONUtils.deserialize(body.asBytes());
   assertMapIsCorrect(map);
 }
  @Override
  public void forceInsert(
      DocumentRevision rev, List<String> revisionHistory, Map<String, Object> attachments) {
    Preconditions.checkState(this.isOpen(), "Database is closed");
    Preconditions.checkNotNull(rev, "Input document revision can not be null");
    Preconditions.checkNotNull(revisionHistory, "Input revision history must not be null");
    Preconditions.checkArgument(
        revisionHistory.size() > 0, "Input revision history must not be empty");
    Preconditions.checkArgument(
        checkCurrentRevisionIsInRevisionHistory(rev, revisionHistory),
        "Current revision must exist in revision history.");
    Preconditions.checkArgument(
        checkRevisionIsInCorrectOrder(revisionHistory), "Revision history must be in right order.");
    CouchUtils.validateDocumentId(rev.getId());
    CouchUtils.validateRevisionId(rev.getRevision());

    Log.v(
        LOG_TAG,
        "forceInsert(): " + rev.toString() + ",\n" + JSONUtils.toPrettyJson(revisionHistory));

    DocumentCreated documentCreated = null;
    DocumentUpdated documentUpdated = null;

    boolean ok = true;

    this.sqlDb.beginTransaction();
    try {
      long seq = 0;
      // sequence here is -1, but we need it to insert the attachment - also might be wanted by
      // subscribers
      if (this.containsDocument(rev.getId())) {
        seq = doForceInsertExistingDocumentWithHistory(rev, revisionHistory);
        rev.initialiseSequence(seq);
        // TODO fetch the parent doc?
        documentUpdated = new DocumentUpdated(null, rev);
      } else {
        seq = doForceInsertNewDocumentWithHistory(rev, revisionHistory);
        rev.initialiseSequence(seq);
        documentCreated = new DocumentCreated(rev);
      }
      // now deal with any attachments
      if (attachments != null) {
        for (String att : attachments.keySet()) {
          String data = (String) ((Map<String, Object>) attachments.get(att)).get("data");
          InputStream is = new Base64InputStream(new ByteArrayInputStream(data.getBytes()));
          String type = (String) ((Map<String, Object>) attachments.get(att)).get("content_type");
          // inline attachments are automatically decompressed, so we don't have to worry about that
          UnsavedStreamAttachment ufa = new UnsavedStreamAttachment(is, att, type);
          boolean result = false;
          try {
            PreparedAttachment preparedAttachment =
                new PreparedAttachment(ufa, this.attachmentManager.attachmentsDir);
            result = this.attachmentManager.addAttachment(preparedAttachment, rev);
          } catch (IOException e) {
            Log.e(LOG_TAG, "IOException when preparing attachment " + ufa + ": " + e);
          }
          if (!result) {
            Log.e(
                LOG_TAG,
                "There was a problem adding the attachment "
                    + ufa
                    + " to the datastore; not force inserting this document: "
                    + rev);
            ok = false;
            break;
          }
        }
      }
      if (ok) {
        this.sqlDb.setTransactionSuccessful();
      }
    } finally {
      this.sqlDb.endTransaction();
      if (ok) {
        if (documentCreated != null) {
          eventBus.post(documentCreated);
        } else if (documentUpdated != null) {
          eventBus.post(documentUpdated);
        }
      }
    }
  }