Projects >> Ektorp >>ecc17e03e4b4879293d2d8ef55ff5d29e7c11735

Chunk
Conflicting content
     * 
    *
  • If the value is a document id, then the document is fetched from couchDB.
  • *
  • If the value is a document, then it is used directly for unmarshalling.
  • <<<<<<< HEAD *
* * {"_id":"_design/ExampleDoc", * "views":{ * "all": {"map": "function(doc) { emit(null, doc._id);}"}, * "by_name": {"map": "function(doc) { emit(doc.name, doc._id);}"} // emit doc id * "by_author": {"map": "function(doc) { emit(doc.author, doc);}"} // emit doc * } * } * * @param * @param query * @param type the type to map the result to * @return the view result mapped as the specified class. */ List queryView(ViewQuery query, Class type); /** * Provides paged view results. Implementation based on the recipe described in the book "CouchDB The Definitive Guide" * http://guide.couchdb.org/editions/1/en/recipes.html#pagination * * This method has the same requirements for the view as the method queryView(ViewQuery query, Class type). * @param query * @param pr * @param type * @return */ Page queryForPage(ViewQuery query, PageRequest pr, Class type); /** * * @param query * @return */ ViewResult queryView(ViewQuery query); /** * Please note that the StreamingViewResult need to be closed after usage. * @param query * @return the view result as a iterable stream. */ StreamingViewResult queryForStreamingView(ViewQuery query); /** * * @param query * @return the view result as a raw InputStream. */ InputStream queryForStream(ViewQuery query); /** * Creates a database on the configured path if it does not exists. */ void createDatabaseIfNotExists(); /** * @return name */ String getDatabaseName(); /** * * @return */ String path(); /** * Convenience method for accessing the underlying HttpClient. * Preferably used wrapped in a org.ektorp.http.RestTemplate. * @return */ HttpClient getConnection(); /** * Provides meta information about this database. * @return */ DbInfo getDbInfo(); /** * Obtains information about a given design document, including the index, * index size and current status of the design document and associated index information. * * @param designDocId * @return */ DesignDocInfo getDesignDocInfo(String designDocId); /** * Compaction compresses the database file by removing unused sections created during updates. * This call is non-blocking, a compaction background task will be created on the CouchDB instance. */ void compact(); /** * This compacts the view index from the current version of the design document. * This call is non-blocking, a compaction background task will be created on the CouchDB instance. * @param designDocumentId */ void compactViews(String designDocumentId); /** * View indexes on disk are named after their MD5 hash of the view definition. * When you change a view, old indexes remain on disk. * To clean up all outdated view indexes (files named after the MD5 representation of views, that does not exist anymore) you can trigger a view cleanup */ void cleanupViews(); /** * Revision limit defines a upper bound of document revisions which CouchDB keeps track of * @return */ int getRevisionLimit(); void setRevisionLimit(int limit); /** * Replicate the content in the source database into this database. * @param source database * @return ReplicationStatus */ ReplicationStatus replicateFrom(String source); /** * Replicate the content in the source database into this database. * Replication is restricted to the specified document ids. * @param source database * @param docIds * @return ReplicationStatus */ ReplicationStatus replicateFrom(String source, Collection docIds); /** * Replicate the content in this database into the specified target database. * The target must exist. * @param target database * @return ReplicationStatus */ ReplicationStatus replicateTo(String target); /** * Replicate the content in this database into the specified target database. * Replication is restricted to the specified document ids. * The target must exist. * @param target database * @param docIds * @return ReplicationStatus */ ReplicationStatus replicateTo(String target, Collection docIds); /** * Add the object to the bulk buffer attached to the executing thread. * A subsequent call to either flushBulkBuffer or clearBulkBuffer is expected. * @param o */ void addToBulkBuffer(Object o); /** * Sends the bulk buffer attached the the executing thread to the database (through a executeBulk call). * The bulk buffer will be cleared when this method is finished. */ List flushBulkBuffer(); /** * Clears the bulk buffer attached the the executing thread. */ void clearBulkBuffer(); /** * Creates, updates or deletes all objects in the supplied collection. * * If the json has no revision set, it will be created, otherwise it will be updated. * If the json document contains a "_deleted"=true field it will be deleted. * * * Some documents may successfully be saved and some may not. * The response will tell the application which documents were saved or not. In the case of a power failure, when the database restarts some may have been saved and some not. * @param an json array with documents ex [{"_id":"1", "name": "hello world" }, "_id":"2", "name": "hello world 2"}] * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. i.e. the list will be empty if everything was completed successfully. */ List executeBulk(InputStream inputStream); /** * Creates, updates or deletes all objects in the supplied collection. * In the case of a power failure, when the database restarts either all the changes will have been saved or none of them. * However, it does not do conflict checking, so the documents will be committed even if this creates conflicts. * @param an json array with documents * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. i.e. the list will be empty if everything was completed successfully. */ List executeAllOrNothing(InputStream inputStream); /** * Creates, updates or deletes all objects in the supplied collection. * * If the object has no revision set, it will be created, otherwise it will be updated. * If the object's serialized json document contains a "_deleted"=true field it will be deleted. * * org.ektorp.BulkDeleteDocument.of(someObject) is the easiest way to create a delete doc for an instance. * * Some documents may successfully be saved and some may not. * The response will tell the application which documents were saved or not. In the case of a power failure, when the database restarts some may have been saved and some not. * @param objects, all objects will have their id and revision set. * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. i.e. the list will be empty if everything was completed successfully. */ List executeBulk(Collection objects); /** * Creates, updates or deletes all objects in the supplied collection. * In the case of a power failure, when the database restarts either all the changes will have been saved or none of them. * However, it does not do conflict checking, so the documents will be committed even if this creates conflicts. * @param objects, all objects will have their id and revision set. * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. i.e. the list will be empty if everything was completed successfully. */ List executeAllOrNothing(Collection objects); /** * Queries the database for changes. * This is a one-off operation. To listen to changes continuously @see changesFeed(ChangesCommand cmd). * @param cmd * @return */ List changes(ChangesCommand cmd); /** * Sets up a continuous changes feed. * The current update sequence in the DB will be used if ChangesCommand does not specify the since parameter. * A heartbeat interval of 10 seconds will be used if ChangesCommand does not specify the heartbeat parameter. * * @param cmd * @return a running changes feed that buffers incoming changes in a unbounded queue (will grow until OutOfMemoryException if not polled). */ ChangesFeed changesFeed(ChangesCommand cmd); /** * * @param designDoc * @param function * @param docId * @return */ String callUpdateHandler(String designDocID, String function, String docId); /** * * @param designDoc * @param function * @param docId * @param params * @return */ String callUpdateHandler(String designDocID, String function, String docId, Map params); /** * Commits any recent changes to the specified database to disk. */ void ensureFullCommit(); ======= * * * {"_id":"_design/ExampleDoc", "views":{ "all": {"map": "function(doc) { emit(null, doc._id);}"}, "by_name": * {"map": "function(doc) { emit(doc.name, doc._id);}"} // emit doc id "by_author": {"map": * "function(doc) { emit(doc.author, doc);}"} // emit doc } } * * @param * @param query * @param type * the type to map the result to * @return the view result mapped as the specified class. */ List queryView(ViewQuery query, Class type); /** * @return ReplicationStatus */ * Provides paged view results. Implementation based on the recipe described in the book * "CouchDB The Definitive Guide" http://guide.couchdb.org/editions/1/en/recipes.html#pagination * * This method has the same requirements for the view as the method queryView(ViewQuery query, Class type). * * @param query * @param pr * @param type * @return */ Page queryForPage(ViewQuery query, PageRequest pr, Class type); /** * * @param query * @return */ ViewResult queryView(ViewQuery query); /** * Please note that the StreamingViewResult need to be closed after usage. * * @param query * @return the view result as a iterable stream. */ StreamingViewResult queryForStreamingView(ViewQuery query); /** * * @param query * @return the view result as a raw InputStream. */ InputStream queryForStream(ViewQuery query); /** * Creates a database on the configured path if it does not exists. */ void createDatabaseIfNotExists(); /** * @return name */ String getDatabaseName(); /** * * @return */ String path(); /** * Convenience method for accessing the underlying HttpClient. Preferably used wrapped in a * org.ektorp.http.RestTemplate. * * @return */ HttpClient getConnection(); /** * Provides meta information about this database. * * @return */ DbInfo getDbInfo(); /** * Obtains information about a given design document, including the index, index size and current status of the * design document and associated index information. * * @param designDocId * @return */ DesignDocInfo getDesignDocInfo(String designDocId); /** * Compaction compresses the database file by removing unused sections created during updates. This call is * non-blocking, a compaction background task will be created on the CouchDB instance. */ void compact(); /** * This compacts the view index from the current version of the design document. This call is non-blocking, a * compaction background task will be created on the CouchDB instance. * * @param designDocumentId */ void compactViews(String designDocumentId); /** * View indexes on disk are named after their MD5 hash of the view definition. When you change a view, old indexes * remain on disk. To clean up all outdated view indexes (files named after the MD5 representation of views, that * does not exist anymore) you can trigger a view cleanup */ void cleanupViews(); /** * Revision limit defines a upper bound of document revisions which CouchDB keeps track of * * @return */ int getRevisionLimit(); void setRevisionLimit(int limit); /** * Replicate the content in the source database into this database. * * @param source * database ReplicationStatus replicateFrom(String source); /** * Replicate the content in the source database into this database. Replication is restricted to the specified * document ids. * * @param source * database * @param docIds * @return ReplicationStatus */ ReplicationStatus replicateFrom(String source, Collection docIds); /** * Replicate the content in this database into the specified target database. The target must exist. * * @param target * database * @return ReplicationStatus */ ReplicationStatus replicateTo(String target); /** * Replicate the content in this database into the specified target database. Replication is restricted to the * specified document ids. The target must exist. * * @param target * database * @param docIds * @return ReplicationStatus */ ReplicationStatus replicateTo(String target, Collection docIds); /** * Add the object to the bulk buffer attached to the executing thread. A subsequent call to either flushBulkBuffer * or clearBulkBuffer is expected. * * @param o */ void addToBulkBuffer(Object o); /** * Sends the bulk buffer attached the the executing thread to the database (through a executeBulk call). The bulk * buffer will be cleared when this method is finished. */ List flushBulkBuffer(); /** * Clears the bulk buffer attached the the executing thread. */ void clearBulkBuffer(); /** * Creates, updates or deletes all objects in the supplied collection. * * If the object has no revision set, it will be created, otherwise it will be updated. If the object's serialized * json document contains a "_deleted"=true field it will be deleted. * * org.ektorp.BulkDeleteDocument.of(someObject) is the easiest way to create a delete doc for an instance. * * Some documents may successfully be saved and some may not. The response will tell the application which documents * were saved or not. In the case of a power failure, when the database restarts some may have been saved and some * not. * * @param objects * , all objects will have their id and revision set. * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. * i.e. the list will be empty if everything was completed successfully. */ List executeBulk(Collection objects); /** * Creates, updates or deletes all objects in the supplied collection. In the case of a power failure, when the * database restarts either all the changes will have been saved or none of them. However, it does not do conflict * checking, so the documents will be committed even if this creates conflicts. * * @param objects * , all objects will have their id and revision set. * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. * i.e. the list will be empty if everything was completed successfully. */ List executeAllOrNothing(Collection objects); /** * Queries the database for changes. This is a one-off operation. To listen to changes continuously @see * changesFeed(ChangesCommand cmd). * * @param cmd * @return */ List changes(ChangesCommand cmd); /** * Sets up a continuous changes feed. The current update sequence in the DB will be used if ChangesCommand does not * specify the since parameter. A heartbeat interval of 10 seconds will be used if ChangesCommand does not specify * the heartbeat parameter. * * @param cmd * @return a running changes feed that buffers incoming changes in a unbounded queue (will grow until * OutOfMemoryException if not polled). */ ChangesFeed changesFeed(ChangesCommand cmd); /** * * @param designDoc * @param function * @param docId * @return */ String callUpdateHandler(String designDocID, String function, String docId); /** * * @param designDoc * @param function * @param docId * @param params * @return */ String callUpdateHandler(String designDocID, String function, String docId, Map params); T callUpdateHandler(final UpdateHandlerRequest req, final Class c); String callUpdateHandler(final UpdateHandlerRequest req); /** * Commits any recent changes to the specified database to disk. */ void ensureFullCommit(); >>>>>>> 262208f7a653371ac353b3f23d48511f4439cf56 }
Solution content
     * 
    *
  • If the value is a document id, then the document is fetched from couchDB.
  • *
  • If the value is a document, then it is used directly for unmarshalling.
  • *
* * {"_id":"_design/ExampleDoc", "views":{ "all": {"map": "function(doc) { emit(null, doc._id);}"}, "by_name": * {"map": "function(doc) { emit(doc.name, doc._id);}"} // emit doc id "by_author": {"map": * "function(doc) { emit(doc.author, doc);}"} // emit doc } } * * @param * @param query * @param type * the type to map the result to * @return the view result mapped as the specified class. */ List queryView(ViewQuery query, Class type); /** * Provides paged view results. Implementation based on the recipe described in the book * "CouchDB The Definitive Guide" http://guide.couchdb.org/editions/1/en/recipes.html#pagination * * This method has the same requirements for the view as the method queryView(ViewQuery query, Class type). * * @param query * @param pr * @param type * @return */ Page queryForPage(ViewQuery query, PageRequest pr, Class type); /** * * @param query * @return */ ViewResult queryView(ViewQuery query); /** * Please note that the StreamingViewResult need to be closed after usage. * * @param query * @return the view result as a iterable stream. */ StreamingViewResult queryForStreamingView(ViewQuery query); /** * * @param query * @return the view result as a raw InputStream. */ InputStream queryForStream(ViewQuery query); /** * Creates a database on the configured path if it does not exists. */ void createDatabaseIfNotExists(); /** * @return name */ String getDatabaseName(); /** * * @return */ String path(); /** * Convenience method for accessing the underlying HttpClient. Preferably used wrapped in a * org.ektorp.http.RestTemplate. * * @return */ HttpClient getConnection(); /** * Provides meta information about this database. * * @return */ DbInfo getDbInfo(); /** * Obtains information about a given design document, including the index, index size and current status of the * design document and associated index information. * * @param designDocId * @return */ DesignDocInfo getDesignDocInfo(String designDocId); /** * Compaction compresses the database file by removing unused sections created during updates. This call is * non-blocking, a compaction background task will be created on the CouchDB instance. */ void compact(); /** * This compacts the view index from the current version of the design document. This call is non-blocking, a * compaction background task will be created on the CouchDB instance. * * @param designDocumentId */ void compactViews(String designDocumentId); /** * View indexes on disk are named after their MD5 hash of the view definition. When you change a view, old indexes * remain on disk. To clean up all outdated view indexes (files named after the MD5 representation of views, that * does not exist anymore) you can trigger a view cleanup */ void cleanupViews(); /** * Revision limit defines a upper bound of document revisions which CouchDB keeps track of * * @return */ int getRevisionLimit(); void setRevisionLimit(int limit); /** * Replicate the content in the source database into this database. * * @param source * database * @return ReplicationStatus */ ReplicationStatus replicateFrom(String source); /** * Replicate the content in the source database into this database. Replication is restricted to the specified * document ids. * * @param source * database * @param docIds * @return ReplicationStatus */ ReplicationStatus replicateFrom(String source, Collection docIds); /** * Replicate the content in this database into the specified target database. The target must exist. * * @param target * database * @return ReplicationStatus */ ReplicationStatus replicateTo(String target); /** * Replicate the content in this database into the specified target database. Replication is restricted to the * specified document ids. The target must exist. * * @param target * database * @param docIds * @return ReplicationStatus */ ReplicationStatus replicateTo(String target, Collection docIds); /** * Add the object to the bulk buffer attached to the executing thread. A subsequent call to either flushBulkBuffer * or clearBulkBuffer is expected. * * @param o */ void addToBulkBuffer(Object o); /** * Sends the bulk buffer attached the the executing thread to the database (through a executeBulk call). The bulk * buffer will be cleared when this method is finished. */ List flushBulkBuffer(); /** * Clears the bulk buffer attached the the executing thread. */ void clearBulkBuffer(); /** * Creates, updates or deletes all objects in the supplied collection. * * If the json has no revision set, it will be created, otherwise it will be updated. * If the json document contains a "_deleted"=true field it will be deleted. * * Some documents may successfully be saved and some may not. * The response will tell the application which documents were saved or not. In the case of a power failure, when the database restarts some may have been saved and some not. * * @param an json array with documents ex [{"_id":"1", "name": "hello world" }, "_id":"2", "name": "hello world 2"}] * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. i.e. the list will be empty if everything was completed successfully. */ List executeBulk(InputStream inputStream); /** * Creates, updates or deletes all objects in the supplied collection. * In the case of a power failure, when the database restarts either all the changes will have been saved or none of them. * However, it does not do conflict checking, so the documents will be committed even if this creates conflicts. * * @param an json array with documents * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. i.e. the list will be empty if everything was completed successfully. */ List executeAllOrNothing(InputStream inputStream); /** * Creates, updates or deletes all objects in the supplied collection. * * If the object has no revision set, it will be created, otherwise it will be updated. If the object's serialized * json document contains a "_deleted"=true field it will be deleted. * * org.ektorp.BulkDeleteDocument.of(someObject) is the easiest way to create a delete doc for an instance. * * Some documents may successfully be saved and some may not. The response will tell the application which documents * were saved or not. In the case of a power failure, when the database restarts some may have been saved and some * not. * * @param objects * , all objects will have their id and revision set. * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. * i.e. the list will be empty if everything was completed successfully. */ List executeBulk(Collection objects); /** * Creates, updates or deletes all objects in the supplied collection. In the case of a power failure, when the * database restarts either all the changes will have been saved or none of them. However, it does not do conflict * checking, so the documents will be committed even if this creates conflicts. * * @param objects * , all objects will have their id and revision set. * @return The list will only contain entries for documents that has any kind of error code returned from CouchDB. * i.e. the list will be empty if everything was completed successfully. */ List executeAllOrNothing(Collection objects); /** * Queries the database for changes. This is a one-off operation. To listen to changes continuously @see * changesFeed(ChangesCommand cmd). * * @param cmd * @return */ List changes(ChangesCommand cmd); /** * Sets up a continuous changes feed. The current update sequence in the DB will be used if ChangesCommand does not * specify the since parameter. A heartbeat interval of 10 seconds will be used if ChangesCommand does not specify * the heartbeat parameter. * * @param cmd * @return a running changes feed that buffers incoming changes in a unbounded queue (will grow until * OutOfMemoryException if not polled). */ ChangesFeed changesFeed(ChangesCommand cmd); /** * * @param designDoc * @param function * @param docId * @return */ String callUpdateHandler(String designDocID, String function, String docId); /** * * @param designDoc * @param function * @param docId * @param params * @return */ String callUpdateHandler(String designDocID, String function, String docId, Map params); T callUpdateHandler(final UpdateHandlerRequest req, final Class c); String callUpdateHandler(final UpdateHandlerRequest req); /** * Commits any recent changes to the specified database to disk. */ void ensureFullCommit();
File
CouchDbConnector.java
Developer's decision
Combination
Kind of conflict
Comment
Method interface
Chunk
Conflicting content
					}
				});
	}
 */
