All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.java.org.lightcouch.CouchDatabaseBase Maven / Gradle / Ivy

There is a newer version: 2.20.1
Show newest version
/*
 * Copyright (C) 2011 lightcouch.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.lightcouch;

import static org.lightcouch.internal.CouchDbUtil.assertNotEmpty;
import static org.lightcouch.internal.CouchDbUtil.close;
import static org.lightcouch.internal.CouchDbUtil.generateUUID;
import static org.lightcouch.internal.CouchDbUtil.getAsString;
import static org.lightcouch.internal.CouchDbUtil.getResponse;
import static org.lightcouch.internal.CouchDbUtil.getResponseList;
import static org.lightcouch.internal.CouchDbUtil.getStream;
import static org.lightcouch.internal.CouchDbUtil.streamToString;
import static org.lightcouch.internal.URIBuilder.buildUri;

import java.io.InputStream;
import java.net.URI;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

/**
 * Contains a Database Public API implementation.
 * @see CouchDatabase
 * @author Ahmed Yehia
 */
public abstract class CouchDatabaseBase {

	static final Log log = LogFactory.getLog(CouchDatabase.class);
	
	CouchDbClientBase client;
	private URI dbURI;
	
	private CouchDbDesign design;
	private String dbName;
	
	
	CouchDatabaseBase(CouchDbClientBase client, String name, boolean create) {
		assertNotEmpty(name, "name");
		this.dbName = name;
		this.client = client;
		this.dbURI   = buildUri(client.getBaseUri()).path(name).path("/").build();
		connect(create);
		this.design = new CouchDbDesign(this);
	}


	/**
	 * Provides access to CouchDB Design Documents.
	 * @see CouchDbDesign
	 */
	public CouchDbDesign design() {
		return design;
	}
	
	/**
	 * Provides access to CouchDB View APIs.
	 * @see View
	 */
	public View view(String viewId) {
		return new View(this, viewId);
	}

		
	/**
	 * Provides access to Change Notifications API.
	 * @see Changes
	 */
	public Changes changes() {
		return new Changes(this);
	}
	
	/**
	 * Finds an Object of the specified type.
	 * @param  Object type.
	 * @param classType The class of type T.
	 * @param id The document id.
	 * @return An object of type T.
	 * @throws NoDocumentException If the document is not found in the database.
	 */
	public  T find(Class classType, String id) {
		assertNotEmpty(classType, "Class");
		assertNotEmpty(id, "id");
		final URI uri = buildUri(getDBUri()).pathToEncode(id).buildEncoded();
		return client.get(uri, classType);
	}
	
	/**
	 * Finds an Object of the specified type.
	 * @param  Object type.
	 * @param classType The class of type T.
	 * @param id The document id.
	 * @param params Extra parameters to append.
	 * @return An object of type T.
	 * @throws NoDocumentException If the document is not found in the database.
	 */
	public  T find(Class classType, String id, Params params) {
		assertNotEmpty(classType, "Class");
		assertNotEmpty(id, "id");
		final URI uri = buildUri(getDBUri()).pathToEncode(id).query(params).buildEncoded();
		return client.get(uri, classType);
	}
	
	/**
	 * Finds an Object of the specified type.
	 * @param  Object type.
	 * @param classType The class of type T.
	 * @param id The document _id field.
	 * @param rev The document _rev field.
	 * @return An object of type T.
	 * @throws NoDocumentException If the document is not found in the database.
	 */
	public  T find(Class classType, String id, String rev) {
		assertNotEmpty(classType, "Class");
		assertNotEmpty(id, "id");
		assertNotEmpty(id, "rev");
		final URI uri = buildUri(getDBUri()).pathToEncode(id).query("rev", rev).buildEncoded();
		return client.get(uri, classType);
	}
	
