本文整理汇总了C#中Couchbase.Lite.Internal.RevisionInternal.GetProperties方法的典型用法代码示例。如果您正苦于以下问题:C# RevisionInternal.GetProperties方法的具体用法?C# RevisionInternal.GetProperties怎么用?C# RevisionInternal.GetProperties使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Couchbase.Lite.Internal.RevisionInternal
的用法示例。
在下文中一共展示了RevisionInternal.GetProperties方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: FindCommonAncestor
/// <summary>
/// Finds the common ancestor.
/// </summary>
/// <remarks>
/// Given a revision and an array of revIDs, finds the latest common ancestor revID
/// and returns its generation #. If there is none, returns 0.
/// </remarks>
/// <returns>The common ancestor.</returns>
/// <param name="rev">Rev.</param>
/// <param name="possibleRevIDs">Possible rev I ds.</param>
internal static int FindCommonAncestor(RevisionInternal rev, IList<string> possibleRevIDs)
{
if (possibleRevIDs == null || possibleRevIDs.Count == 0)
{
return 0;
}
var history = Database.ParseCouchDBRevisionHistory(rev.GetProperties());
Debug.Assert(history != null);
history = history.Intersect(possibleRevIDs).ToList();
var ancestorID = history.Count == 0
? null
: history[0];
if (ancestorID == null)
{
return 0;
}
var parsed = RevisionInternal.ParseRevId(ancestorID);
return parsed.Item1;
}
示例2: ValidateRevision
/// <summary>VALIDATION</summary>
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception>
internal Status ValidateRevision(RevisionInternal newRev, RevisionInternal oldRev, String parentRevId)
{
var validations = Shared.GetValues("validation", Name);
if (validations == null || validations.Count == 0) {
return new Status(StatusCode.Ok);
}
var publicRev = new SavedRevision(this, newRev, parentRevId);
var context = new ValidationContext(this, oldRev, newRev);
Status status = new Status(StatusCode.Ok);
foreach (var validationName in validations.Keys)
{
var validation = GetValidation(validationName);
try {
validation(publicRev, context);
} catch(Exception e) {
Log.E(TAG, String.Format("Validation block '{0}'", validationName), e);
status.Code = StatusCode.Exception;
break;
}
if (context.RejectMessage != null) {
Log.D(TAG, "Failed update of {0}: {1}:{2} Old doc = {3}{2} New doc = {4}", oldRev, context.RejectMessage,
Environment.NewLine, oldRev == null ? null : oldRev.GetProperties(), newRev.GetProperties());
status.Code = StatusCode.Forbidden;
break;
}
}
return status;
}
示例3: QueryView
/// <summary>
/// Queries the specified view using the specified options
/// </summary>
/// <returns>The HTTP response containing the results of the query</returns>
/// <param name="context">The request context</param>
/// <param name="db">The database to run the query in</param>
/// <param name="view">The view to query</param>
/// <param name="options">The options to apply to the query</param>
public static CouchbaseLiteResponse QueryView(ICouchbaseListenerContext context, Database db, View view, QueryOptions options)
{
var result = view.QueryWithOptions(options);
object updateSeq = options.UpdateSeq ? (object)view.LastSequenceIndexed : null;
var mappedResult = new List<object>();
foreach (var row in result) {
row.Database = db;
var dict = row.AsJSONDictionary();
if (context.ContentOptions != DocumentContentOptions.None) {
var doc = dict.Get("doc").AsDictionary<string, object>();
if (doc != null) {
// Add content options:
RevisionInternal rev = new RevisionInternal(doc);
var status = new Status();
rev = DocumentMethods.ApplyOptions(context.ContentOptions, rev, context, db, status);
if (rev != null) {
dict["doc"] = rev.GetProperties();
}
}
}
mappedResult.Add(dict);
}
var body = new Body(new NonNullDictionary<string, object> {
{ "rows", mappedResult },
{ "total_rows", view.TotalRows },
{ "offset", options.Skip },
{ "update_seq", updateSeq }
});
var retVal = context.CreateResponse();
retVal.JsonBody = body;
return retVal;
}
示例4: ProcessAttachmentsForRevision
internal bool ProcessAttachmentsForRevision(RevisionInternal rev, string prevRevId, Status status)
{
if (status == null) {
status = new Status();
}
status.Code = StatusCode.Ok;
var revAttachments = rev.GetAttachments();
if (revAttachments == null) {
return true; // no-op: no attachments
}
// Deletions can't have attachments:
if (rev.IsDeleted() || revAttachments.Count == 0) {
var body = rev.GetProperties();
body.Remove("_attachments");
rev.SetProperties(body);
return true;
}
int generation = RevisionInternal.GenerationFromRevID(prevRevId) + 1;
IDictionary<string, object> parentAttachments = null;
return rev.MutateAttachments((name, attachInfo) =>
{
AttachmentInternal attachment = null;
try {
attachment = new AttachmentInternal(name, attachInfo);
} catch(CouchbaseLiteException e) {
return null;
}
if(attachment.EncodedContent != null) {
// If there's inline attachment data, decode and store it:
BlobKey blobKey = new BlobKey();
if(!Attachments.StoreBlob(attachment.EncodedContent.ToArray(), blobKey)) {
status.Code = StatusCode.AttachmentError;
return null;
}
attachment.BlobKey = blobKey;
} else if(attachInfo.GetCast<bool>("follows")) {
// "follows" means the uploader provided the attachment in a separate MIME part.
// This means it's already been registered in _pendingAttachmentsByDigest;
// I just need to look it up by its "digest" property and install it into the store:
InstallAttachment(attachment, attachInfo);
} else if(attachInfo.GetCast<bool>("stub")) {
// "stub" on an incoming revision means the attachment is the same as in the parent.
if(parentAttachments == null && prevRevId != null) {
parentAttachments = GetAttachmentsFromDoc(rev.GetDocId(), prevRevId, status);
if(parentAttachments == null) {
if(status.Code == StatusCode.Ok || status.Code == StatusCode.NotFound) {
status.Code = StatusCode.BadAttachment;
}
return null;
}
}
var parentAttachment = parentAttachments == null ? null : parentAttachments.Get(name).AsDictionary<string, object>();
if(parentAttachment == null) {
status.Code = StatusCode.BadAttachment;
return null;
}
return parentAttachment;
}
// Set or validate the revpos:
if(attachment.RevPos == 0) {
attachment.RevPos = generation;
} else if(attachment.RevPos >= generation) {
status.Code = StatusCode.BadAttachment;
return null;
}
Debug.Assert(attachment.IsValid);
return attachment.AsStubDictionary();
});
}
示例5: LoadRevisionBody
//Doesn't handle CouchbaseLiteException
internal RevisionInternal LoadRevisionBody(RevisionInternal rev)
{
if (rev.GetSequence() > 0) {
var props = rev.GetProperties();
if (props != null && props.GetCast<string>("_rev") != null && props.GetCast<string>("_id") != null) {
return rev;
}
}
Debug.Assert(rev.GetDocId() != null && rev.GetRevId() != null);
Storage.LoadRevisionBody(rev);
return rev;
}
示例6: TestStubOutAttachmentsInRevBeforeRevPos
public void TestStubOutAttachmentsInRevBeforeRevPos()
{
var hello = new JObject();
hello["revpos"] = 1;
hello["follows"] = true;
var goodbye = new JObject();
goodbye["revpos"] = 2;
goodbye["data"] = "squeee";
var attachments = new JObject();
attachments["hello"] = hello;
attachments["goodbye"] = goodbye;
var properties = new Dictionary<string, object>();
properties["_attachments"] = attachments;
IDictionary<string, object> expected = null;
var rev = new RevisionInternal(properties);
Database.StubOutAttachmentsInRevBeforeRevPos(rev, 3, false);
var checkAttachments = rev.GetProperties()["_attachments"].AsDictionary<string, object>();
var result = (IDictionary<string, object>)checkAttachments["hello"];
expected = new Dictionary<string, object>();
expected["revpos"] = 1;
expected["stub"] = true;
AssertPropertiesAreEqual(expected, result);
result = (IDictionary<string, object>)checkAttachments["goodbye"];
expected = new Dictionary<string, object>();
expected["revpos"] = 2;
expected["stub"] = true;
AssertPropertiesAreEqual(expected, result);
rev = new RevisionInternal(properties);
Database.StubOutAttachmentsInRevBeforeRevPos(rev, 2, false);
checkAttachments = rev.GetProperties()["_attachments"].AsDictionary<string, object>();
result = checkAttachments["hello"].AsDictionary<string, object>();
expected = new Dictionary<string, object>();
expected["revpos"] = 1;
expected["stub"] = true;
AssertPropertiesAreEqual(expected, result);
result = checkAttachments["goodbye"].AsDictionary<string, object>();
expected = goodbye.AsDictionary<string, object>();
AssertPropertiesAreEqual(expected, result);
rev = new RevisionInternal(properties);
Database.StubOutAttachmentsInRevBeforeRevPos(rev, 1, false);
checkAttachments = rev.GetProperties()["_attachments"].AsDictionary<string, object>();
result = checkAttachments["hello"].AsDictionary<string, object>();
expected = hello.AsDictionary<string, object>();
AssertPropertiesAreEqual(expected, result);
result = checkAttachments["goodbye"].AsDictionary<string, object>();
expected = goodbye.AsDictionary<string, object>();
AssertPropertiesAreEqual(expected, result);
//Test the follows mode
rev = new RevisionInternal(properties);
Database.StubOutAttachmentsInRevBeforeRevPos(rev, 3, true);
checkAttachments = rev.GetProperties()["_attachments"].AsDictionary<string, object>();
result = checkAttachments["hello"].AsDictionary<string, object>();
expected = new Dictionary<string, object>();
expected["revpos"] = 1;
expected["stub"] = true;
AssertPropertiesAreEqual(expected, result);
result = checkAttachments["goodbye"].AsDictionary<string, object>();
expected = new Dictionary<string, object>();
expected["revpos"] = 2;
expected["stub"] = true;
AssertPropertiesAreEqual(expected, result);
rev = new RevisionInternal(properties);
Database.StubOutAttachmentsInRevBeforeRevPos(rev, 2, true);
checkAttachments = rev.GetProperties()["_attachments"].AsDictionary<string, object>();
result = checkAttachments["hello"].AsDictionary<string, object>();
expected = new Dictionary<string, object>();
expected["revpos"] = 1;
expected["stub"] = true;
AssertPropertiesAreEqual(expected, result);
result = checkAttachments["goodbye"].AsDictionary<string, object>();
expected = new Dictionary<string, object>();
expected["revpos"] = 2;
expected["follows"] = true;
AssertPropertiesAreEqual(expected, result);
rev = new RevisionInternal(properties);
Database.StubOutAttachmentsInRevBeforeRevPos(rev, 1, true);
checkAttachments = rev.GetProperties()["_attachments"].AsDictionary<string, object>();
result = checkAttachments["hello"].AsDictionary<string, object>();
expected = new Dictionary<string, object>();
expected["revpos"] = 1;
expected["follows"] = true;
AssertPropertiesAreEqual(expected, result);
result = checkAttachments["goodbye"].AsDictionary<string, object>();
expected = new Dictionary<string, object>();
expected["revpos"] = 2;
expected["follows"] = true;
AssertPropertiesAreEqual(expected, result);
}
示例7: PutRevision
/// <summary>Stores a new (or initial) revision of a document.</summary>
/// <remarks>
/// Stores a new (or initial) revision of a document.
/// This is what's invoked by a PUT or POST. As with those, the previous revision ID must be supplied when necessary and the call will fail if it doesn't match.
/// </remarks>
/// <param name="oldRev">The revision to add. If the docID is null, a new UUID will be assigned. Its revID must be null. It must have a JSON body.
/// </param>
/// <param name="prevRevId">The ID of the revision to replace (same as the "?rev=" parameter to a PUT), or null if this is a new document.
/// </param>
/// <param name="allowConflict">If false, an error status 409 will be returned if the insertion would create a conflict, i.e. if the previous revision already has a child.
/// </param>
/// <param name="resultStatus">On return, an HTTP status code indicating success or failure.
/// </param>
/// <returns>A new RevisionInternal with the docID, revID and sequence filled in (but no body).
/// </returns>
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception>
internal RevisionInternal PutRevision(RevisionInternal oldRev, string prevRevId, bool allowConflict, Status resultStatus = null)
{
return PutDocument(oldRev.GetDocId(), oldRev.GetProperties(), prevRevId, allowConflict, resultStatus);
}
示例8: PutRevision
/// <summary>Stores a new (or initial) revision of a document.</summary>
/// <remarks>
/// Stores a new (or initial) revision of a document.
/// This is what's invoked by a PUT or POST. As with those, the previous revision ID must be supplied when necessary and the call will fail if it doesn't match.
/// </remarks>
/// <param name="oldRev">The revision to add. If the docID is null, a new UUID will be assigned. Its revID must be null. It must have a JSON body.
/// </param>
/// <param name="prevRevId">The ID of the revision to replace (same as the "?rev=" parameter to a PUT), or null if this is a new document.
/// </param>
/// <param name="allowConflict">If false, an error status 409 will be returned if the insertion would create a conflict, i.e. if the previous revision already has a child.
/// </param>
/// <returns>A new RevisionInternal with the docID, revID and sequence filled in (but no body).
/// </returns>
/// <exception cref="Couchbase.Lite.CouchbaseLiteException"></exception>
internal RevisionInternal PutRevision(RevisionInternal oldRev, string prevRevId, bool allowConflict)
{
return PutDocument(oldRev.GetDocId(), oldRev.GetProperties(), prevRevId, allowConflict);
}
示例9: ProcessAttachmentsForRevision
internal bool ProcessAttachmentsForRevision(RevisionInternal rev, IList<string> ancestry)
{
var revAttachments = rev.GetAttachments();
if (revAttachments == null) {
return true; // no-op: no attachments
}
// Deletions can't have attachments:
if (rev.IsDeleted() || revAttachments.Count == 0) {
var body = rev.GetProperties();
body.Remove("_attachments");
rev.SetProperties(body);
return true;
}
var prevRevId = ancestry != null && ancestry.Count > 0 ? ancestry[0] : null;
int generation = RevisionInternal.GenerationFromRevID(prevRevId) + 1;
IDictionary<string, object> parentAttachments = null;
return rev.MutateAttachments((name, attachInfo) =>
{
AttachmentInternal attachment = null;
try {
attachment = new AttachmentInternal(name, attachInfo);
} catch(CouchbaseLiteException) {
return null;
}
if(attachment.EncodedContent != null) {
// If there's inline attachment data, decode and store it:
BlobKey blobKey = new BlobKey();
if(!Attachments.StoreBlob(attachment.EncodedContent.ToArray(), blobKey)) {
throw new CouchbaseLiteException(
String.Format("Failed to write attachment ' {0}'to disk", name), StatusCode.AttachmentError);
}
attachment.BlobKey = blobKey;
} else if(attachInfo.GetCast<bool>("follows")) {
// "follows" means the uploader provided the attachment in a separate MIME part.
// This means it's already been registered in _pendingAttachmentsByDigest;
// I just need to look it up by its "digest" property and install it into the store:
InstallAttachment(attachment);
} else if(attachInfo.GetCast<bool>("stub")) {
// "stub" on an incoming revision means the attachment is the same as in the parent.
if(parentAttachments == null && prevRevId != null) {
parentAttachments = GetAttachmentsFromDoc(rev.GetDocId(), prevRevId);
if(parentAttachments == null) {
if(Attachments.HasBlobForKey(attachment.BlobKey)) {
// Parent revision's body isn't known (we are probably pulling a rev along
// with its entire history) but it's OK, we have the attachment already
return attachInfo;
}
var ancestorAttachment = FindAttachment(name, attachment.RevPos, rev.GetDocId(), ancestry);
if(ancestorAttachment != null) {
return ancestorAttachment;
}
throw new CouchbaseLiteException(
String.Format("Unable to find 'stub' attachment {0} in history", name), StatusCode.BadAttachment);
}
}
var parentAttachment = parentAttachments == null ? null : parentAttachments.Get(name).AsDictionary<string, object>();
if(parentAttachment == null) {
throw new CouchbaseLiteException(
String.Format("Unable to find 'stub' attachment {0} in history", name), StatusCode.BadAttachment);
}
return parentAttachment;
}
// Set or validate the revpos:
if(attachment.RevPos == 0) {
attachment.RevPos = generation;
} else if(attachment.RevPos > generation) {
throw new CouchbaseLiteException(
String.Format("Attachment specifies revision generation {0} but document is only at revision generation {1}",
attachment.RevPos, generation), StatusCode.BadAttachment);
}
Debug.Assert(attachment.IsValid);
return attachment.AsStubDictionary();
});
}
示例10: VerifyRev
private void VerifyRev(RevisionInternal rev, IList<RevisionID> history)
{
var gotRev = database.GetDocument(rev.DocID, null, true);
Assert.AreEqual(rev, gotRev);
Assert.AreEqual(rev.GetProperties(), gotRev.GetProperties());
var revHistory = database.GetRevisionHistory(gotRev, null);
Assert.AreEqual(history.Count, revHistory.Count);
for(var i = 0; i < history.Count; i++) {
Assert.AreEqual(history[i], revHistory[i]);
}
}
示例11: PutDocument
internal RevisionInternal PutDocument(string docId, IDictionary<string, object> properties, string prevRevId, bool allowConflict)
{
bool deleting = properties == null || properties.GetCast<bool>("_deleted");
Log.D(TAG, "PUT _id={0}, _rev={1}, _deleted={2}, allowConflict={3}", docId, prevRevId, deleting, allowConflict);
if ((prevRevId != null && docId == null) || (deleting && docId == null)) {
throw new CouchbaseLiteException(StatusCode.BadId);
}
if (properties != null && properties.Get("_attachments").AsDictionary<string, object>() != null) {
var tmpRev = new RevisionInternal(docId, prevRevId, deleting);
tmpRev.SetProperties(properties);
if (!ProcessAttachmentsForRevision(tmpRev, prevRevId == null ? null : new List<string> { prevRevId })) {
return null;
}
properties = tmpRev.GetProperties();
}
StoreValidation validationBlock = null;
if (Shared.HasValues("validation", Name)) {
validationBlock = ValidateRevision;
}
var putRev = Storage.PutRevision(docId, prevRevId, properties, deleting, allowConflict, validationBlock);
if (putRev != null) {
Log.D(TAG, "--> created {0}", putRev);
if (!string.IsNullOrEmpty(docId)) {
var dummy = default(WeakReference);
UnsavedRevisionDocumentCache.TryRemove(docId, out dummy);
}
}
return putRev;
}
示例12: UploadJsonRevision
/// <summary>
/// Uploads the revision as JSON instead of multipart.
/// </summary>
/// <remarks>
/// Fallback to upload a revision if UploadMultipartRevision failed due to the server's rejecting
/// multipart format.
/// </remarks>
/// <param name="rev">Rev.</param>
private void UploadJsonRevision(RevisionInternal rev)
{
// Get the revision's properties:
if (!LocalDatabase.InlineFollowingAttachmentsIn(rev))
{
LastError = new CouchbaseLiteException(StatusCode.BadAttachment);
RevisionFailed();
return;
}
var path = string.Format("/{0}?new_edits=false", Uri.EscapeUriString(rev.GetDocId()));
SendAsyncRequest(HttpMethod.Put, path, rev.GetProperties(), (result, e) =>
{
if (e != null)
{
LastError = e;
RevisionFailed();
}
else
{
Log.V(TAG, "Sent {0} (JSON), response={1}", rev, result);
SafeIncrementCompletedChangesCount();
RemovePending (rev);
}
});
}
示例13: UploadMultipartRevision
private bool UploadMultipartRevision(RevisionInternal revision)
{
MultipartContent multiPart = null;
var revProps = revision.GetProperties();
var attachments = revProps.Get("_attachments").AsDictionary<string,object>();
foreach (var attachmentKey in attachments.Keys) {
var attachment = attachments.Get(attachmentKey).AsDictionary<string,object>();
if (attachment.ContainsKey("follows")) {
if (multiPart == null) {
multiPart = new MultipartContent("related");
try {
var json = Manager.GetObjectMapper().WriteValueAsString(revProps);
var utf8charset = Encoding.UTF8;
//multiPart.Add(new StringContent(json, utf8charset, "application/json"), "param1");
var jsonContent = new StringContent(json, utf8charset, "application/json");
//jsonContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
multiPart.Add(jsonContent);
} catch (IOException e) {
throw new ArgumentException("Not able to serialize revision properties into a multipart request content.", e);
}
}
var blobStore = LocalDatabase.Attachments;
var base64Digest = (string)attachment.Get("digest");
var blobKey = new BlobKey(base64Digest);
var inputStream = blobStore.BlobStreamForKey(blobKey);
if (inputStream == null) {
Log.W(TAG, "Unable to find blob file for blobKey: " + blobKey + " - Skipping upload of multipart revision.");
multiPart = null;
} else {
string contentType = null;
if (attachment.ContainsKey("content_type")) {
contentType = (string)attachment.Get("content_type");
} else {
if (attachment.ContainsKey("content-type")) {
var message = string.Format("Found attachment that uses content-type"
+ " field name instead of content_type (see couchbase-lite-android"
+ " issue #80): " + attachment);
Log.W(TAG, message);
}
}
var content = new StreamContent(inputStream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = attachmentKey
};
content.Headers.ContentType = new MediaTypeHeaderValue(contentType ?? "application/octet-stream");
multiPart.Add(content);
}
}
}
if (multiPart == null) {
return false;
}
var path = string.Format("/{0}?new_edits=false", revision.GetDocId());
// TODO: need to throttle these requests
Log.D(TAG, "Uploading multipart request. Revision: " + revision);
SafeAddToChangesCount(1);
SendAsyncMultipartRequest(HttpMethod.Put, path, multiPart, (result, e) =>
{
if (e != null) {
var httpError = e as HttpResponseException;
if (httpError != null) {
if (httpError.StatusCode == System.Net.HttpStatusCode.UnsupportedMediaType) {
_dontSendMultipart = true;
UploadJsonRevision(revision);
}
} else {
Log.E (TAG, "Exception uploading multipart request", e);
LastError = e;
RevisionFailed();
}
} else {
Log.D (TAG, "Uploaded multipart request. Result: " + result);
SafeIncrementCompletedChangesCount();
RemovePending(revision);
}
});
return true;
}
示例14: GetMultipartWriter
private MultipartWriter GetMultipartWriter(RevisionInternal rev, string boundary)
{
// Find all the attachments with "follows" instead of a body, and put 'em in a multipart stream.
// It's important to scan the _attachments entries in the same order in which they will appear
// in the JSON, because CouchDB expects the MIME bodies to appear in that same order
var bodyStream = default(MultipartWriter);
var attachments = rev.GetAttachments();
foreach (var a in attachments) {
var attachment = a.Value.AsDictionary<string, object>();
if (attachment != null && attachment.GetCast<bool>("follows")) {
if (bodyStream == null) {
// Create the HTTP multipart stream:
bodyStream = new MultipartWriter("multipart/related", boundary);
bodyStream.SetNextPartHeaders(new Dictionary<string, string> {
{ "Content-Type", "application/json" }
});
// Use canonical JSON encoder so that _attachments keys will be written in the
// same order that this for loop is processing the attachments.
var json = Manager.GetObjectMapper().WriteValueAsBytes(rev.GetProperties(), true);
if (CanSendCompressedRequests) {
bodyStream.AddGZippedData(json);
} else {
bodyStream.AddData(json);
}
}
// Add attachment as another MIME part:
var disposition = String.Format("attachment; filename={0}", Misc.QuoteString(a.Key));
var contentType = attachment.GetCast<string>("type");
var contentEncoding = attachment.GetCast<string>("encoding");
bodyStream.SetNextPartHeaders(new NonNullDictionary<string, string> {
{ "Content-Disposition", disposition },
{ "Content-Type", contentType },
{ "Content-Encoding", contentEncoding }
});
var attachmentObj = default(AttachmentInternal);
try {
attachmentObj = LocalDatabase.AttachmentForDict(attachment, a.Key);
} catch(CouchbaseLiteException) {
return null;
}
bodyStream.AddStream(attachmentObj.ContentStream, attachmentObj.Length);
}
}
return bodyStream;
}
示例15: EncodeDocumentJSON
/// <summary>INSERTION:</summary>
internal IEnumerable<Byte> EncodeDocumentJSON(RevisionInternal rev)
{
var origProps = rev.GetProperties();
if (origProps == null)
{
return null;
}
var specialKeysToLeave = new[] { "_removed", "_replication_id", "_replication_state", "_replication_state_time" };
// Don't allow any "_"-prefixed keys. Known ones we'll ignore, unknown ones are an error.
var properties = new Dictionary<String, Object>(origProps.Count);
foreach (var key in origProps.Keys)
{
var shouldAdd = false;
if (key.StartsWith("_", StringComparison.InvariantCultureIgnoreCase))
{
if (!KnownSpecialKeys.Contains(key))
{
Log.E(Tag, "Database: Invalid top-level key '" + key + "' in document to be inserted");
return null;
}
if (specialKeysToLeave.Contains(key))
{
shouldAdd = true;
}
}
else
{
shouldAdd = true;
}
if (shouldAdd)
{
properties.Put(key, origProps.Get(key));
}
}
IEnumerable<byte> json = null;
try
{
json = Manager.GetObjectMapper().WriteValueAsBytes(properties);
}
catch (Exception e)
{
Log.E(Tag, "Error serializing " + rev + " to JSON", e);
}
return json;
}