public class StdCouchDbConnector implements CouchDbConnector {

<<<<<<< HEAD
	private static final int DEFAULT_HEARTBEAT_INTERVAL = 9000;
	private static final Logger LOG = LoggerFactory
			.getLogger(StdCouchDbConnector.class);
	private static final ResponseCallback VOID_RESPONSE_HANDLER = new StdResponseHandler();
	private final ObjectMapper objectMapper;
	private JsonSerializer jsonSerializer;

	private final URI dbURI;
	private final String dbName;

	private final RestTemplate restTemplate;

	private final CouchDbInstance dbInstance;

	private final RevisionResponseHandler revisionHandler;
	private final DocIdResponseHandler docIdResponseHandler;
	
	private final ThreadLocalBulkBufferHolder bulkBufferManager = new ThreadLocalBulkBufferHolder();

	private final static Options EMPTY_OPTIONS = new Options();
	
	public StdCouchDbConnector(String databaseName, CouchDbInstance dbInstance) {
		this(databaseName, dbInstance, new StdObjectMapperFactory());
	}

	public StdCouchDbConnector(String databaseName, CouchDbInstance dbi,
			ObjectMapperFactory om) {
		Assert.hasText(databaseName, "DatabaseName may not be null or empty");
		Assert.notNull(dbi, "CouchDbInstance may not be null");
		Assert.notNull(om, "ObjectMapperFactory may not be null");

		DbPath dbp = DbPath.fromString(databaseName);
		dbName = dbp.getDbName();
		this.dbURI = URI.prototype(dbp.getPath());
		this.dbInstance = dbi;
		this.objectMapper = om.createObjectMapper(this);

		this.jsonSerializer = new StreamingJsonSerializer(objectMapper);
		this.restTemplate = new RestTemplate(dbi.getConnection());
		this.revisionHandler = new RevisionResponseHandler(objectMapper);
		this.docIdResponseHandler = new DocIdResponseHandler(objectMapper);
	}