	/**
	 * This method finds any document given a URI.
	 * 

The URI must be URI-encoded. * @param classType The class of type T. * @param uri The URI as string. * @return An object of type T. */ public T findAny(Class classType, String uri) { assertNotEmpty(classType, "Class"); assertNotEmpty(uri, "uri"); return client.get(URI.create(uri), classType); } /** * Finds a document and return the result as {@link InputStream}. *

Note: The stream must be closed after use to release the connection. * @param id The document _id field. * @return The result as {@link InputStream} * @throws NoDocumentException If the document is not found in the database. * @see #find(String, String) */ public InputStream find(String id) { assertNotEmpty(id, "id"); return client.get(buildUri(getDBUri()).path(id).build()); } /** * Finds a document given id and revision and returns the result as {@link InputStream}. *

Note: The stream must be closed after use to release the connection. * @param id The document _id field. * @param rev The document _rev field. * @return The result as {@link InputStream} * @throws NoDocumentException If the document is not found in the database. */ public InputStream find(String id, String rev) { assertNotEmpty(id, "id"); assertNotEmpty(rev, "rev"); final URI uri = buildUri(getDBUri()).path(id).query("rev", rev).build(); return client.get(uri); } /** * Checks if a document exist in the database. * @param id The document _id field. * @return true If the document is found, false otherwise. */ public boolean contains(String id) { assertNotEmpty(id, "id"); HttpResponse response = null; try { response = client.head(buildUri(getDBUri()).path(id).build()); } catch (NoDocumentException e) { return false; } finally { close(response); } return true; } /** * Saves an object in the database, using HTTP PUT request. *

If the object doesn't have an _id value, the code will assign a UUID as the document id. * @param object The object to save * @throws DocumentConflictException If a conflict is detected during the save. * @return {@link Response} */ public Response save(Object object) { return client.put(getDBUri(), object, true); } /** * Saves an object in the database using HTTP POST request. *

The database will be responsible for generating the document id. * @param object The object to save * @return {@link Response} */ public Response post(Object object) { assertNotEmpty(object, "object"); HttpResponse response = null; try { URI uri = buildUri(getDBUri()).build(); response = client.post(uri, getGson().toJson(object)); return getResponse(response,Response.class, client.getGson()); } finally { close(response); } } /** * Saves a document with batch=ok query param. * @param object The object to save. */ public void batch(Object object) { assertNotEmpty(object, "object"); HttpResponse response = null; try { URI uri = buildUri(getDBUri()).query("batch", "ok").build(); response = client.post(uri, getGson().toJson(object)); } finally { close(response); } } /** * Updates an object in the database, the object must have the correct _id and _rev values. * @param object The object to update * @throws DocumentConflictException If a conflict is detected during the update. * @return {@link Response} */ public Response update(Object object) { return client.put(getDBUri(), object, false); } /** * Removes a document from the database. *

The object must have the correct _id and _rev values. * @param object The document to remove as object. * @throws NoDocumentException If the document is not found in the database. * @return {@link Response} */ public Response remove(Object object) { assertNotEmpty(object, "object"); JsonObject jsonObject = getGson().toJsonTree(object).getAsJsonObject(); final String id = getAsString(jsonObject, "_id"); final String rev = getAsString(jsonObject, "_rev"); return remove(id, rev); } /** * Removes a document from the database given both a document _id and _rev values. * @param id The document _id field. * @param rev The document _rev field. * @throws NoDocumentException If the document is not found in the database. * @return {@link Response} */ public Response remove(String id, String rev) { assertNotEmpty(id, "id"); assertNotEmpty(rev, "rev"); final URI uri = buildUri(getDBUri()).pathToEncode(id).query("rev", rev).buildEncoded(); return client.delete(uri); } /** * Performs a Bulk Documents insert request. * @param objects The {@link List} of objects. * @param allOrNothing Indicates whether the request has all-or-nothing semantics. * @return {@code List} Containing the resulted entries. */ public List bulk(List objects, boolean allOrNothing) { assertNotEmpty(objects, "objects"); HttpResponse response = null; try { final String allOrNothingVal = allOrNothing ? "\"all_or_nothing\": true, " : ""; final URI uri = buildUri(getDBUri()).path("_bulk_docs").build(); final String json = String.format("{%s%s%s}", allOrNothingVal, "\"docs\": ", getGson().toJson(objects)); response = client.post(uri, json); return getResponseList(response, client.getGson(), Response.class, new TypeToken>(){}.getType()); } finally { close(response); } } /** * Saves an attachment to a new document with a generated UUID as the document id. *

To retrieve an attachment, see {@link #find(String)}. * @param instream The {@link InputStream} holding the binary data. * @param name The attachment name. * @param contentType The attachment "Content-Type". * @return {@link Response} */ public Response saveAttachment(InputStream in, String name, String contentType) { assertNotEmpty(in, "in"); assertNotEmpty(name, "name"); assertNotEmpty(contentType, "ContentType"); final URI uri = buildUri(getDBUri()).path(generateUUID()).path("/").path(name).build(); return client.put(uri, in, contentType); } /** * Saves an attachment to an existing document given both a document id * and revision, or save to a new document given only the id, and rev as {@code null}. *

To retrieve an attachment, see {@link #find(String)}. * @param instream The {@link InputStream} holding the binary data. * @param name The attachment name. * @param contentType The attachment "Content-Type". * @param docId The document id to save the attachment under, or {@code null} to save under a new document. * @param docRev The document revision to save the attachment under, or {@code null} when saving to a new document. * @throws DocumentConflictException * @return {@link Response} */ public Response saveAttachment(InputStream in, String name, String contentType, String docId, String docRev) { assertNotEmpty(in, "in"); assertNotEmpty(name, "name"); assertNotEmpty(contentType, "ContentType"); assertNotEmpty(docId, "docId"); final URI uri = buildUri(getDBUri()).path(docId).path("/").path(name).query("rev", docRev).build(); return client.put(uri, in, contentType); } /** * Invokes an Update Handler. *

	 * String query = "field=foo&value=bar";
	 * String output = dbClient.invokeUpdateHandler("designDoc/update1", "docId", query);
	 * 
* @param updateHandlerUri The Update Handler URI, in the format: designDoc/update1 * @param docId The document id to update. * @param query The query string parameters, e.g, field=field1&value=value1 * @return The output of the request. */ public String invokeUpdateHandler(String updateHandlerUri, String docId, String query) { assertNotEmpty(updateHandlerUri, "uri"); assertNotEmpty(docId, "docId"); final String[] v = updateHandlerUri.split("/"); final String path = String.format("_design/%s/_update/%s/", v[0], v[1]); final URI uri = buildUri(getDBUri()).path(path).path(docId).query(query).build(); final HttpResponse response = client.executeRequest(new HttpPut(uri)); return streamToString(getStream(response)); } /** * Invokes an Update Handler. *

Use this method in particular when the docId contain special characters such as slashes (/). *

	 * Params params = new Params()
	 *	.addParam("field", "foo")
	 *	.addParam("value", "bar"); 
	 * String output = dbClient.invokeUpdateHandler("designDoc/update1", "docId", params);
	 * 
* @param updateHandlerUri The Update Handler URI, in the format: designDoc/update1 * @param docId The document id to update. * @param query The query parameters as {@link Params}. * @return The output of the request. */ public String invokeUpdateHandler(String updateHandlerUri, String docId, Params params) { assertNotEmpty(updateHandlerUri, "uri"); assertNotEmpty(docId, "docId"); final String[] v = updateHandlerUri.split("/"); final String path = String.format("_design/%s/_update/%s/", v[0], v[1]); final URI uri = buildUri(getDBUri()).path(path).pathToEncode(docId).query(params).buildEncoded(); final HttpResponse response = client.executeRequest(new HttpPut(uri)); return streamToString(getStream(response)); } /** * Synchronize all design documents with the database. */ public void syncDesignDocsWithDb() { design().synchronizeAllWithDb(); } /** * @return The database URI. */ public URI getDBUri() { return dbURI; } // End - Public API /** * @return {@link CouchDbInfo} Containing the DB info. */ public CouchDbInfo info() { return client.get(buildUri(getDBUri()).build(), CouchDbInfo.class); } /** * Triggers a database compact request. */ public void compact() { HttpResponse response = null; try { response = client.post(buildUri(getDBUri()).path("_compact").build(), ""); } finally { close(response); } } /** * Requests the database commits any recent changes to disk. */ public void ensureFullCommit() { HttpResponse response = null; try { response = client.post(buildUri(getDBUri()).path("_ensure_full_commit").build(), ""); } finally { close(response); } } /** * @return the dbName */ public String getDbName() { return dbName; } private void connect(boolean create) { InputStream getresp = null; HttpResponse putresp = null; try { getresp = get(dbURI); } catch (NoDocumentException e) { // db doesn't exist if (!create) { throw e; } final HttpPut put = new HttpPut(dbURI); putresp = client.executeRequest(put); log.info(String.format("Created Database: '%s'", dbName)); } finally { close(getresp); close(putresp); } } // Helpers Gson getGson() { return client.getGson(); } InputStream get(HttpGet httpGet) { return client.get(httpGet); } T get(URI uri, Class classType) { return client.get(uri, classType); } InputStream get(URI uri) { return client.get(uri); } HttpResponse post(URI uri, String json) { return client.post(uri, json); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy