LCOV - code coverage report
Current view: top level - lib/src - wilt.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 198 234 84.6 %
Date: 2017-07-19 Functions: 0 0 -

          Line data    Source code
       1             : /*
       2             :  * Package : Wilt
       3             :  * Author : S. Hamblett <steve.hamblett@linux.com>
       4             :  * Date   : 04/06/2013
       5             :  * Copyright :  S.Hamblett@OSCF
       6             :  *
       7             :  * The Wilt class provides core functionality for interacting with CouchDB databases from
       8             :  * both the browser and the server. Wilt should not be instantiated standalone but rather through
       9             :  * inclusion of one of the wilt_browser_client or wilt_server_client files.
      10             :  * 
      11             :  * Further documentation can be found in the docs folder.
      12             :  * 
      13             :  */
      14             : 
      15             : part of wilt;
      16             : 
      17             : class Wilt {
      18             :   /// URL constant for CouchDB SESSION function
      19             :   static const String session = "/_session";
      20             : 
      21             :   /// URL constant for CouchDB STATS function
      22             :   static const String stats = "/_stats";
      23             : 
      24             :   /// URL constant for CouchDB ALLDBS function
      25             :   static const String alldbs = "/_all_dbs";
      26             : 
      27             :   /// URL constant for CouchDB ALLDOCS function
      28             :   static const String alldocs = "/_all_docs";
      29             : 
      30             :   /// URL constant for CouchDB BULKDOCS function
      31             :   static const String bulkdocs = "/_bulk_docs";
      32             : 
      33             :   /// URL constant for CouchDB UUID function
      34             :   static const String uuids = "/_uuids";
      35             : 
      36             :   /// Etag header
      37             :   static const String etag = 'etag';
      38             : 
      39             :   /// AUTH_BASIC denotes Basic HTTP authentication.
      40             :   /// If login is called AUTH_BASIC is set, otherwise it defaults to AUTH_NONE
      41             :   static const String authBasic = 'basic';
      42             : 
      43             :   /// No authentication
      44             :   static const String authNone = 'none';
      45             : 
      46             :   /// Operation types and method definitions
      47             :   static const String gett = 'GET_GET';
      48             :   static const String headd = 'HEAD_HEAD';
      49             :   static const String postt = 'POST_POST';
      50             :   static const String putt = 'PUT_PUT';
      51             :   static const String deletee = 'DELETE_DELETE';
      52             :   static const String copy = 'COPY_COPY';
      53             :   static const String getDocumentt = 'GET_DOCUMENT';
      54             :   static const String deleteDocumentt = 'DELETE_DOCUMENT';
      55             :   static const String putDocumentt = 'PUT_DOCUMENT';
      56             :   static const String postDocumentt = 'POST_DOCUMENT';
      57             :   static const String postDocumentStringg = 'POST_DOCUMENTSTRING';
      58             :   static const String copyDocumentt = 'COPY_DOCUMENT';
      59             :   static const String getAllDocss = 'GET_ALLDOCS';
      60             :   static const String bulkk = 'POST_BULK';
      61             :   static const String bulkStringg = 'POST_BULKSTRING';
      62             :   static const String createDatabasee = 'PUT_DATABASE';
      63             :   static const String deleteDatabasee = 'DELETE_DATABASE';
      64             :   static const String databaseInfo = 'GET_DATABASEINFO';
      65             :   static const String getSessionn = 'GET_SESSION';
      66             :   static const String getStatss = 'GET_STATS';
      67             :   static const String getAllDbss = 'GET_ALLDBS';
      68             :   static const String createAttachmentt = 'PUT_CREATEATTACH';
      69             :   static const String updateAttachmentt = 'PUT_UPDATEATTACH';
      70             :   static const String deleteAttachmentt = 'DELETE_ATTACH';
      71             :   static const String getAttachmentt = 'GET_ATTACH';
      72             :   static const String generateIdss = 'GET_IDS';
      73             : 
      74             :   /// Please use the wilt_browser_client or wilt_server_client import files to
      75             :   /// instantiate a Wilt object for use in either the browser or server environment.
      76             :   /// You can do this here but you must supply either a browser or server HTTP adapter
      77             :   /// to use.
      78             :   Wilt(this._host, this._port, this._scheme, this._httpAdapter,
      79           1 :       [this._clientCompletion = null]) {
      80           3 :     if ((host == null) || (port == null) || (scheme == null)) {
      81           1 :       throw new WiltException(WiltException.badConstParams);
      82             :     }
      83             : 
      84           1 :     if (_httpAdapter == null) {
      85           0 :       throw new WiltException(WiltException.badConstNoAdapter);
      86             :     }
      87             :   }
      88             : 
      89             :   /// Database name
      90             :   String _db = null;
      91           1 :   String get db => _db;
      92           1 :   set db(String name) => _db = name;
      93             : 
      94             :   /// Change notification database name
      95             :   String changeNotificationDbName = null;
      96             : 
      97             :   /// Host name
      98             :   String _host = null;
      99           1 :   String get host => _host;
     100             : 
     101             :   /// Port number
     102             :   String _port = null;
     103           1 :   String get port => _port;
     104             : 
     105             :   /// HTTP scheme
     106             :   String _scheme = null;
     107           1 :   String get scheme => _scheme;
     108             : 
     109             :   /// HTTP Adapter
     110             :   WiltHTTPAdapter _httpAdapter = null;
     111           0 :   set httpAdapter(WiltHTTPAdapter adapter) => _httpAdapter = adapter;
     112           0 :   WiltHTTPAdapter get httpAdapter => _httpAdapter;
     113             : 
     114             :   /// Change notification
     115             :   _WiltChangeNotification _changeNotifier = null;
     116             : 
     117             :   /// Change notification event stream
     118             :   /// This is a broadcast stream so can support more than one listener.
     119             :   Stream<WiltChangeNotificationEvent> get changeNotification =>
     120           3 :       _changeNotifier.changeNotification.stream;
     121             : 
     122             :   /// Change notification paused state
     123           2 :   bool get changeNotificationsPaused => _changeNotifier.pause;
     124             : 
     125             :   /// Completion function
     126             :   var _clientCompletion = null;
     127             : 
     128             :   /// Completion callback
     129             :   set resultCompletion(final Object completion) {
     130           0 :     _clientCompletion = completion;
     131             :   }
     132             : 
     133             :   /// Response getter for completion callbacks
     134             :   jsonobject.JsonObject _completionResponse;
     135           0 :   jsonobject.JsonObject get completionResponse => _completionResponse;
     136             : 
     137             :   /// Authentication, user name
     138             :   String _user = null;
     139             : 
     140             :   /// Authentication, user password
     141             :   String _password = null;
     142             : 
     143             :   /// Authentication, type
     144             :   String authenticationType = authNone;
     145             : 
     146             :   /// The internal HTTP request method. This wraps the
     147             :   /// HTTP adapter class.
     148             :   Future<jsonobject.JsonObject> _httpRequest(String method, String url,
     149             :       {String data: null, Map headers: null}) {
     150             :     /* Build the request for the HttpAdapter*/
     151           1 :     final Map wiltHeaders = new Map<String, String>();
     152           1 :     wiltHeaders["Accept"] = "application/json";
     153           1 :     if (headers != null) wiltHeaders.addAll(headers);
     154             : 
     155             :     /* Build the URL */
     156           4 :     final String wiltUrl = "$scheme$host:$port$url";
     157             : 
     158             :     /* Check for authentication */
     159           1 :     if (_user != null) {
     160           1 :       switch (authenticationType) {
     161           1 :         case authBasic:
     162           3 :           final String authStringToEncode = "$_user:$_password";
     163             :           final String encodedAuthString =
     164           2 :               CryptoUtils.bytesToBase64(authStringToEncode.codeUnits);
     165           1 :           final String authString = "Basic $encodedAuthString";
     166           1 :           wiltHeaders['Authorization'] = authString;
     167             :           break;
     168             : 
     169           0 :         case authNone:
     170             :           break;
     171             :       }
     172             :     }
     173             : 
     174             :     /* Execute the request*/
     175             :     final Future<jsonobject.JsonObject> completion =
     176           2 :         _httpAdapter.httpRequest(method, wiltUrl, data, wiltHeaders)
     177           1 :           ..then((jsonResponse) {
     178           1 :             if (_clientCompletion != null) {
     179           0 :               _completionResponse = jsonResponse;
     180           0 :               _clientCompletion();
     181             :             }
     182             :           });
     183             : 
     184             :     return completion;
     185             :   }
     186             : 
     187             :   /// Takes a URL and key/value pair for a URL parameter and adds this
     188             :   /// to the query parameters of the URL.
     189             :   String _setURLParameter(String url, String key, String value) {
     190           1 :     final originalUrl = Uri.parse(url);
     191           1 :     final Map queryParams = originalUrl.queryParameters;
     192           1 :     final Map newQueryParams = new Map<String, String>.from(queryParams);
     193           1 :     newQueryParams[key] = value;
     194             : 
     195           1 :     final newUrl = new Uri(
     196           1 :         scheme: originalUrl.scheme,
     197           1 :         userInfo: originalUrl.userInfo,
     198           1 :         host: originalUrl.host,
     199           1 :         port: originalUrl.port,
     200           1 :         path: originalUrl.path,
     201             :         queryParameters: newQueryParams);
     202             : 
     203           1 :     final String returnUrl = newUrl.toString();
     204             :     return returnUrl /* Private */;
     205             :   }
     206             : 
     207             :   /// Conditions the URL for use by Wilt and checks for
     208             :   /// a valid database by default.
     209             :   String _conditionUrl(String url) {
     210           1 :     if (db == null) {
     211             :       return WiltException.noDatabaseSpecified;
     212             :     }
     213             :     if (url == null) {
     214             :       return '/';
     215             :     }
     216             :     String urlRet = url;
     217             :     /* The first char of the URL should be a slash. */
     218           1 :     if (!url.startsWith('/')) {
     219           1 :       urlRet = "/$urlRet";
     220             :     }
     221           1 :     if (db != null) {
     222           2 :       urlRet = "/$db$urlRet";
     223             :     }
     224             :     return urlRet;
     225             :   }
     226             : 
     227             :   /// Raise an exception from a future API call.
     228             :   /// If we are using completion throw an exception as normal.
     229             :   Future<WiltException> _raiseException(String name) {
     230           1 :     if (_clientCompletion == null) {
     231           2 :       return new Future.error(new WiltException(name));
     232             :     } else {
     233           0 :       throw new WiltException(name);
     234             :     }
     235             :   }
     236             : 
     237             :   /// Basic method where only a URL and a method is passed.
     238             :   /// Wilt applies no checks to this URL nor does it add the
     239             :   /// database, the format of this is entirely up to the user.
     240             :   ///
     241             :   /// This can be used for CouchDb functions that are not directly supported by Wilt,
     242             :   /// e.g views, attachments and design documents.
     243             :   Future<jsonobject.JsonObject> httpRequest(String url,
     244             :       {String method: "GET"}) {
     245           1 :     return _httpRequest(method, url);
     246             :   }
     247             : 
     248             :   /// Performs an HTTP GET operation, the URL is conditioned and
     249             :   /// the current database added.
     250             :   Future get(String url) {
     251           1 :     final String url1 = _conditionUrl(url);
     252           1 :     if (url1 == WiltException.noDatabaseSpecified) {
     253           1 :       return _raiseException(WiltException.noDatabaseSpecified);
     254             :     }
     255             : 
     256             :     /* Perform the get */
     257           0 :     return _httpRequest('GET', url1);
     258             :   }
     259             : 
     260             :   /// Performs a HTTP HEAD operation, the URL is conditioned and
     261             :   /// the current database added.
     262             :   Future head(String url) {
     263           1 :     final String url1 = _conditionUrl(url);
     264           1 :     if (url1 == WiltException.noDatabaseSpecified) {
     265           1 :       return _raiseException(WiltException.noDatabaseSpecified);
     266             :     }
     267             : 
     268             :     /* Perform the head */
     269           1 :     return _httpRequest(headd, url1);
     270             :   }
     271             : 
     272             :   /// Performs a HTTP POST operation,, the URL is conditioned and
     273             :   /// the current database added.
     274             :   Future post(String url, String data, [Map headers]) {
     275           1 :     final String url1 = _conditionUrl(url);
     276           1 :     if (url1 == WiltException.noDatabaseSpecified) {
     277           1 :       return _raiseException(WiltException.noDatabaseSpecified);
     278             :     }
     279             : 
     280             :     /* Perform the post */
     281           0 :     return _httpRequest('POST', url1, data: data, headers: headers);
     282             :   }
     283             : 
     284             :   /// Performs a HTTP PUT operation,, the URL is conditioned and
     285             :   /// the current database added.
     286             :   Future put(String url, String data, [Map headers]) {
     287           1 :     final String url1 = _conditionUrl(url);
     288           1 :     if (url1 == WiltException.noDatabaseSpecified) {
     289           1 :       return _raiseException(WiltException.noDatabaseSpecified);
     290             :     }
     291             : 
     292             :     /* Perform the put */
     293           0 :     return _httpRequest('PUT', url1, data: data, headers: headers);
     294             :   }
     295             : 
     296             :   /// Performs a HTTP DELETE operation,, the URL is conditioned and
     297             :   /// the current database added.
     298             :   Future delete(String url) {
     299           1 :     final String url1 = _conditionUrl(url);
     300           1 :     if (url1 == WiltException.noDatabaseSpecified) {
     301           1 :       return _raiseException(WiltException.noDatabaseSpecified);
     302             :     }
     303             : 
     304             :     /* Perform the delete */
     305           0 :     return _httpRequest('DELETE', url1);
     306             :   }
     307             : 
     308             :   /// Performs an HTTP GET operation for the supplied document id and
     309             :   /// optional revision. If withAttachments is set the the body of
     310             :   /// any attachments are also supplied, note this could make this
     311             :   /// a large transfer.
     312             :   Future getDocument(String id,
     313             :       [String rev = null, bool withAttachments = false]) {
     314             :     if (id == null) {
     315           1 :       return _raiseException(WiltException.getDocNoId);
     316             :     }
     317             : 
     318             :     String url = id;
     319             :     if (rev != null) {
     320           0 :       url = _setURLParameter(url, 'rev', rev);
     321             :     }
     322             : 
     323             :     if (withAttachments) {
     324           1 :       url = _setURLParameter(url, 'attachments', 'true');
     325             :     }
     326             : 
     327           1 :     url = _conditionUrl(url);
     328           1 :     return _httpRequest('GET_DOCUMENT', url);
     329             :   }
     330             : 
     331             :   /// Gets a documents current revision, returns null if
     332             :   /// the document does not exist.
     333             :   Future getDocumentRevision(String id) {
     334             :     if (id == null) {
     335           1 :       return _raiseException(WiltException.getDocRevNoId);
     336             :     }
     337             : 
     338           1 :     final Completer completer = new Completer();
     339           2 :     head(id).then((res) {
     340             :       final jsonobject.JsonObject headers =
     341           2 :           new jsonobject.JsonObject.fromMap(res.allResponseHeaders);
     342             :       if (headers != null) {
     343           1 :         if (headers.containsKey(etag)) {
     344           1 :           String ver = headers.etag;
     345           3 :           ver = ver.substring(1, ver.length - 1);
     346           1 :           completer.complete(ver);
     347             :         } else {
     348           0 :           completer.complete(null);
     349             :         }
     350             :       }
     351             :     });
     352             : 
     353           1 :     return completer.future;
     354             :   }
     355             : 
     356             :   /// DELETE's the specified document. Must have a revision.
     357             :   /// If preserve is set to true the whole document is preserved
     358             :   /// and marked as deleted otherwise only a stub document is
     359             :   /// kept. Default is to not preserve.
     360             :   Future deleteDocument(String id, String rev, [bool preserve = false]) {
     361             :     if ((id == null) || (rev == null)) {
     362           1 :       return _raiseException(WiltException.deleteDocNoIdRev);
     363             :     }
     364           1 :     final Completer completer = new Completer();
     365             : 
     366             :     /* Check the preserve flag */
     367             :     if (preserve) {
     368           2 :       getDocument(id).then((jsonobject.JsonObject res) {
     369             :         if (res != null) {
     370           1 :           jsonobject.JsonObject resp = res.jsonCouchResponse;
     371           1 :           resp = WiltUserUtils.addDocumentDeleteJo(resp);
     372           2 :           putDocument(id, resp).then((res1) {
     373           1 :             completer.complete(res1);
     374             :           });
     375             :         } else {
     376           0 :           completer.complete(null);
     377             :         }
     378             :       });
     379           1 :       return completer.future;
     380             :     } else {
     381             :       String url = id;
     382           1 :       url = _setURLParameter(url, 'rev', rev);
     383           1 :       url = _conditionUrl(url);
     384           1 :       return _httpRequest('DELETE_DOCUMENT', url);
     385             :     }
     386             :   }
     387             : 
     388             :   /// PUT's to the specified  document.
     389             :   ///
     390             :   /// For an update the revision must be specified, this can be in the
     391             :   /// document body as a _rev parameter or specified in the call in which
     392             :   /// case this will be added to the document body.
     393             :   Future putDocument(String id, jsonobject.JsonObject document,
     394             :       [String rev = null]) {
     395             :     if ((id == null) || (document == null)) {
     396           1 :       return _raiseException(WiltException.putDocNoIdBody);
     397             :     }
     398             : 
     399             :     /* Check for a revision */
     400             :     String jsonData = null;
     401             : 
     402             :     try {
     403             :       if (rev != null) {
     404           1 :         jsonData = WiltUserUtils.addDocumentRev(document, rev);
     405             :       } else {
     406           1 :         jsonData = JSON.encode(document);
     407             :       }
     408             :     } catch (e) {
     409           0 :       return _raiseException(WiltException.putDocCantStringify);
     410             :     }
     411             : 
     412           1 :     final String url = _conditionUrl(id);
     413           1 :     return _httpRequest(putDocumentt, url, data: jsonData);
     414             :   }
     415             : 
     416             :   /// PUT's to the specified  document where the document is supplied as
     417             :   /// a JSON string. Must be used if '_id' and or '_rev' are needed.
     418             :   Future putDocumentString(String id, String document, [String rev = null]) {
     419             :     if ((id == null) || (document == null)) {
     420           0 :       return _raiseException(WiltException.putDocStringNoIdBody);
     421             :     }
     422             : 
     423             :     /* Check for a revision */
     424             :     String id1 = id;
     425             :     if (rev != null) {
     426           0 :       id1 = "$id1?rev=$rev";
     427             :     }
     428           1 :     final String url = _conditionUrl(id1);
     429           1 :     return _httpRequest(putDocumentt, url, data: document);
     430             :   }
     431             : 
     432             :   /// POST's the specified document.
     433             :   /// An optional path to the document can be specified.
     434             :   Future postDocument(jsonobject.JsonObject document, {String path: null}) {
     435             :     if (document == null) {
     436           1 :       return _raiseException(WiltException.postDocNoBody);
     437             :     }
     438             : 
     439             :     String url = "";
     440           0 :     if (path != null) url = "$url/$path";
     441             : 
     442             :     /* Set the content type for a post */
     443           1 :     final Map headers = new Map<String, String>();
     444           1 :     headers["Content-Type"] = "application/json";
     445             : 
     446             :     String jsonData = null;
     447             :     try {
     448           1 :       jsonData = JSON.encode(document);
     449             :     } catch (e) {
     450           0 :       return _raiseException(WiltException.postDocCantStringify);
     451             :     }
     452             : 
     453           1 :     url = _conditionUrl(url);
     454           1 :     return _httpRequest(postDocumentt, url, data: jsonData, headers: headers);
     455             :   }
     456             : 
     457             :   /// POST's to the specified  document where the document is supplied as
     458             :   /// a JSON string. Must be used if '_id' and or '_rev' are needed.
     459             :   Future postDocumentString(String document, {String path: null}) {
     460             :     if (document == null) {
     461           1 :       return _raiseException(WiltException.postDocStringNoBody);
     462             :     }
     463             : 
     464             :     String url = "";
     465           0 :     if (path != null) url = "$url/$path";
     466             : 
     467             :     /* Set the content type for a post */
     468           0 :     final Map headers = new Map<String, String>();
     469           0 :     headers["Content-Type"] = "application/json";
     470             : 
     471           0 :     url = _conditionUrl(url);
     472           0 :     return _httpRequest('POST_DOCUMENT_STRING', url,
     473             :         data: document, headers: headers);
     474             :   }
     475             : 
     476             :   /// Copies the source document to the destination document with an optional revision
     477             :   /// NOTE this method uses the CouchDB COPY method which is not standard HTTP.
     478             :   Future copyDocument(String sourceId, String destinationId,
     479             :       [String rev = null]) {
     480             :     if (sourceId == null) {
     481           1 :       return _raiseException(WiltException.copyDocNoSrcId);
     482             :     }
     483             : 
     484             :     if (destinationId == null) {
     485           1 :       return _raiseException(WiltException.copyDocNoDestId);
     486             :     }
     487             : 
     488             :     String url = sourceId;
     489             : 
     490             :     /* Create the special COPY header */
     491           1 :     final Map headers = new Map<String, String>();
     492             :     String destination = destinationId;
     493           0 :     if (rev != null) destination = "$destinationId?rev=$rev";
     494           1 :     headers['Destination'] = destination;
     495             : 
     496           1 :     url = _conditionUrl(url);
     497           1 :     return _httpRequest('COPY_DOCUMENT', url, headers: headers);
     498             :   }
     499             : 
     500             :   /// Get all documents.
     501             :   /// The parameters should be self explanatory and are addative.
     502             :   /// Refer to the CouchDb documentation for further explanation.
     503             :   Future getAllDocs(
     504             :       {bool includeDocs: false,
     505             :       int limit: null,
     506             :       String startKey: null,
     507             :       String endKey: null,
     508             :       List<String> keys: null,
     509             :       bool descending: false}) {
     510             :     /* Validate the parameters */
     511           1 :     if ((limit != null) && (limit < 0)) {
     512           1 :       return _raiseException(WiltException.getAllDocsLimit);
     513             :     }
     514             : 
     515             :     String url = alldocs;
     516             : 
     517             :     /* Check the parameters and build the URL as needed */
     518             :     if (includeDocs) {
     519           1 :       url = _setURLParameter(url, 'include_docs', "true");
     520             :     }
     521             : 
     522             :     if (limit != null) {
     523           2 :       url = _setURLParameter(url, 'limit', limit.toString());
     524             :     }
     525             : 
     526             :     if (startKey != null) {
     527           1 :       final String jsonStartkey = '"$startKey"';
     528           1 :       url = _setURLParameter(url, 'startkey', jsonStartkey);
     529             :     }
     530             : 
     531             :     if (endKey != null) {
     532           1 :       final String jsonEndkey = '"$endKey"';
     533           1 :       url = _setURLParameter(url, 'endkey', jsonEndkey);
     534             :     }
     535             : 
     536             :     if (descending) {
     537           2 :       url = _setURLParameter(url, 'descending', descending.toString());
     538             :     }
     539             : 
     540             :     if (keys != null) {
     541           1 :       final String keyString = JSON.encode(keys);
     542           1 :       url = _setURLParameter(url, 'keys', keyString);
     543             :     }
     544             : 
     545           1 :     url = _conditionUrl(url);
     546           1 :     return _httpRequest('GET_ALLDOCS', url);
     547             :   }
     548             : 
     549             :   /// Bulk insert
     550             :   /// Bulk inserts a list of documents
     551             :   Future bulk(List<jsonobject.JsonObject> docs, [bool allOrNothing = false]) {
     552             :     /* Validate the parameters */
     553             :     if (docs == null) {
     554           0 :       return _raiseException(WiltException.bulkNoDocList);
     555             :     }
     556             : 
     557             :     String url = bulkdocs;
     558             : 
     559             :     if (allOrNothing) {
     560           0 :       url = _setURLParameter(url, 'all_or_nothing', allOrNothing.toString());
     561             :     }
     562             : 
     563             :     /* Create the bulk insertion data structure */
     564           1 :     final Map documentMap = new Map<String, List>();
     565           1 :     documentMap["docs"] = docs;
     566             :     String docString = null;
     567             :     try {
     568           1 :       docString = JSON.encode(documentMap);
     569             :     } catch (e) {
     570           0 :       return _raiseException(WiltException.bulkCantStringify);
     571             :     }
     572             : 
     573             :     /* Must set the content type for a post */
     574           1 :     final Map headers = new Map<String, String>();
     575           1 :     headers["Content-Type"] = "application/json";
     576             : 
     577           1 :     url = _conditionUrl(url);
     578           1 :     return _httpRequest(bulkk, url, data: docString, headers: headers);
     579             :   }
     580             : 
     581             :   /// Bulk insert JSON string version.
     582             :   /// Must be used if '_id' and or '_rev' are needed in ANY of the documents
     583             :   Future bulkString(String docs, [bool allOrNothing = false]) {
     584             :     /* Validate the parameters */
     585             :     if (docs == null) {
     586           0 :       return _raiseException(WiltException.bulkStringNoDoc);
     587             :     }
     588             : 
     589             :     String url = bulkdocs;
     590             : 
     591             :     if (allOrNothing) {
     592           0 :       url = _setURLParameter(url, 'all_or_nothing', allOrNothing.toString());
     593             :     }
     594             : 
     595             :     /* Must set the content type for a post */
     596           1 :     final Map headers = new Map<String, String>();
     597           1 :     headers["Content-Type"] = "application/json";
     598             : 
     599           1 :     url = _conditionUrl(url);
     600           1 :     return _httpRequest(bulkStringg, url, data: docs, headers: headers);
     601             :   }
     602             : 
     603             :   /// Creates a database with the specified name.
     604             :   Future createDatabase(String name) {
     605             :     if ((name == null)) {
     606           1 :       return _raiseException(WiltException.createDbNoName);
     607             :     }
     608             : 
     609             :     /* The first char of the URL should be a slash. */
     610             :     String url = name;
     611           1 :     if (!url.startsWith('/')) {
     612           1 :       url = "/$url";
     613             :     }
     614             : 
     615           1 :     return _httpRequest(createDatabasee, url);
     616             :   }
     617             : 
     618             :   /// Deletes the specified database
     619             :   Future deleteDatabase(String name) {
     620             :     if (name == null) {
     621           1 :       return _raiseException(WiltException.deleteDbNoName);
     622             :     }
     623             : 
     624             :     /* The first char of the URL should be a slash. */
     625             :     String url = name;
     626           1 :     if (!url.startsWith('/')) {
     627           1 :       url = "/$url";
     628             :     }
     629             : 
     630             :     /* Null the current database if we have deleted it */
     631           2 :     if (name == db) _db = null;
     632             : 
     633           1 :     return _httpRequest(deleteDatabasee, url);
     634             :   }
     635             : 
     636             :   /// Get information about a database
     637             :   Future getDatabaseInfo([String dbName = null]) {
     638             :     String name;
     639             :     if (dbName != null) {
     640             :       name = dbName;
     641             :     } else {
     642           1 :       name = db;
     643             :     }
     644             : 
     645           1 :     final String url = "/$name";
     646             : 
     647           1 :     return _httpRequest(databaseInfo, url);
     648             :   }
     649             : 
     650             :   /// Get current session information from CouchDB
     651             :   Future getSession() {
     652             :     final String url = session;
     653             : 
     654           1 :     return _httpRequest(getSessionn, url);
     655             :   }
     656             : 
     657             :   /// Get current stats from CouchDB
     658             :   Future getStats() {
     659             :     final String url = stats;
     660             : 
     661           1 :     return _httpRequest(getStatss, url);
     662             :   }
     663             : 
     664             :   /// Get all the databases from CouchDB
     665             :   Future getAllDbs() {
     666             :     final String url = alldbs;
     667             : 
     668           1 :     return _httpRequest(getAllDbss, url);
     669             :   }
     670             : 
     671             :   /// Create an attachment on an existing document.
     672             :   /// contentType is in the form of a mime type e.g. 'image/png'
     673             :   /// If the document needs to be created as well as the attachment set the rev to ''
     674             :   Future createAttachment(String docId, String attachmentName, String rev,
     675             :       String contentType, String payload) {
     676             :     /**
     677             :     * Check all parameters are supplied
     678             :     */
     679             :     if (docId == null) {
     680           1 :       return _raiseException(WiltException.createAttNoDocId);
     681             :     }
     682             : 
     683             :     if (attachmentName == null) {
     684           1 :       return _raiseException(WiltException.createAttNoName);
     685             :     }
     686             : 
     687             :     if (rev == null) {
     688           1 :       return _raiseException(WiltException.createAttNoRev);
     689             :     }
     690             : 
     691             :     if (contentType == null) {
     692           1 :       return _raiseException(WiltException.createAttNoContentType);
     693             :     }
     694             : 
     695             :     if (payload == null) {
     696           1 :       return _raiseException(WiltException.createAttNoPayload);
     697             :     }
     698             : 
     699             :     /**
     700             :      * Set the headers
     701             :      */
     702           1 :     final Map headers = new Map<String, String>();
     703           1 :     headers["Content-Type"] = contentType;
     704             : 
     705             :     /**
     706             :      * Make the PUT request
     707             :      */
     708             :     String url;
     709           1 :     if (rev != '') {
     710           1 :       url = "$docId/$attachmentName?rev=$rev";
     711             :     } else {
     712           1 :       url = "$docId/$attachmentName";
     713             :     }
     714             : 
     715           1 :     url = _conditionUrl(url);
     716           1 :     return _httpRequest(createAttachmentt, url,
     717             :         data: payload, headers: headers);
     718             :   }
     719             : 
     720             :   /// Update an attachment on an existing document.
     721             :   /// contentType is in the form of a mime type e.g. 'image/png'
     722             :   Future updateAttachment(String docId, String attachmentName, String rev,
     723             :       String contentType, String payload) {
     724             :     /**
     725             :     * Check all parameters are supplied
     726             :     */
     727             :     if (docId == null) {
     728           1 :       return _raiseException(WiltException.updateAttNoDocId);
     729             :     }
     730             : 
     731             :     if (attachmentName == null) {
     732           1 :       return _raiseException(WiltException.updateAttNoName);
     733             :     }
     734             : 
     735             :     if (rev == null) {
     736           1 :       return _raiseException(WiltException.updateAttNoRev);
     737             :     }
     738             : 
     739             :     if (contentType == null) {
     740           1 :       return _raiseException(WiltException.updateAttNoContentType);
     741             :     }
     742             : 
     743             :     if (payload == null) {
     744           1 :       return _raiseException(WiltException.updateAttNoPayload);
     745             :     }
     746             : 
     747             :     /**
     748             :      * Set the headers
     749             :      */
     750           1 :     final Map headers = new Map<String, String>();
     751           1 :     headers["Content-Type"] = contentType;
     752             : 
     753           1 :     String url = "$docId/$attachmentName?rev=$rev";
     754             : 
     755           1 :     url = _conditionUrl(url);
     756           1 :     return _httpRequest(updateAttachmentt, url,
     757             :         data: payload, headers: headers);
     758             :   }
     759             : 
     760             :   /// Delete an attachment
     761             :   Future deleteAttachment(String docId, String attachmentName, String rev) {
     762             :     if (docId == null) {
     763           1 :       return _raiseException(WiltException.deleteAttNoDocId);
     764             :     }
     765             : 
     766             :     if (attachmentName == null) {
     767           1 :       return _raiseException(WiltException.deleteAttNoName);
     768             :     }
     769             : 
     770             :     if (rev == null) {
     771           1 :       return _raiseException(WiltException.deleteAttNoRev);
     772             :     }
     773             : 
     774           1 :     String url = "$docId/$attachmentName?rev=$rev";
     775             : 
     776           1 :     url = _conditionUrl(url);
     777           1 :     return _httpRequest(deleteAttachmentt, url);
     778             :   }
     779             : 
     780             :   /// Get an attachment
     781             :   Future getAttachment(String docId, String attachmentName) {
     782             :     if (docId == null) {
     783           1 :       return _raiseException(WiltException.getAttNoDocId);
     784             :     }
     785             : 
     786             :     if (attachmentName == null) {
     787           1 :       return _raiseException(WiltException.getAttNoName);
     788             :     }
     789             : 
     790           1 :     String url = "$docId/$attachmentName";
     791             : 
     792           1 :     url = _conditionUrl(url);
     793           1 :     return _httpRequest(getAttachmentt, url);
     794             :   }
     795             : 
     796             :   /// Change notification start, see the WiltChangeNotification class for more details
     797             :   ///
     798             :   /// If a database name is not supplied the currently selected database is used.
     799             :   ///
     800             :   /// If auth credentials are not set raise an exception.
     801             :   void startChangeNotification(
     802             :       [WiltChangeNotificationParameters parameters = null,
     803             :       String databaseName = null]) {
     804           1 :     if (_user == null) {
     805           1 :       throw new WiltException(WiltException.cnNoAuth);
     806             :     }
     807             :     String name;
     808             :     if (databaseName == null) {
     809           1 :       name = db;
     810             :     } else {
     811             :       name = databaseName;
     812             :     }
     813             : 
     814           1 :     changeNotificationDbName = name;
     815           2 :     _changeNotifier = new _WiltChangeNotification(
     816           4 :         _host, _port, _scheme, _httpAdapter, name, parameters);
     817             :   }
     818             : 
     819             :   /// Change notification stop, see the WiltChangeNotification class for more details
     820             :   ///
     821             :   /// Note that this destroys the internal changeNotifier object which can only be
     822             :   /// reinstated by a call to startChangeNotification.
     823             :   void stopChangeNotification() {
     824           2 :     _changeNotifier.stopNotifications();
     825           1 :     _changeNotifier = null;
     826           1 :     changeNotificationDbName = null;
     827             :   }
     828             : 
     829             :   /// Change the parameter set for change notifications.
     830             :   ///
     831             :   /// Note that database name, host, port and scheme are not changeable.
     832             :   void updateChangeNotificationParameters(
     833             :       WiltChangeNotificationParameters parameters) {
     834             :     if (parameters == null) {
     835           0 :       throw new WiltException(WiltException.updateCnpNoParams);
     836             :     }
     837             : 
     838           0 :     if (_changeNotifier == null) {
     839           0 :       throw new WiltException(WiltException.updateCnpNoNotifier);
     840             :     }
     841             : 
     842           0 :     _changeNotifier.parameters = parameters;
     843             :   }
     844             : 
     845             :   /// Pause change notifications
     846             :   void pauseChangeNotifications() {
     847           2 :     _changeNotifier.pause = true;
     848           2 :     _changeNotifier.stopNotifications();
     849             :   }
     850             : 
     851             :   /// Restart change notifications after a pause
     852             :   void restartChangeNotifications() {
     853           2 :     _changeNotifier.pause = false;
     854           2 :     _changeNotifier.restartChangeNotifications();
     855             :   }
     856             : 
     857             :   /// Authentication.
     858             :   /// Updates the login credentials in Wilt that will be used for all further
     859             :   /// requests to CouchDB. Both user name and password must be set, even if one
     860             :   /// or the other is '' i.e empty. After logging in all communication with CouchDB
     861             :   /// is made using the selected authentication method.
     862             :   void login(String user, String password) {
     863             :     if ((user == null) || (password == null)) {
     864           1 :       throw new WiltException(WiltException.loginWrongParams);
     865             :     }
     866             : 
     867           1 :     _user = user;
     868           1 :     _password = password;
     869           1 :     authenticationType = authBasic;
     870             : 
     871             :     /* Set the auth details for change notification */
     872           5 :     _httpAdapter.notificationAuthParams(_user, _password, authenticationType);
     873             :   }
     874             : 
     875             :   /// Ask CouchDB to generate document Id's.
     876             :   Future generateIds([int amount = 10]) {
     877           1 :     if (amount < 1) {
     878           1 :       return _raiseException(WiltException.genIdsAmount);
     879             :     }
     880             : 
     881             :     String url = uuids;
     882             : 
     883           2 :     url = url + "?count=${amount}";
     884             : 
     885           1 :     return _httpRequest(generateIdss, url);
     886             :   }
     887             : }

Generated by: LCOV version 1.10