	public String path() {
		return dbURI.toString();

	public void create(final Object o) {
		Assert.notNull(o, "Document may not be null");
		Assert.isTrue(Documents.isNew(o), "Object must be new");

		String json = jsonSerializer.toJson(o);
		String id = Documents.getId(o);
		DocumentOperationResult result;
		if (id != null) {
			result = restTemplate.put(URIWithDocId(id), json, revisionHandler);
		} else {
								DbInfo.class);
		try {
			result = restTemplate.post(dbURI.toString(), json, revisionHandler);
			Documents.setId(o, result.getId());
		}
		Documents.setRevision(o, result.getRevision());
	}

	public void create(String id, Object node) {
		assertDocIdHasValue(id);
		Assert.notNull(node, "node may not be null");
		restTemplate.put(URIWithDocId(id), jsonSerializer.toJson(node));
	}

	private String URIWithDocId(String id) {
		return dbURI.append(id).toString();
	}

	public boolean contains(String id) {
		return restTemplate.head(URIWithDocId(id),
				new ResponseCallback() {

					public Boolean error(HttpResponse hr) {
						if (hr.getCode() == HttpStatus.NOT_FOUND) {
							return Boolean.FALSE;
						}
						throw new DbAccessException(hr.toString());
					}

					public Boolean success(HttpResponse hr) throws Exception {
						return Boolean.TRUE;
					}

				});
	}

	public String createAttachment(String docId, AttachmentInputStream data) {
		return createAttachment(docId, null, data);
	}

	public String createAttachment(String docId, String revision,
			AttachmentInputStream data) {
		assertDocIdHasValue(docId);
		URI uri = dbURI.append(docId).append(data.getId());
		if (revision != null) {
			uri.param("rev", revision);
		}
		return restTemplate.put(uri.toString(), data, data.getContentType(),
				data.getContentLength(), revisionHandler).getRevision();
	}

	public AttachmentInputStream getAttachment(final String id,
			final String attachmentId) {
		assertDocIdHasValue(id);
		Assert.hasText(attachmentId, "attachmentId must have a value");
		if (LOG.isTraceEnabled()) {
			LOG.trace("fetching attachment for doc: {} attachmentId: {}", id,
					attachmentId);
		}
		HttpResponse r = restTemplate.get(dbURI.append(id).append(attachmentId)
				.toString());
		return new AttachmentInputStream(attachmentId, r.getContent(),
				r.getContentType(), r.getContentLength());
	}

	public String delete(Object o) {
		Assert.notNull(o, "document may not be null");
		return delete(Documents.getId(o), Documents.getRevision(o));
	}

	@Override
	public PurgeResult purge(Map> revisionsToPurge) {
		return restTemplate.post(dbURI.append("_purge").toString(), jsonSerializer.toJson(revisionsToPurge), new StdResponseHandler() {
			@Override
			public PurgeResult success(HttpResponse hr) throws Exception {
				return objectMapper.readValue(hr.getContent(), PurgeResult.class);
			}
		});
	}
	
	public  T get(final Class c, String id) {
		return get(c, id, EMPTY_OPTIONS);
	}
	
	@Override
	public  T get(final Class c, String id, Options options) {
		Assert.notNull(c, "Class may not be null");
		assertDocIdHasValue(id);
		URI uri = dbURI.append(id);
		applyOptions(options, uri);
		return restTemplate.get(uri.toString(),
				new StdResponseHandler() {
					public T success(HttpResponse hr) throws Exception {
						return objectMapper.readValue(hr.getContent(), c);
					}
				});
	}
	
	public  T get(final Class c, String id, String rev) {
		Assert.notNull(c, "Class may not be null");
		assertDocIdHasValue(id);
		Assert.hasText(rev, "Revision may not be null or empty");
		return get(c, id, new Options().revision(rev));
	}
	
	public  T getWithConflicts(final Class c, String id) {
		Assert.notNull(c, "Class may not be null");
		assertDocIdHasValue(id);
		return get(c, id, new Options().includeConflicts());
	}

	@Override
	public  T find(Class c, String id) {
		return find(c, id, EMPTY_OPTIONS);
	}
	
	@Override
	public  T find(final Class c, String id, Options options) {
		Assert.notNull(c, "Class may not be null");
		assertDocIdHasValue(id);
		URI uri = dbURI.append(id);
		applyOptions(options, uri);
		return restTemplate.get(uri.toString(),
				new StdResponseHandler() {
					public T success(HttpResponse hr) throws Exception {
						return objectMapper.readValue(hr.getContent(), c);
					}
			
					public T error(HttpResponse hr) {
						return hr.getCode() == HttpStatus.NOT_FOUND ? null : super.error(hr);
					}
				});
	}

	private void applyOptions(Options options, URI uri) {
		if (options != null && !options.isEmpty()) {
			uri.params(options.getOptions());
		}
	}
	
	public List getRevisions(String id) {
		assertDocIdHasValue(id);
		return restTemplate.get(dbURI.append(id).param("revs_info", "true")
				.toString(), new StdResponseHandler>() {

			public List success(HttpResponse hr) throws Exception {
				JsonNode root = objectMapper.readValue(hr.getContent(),
						JsonNode.class);
				List revs = new ArrayList();
				for (Iterator i = root.get("_revs_info")
						.getElements(); i.hasNext();) {
					JsonNode rev = i.next();
					revs.add(new Revision(rev.get("rev").getTextValue(), rev
							.get("status").getTextValue()));
				}
				return revs;
			}

			public List error(HttpResponse hr) {
				if (hr.getCode() == HttpStatus.NOT_FOUND) {
					return Collections.emptyList();
				}
				return super.error(hr);
			}
		});
	}

	public InputStream getAsStream(String id) {
		assertDocIdHasValue(id);
		return getAsStream(id, EMPTY_OPTIONS);
	}
	
	@Override
	public InputStream getAsStream(String id, Options options) {
		URI uri = dbURI.append(id);
		applyOptions(options, uri);
		HttpResponse r = restTemplate.get(uri.toString());
		return r.getContent();
	}

	public InputStream getAsStream(String id, String rev) {
		assertDocIdHasValue(id);
		Assert.hasText(rev, "Revision may not be null or empty");
		return getAsStream(id, new Options().revision(rev));
	}

	public void update(final Object o) {
		Assert.notNull(o, "Document cannot be null");
		final String id = Documents.getId(o);
		assertDocIdHasValue(id);
		restTemplate.put(dbURI.append(id).toString(), jsonSerializer.toJson(o),
				new StdResponseHandler() {

					public Void success(HttpResponse hr) throws Exception {
						JsonNode n = objectMapper.readValue(hr.getContent(),
								JsonNode.class);
						Documents.setRevision(o, n.get("rev").getTextValue());
						return null;
					}

					public Void error(HttpResponse hr) {
						if (hr.getCode() == HttpStatus.CONFLICT) {
							throw new UpdateConflictException(id, Documents
									.getRevision(o));
						}
						return super.error(hr);
					}
				});
	}

	public String delete(String id, String revision) {
		assertDocIdHasValue(id);
		return restTemplate.delete(
				dbURI.append(id).param("rev", revision).toString(),
				revisionHandler).getRevision();
	}

	public List getAllDocIds() {
		return restTemplate.get(dbURI.append("_all_docs").toString(),
				docIdResponseHandler);
	}

	public void createDatabaseIfNotExists() {
		if (!dbInstance.checkIfDbExists(new DbPath(dbName))) {
			dbInstance.createDatabase(dbName);
		}
	}

	public String getDatabaseName() {
		return dbName;
	}

	public  List queryView(final ViewQuery query, final Class type) {
		Assert.notNull(query, "query may not be null");
		query.dbPath(dbURI.toString());

		EmbeddedDocViewResponseHandler rh = new EmbeddedDocViewResponseHandler(
				type, objectMapper, query.isIgnoreNotFound());

		return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
				query.getKeysAsJson(), rh) : restTemplate.get(
				query.buildQuery(), rh);
	}
	
	public  Page queryForPage(ViewQuery query, PageRequest pr, Class type) {
		Assert.notNull(query, "query may not be null");
		Assert.notNull(pr, "PageRequest may not be null");
		Assert.notNull(type, "type may not be null");
		
		query.dbPath(dbURI.toString());
		if (LOG.isDebugEnabled()) {
			LOG.debug("startKey: {}", pr.getStartKey());
			LOG.debug("startDocId: {}", pr.getStartKeyDocId());
		}
		PageResponseHandler ph = new PageResponseHandler(pr, type, objectMapper, query.isIgnoreNotFound());
		query = PageRequest.applyPagingParameters(query, pr);
		return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
				query.getKeysAsJson(), ph) : restTemplate.get(
				query.buildQuery(), ph);
	}

	public ViewResult queryView(ViewQuery query) {
		Assert.notNull(query, "query cannot be null");
		query.dbPath(dbURI.toString());
		ResponseCallback rh = new StdResponseHandler() {

			public ViewResult success(HttpResponse hr) throws Exception {
				return new ViewResult(objectMapper.readTree(hr.getContent()));
			}

		};
		return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
				query.getKeysAsJson(), rh) : restTemplate.get(
				query.buildQuery(), rh);
	}

	public StreamingViewResult queryForStreamingView(ViewQuery query) {
		return new StreamingViewResult(objectMapper,queryForStream(query));
	}
	
	public InputStream queryForStream(ViewQuery query) {
		Assert.notNull(query, "query cannot be null");
		query.dbPath(dbURI.toString());
		return query.hasMultipleKeys() ? restTemplate.postUncached(query.buildQuery(),
				query.getKeysAsJson()).getContent() : restTemplate.getUncached(
				query.buildQuery()).getContent();
	}

	public String deleteAttachment(String docId, String revision,
			String attachmentId) {
		return restTemplate.delete(
				dbURI.append(docId).append(attachmentId).param("rev", revision)
						.toString(), revisionHandler).getRevision();
	}

	private void assertDocIdHasValue(String docId) {
		Assert.hasText(docId, "document id cannot be empty");
	}

	public HttpClient getConnection() {
		return dbInstance.getConnection();
	}

	public DbInfo getDbInfo() {
		return restTemplate.get(dbURI.toString(),
				new StdResponseHandler() {

					public DbInfo success(HttpResponse hr) throws Exception {
						return objectMapper.readValue(hr.getContent(),
	}

	public DesignDocInfo getDesignDocInfo(String designDocId) {
		Assert.hasText(designDocId, "designDocId may not be null or empty");
		String uri = dbURI.append("_design").append(designDocId)
				.append("_info").toString();

		return restTemplate.get(uri, new StdResponseHandler() {

			public DesignDocInfo success(HttpResponse hr) throws Exception {
				return objectMapper.readValue(hr.getContent(),
						DesignDocInfo.class);
			}
		});
	}

	public void compact() {
		restTemplate.post(dbURI.append("_compact").toString(), "not_used",
				VOID_RESPONSE_HANDLER);
	}

	public void cleanupViews() {
		restTemplate.post(dbURI.append("_view_cleanup").toString(), "not_used",
				VOID_RESPONSE_HANDLER);
	}

	public ReplicationStatus replicateFrom(String source) {
		ReplicationCommand cmd = new ReplicationCommand.Builder()
				.target(dbName).source(source).build();

		return dbInstance.replicate(cmd);
	}

	public ReplicationStatus replicateFrom(String source,
			Collection docIds) {
		ReplicationCommand cmd = new ReplicationCommand.Builder()
				.target(dbName).source(source).docIds(docIds).build();

		return dbInstance.replicate(cmd);
	}

	public ReplicationStatus replicateTo(String target) {
		ReplicationCommand cmd = new ReplicationCommand.Builder()
				.target(target).source(dbName).build();

		return dbInstance.replicate(cmd);
	}

	public ReplicationStatus replicateTo(String target,
			Collection docIds) {
		ReplicationCommand cmd = new ReplicationCommand.Builder()
				.target(target).source(dbName).docIds(docIds).build();

		return dbInstance.replicate(cmd);
	}

	public void compactViews(String designDocumentId) {
		Assert.hasText(designDocumentId,
				"designDocumentId may not be null or empty");
		restTemplate.post(dbURI.append("_compact").append(designDocumentId)
				.toString(), "not_used", VOID_RESPONSE_HANDLER);
	}

	public List executeAllOrNothing(
            InputStream inputStream) {
        return executeBulk(inputStream, true);
    }

    public List executeBulk(InputStream inputStream) {
        return executeBulk(inputStream, false);
    }
	
	public List executeAllOrNothing(
			Collection objects) {
		return executeBulk(objects, true);
	}

	public List executeBulk(Collection objects) {
		return executeBulk(objects, false);
	}

	public void addToBulkBuffer(Object o) {
		bulkBufferManager.add(o);
		LOG.debug("{} added to bulk buffer", o);
	}
	
	public void clearBulkBuffer() {
		bulkBufferManager.clear();
		LOG.debug("bulk buffer cleared");
	}
	
	public List flushBulkBuffer() {
			Collection buffer = bulkBufferManager.getCurrentBuffer();
			if (buffer != null && !buffer.isEmpty()) {
				LOG.debug("flushing bulk buffer");
				return executeBulk(buffer);
			} else {
				LOG.debug("bulk buffer was empty");
				return Collections.emptyList();
			}	
		} finally {
			clearBulkBuffer();
		}
		
	}
	
	public void setJsonSerializer(JsonSerializer js) {
		Assert.notNull(js, "JsonSerializer may not be null");
		this.jsonSerializer = js;
	}

	
	private List executeBulk(InputStream inputStream,
            boolean allOrNothing) {
        
	    BulkDocumentWriter writer = new BulkDocumentWriter(objectMapper);
	    
        return restTemplate.post(
                dbURI.append("_bulk_docs").toString(), 
                writer.createInputStreamWrapper(allOrNothing, inputStream),
                new BulkOperationResponseHandler(objectMapper));
    }
	
	private List executeBulk(Collection objects,
			boolean allOrNothing) {
		BulkOperation op = jsonSerializer.createBulkOperation(objects,
				allOrNothing);
		List result = restTemplate.post(
				dbURI.append("_bulk_docs").toString(), op.getData(),
				new BulkOperationResponseHandler(objects, objectMapper));
		op.awaitCompletion();
		return result;
	}

	public int getRevisionLimit() {
		return restTemplate.get(dbURI.append("_revs_limit").toString(),
				new StdResponseHandler() {
					@Override
					public Integer success(HttpResponse hr) throws Exception {
						JsonNode rlimit = objectMapper.readTree(hr.getContent());
						return rlimit.getValueAsInt();
					}
				});
	}

	public void setRevisionLimit(int limit) {
		restTemplate.put(dbURI.append("_revs_limit").toString(),
				Integer.toString(limit), VOID_RESPONSE_HANDLER);
	}

	private InputStream changesAsStream(ChangesCommand cmd) {
		HttpResponse r = restTemplate.get(dbURI.append(cmd.toString())
				.toString());
		return r.getContent();
	}

	public List changes(ChangesCommand cmd) {
		if (cmd.continuous) {
			throw new IllegalArgumentException(
					"ChangesCommand may not declare continous = true while calling changes");
		}

		ChangesCommand actualCmd = new ChangesCommand.Builder().merge(cmd)
				.continuous(false).build();

		List changes = new ArrayList();
		try {
			JsonNode node = objectMapper.readTree(changesAsStream(actualCmd));
			JsonNode results = node.findPath("results");

			for (JsonNode change : results) {
				changes.add(new StdDocumentChange(change));
			}
		} catch (IOException e) {
			throw Exceptions.propagate(e);
		}
		return changes;
	}

	public ChangesFeed changesFeed(ChangesCommand cmd) {
		int heartbeat = cmd.heartbeat > 0 ? cmd.heartbeat
				: DEFAULT_HEARTBEAT_INTERVAL;
		
		String since = cmd.since != null ? cmd.since : getDbInfo().getUpdateSeqAsString();

		ChangesCommand actualCmd = new ChangesCommand.Builder().merge(cmd)
				.continuous(true).heartbeat(heartbeat).since(since).build();

		return new ContinuousChangesFeed(dbName, restTemplate.getUncached(dbURI.append(actualCmd.toString()).toString()));
	}
	
	@Override
	public String callUpdateHandler(String designDocID, String function,
			String docID) {
		return callUpdateHandler(designDocID, function, docID, null);
	}
	
	public String callUpdateHandler(String designDocID, String function, String docID, Map params) {
		Assert.hasText(designDocID, "designDocID may not be null or empty");
		Assert.hasText(function, "functionName may not be null or empty");
		Assert.hasText(docID, "docId may not be null or empty");
 		URI uri = dbURI.append(designDocID).append("_update").append(function)
 				.append(docID);
 		if(params != null && !params.isEmpty()) {
 			for (Map.Entry p : params.entrySet()) {
 	 			uri.param(p.getKey(), p.getValue());
 	 		}	
 		}
 		
 		return restTemplate.put(uri.toString(), "", new StdResponseHandler() {
 
 			public String success(HttpResponse hr)
 					throws JsonProcessingException, IOException {
 				return IOUtils.toString(hr.getContent(), "UTF-8");
 			}
 
 		});
 
 	}
	
	@Override
	public void ensureFullCommit() {
		restTemplate.post(dbURI.append("_ensure_full_commit").toString(), "");
	}

	
=======
    private static final int DEFAULT_HEARTBEAT_INTERVAL = 9000;
    private static final Logger LOG = LoggerFactory
            .getLogger(StdCouchDbConnector.class);
    private static final ResponseCallback VOID_RESPONSE_HANDLER = new StdResponseHandler();
    private final ObjectMapper objectMapper;
    private JsonSerializer jsonSerializer;

    private final URI dbURI;
    private final String dbName;

    private final RestTemplate restTemplate;

    private final CouchDbInstance dbInstance;

    private final RevisionResponseHandler revisionHandler;
    private final DocIdResponseHandler docIdResponseHandler;

    private final ThreadLocalBulkBufferHolder bulkBufferManager = new ThreadLocalBulkBufferHolder();

    private final static Options EMPTY_OPTIONS = new Options();

    public StdCouchDbConnector(String databaseName, CouchDbInstance dbInstance) {
        this(databaseName, dbInstance, new StdObjectMapperFactory());
    }

    public StdCouchDbConnector(String databaseName, CouchDbInstance dbi,
            ObjectMapperFactory om) {
        Assert.hasText(databaseName, "DatabaseName may not be null or empty");
        Assert.notNull(dbi, "CouchDbInstance may not be null");
        Assert.notNull(om, "ObjectMapperFactory may not be null");

        DbPath dbp = DbPath.fromString(databaseName);
        dbName = dbp.getDbName();
        this.dbURI = URI.prototype(dbp.getPath());
        this.dbInstance = dbi;
        this.objectMapper = om.createObjectMapper(this);

        this.jsonSerializer = new StreamingJsonSerializer(objectMapper);
        this.restTemplate = new RestTemplate(dbi.getConnection());
        this.revisionHandler = new RevisionResponseHandler(objectMapper);
        this.docIdResponseHandler = new DocIdResponseHandler(objectMapper);
    }

    @Override
    public String path() {
        return dbURI.toString();
    }

    @Override
    public void create(final Object o) {
        Assert.notNull(o, "Document may not be null");
        Assert.isTrue(Documents.isNew(o), "Object must be new");

        String json = jsonSerializer.toJson(o);
        String id = Documents.getId(o);
        DocumentOperationResult result;
        if (id != null) {
            result = restTemplate.put(URIWithDocId(id), json, revisionHandler);
        } else {
            result = restTemplate.post(dbURI.toString(), json, revisionHandler);
            Documents.setId(o, result.getId());
        }
        Documents.setRevision(o, result.getRevision());
    }

    @Override
    public void create(String id, Object node) {
        assertDocIdHasValue(id);
        Assert.notNull(node, "node may not be null");
        restTemplate.put(URIWithDocId(id), jsonSerializer.toJson(node));
    }

    private String URIWithDocId(String id) {
        return dbURI.append(id).toString();
    }

    @Override
    public boolean contains(String id) {
        return restTemplate.head(URIWithDocId(id),
                new ResponseCallback() {

                    @Override
                    public Boolean error(HttpResponse hr) {
                        if (hr.getCode() == HttpStatus.NOT_FOUND) {
                            return Boolean.FALSE;
                        }
                        throw new DbAccessException(hr.toString());
                    }

                    @Override
                    public Boolean success(HttpResponse hr) throws Exception {
                        return Boolean.TRUE;
                    }

                });
    }

    @Override
    public String createAttachment(String docId, AttachmentInputStream data) {
        return createAttachment(docId, null, data);
    }

    @Override
    public String createAttachment(String docId, String revision,
            AttachmentInputStream data) {
        assertDocIdHasValue(docId);
        URI uri = dbURI.append(docId).append(data.getId());
        if (revision != null) {
            uri.param("rev", revision);
        }
        return restTemplate.put(uri.toString(), data, data.getContentType(),
                data.getContentLength(), revisionHandler).getRevision();
    }

    @Override
    public AttachmentInputStream getAttachment(final String id,
            final String attachmentId) {
        assertDocIdHasValue(id);
        Assert.hasText(attachmentId, "attachmentId must have a value");
        if (LOG.isTraceEnabled()) {
            LOG.trace("fetching attachment for doc: {} attachmentId: {}", id,
                    attachmentId);
        }
        HttpResponse r = restTemplate.get(dbURI.append(id).append(attachmentId)
                .toString());
        return new AttachmentInputStream(attachmentId, r.getContent(),
                r.getContentType(), r.getContentLength());
    }

    @Override
    public String delete(Object o) {
        Assert.notNull(o, "document may not be null");
        return delete(Documents.getId(o), Documents.getRevision(o));
    }

    @Override
    public PurgeResult purge(Map> revisionsToPurge) {
        return restTemplate.post(dbURI.append("_purge").toString(), jsonSerializer.toJson(revisionsToPurge),
                new StdResponseHandler() {
                    @Override
                    public PurgeResult success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), PurgeResult.class);
                    }
                });
    }

    @Override
    public  T get(final Class c, String id) {
        return get(c, id, EMPTY_OPTIONS);
    }

    @Override
    public  T get(final Class c, String id, Options options) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        URI uri = dbURI.append(id);
        applyOptions(options, uri);
        return restTemplate.get(uri.toString(),
                new StdResponseHandler() {
                    @Override
        assertDocIdHasValue(id);
                    public T success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), c);
                    }
                });
    }

    @Override
    public  T get(final Class c, String id, String rev) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        Assert.hasText(rev, "Revision may not be null or empty");
        return get(c, id, new Options().revision(rev));
    }

    @Override
    public  T getWithConflicts(final Class c, String id) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        return get(c, id, new Options().includeConflicts());
    }

    @Override
    public  T find(Class c, String id) {
        return find(c, id, EMPTY_OPTIONS);
    }

    @Override
    public  T find(final Class c, String id, Options options) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        URI uri = dbURI.append(id);
        applyOptions(options, uri);
        return restTemplate.get(uri.toString(),
                new StdResponseHandler() {
                    @Override
                    public T success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), c);
                    }

                    @Override
                    public T error(HttpResponse hr) {
                        return hr.getCode() == HttpStatus.NOT_FOUND ? null : super.error(hr);
                    }
                });
    }

    private void applyOptions(Options options, URI uri) {
        if (options != null && !options.isEmpty()) {
            uri.params(options.getOptions());
        }
    }

    @Override
    public List getRevisions(String id) {
        assertDocIdHasValue(id);
        return restTemplate.get(dbURI.append(id).param("revs_info", "true")
                .toString(), new StdResponseHandler>() {

            @Override
            public List success(HttpResponse hr) throws Exception {
                JsonNode root = objectMapper.readValue(hr.getContent(),
                        JsonNode.class);
                List revs = new ArrayList();
                for (Iterator i = root.get("_revs_info")
                        .getElements(); i.hasNext();) {
                    JsonNode rev = i.next();
                    revs.add(new Revision(rev.get("rev").getTextValue(), rev
                            .get("status").getTextValue()));
                }
                return revs;
            }

            @Override
            public List error(HttpResponse hr) {
                if (hr.getCode() == HttpStatus.NOT_FOUND) {
                    return Collections.emptyList();
                }
                return super.error(hr);
            }
        });
    }

    @Override
    public InputStream getAsStream(String id) {
        assertDocIdHasValue(id);
        return getAsStream(id, EMPTY_OPTIONS);
    }

    @Override
    public InputStream getAsStream(String id, Options options) {
        URI uri = dbURI.append(id);
        applyOptions(options, uri);
        HttpResponse r = restTemplate.get(uri.toString());
        return r.getContent();
    }

    @Override
    public InputStream getAsStream(String id, String rev) {
                    }
        Assert.hasText(rev, "Revision may not be null or empty");
        return getAsStream(id, new Options().revision(rev));
    }

    @Override
    public void update(final Object o) {
        Assert.notNull(o, "Document cannot be null");
        final String id = Documents.getId(o);
        assertDocIdHasValue(id);
        restTemplate.put(dbURI.append(id).toString(), jsonSerializer.toJson(o),
                new StdResponseHandler() {

                    @Override
                    public Void success(HttpResponse hr) throws Exception {
                        JsonNode n = objectMapper.readValue(hr.getContent(),
                                JsonNode.class);
                        Documents.setRevision(o, n.get("rev").getTextValue());
                        return null;
                    }

                    @Override
                    public Void error(HttpResponse hr) {
                        if (hr.getCode() == HttpStatus.CONFLICT) {
                            throw new UpdateConflictException(id, Documents
                                    .getRevision(o));
                        }
                        return super.error(hr);
                    }
                });
    }

    @Override
    public String delete(String id, String revision) {
        assertDocIdHasValue(id);
        return restTemplate.delete(
                dbURI.append(id).param("rev", revision).toString(),
                revisionHandler).getRevision();
    }

    @Override
    public List getAllDocIds() {
        return restTemplate.get(dbURI.append("_all_docs").toString(),
                docIdResponseHandler);
    }

    @Override
    public void createDatabaseIfNotExists() {
        if (!dbInstance.checkIfDbExists(new DbPath(dbName))) {
            dbInstance.createDatabase(dbName);
        }
    }

    @Override
    public String getDatabaseName() {
        return dbName;
    }

    @Override
    public  List queryView(final ViewQuery query, final Class type) {
        Assert.notNull(query, "query may not be null");
        query.dbPath(dbURI.toString());

        EmbeddedDocViewResponseHandler rh = new EmbeddedDocViewResponseHandler(
                type, objectMapper, query.isIgnoreNotFound());

        return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
                query.getKeysAsJson(), rh) : restTemplate.get(
                query.buildQuery(), rh);
    }

    @Override
    public  Page queryForPage(ViewQuery query, PageRequest pr, Class type) {
        Assert.notNull(query, "query may not be null");
        Assert.notNull(pr, "PageRequest may not be null");
        Assert.notNull(type, "type may not be null");

        query.dbPath(dbURI.toString());
        if (LOG.isDebugEnabled()) {
            LOG.debug("startKey: {}", pr.getStartKey());
            LOG.debug("startDocId: {}", pr.getStartKeyDocId());
        }
        PageResponseHandler ph = new PageResponseHandler(pr, type, objectMapper, query.isIgnoreNotFound());
        query = PageRequest.applyPagingParameters(query, pr);
        return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
                query.getKeysAsJson(), ph) : restTemplate.get(
                query.buildQuery(), ph);
    }

    @Override
    public ViewResult queryView(ViewQuery query) {
        Assert.notNull(query, "query cannot be null");
        query.dbPath(dbURI.toString());
        ResponseCallback rh = new StdResponseHandler() {

            @Override

            public ViewResult success(HttpResponse hr) throws Exception {
                return new ViewResult(objectMapper.readTree(hr.getContent()));
            }

        };
        return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
                query.getKeysAsJson(), rh) : restTemplate.get(
                query.buildQuery(), rh);
    }

    @Override
    public StreamingViewResult queryForStreamingView(ViewQuery query) {
        return new StreamingViewResult(objectMapper, queryForStream(query));
    }

    @Override
    public InputStream queryForStream(ViewQuery query) {
        Assert.notNull(query, "query cannot be null");
        query.dbPath(dbURI.toString());
        return query.hasMultipleKeys() ? restTemplate.postUncached(query.buildQuery(),
                query.getKeysAsJson()).getContent() : restTemplate.getUncached(
                query.buildQuery()).getContent();
    }

    @Override
    public String deleteAttachment(String docId, String revision,
            String attachmentId) {
        return restTemplate.delete(
                dbURI.append(docId).append(attachmentId).param("rev", revision)
                        .toString(), revisionHandler).getRevision();
    }

    private void assertDocIdHasValue(String docId) {
        Assert.hasText(docId, "document id cannot be empty");
    }

    @Override
    public HttpClient getConnection() {
        return dbInstance.getConnection();
    }

    @Override
    public DbInfo getDbInfo() {
        return restTemplate.get(dbURI.toString(),
                new StdResponseHandler() {

                    @Override
                    public DbInfo success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(),
                                DbInfo.class);
                    }
                });
    }

    @Override
    public DesignDocInfo getDesignDocInfo(String designDocId) {
        Assert.hasText(designDocId, "designDocId may not be null or empty");
        String uri = dbURI.append("_design").append(designDocId)
                .append("_info").toString();

        return restTemplate.get(uri, new StdResponseHandler() {

            @Override
            public DesignDocInfo success(HttpResponse hr) throws Exception {
                return objectMapper.readValue(hr.getContent(),
                        DesignDocInfo.class);
            }
        });
    }

    @Override
    public void compact() {
        restTemplate.post(dbURI.append("_compact").toString(), "not_used",
                VOID_RESPONSE_HANDLER);
    }

    @Override
    public void cleanupViews() {
        restTemplate.post(dbURI.append("_view_cleanup").toString(), "not_used",
                VOID_RESPONSE_HANDLER);
    }

    @Override
    public ReplicationStatus replicateFrom(String source) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(dbName).source(source).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public ReplicationStatus replicateFrom(String source,
            Collection docIds) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(dbName).source(source).docIds(docIds).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public ReplicationStatus replicateTo(String target) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(target).source(dbName).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public ReplicationStatus replicateTo(String target,
            Collection docIds) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(target).source(dbName).docIds(docIds).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public void compactViews(String designDocumentId) {
        Assert.hasText(designDocumentId,
                "designDocumentId may not be null or empty");
        restTemplate.post(dbURI.append("_compact").append(designDocumentId)
                .toString(), "not_used", VOID_RESPONSE_HANDLER);
    }

    @Override
    public List executeAllOrNothing(
            Collection objects) {
        return executeBulk(objects, true);
    }

    @Override
    public List executeBulk(Collection objects) {
        return executeBulk(objects, false);
    }

    @Override
    public void addToBulkBuffer(Object o) {
        bulkBufferManager.add(o);
        LOG.debug("{} added to bulk buffer", o);
    }

    @Override
    public void clearBulkBuffer() {
        bulkBufferManager.clear();
        LOG.debug("bulk buffer cleared");
    }

    @Override
    public List flushBulkBuffer() {
        try {
            Collection buffer = bulkBufferManager.getCurrentBuffer();
            if (buffer != null && !buffer.isEmpty()) {
                LOG.debug("flushing bulk buffer");
                return executeBulk(buffer);
            } else {
                LOG.debug("bulk buffer was empty");
                return Collections.emptyList();
            }
        } finally {
            clearBulkBuffer();
        }

    }

    public void setJsonSerializer(JsonSerializer js) {
        Assert.notNull(js, "JsonSerializer may not be null");
        this.jsonSerializer = js;
    }

    private List executeBulk(Collection objects,
            boolean allOrNothing) {
        BulkOperation op = jsonSerializer.createBulkOperation(objects,
                allOrNothing);
        List result = restTemplate.post(
                dbURI.append("_bulk_docs").toString(), op.getData(),
                new BulkOperationResponseHandler(objects, objectMapper));
        op.awaitCompletion();
        return result;
    }

    @Override
    public int getRevisionLimit() {
        return restTemplate.get(dbURI.append("_revs_limit").toString(),
                new StdResponseHandler() {
                    @Override
                    public Integer success(HttpResponse hr) throws Exception {
                        JsonNode rlimit = objectMapper.readTree(hr.getContent());
                        return rlimit.getValueAsInt();
                    }
                });
    }

    @Override
    public void setRevisionLimit(int limit) {
        restTemplate.put(dbURI.append("_revs_limit").toString(),
                Integer.toString(limit), VOID_RESPONSE_HANDLER);
    }

    private InputStream changesAsStream(ChangesCommand cmd) {
        HttpResponse r = restTemplate.get(dbURI.append(cmd.toString())
                .toString());
        return r.getContent();
    }

    @Override
    public List changes(ChangesCommand cmd) {
        if (cmd.continuous) {
            throw new IllegalArgumentException(
                    "ChangesCommand may not declare continous = true while calling changes");
        }

        ChangesCommand actualCmd = new ChangesCommand.Builder().merge(cmd)
                .continuous(false).build();

        List changes = new ArrayList();
        try {
            JsonNode node = objectMapper.readTree(changesAsStream(actualCmd));
            JsonNode results = node.findPath("results");

            for (JsonNode change : results) {
                changes.add(new StdDocumentChange(change));
            }
        } catch (IOException e) {
            throw Exceptions.propagate(e);
        }
        return changes;
    }

    @Override
    public ChangesFeed changesFeed(ChangesCommand cmd) {
        int heartbeat = cmd.heartbeat > 0 ? cmd.heartbeat
                : DEFAULT_HEARTBEAT_INTERVAL;

        String since = cmd.since != null ? cmd.since : getDbInfo().getUpdateSeqAsString();

        ChangesCommand actualCmd = new ChangesCommand.Builder().merge(cmd)
                .continuous(true).heartbeat(heartbeat).since(since).build();

        return new ContinuousChangesFeed(dbName,
                restTemplate.getUncached(dbURI.append(actualCmd.toString()).toString()));
    }

    @Override
    public String callUpdateHandler(String designDocID, String function,
            String docID) {
        return callUpdateHandler(designDocID, function, docID, null);
    }

    @Override
    public String callUpdateHandler(String designDocID, String function, String docID, Map params) {
        Assert.hasText(designDocID, "designDocID may not be null or empty");
        Assert.hasText(function, "functionName may not be null or empty");
        Assert.hasText(docID, "docId may not be null or empty");

        UpdateHandlerRequest req = new UpdateHandlerRequest();
        req.dbPath(dbURI.toString())
                .designDocId(designDocID)
                .functionName(function)
                .docId(docID)
                .params(params)
                .buildRequestUri();

        return callUpdateHandler(req);
    }

    private String serializeUpdateHandlerRequestBody(Object o) {
        if (o == null) {
            return "";
        } else if (o instanceof String) {
            return (String) o;
        } else {
            try {
                return objectMapper.writeValueAsString(o);
            } catch (Exception e) {
                throw Exceptions.propagate(e);
            }
        }
    }

    @Override
    public String callUpdateHandler(final UpdateHandlerRequest req) {
        Assert.hasText(req.getDesignDocId(), "designDocID may not be null or empty");
        Assert.hasText(req.getFunctionName(), "functionName may not be null or empty");
        Assert.hasText(req.getDocId(), "docId may not be null or empty");

        req.dbPath(dbURI.toString());

        return restTemplate.put(req.buildRequestUri(),
                serializeUpdateHandlerRequestBody(req.getBody()),
                new StdResponseHandler() {

                    @Override
                    public String success(HttpResponse hr)
                            throws JsonProcessingException, IOException {
                        return IOUtils.toString(hr.getContent(), "UTF-8");
                });
    }

    @Override
    public  T callUpdateHandler(final UpdateHandlerRequest req, final Class c) {
        Assert.hasText(req.getDesignDocId(), "designDocID may not be null or empty");
        Assert.hasText(req.getFunctionName(), "functionName may not be null or empty");
        Assert.hasText(req.getDocId(), "docId may not be null or empty");

        req.dbPath(dbURI.toString());

        return restTemplate.put(req.buildRequestUri(),
                serializeUpdateHandlerRequestBody(req.getBody()),
                new StdResponseHandler() {

                    @Override
                    public T success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), c);
                    }

                    @Override
                    public T error(HttpResponse hr) {
                        if (hr.getCode() == HttpStatus.CONFLICT) {
                            throw new UpdateConflictException(req.getDocId(), "");
                        }
                        return null;
                    }
                });
    }

    @Override
    public void ensureFullCommit() {
        restTemplate.post(dbURI.append("_ensure_full_commit").toString(), "");
    }

