/// <summary>
 /// Combine original user data with the taxonomy epoch. </summary>
 private IDictionary<string, string> CombinedCommitData(IDictionary<string, string> commitData)
 {
     IDictionary<string, string> m = new Dictionary<string, string>();
     if (commitData != null)
     {
         m.PutAll(commitData);
     }
     m[INDEX_EPOCH] = Convert.ToString(indexEpoch, 16);
     return m;
 }
        /// <summary>
        /// Gets or sets the userProperties of the <see cref="Couchbase.Lite.Revision"/>.
        /// </summary>
        /// <remarks>
        /// Gets or sets the userProperties of the <see cref="Couchbase.Lite.Revision"/>. 
        /// Get, returns the properties of the <see cref="Couchbase.Lite.Revision"/> 
        /// without any properties with keys prefixed with '_' (which contain Couchbase Lite data). 
        /// Set, replaces all properties except for those with keys prefixed with '_'.
        /// </remarks>
        /// <value>The userProperties of the <see cref="Couchbase.Lite.Revision"/>.</value>
        public void SetUserProperties(IDictionary<String, Object> userProperties) 
        {
            var newProps = new Dictionary<String, Object>();
            newProps.PutAll(userProperties);

            foreach (string key in Properties.Keys)
                {
                    if (key.StartsWith("_", StringComparison.InvariantCultureIgnoreCase))
                    {
                        newProps.Put(key, properties.Get(key));
                    }
                }
                // Preserve metadata properties
                properties = newProps;
        }
 public virtual IDictionary<string, object> ChangesFeedPOSTBodyMap()
 {
     if (!usePOST)
     {
         return null;
     }
     if (docIDs != null && docIDs.Count > 0)
     {
         filterName = "_doc_ids";
         filterParams = new Dictionary<string, object>();
         filterParams.Put("doc_ids", docIDs);
     }
     IDictionary<string, object> post = new Dictionary<string, object>();
     post.Put("feed", GetFeed());
     post.Put("heartbeat", GetHeartbeatMilliseconds());
     if (includeConflicts)
     {
         post.Put("style", "all_docs");
     }
     else
     {
         post.Put("style", null);
     }
     if (lastSequenceID != null)
     {
         try
         {
             post.Put("since", long.Parse(lastSequenceID.ToString()));
         }
         catch (FormatException)
         {
             post.Put("since", lastSequenceID.ToString());
         }
     }
     if (mode == ChangeTracker.ChangeTrackerMode.LongPoll && limit > 0)
     {
         post.Put("limit", limit);
     }
     else
     {
         post.Put("limit", null);
     }
     if (filterName != null)
     {
         post.Put("filter", filterName);
         post.PutAll(filterParams);
     }
     return post;
 }
 /// <summary>https://github.com/couchbase/couchbase-lite-android/issues/66</summary>
 /// <exception cref="System.Exception"></exception>
 public virtual void TestPushUpdatedDocWithoutReSendingAttachments()
 {
     NUnit.Framework.Assert.AreEqual(0, database.GetLastSequenceNumber());
     IDictionary<string, object> properties1 = new Dictionary<string, object>();
     properties1.Put("dynamic", 1);
     Document doc = CreateDocWithProperties(properties1);
     SavedRevision doc1Rev = doc.GetCurrentRevision();
     // Add attachment to document
     UnsavedRevision doc2UnsavedRev = doc.CreateRevision();
     InputStream attachmentStream = GetAsset("attachment.png");
     doc2UnsavedRev.SetAttachment("attachment.png", "image/png", attachmentStream);
     SavedRevision doc2Rev = doc2UnsavedRev.Save();
     NUnit.Framework.Assert.IsNotNull(doc2Rev);
     CustomizableMockHttpClient mockHttpClient = new CustomizableMockHttpClient();
     mockHttpClient.AddResponderFakeLocalDocumentUpdate404();
     // http://url/db/foo (foo==docid)
     mockHttpClient.SetResponder(doc.GetId(), new _Responder_1593(doc));
     // create replication and add observer
     manager.SetDefaultHttpClientFactory(MockFactoryFactory(mockHttpClient));
     Replication pusher = database.CreatePushReplication(GetReplicationURL());
     RunReplication(pusher);
     IList<HttpWebRequest> captured = mockHttpClient.GetCapturedRequests();
     foreach (HttpWebRequest httpRequest in captured)
     {
         // verify that there are no PUT requests with attachments
         if (httpRequest is HttpPut)
         {
             HttpPut httpPut = (HttpPut)httpRequest;
             HttpEntity entity = httpPut.GetEntity();
         }
     }
     //assertFalse("PUT request with updated doc properties contains attachment", entity instanceof MultipartEntity);
     mockHttpClient.ClearCapturedRequests();
     Document oldDoc = database.GetDocument(doc.GetId());
     UnsavedRevision aUnsavedRev = oldDoc.CreateRevision();
     IDictionary<string, object> prop = new Dictionary<string, object>();
     prop.PutAll(oldDoc.GetProperties());
     prop.Put("dynamic", (int)oldDoc.GetProperty("dynamic") + 1);
     aUnsavedRev.SetProperties(prop);
     SavedRevision savedRev = aUnsavedRev.Save();
     mockHttpClient.SetResponder(doc.GetId(), new _Responder_1630(doc, savedRev));
     string json = string.Format("{\"%s\":{\"missing\":[\"%s\"],\"possible_ancestors\":[\"%s\",\"%s\"]}}"
         , doc.GetId(), savedRev.GetId(), doc1Rev.GetId(), doc2Rev.GetId());
     mockHttpClient.SetResponder("_revs_diff", new _Responder_1642(mockHttpClient, json
         ));
     pusher = database.CreatePushReplication(GetReplicationURL());
     RunReplication(pusher);
     captured = mockHttpClient.GetCapturedRequests();
     foreach (HttpWebRequest httpRequest_1 in captured)
     {
         // verify that there are no PUT requests with attachments
         if (httpRequest_1 is HttpPut)
         {
             HttpPut httpPut = (HttpPut)httpRequest_1;
             HttpEntity entity = httpPut.GetEntity();
             NUnit.Framework.Assert.IsFalse("PUT request with updated doc properties contains attachment"
                 , entity is MultipartEntity);
         }
     }
 }
 /// <exception cref="System.Exception"></exception>
 public virtual void TestConflict()
 {
     IDictionary<string, object> prop = new Dictionary<string, object>();
     prop.Put("foo", "bar");
     Database db = StartDatabase();
     Document doc = CreateDocumentWithProperties(db, prop);
     SavedRevision rev1 = doc.GetCurrentRevision();
     IDictionary<string, object> properties = new Dictionary<string, object>();
     properties.PutAll(doc.GetProperties());
     properties.Put("tag", 2);
     SavedRevision rev2a = doc.PutProperties(properties);
     properties = new Dictionary<string, object>();
     properties.PutAll(rev1.GetProperties());
     properties.Put("tag", 3);
     UnsavedRevision newRev = rev1.CreateRevision();
     newRev.SetProperties(properties);
     bool allowConflict = true;
     SavedRevision rev2b = newRev.Save(allowConflict);
     NUnit.Framework.Assert.IsNotNull("Failed to create a a conflict", rev2b);
     IList<SavedRevision> confRevs = new AList<SavedRevision>();
     confRevs.AddItem(rev2b);
     confRevs.AddItem(rev2a);
     NUnit.Framework.Assert.AreEqual(doc.GetConflictingRevisions(), confRevs);
     NUnit.Framework.Assert.AreEqual(doc.GetLeafRevisions(), confRevs);
     SavedRevision defaultRev;
     SavedRevision otherRev;
     if (Sharpen.Runtime.CompareOrdinal(rev2a.GetId(), rev2b.GetId()) > 0)
     {
         defaultRev = rev2a;
         otherRev = rev2b;
     }
     else
     {
         defaultRev = rev2b;
         otherRev = rev2a;
     }
     NUnit.Framework.Assert.AreEqual(doc.GetCurrentRevision(), defaultRev);
     Query query = db.CreateAllDocumentsQuery();
     query.SetAllDocsMode(Query.AllDocsMode.ShowConflicts);
     QueryEnumerator rows = query.Run();
     NUnit.Framework.Assert.AreEqual(rows.GetCount(), 1);
     QueryRow row = rows.GetRow(0);
     IList<SavedRevision> revs = row.GetConflictingRevisions();
     NUnit.Framework.Assert.AreEqual(revs.Count, 2);
     NUnit.Framework.Assert.AreEqual(revs[0], defaultRev);
     NUnit.Framework.Assert.AreEqual(revs[1], otherRev);
 }
 //TODO issue: deleteLocalDocument should return error.code( see ios)
 // HISTORY
 /// <exception cref="System.Exception"></exception>
 public virtual void TestHistory()
 {
     IDictionary<string, object> properties = new Dictionary<string, object>();
     properties.Put("testName", "test06_History");
     properties.Put("tag", 1);
     Database db = StartDatabase();
     Document doc = CreateDocumentWithProperties(db, properties);
     string rev1ID = doc.GetCurrentRevisionId();
     Log.I(Tag, "1st revision: " + rev1ID);
     NUnit.Framework.Assert.IsNotNull("1st revision looks wrong: " + rev1ID, rev1ID.StartsWith
         ("1-"));
     NUnit.Framework.Assert.AreEqual(doc.GetUserProperties(), properties);
     properties = new Dictionary<string, object>();
     properties.PutAll(doc.GetProperties());
     properties.Put("tag", 2);
     NUnit.Framework.Assert.IsNotNull(!properties.Equals(doc.GetProperties()));
     NUnit.Framework.Assert.IsNotNull(doc.PutProperties(properties));
     string rev2ID = doc.GetCurrentRevisionId();
     Log.I(Tag, "rev2ID" + rev2ID);
     NUnit.Framework.Assert.IsNotNull("2nd revision looks wrong:" + rev2ID, rev2ID.StartsWith
         ("2-"));
     IList<SavedRevision> revisions = doc.GetRevisionHistory();
     Log.I(Tag, "Revisions = " + revisions);
     NUnit.Framework.Assert.AreEqual(revisions.Count, 2);
     SavedRevision rev1 = revisions[0];
     NUnit.Framework.Assert.AreEqual(rev1.GetId(), rev1ID);
     IDictionary<string, object> gotProperties = rev1.GetProperties();
     NUnit.Framework.Assert.AreEqual(1, gotProperties.Get("tag"));
     SavedRevision rev2 = revisions[1];
     NUnit.Framework.Assert.AreEqual(rev2.GetId(), rev2ID);
     NUnit.Framework.Assert.AreEqual(rev2, doc.GetCurrentRevision());
     gotProperties = rev2.GetProperties();
     NUnit.Framework.Assert.AreEqual(2, gotProperties.Get("tag"));
     IList<SavedRevision> tmp = new AList<SavedRevision>();
     tmp.AddItem(rev2);
     NUnit.Framework.Assert.AreEqual(doc.GetConflictingRevisions(), tmp);
     NUnit.Framework.Assert.AreEqual(doc.GetLeafRevisions(), tmp);
 }