main.java.com.cloudant.client.api.Database Maven / Gradle / Ivy
Show all versions of cloudant-client Show documentation
/*
* Copyright (c) 2016 IBM Corp. All rights reserved.
*
* 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 com.cloudant.client.api;
import static com.cloudant.client.org.lightcouch.internal.CouchDbUtil.assertNotEmpty;
import static com.cloudant.client.org.lightcouch.internal.CouchDbUtil.assertNotNull;
import static com.cloudant.client.org.lightcouch.internal.CouchDbUtil.close;
import static com.cloudant.client.org.lightcouch.internal.CouchDbUtil.createPost;
import static com.cloudant.client.org.lightcouch.internal.CouchDbUtil.getAsString;
import static com.cloudant.client.org.lightcouch.internal.CouchDbUtil.getResponse;
import static com.cloudant.client.org.lightcouch.internal.CouchDbUtil.getResponseList;
import com.cloudant.client.api.model.DbInfo;
import com.cloudant.client.api.model.FindByIndexOptions;
import com.cloudant.client.api.model.Index;
import com.cloudant.client.api.model.IndexField;
import com.cloudant.client.api.model.Params;
import com.cloudant.client.api.model.Permissions;
import com.cloudant.client.api.model.Shard;
import com.cloudant.client.api.views.AllDocsRequestBuilder;
import com.cloudant.client.api.views.ViewRequestBuilder;
import com.cloudant.client.internal.DatabaseURIHelper;
import com.cloudant.client.internal.URIBase;
import com.cloudant.client.internal.util.DeserializationTypes;
import com.cloudant.client.internal.views.AllDocsRequestBuilderImpl;
import com.cloudant.client.internal.views.AllDocsRequestResponse;
import com.cloudant.client.internal.views.ViewQueryParameters;
import com.cloudant.client.org.lightcouch.CouchDatabase;
import com.cloudant.client.org.lightcouch.CouchDbException;
import com.cloudant.client.org.lightcouch.DocumentConflictException;
import com.cloudant.client.org.lightcouch.NoDocumentException;
import com.cloudant.client.org.lightcouch.Response;
import com.cloudant.http.Http;
import com.cloudant.http.HttpConnection;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;
/**
* Contains a Database Public API implementation.
*
* Methods may throw a {@link NoDocumentException} if the database does not exist.
*
* @author Mario Briggs
* @since 0.0.1
*/
public class Database {
static final Logger log = Logger.getLogger(Database.class.getCanonicalName());
private CouchDatabase db;
private CloudantClient client;
private final URI apiV2DBSecurityURI;
/**
* Internal constructor for creating a new Database instance.
*
* @param client the CloudantClient instance to connect with
* @param db the CouchDatabase for executing operations
*/
Database(CloudantClient client, CouchDatabase db) {
super();
this.client = client;
this.db = db;
apiV2DBSecurityURI = new URIBase(client.getBaseUri()).path("_api").path("v2").path("db")
.path(db.getDbName()).path("_security").build();
}
/**
* Constructor for subclasses that want to override Database methods. The supplied Database
* instance is used to instantiate the super class. As such for non-overridden methods the
* implementation of the extending class will be identical to the original Database instance.
*
* Usage example:
*
* {@code
* public class ExtendedDatabase extends Database {
* public ExtendedDatabase(Database database) {
* super(database);
* }
* }
* }
*
*
* @param db existing Database instance
* @since 2.3.0
*/
protected Database(Database db) {
this(db.client, db.db);
}
/**
* Set permissions for a user/apiKey on this database.
*
* Note this method is only applicable to databases that support the
*
* Cloudant authorization API
* such as Cloudant DBaaS. For unsupported databases consider using the /db/_security
* endpoint.
*
* Example usage to set read-only access for a new key on the "example" database:
*
* {@code
* // generate an API key
* ApiKey key = client.generateApiKey();
*
* // get the "example" database
* Database db = client.database("example", false);
*
* // set read-only permissions
* db.setPermissions(key.getKey(), EnumSet.of(Permissions._reader));
* }
*
*
* @param userNameorApikey the user or key to apply permissions to
* @param permissions permissions to grant
* @throws UnsupportedOperationException if called on a database that does not provide the
* Cloudant authorization API
* @see CloudantClient#generateApiKey()
* @see Roles
* @see Modifying
* permissions
*/
public void setPermissions(String userNameorApikey, EnumSet permissions) {
assertNotEmpty(userNameorApikey, "userNameorApikey");
assertNotEmpty(permissions, "permissions");
final JsonArray jsonPermissions = new JsonArray();
for (Permissions s : permissions) {
final JsonPrimitive permission = new JsonPrimitive(s.toString());
jsonPermissions.add(permission);
}
// get existing permissions
JsonObject perms = getPermissionsObject();
// now set back
JsonElement elem = perms.get("cloudant");
if (elem == null) {
perms.addProperty("_id", "_security");
elem = new JsonObject();
perms.add("cloudant", elem);
}
elem.getAsJsonObject().add(userNameorApikey, jsonPermissions);
HttpConnection put = Http.PUT(apiV2DBSecurityURI, "application/json");
put.setRequestBody(client.getGson().toJson(perms));
// CouchDbExceptions will be thrown for non-2XX cases
client.couchDbClient.executeToResponse(put);
}
/**
* @return /api/v2/db/$dbname/_security JSON data
* @throws UnsupportedOperationException if called on a database that does not provide the
* Cloudant authorization API
*/
private JsonObject getPermissionsObject() {
try {
return client.couchDbClient.get(apiV2DBSecurityURI, JsonObject.class);
} catch (CouchDbException exception) {
//currently we can't inspect the HttpResponse code
//being in this catch block means it was not a 20x code
//look for the "bad request" that implies the endpoint is not supported
if (exception.getMessage().toLowerCase(Locale.ENGLISH).contains("bad request")) {
throw new UnsupportedOperationException("The methods getPermissions and " +
"setPermissions are not supported for this database, consider using the " +
"/db/_security endpoint.");
} else {
throw exception;
}
}
}
/**
* Returns the Permissions of this database.
*
* Note this method is only applicable to databases that support the
*
* Cloudant authorization API
* such as Cloudant DBaaS. For unsupported databases consider using the /db/_security
* endpoint.
*
*
* @return the map of userNames to their Permissions
* @throws UnsupportedOperationException if called on a database that does not provide the
* Cloudant authorization API
* @see Roles
* @see Viewing
* permissions
*/
public Map> getPermissions() {
JsonObject perms = getPermissionsObject();
return client.getGson().getAdapter(DeserializationTypes.PERMISSIONS_MAP_TOKEN).fromJsonTree
(perms);
}
/**
* Get info about the shards in the database.
*
* @return List of shards
* @see _shards
*/
public List getShards() {
InputStream response = null;
try {
response = client.couchDbClient.get(new DatabaseURIHelper(db.getDBUri()).path("_shards")
.build());
return getResponseList(response, client.getGson(), DeserializationTypes.SHARDS);
} finally {
close(response);
}
}
/**
* Get info about the shard a document belongs to.
*
* @param docId document ID
* @return Shard info
* @see _shards
*/
public Shard getShard(String docId) {
assertNotEmpty(docId, "docId");
return client.couchDbClient.get(new DatabaseURIHelper(db.getDBUri()).path("_shards")
.path(docId).build(),
Shard.class);
}
/**
* Create a new index
*
* Example usage creating an index that sorts ascending on name, then by year.
*
*
* {@code
* db.createIndex("Person_name", "Person_name", null, new IndexField[]{
* new IndexField("Person_name",SortOrder.asc),
* new IndexField("Movie_year",SortOrder.asc)});
* }
*
*
* Example usage creating an index that sorts ascending by year.
*
*
* {@code
* db.createIndex("Movie_year", "Movie_year", null, new IndexField[]{
* new IndexField("Movie_year",SortOrder.asc)});
* }
*
*
* @param indexName optional name of the index (if not provided one will be generated)
* @param designDocName optional name of the design doc in which the index will be created
* @param indexType optional, type of index (only "json" as of now)
* @param fields array of fields in the index
*/
public void createIndex(String indexName, String designDocName, String indexType,
IndexField[] fields) {
JsonObject indexDefn = getIndexDefinition(indexName, designDocName, indexType, fields);
createIndex(indexDefn.toString());
}
/**
* Create a new index from a JSON string
*
* @param indexDefinition String representation of the index definition JSON
* @see #createIndex(String, String, String, IndexField[])
* @see
* index definition
*/
public void createIndex(String indexDefinition) {
assertNotEmpty(indexDefinition, "indexDefinition");
InputStream putresp = null;
URI uri = new DatabaseURIHelper(db.getDBUri()).path("_index").build();
try {
putresp = client.couchDbClient.executeToInputStream(createPost(uri, indexDefinition,
"application/json"));
String result = getAsString(putresp, "result");
if (result.equalsIgnoreCase("created")) {
log.info(String.format("Created Index: '%s'", indexDefinition));
} else {
log.warning(String.format("Index already exists : '%s'", indexDefinition));
}
} finally {
close(putresp);
}
}
/**
* Find documents using an index
*
* @param selectorJson String representation of a JSON object describing criteria used to
* select documents. For example:
* {@code "{ \"selector\": {} }"}.
* @param classOfT The class of Java objects to be returned
* @param the type of the Java object to be returned
* @return List of classOfT objects
* @see #findByIndex(String, Class, FindByIndexOptions)
* @see
* selector syntax
*/
public List findByIndex(String selectorJson, Class classOfT) {
return findByIndex(selectorJson, classOfT, new FindByIndexOptions());
}
/**
* Find documents using an index
*
* Example usage to return the name and year of movies starring
* Alec Guinness since 1960 with the results sorted by year descending:
*
*
* {@code
* List movies = db.findByIndex("\"selector\": {
* \"Movie_year\": {\"$gt\": 1960}, \"Person_name\": \"Alec Guinness\"
* }",
* Movie.class,
* new FindByIndexOptions()
* .sort(new IndexField("Movie_year", SortOrder.desc))
* .fields("Movie_name").fields("Movie_year"));
* }
*
*
* @param selectorJson String representation of a JSON object describing criteria used to
* select documents. For example:
* {@code "{ \"selector\": {} }"}.
* @param options {@link FindByIndexOptions query Index options}
* @param classOfT The class of Java objects to be returned
* @param the type of the Java object to be returned
* @return List of classOfT objects
* @see
* selector syntax
*/
public List findByIndex(String selectorJson, Class classOfT, FindByIndexOptions
options) {
assertNotNull(selectorJson, "selectorJson");
// If it wasn't null we can safely trim
selectorJson = selectorJson.trim();
assertNotEmpty(selectorJson, "selectorJson");
assertNotEmpty(options, "options");
URI uri = new DatabaseURIHelper(db.getDBUri()).path("_find").build();
JsonObject body = getFindByIndexBody(selectorJson, options);
InputStream stream = null;
try {
stream = client.couchDbClient.executeToInputStream(createPost(uri, body.toString(),
"application/json"));
Reader reader = new InputStreamReader(stream, "UTF-8");
JsonArray jsonArray = new JsonParser().parse(reader)
.getAsJsonObject().getAsJsonArray("docs");
List list = new ArrayList();
for (JsonElement jsonElem : jsonArray) {
JsonElement elem = jsonElem.getAsJsonObject();
T t = client.getGson().fromJson(elem, classOfT);
list.add(t);
}
return list;
} catch (UnsupportedEncodingException e) {
// This should never happen as every implementation of the java platform is required
// to support UTF-8.
throw new RuntimeException(e);
} finally {
close(stream);
}
}
/**
* List all indices
* Example usage:
*
* {@code
* List indices = db.listIndices();
* }
*
*
* @return List of Index objects
*/
public List listIndices() {
InputStream response = null;
try {
URI uri = new DatabaseURIHelper(db.getDBUri()).path("_index").build();
response = client.couchDbClient.get(uri);
return getResponseList(response, client.getGson(), DeserializationTypes.INDICES);
} finally {
close(response);
}
}
/**
* Delete an index
*
* @param indexName name of the index
* @param designDocId ID of the design doc
*/
public void deleteIndex(String indexName, String designDocId) {
assertNotEmpty(indexName, "indexName");
assertNotEmpty(designDocId, "designDocId");
URI uri = new DatabaseURIHelper(db.getDBUri()).path("_index").path(designDocId)
.path("json").path(indexName).build();
InputStream response = null;
try {
HttpConnection connection = Http.DELETE(uri);
response = client.couchDbClient.executeToInputStream(connection);
getResponse(response, Response.class, client.getGson());
} finally {
close(response);
}
}
/**
* Provides access to Cloudant Search APIs.
*
* @param searchIndexId the name of the index to search
* @return Search object for searching the index
* @see Search
*/
public Search search(String searchIndexId) {
return new Search(client, this, searchIndexId);
}
/**
* Get a manager that has convenience methods for managing design documents.
*
* @return a {@link DesignDocumentManager} for this database
* @see DesignDocumentManager
*/
public DesignDocumentManager getDesignDocumentManager() {
return new DesignDocumentManager(client, this);
}
/**
* @param designDoc containing the view
* @param viewName the view name
* @return a builder to build view requests for the specified design document and view of
* this database
* @see Using views
*/
public ViewRequestBuilder getViewRequestBuilder(String designDoc, String viewName) {
return new ViewRequestBuilder(client, this, designDoc, viewName);
}
/**
* Build a request for the _all_docs endpoint.
*
* Example usage:
*
*
* {@code
* getAllDocsRequestBuilder().build().getResponse();
* }
*
*
* @return a request builder for the _all_docs endpoint of this database
*/
public AllDocsRequestBuilder getAllDocsRequestBuilder() {
return new AllDocsRequestBuilderImpl(new ViewQueryParameters(client, this, "", "", String.class,
AllDocsRequestResponse.Revision.class) {
protected DatabaseURIHelper getViewURIBuilder() {
return new DatabaseURIHelper(db.getDBUri()).path("_all_docs");
}
});
}
/**
* Provides access for interacting with the changes feed.
*
* See the {@link com.cloudant.client.api.Changes} API for examples.
*
*
* @return a Changes object for using the changes feed
* @see com.cloudant.client.api.Changes
* @see Databases - get
* changes
*/
public Changes changes() {
return new Changes(client, this);
}
/**
* Retrieve the document with the specified ID from the database and deserialize to an
* instance of the POJO of type T.
*
* @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
* @see #find(Class, String, String)
* @see Documents -
* read
*/
public T find(Class classType, String id) {
return db.find(classType, id);
}
/**
* Retrieve the document with the specified ID from the database and deserialize to an
* instance of the POJO of type T. Uses the additional parameters specified when making the
* {@code GET} request.
* Example usage to get inline attachments:
*
* {@code
* Foo foo = db.find(Foo.class, "exampleId", new Params().attachments());
* String attachmentData = foo.getAttachments().get("attachment.txt").getData();
* }
*
*
* @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.
* @see Params
* @see Documents -
* read
*/
public T find(Class classType, String id, Params params) {
assertNotEmpty(params, "params");
return db.find(classType, id, params.getInternalParams());
}
/**
* Retrieve the document with the specified ID at the specified revision from the database
* and deserialize to an instance of the POJO of type T.
* Example usage:
*
* {@code
* Foo foo = db.find(Foo.class, "exampleId", "1-12345exampleRev");
* }
*
*
* @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.
* @see Documents -
* read
*/
public T find(Class classType, String id, String rev) {
return db.find(classType, id, rev);
}
/**
* This method finds any document given a URI.
* The URI must be URI-encoded.
*
* Example usage retrieving the Foo POJO with document ID "exampleId" from the database
* "exampleDb" in the "example" Cloudant account.
*
*
* {@code
* Foo foo = db.findAny(Foo.class, "https://example.cloudant.com/exampleDb/exampleId");
* }
*
*
* @param classType the class of type T
* @param uri the URI as string
* @param the type of Java object to return
* @return an object of type T
*/
public T findAny(Class classType, String uri) {
return db.findAny(classType, uri);
}
/**
* Finds the document with the specified document ID and returns it as an {@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) {
return db.find(id);
}
/**
* Finds the document with the specified document ID and revision and returns it as {@link
* InputStream}.
* Note: The stream must be closed after use to release the connection.
* Example usage:
*
* {@code
* InputStream inputStream = null;
* try{
* inputStream = db.find("exampleId", "1-12345exampleRev");
* //do stuff with the stream
* } finally {
* //close the input stream
* inputStream.close();
* }
* }
*
*
* @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 at the specified
* revision
* @see Documents -
* read
*/
public InputStream find(String id, String rev) {
return db.find(id, rev);
}
/**
* Checks if a document exists in the database.
*
* @param id the document _id field
* @return {@code true} if the document is found, {@code false} otherwise
*/
public boolean contains(String id) {
return db.contains(id);
}
/**
* Saves a document in the database.
* If the serialized object's JSON does not contain an {@code _id} field, then a UUID will
* be generated for the document ID.
*
*
* Example of inserting a JsonObject into the database:
*
*
* {@code
* JsonObject json = new JsonObject();
* json.addProperty("_id", "test-doc-id-2");
* json.add("json-array", new JsonArray());
* Response response = db.save(json);
* }
*
*
* Example of inserting a POJO into the database:
*
*
* {@code
* Foo foo = new Foo();
* Response response = db.save(foo);
* }
*
*
* Example of inserting a Map into the database:
*
*
* {@code
* Map map = new HashMap<>();
* map.put("_id", "test-doc-id-1");
* map.put("title", "test-doc");
* Response response = db.save(map);
* }
*
*
*
* Note that the Java object is not modified by the save operation and so will not include the
* revision generated by the database server. You can obtain the server revision for this write
* from the response, for example:
*
*
* {@code
* Foo foo = new Foo();
* Response response = db.save(foo);
* foo.setRevision(response.getRevision());
* }
*
*
* @param object the object to save
* @return {@link com.cloudant.client.api.model.Response}
* @throws DocumentConflictException If a conflict is detected during the save.
*/
public com.cloudant.client.api.model.Response save(Object object) {
Response couchDbResponse = db.save(object);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Saves a document in the database similarly to {@link Database#save(Object)} but using a
* specific write quorum.
*
* @param object the object to save
* @param writeQuorum the write quorum
* @return {@link com.cloudant.client.api.model.Response}
* @throws DocumentConflictException If a conflict is detected during the save.
* @see Database#save(Object)
* @see
* Documents - quorum
*/
public com.cloudant.client.api.model.Response save(Object object, int writeQuorum) {
Response couchDbResponse = client.couchDbClient.put(getDBUri(), object, true, writeQuorum);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Creates a document in the database using a HTTP {@code POST} request.
* If the serialized object's JSON does not contain an {@code _id} field, then the server
* will generate a document ID.
*
* Example of creating a document in the database for a POJO:
*
*
* {@code
* Foo foo = new Foo();
* Response response = db.post(foo);
* }
*
*
* Note that the Java object is not modified by the create operation and so will not include the
* revision generated by the database server. You can obtain the server revision for this write
* from the response, for example:
*
*
* {@code
* Foo foo = new Foo();
* Response response = db.post(foo);
* foo.setRevision(response.getRevision());
* }
*
*
* @param object The object to save
* @return {@link com.cloudant.client.api.model.Response}
* @see Documents - create
*/
public com.cloudant.client.api.model.Response post(Object object) {
Response couchDbResponse = db.post(object);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Creates a document in the database similarly to {@link Database#post(Object)} but using a
* specific write quorum.
*
* @param object The object to save
* @param writeQuorum the write Quorum
* @return {@link com.cloudant.client.api.model.Response}
* @see Database#post(Object)
* @see
* Documents - quorum
*/
public com.cloudant.client.api.model.Response post(Object object, int writeQuorum) {
assertNotEmpty(object, "object");
InputStream response = null;
try {
URI uri = new DatabaseURIHelper(db.getDBUri()).query("w", writeQuorum).build();
response = client.couchDbClient.executeToInputStream(createPost(uri, client.getGson()
.toJson(object),
"application/json"));
Response couchDbResponse = getResponse(response, Response.class, client.getGson());
com.cloudant.client.api.model.Response cloudantResponse = new com.cloudant.client.api
.model.Response(couchDbResponse);
return cloudantResponse;
} finally {
close(response);
}
}
/**
* Updates an object in the database, the object must have the correct {@code _id} and
* {@code _rev} values.
* Example usage:
*
* {@code
* //get a Bar object from the database
* Bar bar = db.find(Bar.class, "exampleId");
* //change something about bar
* bar.setSomeProperty(true);
* //now update the remote Bar
* Response responseUpdate = db.update(bar);
* }
*
*
* Note that the Java object is not modified by the update operation and so will not include the
* revision generated by the database server. You can obtain the server revision for this write
* from the response, for example:
*
*
* {@code
* Foo foo = new Foo();
* Response response = db.update(foo);
* foo.setRevision(response.getRevision());
* }
*
*
* @param object the object to update
* @return {@link com.cloudant.client.api.model.Response}
* @throws DocumentConflictException if a conflict is detected during the update.
* @see Documents -
* update
*/
public com.cloudant.client.api.model.Response update(Object object) {
Response couchDbResponse = db.update(object);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Updates an object in the database similarly to {@link #update(Object)}, but specifying the
* write quorum.
*
* @param object the object to update
* @param writeQuorum the write quorum
* @return {@link com.cloudant.client.api.model.Response}
* @throws DocumentConflictException if a conflict is detected during the update.
* @see Database#update(Object)
* @see
* Documents - quorum
*/
public com.cloudant.client.api.model.Response update(Object object, int writeQuorum) {
Response couchDbResponse = client.couchDbClient.put(getDBUri(), object, false, writeQuorum);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Removes a document from the database.
* The object must have the correct {@code _id} and {@code _rev} values.
* Example usage:
*
* {@code
* //get a Bar object from the database
* Bar bar = db.find(Bar.class, "exampleId");
* //now remove the remote Bar
* Response response = db.remove(bar);
* }
*
*
* @param object the document to remove as an object
* @return {@link com.cloudant.client.api.model.Response}
* @throws NoDocumentException If the document is not found in the database.
* @see Documents -
* delete
*/
public com.cloudant.client.api.model.Response remove(Object object) {
Response couchDbResponse = db.remove(object);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Removes the document from the database with the specified {@code _id} and {@code _rev}
* values.
* Example usage:
*
* {@code
* Response response = db.remove("exampleId", "1-12345exampleRev");
* }
*
*
* @param id the document _id field
* @param rev the document _rev field
* @return {@link com.cloudant.client.api.model.Response}
* @throws NoDocumentException If the document is not found in the database.
* @see Documents -
* delete
*/
public com.cloudant.client.api.model.Response remove(String id, String rev) {
Response couchDbResponse = db.remove(id, rev);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Uses the {@code _bulk_docs} endpoint to insert multiple documents into the database in a
* single HTTP request.
* Example usage:
*
* {@code
* //create a list
* List
*
* @param objects the {@link List} of objects
* @return {@code List} one per object
* @see
* Documents - bulk operations
*/
public List bulk(List> objects) {
List couchDbResponseList = db.bulk(objects, false);
List cloudantResponseList = new ArrayList();
for (Response couchDbResponse : couchDbResponseList) {
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
cloudantResponseList.add(response);
}
return cloudantResponseList;
}
/**
* Creates an attachment from the specified InputStream and a new document with a generated
* document ID.
* Example usage:
*
* {@code
* byte[] bytesToDB = "binary data".getBytes();
* ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesToDB);
* Response response = db.saveAttachment(bytesIn, "foo.txt", "text/plain");
* }
*
* To retrieve an attachment, see {@link #find(Class, String, Params)}
*
* @param in The {@link InputStream} providing the binary data.
* @param name The attachment name.
* @param contentType The attachment "Content-Type".
* @return {@link com.cloudant.client.api.model.Response}
* @see Attachments
*/
public com.cloudant.client.api.model.Response saveAttachment(InputStream in, String name,
String contentType) {
Response couchDbResponse = db.saveAttachment(in, name, contentType);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Creates or updates an attachment on the given document ID and revision.
*
* If {@code docId} and {@code docRev} are {@code null} a new document will be created.
*
*
* Example usage:
*
*
* {@code
* byte[] bytesToDB = "binary data".getBytes();
* ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesToDB);
* Response response = db.saveAttachment(bytesIn, "foo.txt", "text/plain","exampleId","3-rev");
* }
*
* 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(Class, String, Params)}
*
* @param in The {@link InputStream} providing 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 with a generated ID.
* @param docRev The document revision to save the attachment under, or {@code null}
* when saving to a new document.
* @return {@link Response}
* @throws DocumentConflictException if the attachment cannot be saved because of a conflict
* @see Attachments
*/
public com.cloudant.client.api.model.Response saveAttachment(InputStream in, String name,
String contentType, String
docId, String docRev) {
Response couchDbResponse = db.saveAttachment(in, name, contentType, docId, docRev);
com.cloudant.client.api.model.Response response = new com.cloudant.client.api.model
.Response(couchDbResponse);
return response;
}
/**
* Invokes an Update Handler.
* Example usage:
*
* {@code
* final String newValue = "foo bar";
* Params params = new Params()
* .addParam("field", "title")
* .addParam("value", newValue);
* String output = db.invokeUpdateHandler("example/example_update", "exampleId", params);
*
* }
*
*
* 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.
* If no id is provided, then a document will be created.
* @param params The query parameters as {@link Params}.
* @return The output of the request.
* @see
* Design documents - update handlers
*/
public String invokeUpdateHandler(String updateHandlerUri, String docId,
Params params) {
assertNotEmpty(params, "params");
return db.invokeUpdateHandler(updateHandlerUri, docId, params.getInternalParams());
}
/**
* @return The database URI.
*/
public URI getDBUri() {
return db.getDBUri();
}
/**
* Get information about this database.
*
* @return DbInfo encapsulating the database info
* @see Databases -
* read
*/
public DbInfo info() {
return client.couchDbClient.get(new DatabaseURIHelper(db.getDBUri()).getDatabaseUri(),
DbInfo.class);
}
/**
* Requests the database commits any recent changes to disk.
*
* @see
* CouchDB _ensure_full_commit
*
*/
public void ensureFullCommit() {
db.ensureFullCommit();
}
// private helper methods
/**
* Form a create index json from parameters
*/
private JsonObject getIndexDefinition(String indexName, String designDocName,
String indexType, IndexField[] fields) {
assertNotEmpty(fields, "index fields");
JsonObject indexObject = new JsonObject();
if (!(indexName == null || indexName.isEmpty())) {
indexObject.addProperty("name", indexName);
}
if (!(designDocName == null || designDocName.isEmpty())) {
indexObject.addProperty("ddoc", designDocName);
}
if (!(indexType == null || indexType.isEmpty())) {
indexObject.addProperty("type", indexType);
}
JsonArray fieldsArray = new JsonArray();
for (int i = 0; i < fields.length; i++) {
JsonObject fieldObject = new JsonObject();
fieldObject.addProperty(fields[i].getName(), fields[i].getOrder().toString());
fieldsArray.add(fieldObject);
}
JsonObject arrayOfFields = new JsonObject();
arrayOfFields.add("fields", fieldsArray);
indexObject.add("index", arrayOfFields);
return indexObject;
}
private JsonObject getFindByIndexBody(String selectorJson,
FindByIndexOptions options) {
JsonArray fieldsArray = new JsonArray();
if (options.getFields().size() > 0) {
for (String field : options.getFields()) {
JsonPrimitive jsonField = client.getGson().fromJson(field,
JsonPrimitive.class);
fieldsArray.add(jsonField);
}
}
JsonArray sortArray = new JsonArray();
if (options.getSort().size() > 0) {
for (IndexField sort : options.getSort()) {
JsonObject sortObject = new JsonObject();
sortObject.addProperty(sort.getName(), sort.getOrder().toString());
sortArray.add(sortObject);
}
}
JsonObject indexObject = new JsonObject();
//parse and find if valid json issue #28
JsonObject selectorObject = null;
boolean isObject = true;
try {
selectorObject = getGson().fromJson(selectorJson, JsonObject.class);
} catch (JsonParseException e) {
isObject = false;
}
if (!isObject) {
if (selectorJson.startsWith("\"selector\"")) {
selectorJson = selectorJson.substring(selectorJson.indexOf(":") + 1,
selectorJson.length()).trim();
selectorObject = getGson().fromJson(selectorJson, JsonObject.class);
} else {
throw new JsonParseException("selectorJson should be valid json or like " +
"\"selector\": {...} ");
}
}
if (selectorObject.has("selector")) {
indexObject.add("selector", selectorObject.get("selector"));
} else {
indexObject.add("selector", selectorObject);
}
if (fieldsArray.size() > 0) {
indexObject.add("fields", fieldsArray);
}
if (sortArray.size() > 0) {
indexObject.add("sort", sortArray);
}
if (options.getLimit() != null) {
indexObject.addProperty("limit", options.getLimit());
}
if (options.getSkip() != null) {
indexObject.addProperty("skip", options.getSkip());
}
if (options.getReadQuorum() != null) {
indexObject.addProperty("r", options.getReadQuorum());
}
if (options.getUseIndex() != null) {
indexObject.add("use_index", getGson().fromJson(options.getUseIndex(),
JsonElement.class));
}
return indexObject;
}
Gson getGson() {
return client.getGson();
}
}