>>>>>>> 262208f7a653371ac353b3f23d48511f4439cf56
}
Solution content
    @Override

            @Override
 */
public class StdCouchDbConnector implements CouchDbConnector {

    private static final int DEFAULT_HEARTBEAT_INTERVAL = 9000;
    private static final Logger LOG = LoggerFactory
            .getLogger(StdCouchDbConnector.class);
    private static final ResponseCallback VOID_RESPONSE_HANDLER = new StdResponseHandler();
    private final ObjectMapper objectMapper;
    private JsonSerializer jsonSerializer;

    private final URI dbURI;
    private final String dbName;

    private final RestTemplate restTemplate;

    private final CouchDbInstance dbInstance;

    private final RevisionResponseHandler revisionHandler;
    private final DocIdResponseHandler docIdResponseHandler;

    private final ThreadLocalBulkBufferHolder bulkBufferManager = new ThreadLocalBulkBufferHolder();

    private final static Options EMPTY_OPTIONS = new Options();

    public StdCouchDbConnector(String databaseName, CouchDbInstance dbInstance) {
        this(databaseName, dbInstance, new StdObjectMapperFactory());
    }

    public StdCouchDbConnector(String databaseName, CouchDbInstance dbi,
            ObjectMapperFactory om) {
        Assert.hasText(databaseName, "DatabaseName may not be null or empty");
        Assert.notNull(dbi, "CouchDbInstance may not be null");
        Assert.notNull(om, "ObjectMapperFactory may not be null");

        DbPath dbp = DbPath.fromString(databaseName);
        dbName = dbp.getDbName();
        this.dbURI = URI.prototype(dbp.getPath());
        this.dbInstance = dbi;
        this.objectMapper = om.createObjectMapper(this);

    }
        this.jsonSerializer = new StreamingJsonSerializer(objectMapper);
        this.restTemplate = new RestTemplate(dbi.getConnection());
        this.revisionHandler = new RevisionResponseHandler(objectMapper);
        this.docIdResponseHandler = new DocIdResponseHandler(objectMapper);
    }

    @Override
    public String path() {
        return dbURI.toString();
    }

    @Override
    public void create(final Object o) {
        Assert.notNull(o, "Document may not be null");
        Assert.isTrue(Documents.isNew(o), "Object must be new");

        String json = jsonSerializer.toJson(o);
        String id = Documents.getId(o);
        DocumentOperationResult result;
        if (id != null) {
            result = restTemplate.put(URIWithDocId(id), json, revisionHandler);
        } else {
            result = restTemplate.post(dbURI.toString(), json, revisionHandler);
            Documents.setId(o, result.getId());
        }
        Documents.setRevision(o, result.getRevision());
    }

    @Override
    public void create(String id, Object node) {
        assertDocIdHasValue(id);
        Assert.notNull(node, "node may not be null");
        restTemplate.put(URIWithDocId(id), jsonSerializer.toJson(node));
    }

    private String URIWithDocId(String id) {
        return dbURI.append(id).toString();
    }

    @Override
    public boolean contains(String id) {
        return restTemplate.head(URIWithDocId(id),
                new ResponseCallback() {

                    @Override
                    public Boolean error(HttpResponse hr) {
                        if (hr.getCode() == HttpStatus.NOT_FOUND) {
                            return Boolean.FALSE;
                        }
                        throw new DbAccessException(hr.toString());
                    }

                    @Override
                    public Boolean success(HttpResponse hr) throws Exception {
                        return Boolean.TRUE;
                    }

                });
    }

    @Override
    public String createAttachment(String docId, AttachmentInputStream data) {
        return createAttachment(docId, null, data);
    }

    @Override
    public String createAttachment(String docId, String revision,
            AttachmentInputStream data) {
        assertDocIdHasValue(docId);
        URI uri = dbURI.append(docId).append(data.getId());
        if (revision != null) {
            uri.param("rev", revision);
        }
        return restTemplate.put(uri.toString(), data, data.getContentType(),
                data.getContentLength(), revisionHandler).getRevision();
    }

    @Override
    public AttachmentInputStream getAttachment(final String id,
            final String attachmentId) {
        assertDocIdHasValue(id);
        Assert.hasText(attachmentId, "attachmentId must have a value");
        if (LOG.isTraceEnabled()) {
            LOG.trace("fetching attachment for doc: {} attachmentId: {}", id,
                    attachmentId);
        }
        HttpResponse r = restTemplate.get(dbURI.append(id).append(attachmentId)
                .toString());
        return new AttachmentInputStream(attachmentId, r.getContent(),
                r.getContentType(), r.getContentLength());
    }

    @Override
    public String delete(Object o) {
        Assert.notNull(o, "document may not be null");
        return delete(Documents.getId(o), Documents.getRevision(o));
    }

    public PurgeResult purge(Map> revisionsToPurge) {
        return restTemplate.post(dbURI.append("_purge").toString(), jsonSerializer.toJson(revisionsToPurge),
                new StdResponseHandler() {
                    @Override
                    public PurgeResult success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), PurgeResult.class);
                    }
                });
    }

    @Override
    public  T get(final Class c, String id) {
        return get(c, id, EMPTY_OPTIONS);
    }

    @Override
    public  T get(final Class c, String id, Options options) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        URI uri = dbURI.append(id);
        applyOptions(options, uri);
        return restTemplate.get(uri.toString(),
                new StdResponseHandler() {
                    @Override
                    public T success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), c);
                    }
                });
    }

    @Override
    public  T get(final Class c, String id, String rev) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        Assert.hasText(rev, "Revision may not be null or empty");
        return get(c, id, new Options().revision(rev));
    }

    @Override
    public  T getWithConflicts(final Class c, String id) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        return get(c, id, new Options().includeConflicts());
    }

    @Override
    public  T find(Class c, String id) {
        return find(c, id, EMPTY_OPTIONS);
    }

    @Override
    public  T find(final Class c, String id, Options options) {
        Assert.notNull(c, "Class may not be null");
        assertDocIdHasValue(id);
        URI uri = dbURI.append(id);
        applyOptions(options, uri);
        return restTemplate.get(uri.toString(),
                new StdResponseHandler() {
                    @Override
                    public T success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), c);
                    }

                    @Override
                    public T error(HttpResponse hr) {
                        return hr.getCode() == HttpStatus.NOT_FOUND ? null : super.error(hr);
                    }
                });
    }

    private void applyOptions(Options options, URI uri) {
        if (options != null && !options.isEmpty()) {
            uri.params(options.getOptions());
        }
    }

    @Override
    public List getRevisions(String id) {
        assertDocIdHasValue(id);
        return restTemplate.get(dbURI.append(id).param("revs_info", "true")
                .toString(), new StdResponseHandler>() {

            @Override
            public List success(HttpResponse hr) throws Exception {
                JsonNode root = objectMapper.readValue(hr.getContent(),
                        JsonNode.class);
                List revs = new ArrayList();
                for (Iterator i = root.get("_revs_info")
                        .getElements(); i.hasNext();) {
                    JsonNode rev = i.next();
                    revs.add(new Revision(rev.get("rev").getTextValue(), rev
                            .get("status").getTextValue()));
                }
                return revs;
            }
            public List error(HttpResponse hr) {
                if (hr.getCode() == HttpStatus.NOT_FOUND) {
                    return Collections.emptyList();
                }
                return super.error(hr);
            }
        });
    }

    @Override
    public InputStream getAsStream(String id) {
        assertDocIdHasValue(id);
        return getAsStream(id, EMPTY_OPTIONS);
    }

    @Override
    public InputStream getAsStream(String id, Options options) {
        URI uri = dbURI.append(id);
        applyOptions(options, uri);
        HttpResponse r = restTemplate.get(uri.toString());
        return r.getContent();
    }

    @Override
    public InputStream getAsStream(String id, String rev) {
        assertDocIdHasValue(id);
        Assert.hasText(rev, "Revision may not be null or empty");
        return getAsStream(id, new Options().revision(rev));
    }

    @Override
    public void update(final Object o) {
        Assert.notNull(o, "Document cannot be null");
        final String id = Documents.getId(o);
        assertDocIdHasValue(id);
        restTemplate.put(dbURI.append(id).toString(), jsonSerializer.toJson(o),
                new StdResponseHandler() {

                    @Override
                    public Void success(HttpResponse hr) throws Exception {
                        JsonNode n = objectMapper.readValue(hr.getContent(),
                                JsonNode.class);
                        Documents.setRevision(o, n.get("rev").getTextValue());
                        return null;
                    }

                    @Override
                    public Void error(HttpResponse hr) {
                        if (hr.getCode() == HttpStatus.CONFLICT) {
                            throw new UpdateConflictException(id, Documents
                                    .getRevision(o));
                        }
                        return super.error(hr);
                    }
                });
    }

    @Override
    public String delete(String id, String revision) {
        assertDocIdHasValue(id);
        return restTemplate.delete(
                dbURI.append(id).param("rev", revision).toString(),
                revisionHandler).getRevision();
    }

    @Override
    public List getAllDocIds() {
        return restTemplate.get(dbURI.append("_all_docs").toString(),
                docIdResponseHandler);
    }

    @Override
    public void createDatabaseIfNotExists() {
        if (!dbInstance.checkIfDbExists(new DbPath(dbName))) {
            dbInstance.createDatabase(dbName);
        }
    }

    @Override
    public String getDatabaseName() {
        return dbName;
    }

    @Override
    public  List queryView(final ViewQuery query, final Class type) {
        Assert.notNull(query, "query may not be null");
        query.dbPath(dbURI.toString());

        EmbeddedDocViewResponseHandler rh = new EmbeddedDocViewResponseHandler(
                type, objectMapper, query.isIgnoreNotFound());

        return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
                query.getKeysAsJson(), rh) : restTemplate.get(
                query.buildQuery(), rh);
    }

    @Override
    public  Page queryForPage(ViewQuery query, PageRequest pr, Class type) {
        Assert.notNull(query, "query may not be null");

        Assert.notNull(pr, "PageRequest may not be null");
        Assert.notNull(type, "type may not be null");

        query.dbPath(dbURI.toString());
        if (LOG.isDebugEnabled()) {
            LOG.debug("startKey: {}", pr.getStartKey());
            LOG.debug("startDocId: {}", pr.getStartKeyDocId());
        }
        PageResponseHandler ph = new PageResponseHandler(pr, type, objectMapper, query.isIgnoreNotFound());
        query = PageRequest.applyPagingParameters(query, pr);
        return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
                query.getKeysAsJson(), ph) : restTemplate.get(
                query.buildQuery(), ph);
    }

    @Override
    public ViewResult queryView(ViewQuery query) {
        Assert.notNull(query, "query cannot be null");
        query.dbPath(dbURI.toString());
        ResponseCallback rh = new StdResponseHandler() {

            @Override
            public ViewResult success(HttpResponse hr) throws Exception {
                return new ViewResult(objectMapper.readTree(hr.getContent()));
            }

        };
        return query.hasMultipleKeys() ? restTemplate.post(query.buildQuery(),
                query.getKeysAsJson(), rh) : restTemplate.get(
                query.buildQuery(), rh);
    }

    @Override
    public StreamingViewResult queryForStreamingView(ViewQuery query) {
        return new StreamingViewResult(objectMapper, queryForStream(query));
    }

    @Override
    public InputStream queryForStream(ViewQuery query) {
        Assert.notNull(query, "query cannot be null");
        query.dbPath(dbURI.toString());
        return query.hasMultipleKeys() ? restTemplate.postUncached(query.buildQuery(),
                query.getKeysAsJson()).getContent() : restTemplate.getUncached(
                query.buildQuery()).getContent();
    }

    @Override
    public String deleteAttachment(String docId, String revision,
            String attachmentId) {
        return restTemplate.delete(
                dbURI.append(docId).append(attachmentId).param("rev", revision)
                        .toString(), revisionHandler).getRevision();
    }

    private void assertDocIdHasValue(String docId) {
        Assert.hasText(docId, "document id cannot be empty");
    }

    @Override
    public HttpClient getConnection() {
        return dbInstance.getConnection();
    }

    @Override
    public DbInfo getDbInfo() {
        return restTemplate.get(dbURI.toString(),
                new StdResponseHandler() {

                    @Override
                    public DbInfo success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(),
                                DbInfo.class);
                    }
                });
    }

    @Override
    public DesignDocInfo getDesignDocInfo(String designDocId) {
        Assert.hasText(designDocId, "designDocId may not be null or empty");
        String uri = dbURI.append("_design").append(designDocId)
                .append("_info").toString();

        return restTemplate.get(uri, new StdResponseHandler() {

            @Override
            public DesignDocInfo success(HttpResponse hr) throws Exception {
                return objectMapper.readValue(hr.getContent(),
                        DesignDocInfo.class);
            }
        });
    }

    @Override
    public void compact() {
        restTemplate.post(dbURI.append("_compact").toString(), "not_used",
                VOID_RESPONSE_HANDLER);
    @Override
    public void cleanupViews() {
        restTemplate.post(dbURI.append("_view_cleanup").toString(), "not_used",
                VOID_RESPONSE_HANDLER);
    }

    @Override
    public ReplicationStatus replicateFrom(String source) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(dbName).source(source).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public ReplicationStatus replicateFrom(String source,
            Collection docIds) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(dbName).source(source).docIds(docIds).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public ReplicationStatus replicateTo(String target) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(target).source(dbName).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public ReplicationStatus replicateTo(String target,
            Collection docIds) {
        ReplicationCommand cmd = new ReplicationCommand.Builder()
                .target(target).source(dbName).docIds(docIds).build();

        return dbInstance.replicate(cmd);
    }

    @Override
    public void compactViews(String designDocumentId) {
        Assert.hasText(designDocumentId,
                "designDocumentId may not be null or empty");
        restTemplate.post(dbURI.append("_compact").append(designDocumentId)
                .toString(), "not_used", VOID_RESPONSE_HANDLER);
    }
    
    @Override
    public List executeAllOrNothing(
            InputStream inputStream) {
        return executeBulk(inputStream, true);
    }

    @Override
    public List executeBulk(InputStream inputStream) {
        return executeBulk(inputStream, false);
    }
    
    private List executeBulk(InputStream inputStream,
            boolean allOrNothing) {
        BulkDocumentWriter writer = new BulkDocumentWriter(objectMapper);

        return restTemplate.post(
            dbURI.append("_bulk_docs").toString(),
            writer.createInputStreamWrapper(allOrNothing, inputStream),
            new BulkOperationResponseHandler(objectMapper));

    }

    @Override
    public List executeAllOrNothing(
            Collection objects) {
        return executeBulk(objects, true);
    }

    @Override
    public List executeBulk(Collection objects) {
        return executeBulk(objects, false);
    }

    @Override
    public void addToBulkBuffer(Object o) {
        bulkBufferManager.add(o);
        LOG.debug("{} added to bulk buffer", o);
    }

    @Override
    public void clearBulkBuffer() {
        bulkBufferManager.clear();
        LOG.debug("bulk buffer cleared");
    }

    @Override
    public List flushBulkBuffer() {
        try {
            Collection buffer = bulkBufferManager.getCurrentBuffer();
            if (buffer != null && !buffer.isEmpty()) {
                LOG.debug("flushing bulk buffer");
                return executeBulk(buffer);
            } else {
                LOG.debug("bulk buffer was empty");
                return Collections.emptyList();
            }
        } finally {
            clearBulkBuffer();
        }

    }

    public void setJsonSerializer(JsonSerializer js) {
        Assert.notNull(js, "JsonSerializer may not be null");
        this.jsonSerializer = js;
    }

    private List executeBulk(Collection objects,
            boolean allOrNothing) {
        BulkOperation op = jsonSerializer.createBulkOperation(objects,
                allOrNothing);
        List result = restTemplate.post(
                dbURI.append("_bulk_docs").toString(), op.getData(),
                new BulkOperationResponseHandler(objects, objectMapper));
        op.awaitCompletion();
        return result;
    }

    @Override
    public int getRevisionLimit() {
        return restTemplate.get(dbURI.append("_revs_limit").toString(),
                new StdResponseHandler() {
                    @Override
                    public Integer success(HttpResponse hr) throws Exception {
                        JsonNode rlimit = objectMapper.readTree(hr.getContent());
                        return rlimit.getValueAsInt();
                    }
                });
    }

    @Override
    public void setRevisionLimit(int limit) {
        restTemplate.put(dbURI.append("_revs_limit").toString(),
                Integer.toString(limit), VOID_RESPONSE_HANDLER);
    }

    private InputStream changesAsStream(ChangesCommand cmd) {
        HttpResponse r = restTemplate.get(dbURI.append(cmd.toString())
                .toString());
        return r.getContent();
    }

    @Override
    public List changes(ChangesCommand cmd) {
        if (cmd.continuous) {
            throw new IllegalArgumentException(
                    "ChangesCommand may not declare continous = true while calling changes");
        }

        ChangesCommand actualCmd = new ChangesCommand.Builder().merge(cmd)
                .continuous(false).build();

        List changes = new ArrayList();
        try {
            JsonNode node = objectMapper.readTree(changesAsStream(actualCmd));
            JsonNode results = node.findPath("results");

            for (JsonNode change : results) {
                changes.add(new StdDocumentChange(change));
            }
        } catch (IOException e) {
            throw Exceptions.propagate(e);
        }
        return changes;
    }

    @Override
    public ChangesFeed changesFeed(ChangesCommand cmd) {
        int heartbeat = cmd.heartbeat > 0 ? cmd.heartbeat
                : DEFAULT_HEARTBEAT_INTERVAL;

        String since = cmd.since != null ? cmd.since : getDbInfo().getUpdateSeqAsString();

        ChangesCommand actualCmd = new ChangesCommand.Builder().merge(cmd)
                .continuous(true).heartbeat(heartbeat).since(since).build();

        return new ContinuousChangesFeed(dbName,
                restTemplate.getUncached(dbURI.append(actualCmd.toString()).toString()));
    }

    @Override
    public String callUpdateHandler(String designDocID, String function,
            String docID) {
        return callUpdateHandler(designDocID, function, docID, null);
    }

    @Override
    public String callUpdateHandler(String designDocID, String function, String docID, Map params) {
        Assert.hasText(designDocID, "designDocID may not be null or empty");
        Assert.hasText(function, "functionName may not be null or empty");
        Assert.hasText(docID, "docId may not be null or empty");

        UpdateHandlerRequest req = new UpdateHandlerRequest();
        req.dbPath(dbURI.toString())
                .designDocId(designDocID)
                .functionName(function)
                .docId(docID)
                .params(params)
                .buildRequestUri();

        return callUpdateHandler(req);
    }

    private String serializeUpdateHandlerRequestBody(Object o) {
        if (o == null) {
            return "";
        } else if (o instanceof String) {
            return (String) o;
        } else {
            try {
                return objectMapper.writeValueAsString(o);
            } catch (Exception e) {
                throw Exceptions.propagate(e);
            }
        }
    }

    @Override
    public String callUpdateHandler(final UpdateHandlerRequest req) {
        Assert.hasText(req.getDesignDocId(), "designDocID may not be null or empty");
        Assert.hasText(req.getFunctionName(), "functionName may not be null or empty");
        Assert.hasText(req.getDocId(), "docId may not be null or empty");

        req.dbPath(dbURI.toString());

        return restTemplate.put(req.buildRequestUri(),
                serializeUpdateHandlerRequestBody(req.getBody()),
                new StdResponseHandler() {

                    @Override
                    public String success(HttpResponse hr)
                            throws JsonProcessingException, IOException {
                        return IOUtils.toString(hr.getContent(), "UTF-8");
                    }

                });
    }

    @Override
    public  T callUpdateHandler(final UpdateHandlerRequest req, final Class c) {
        Assert.hasText(req.getDesignDocId(), "designDocID may not be null or empty");
        Assert.hasText(req.getFunctionName(), "functionName may not be null or empty");
        Assert.hasText(req.getDocId(), "docId may not be null or empty");

        req.dbPath(dbURI.toString());

        return restTemplate.put(req.buildRequestUri(),
                serializeUpdateHandlerRequestBody(req.getBody()),
                new StdResponseHandler() {

                    @Override
                    public T success(HttpResponse hr) throws Exception {
                        return objectMapper.readValue(hr.getContent(), c);
                    }

                    @Override
                    public T error(HttpResponse hr) {
                        if (hr.getCode() == HttpStatus.CONFLICT) {
                            throw new UpdateConflictException(req.getDocId(), "");
                        }
                        return null;
                    }
                });
    }

    @Override
    public void ensureFullCommit() {
        restTemplate.post(dbURI.append("_ensure_full_commit").toString(), "");
    }

}
File
StdCouchDbConnector.java
Developer's decision
Combination
Kind of conflict
Annotation
Attribute
Method declaration
Method invocation