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

com.couchbase.lite.internal.core.C4Document Maven / Gradle / Ivy

//
// Copyright (c) 2020, 2017 Couchbase, Inc 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.couchbase.lite.internal.core;

import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;

import com.couchbase.lite.LiteCoreException;
import com.couchbase.lite.internal.fleece.FLDict;
import com.couchbase.lite.internal.fleece.FLSharedKeys;
import com.couchbase.lite.internal.fleece.FLSliceResult;


@SuppressWarnings({"PMD.GodClass", "PMD.TooManyMethods"})
public class C4Document extends C4NativePeer {
    public static boolean dictContainsBlobs(FLSliceResult dict, FLSharedKeys sk) {
        return dictContainsBlobs(dict.getHandle(), sk.getHandle());
    }

    //-------------------------------------------------------------------------
    // Constructor
    //-------------------------------------------------------------------------
    C4Document(long db, String docID, boolean mustExist) throws LiteCoreException { this(get(db, docID, mustExist)); }

    C4Document(long db, long sequence) throws LiteCoreException { this(getBySequence(db, sequence)); }

    C4Document(long handle) { super(handle); }

    //-------------------------------------------------------------------------
    // public methods
    //-------------------------------------------------------------------------

    // - C4Document

    public int getFlags() { return withPeer(0, C4Document::getFlags); }

    @Nullable
    public String getDocID() { return withPeer(null, C4Document::getDocID); }

    @Nullable
    public String getRevID() { return withPeer(null, C4Document::getRevID); }

    public long getSequence() { return withPeer(0L, C4Document::getSequence); }

    // - C4Revision

    @Nullable
    public String getSelectedRevID() { return withPeer(null, C4Document::getSelectedRevID); }

    public long getSelectedSequence() { return withPeer(0L, C4Document::getSelectedSequence); }

    public FLDict getSelectedBody2() {
        final long value = withPeer(null, C4Document::getSelectedBody2);
        return value == 0 ? null : new FLDict(value);
    }

    // - Lifecycle

    public int getSelectedFlags() { return withPeer(0, C4Document::getSelectedFlags); }

    public void save(int maxRevTreeDepth) throws LiteCoreException { save(getPeer(), maxRevTreeDepth); }

    // - Revisions

    public boolean selectNextRevision() { return withPeer(false, C4Document::selectNextRevision); }

    public void selectNextLeafRevision(boolean includeDeleted, boolean withBody) throws LiteCoreException {
        selectNextLeafRevision(getPeer(), includeDeleted, withBody);
    }

    // - Purging and Expiration

    public void resolveConflict(String winningRevID, String losingRevID, byte[] mergeBody, int mergedFlags)
        throws LiteCoreException {
        resolveConflict(getPeer(), winningRevID, losingRevID, mergeBody, mergedFlags);
    }

    // - Creating and Updating Documents

    public C4Document update(FLSliceResult body, int flags) throws LiteCoreException {
        final long bodyHandle = (body != null) ? body.getHandle() : 0;
        final long newDoc = withPeerThrows(0L, h -> update2(h, bodyHandle, flags));
        return (newDoc == 0) ? null : new C4Document(newDoc);
    }

    @VisibleForTesting
    public C4Document update(byte[] body, int flags) throws LiteCoreException {
        final long newDoc = withPeerThrows(0L, h -> update(h, body, flags));
        return (newDoc == 0) ? null : new C4Document(newDoc);
    }

    // - Helper methods

    // helper methods for Document
    public boolean deleted() { return isSelectedRevFlags(C4Constants.RevisionFlags.DELETED); }

    public boolean exists() { return isFlags(C4Constants.DocumentFlags.EXISTS); }

    public boolean isSelectedRevFlags(int flag) { return (getSelectedFlags() & flag) == flag; }

    // - Fleece

    @Nullable
    public String bodyAsJSON(boolean canonical) throws LiteCoreException {
        return withPeerThrows(null, h -> bodyAsJSON(h, canonical));
    }

    //-------------------------------------------------------------------------
    // protected methods
    //-------------------------------------------------------------------------

    @SuppressWarnings("NoFinalizer")
    @Override
    protected void finalize() throws Throwable {
        try { free(); }
        finally { super.finalize(); }
    }

    //-------------------------------------------------------------------------
    // package protected methods
    //-------------------------------------------------------------------------

    // - Lifecycle

    byte[] getSelectedBody() { return withPeer(null, C4Document::getSelectedBody); }

    @VisibleForTesting
    void free() {
        final long handle = getPeerAndClear();
        if (handle == 0L) { return; }

        free(handle);
    }

    // - Revisions

    @VisibleForTesting
    boolean selectCurrentRevision() { return withPeer(false, C4Document::selectCurrentRevision); }

    @VisibleForTesting
    void loadRevisionBody() throws LiteCoreException { loadRevisionBody(getPeer()); }

    @VisibleForTesting
    boolean hasRevisionBody() { return withPeer(false, C4Document::hasRevisionBody); }

    @VisibleForTesting
    boolean selectParentRevision() { return withPeer(false, C4Document::selectParentRevision); }

    @VisibleForTesting
    boolean selectFirstPossibleAncestorOf(String revID) {
        return withPeer(false, h -> selectFirstPossibleAncestorOf(h, revID));
    }

    @VisibleForTesting
    boolean selectNextPossibleAncestorOf(String revID) {
        return withPeer(false, h -> selectNextPossibleAncestorOf(h, revID));
    }

    @VisibleForTesting
    boolean selectCommonAncestorRevision(String revID1, String revID2) {
        return withPeer(false, h -> selectCommonAncestorRevision(h, revID1, revID2));
    }

    // - Purging and Expiration

    @VisibleForTesting
    int purgeRevision(String revID) throws LiteCoreException {
        return withPeerThrows(0, h -> purgeRevision(h, revID));
    }

    //-------------------------------------------------------------------------
    // private methods
    //-------------------------------------------------------------------------

    private boolean isFlags(int flag) { return (getFlags() & flag) == flag; }

    @SuppressWarnings("PMD.UnusedPrivateMethod")
    private boolean conflicted() { return isFlags(C4Constants.DocumentFlags.CONFLICTED); }

    @SuppressWarnings("PMD.UnusedPrivateMethod")
    private boolean accessRemoved() { return isSelectedRevFlags(C4Constants.RevisionFlags.PURGED); }

    //-------------------------------------------------------------------------
    // native methods
    //-------------------------------------------------------------------------

    // - Purging and Expiration

    static native void setExpiration(long db, String docID, long timestamp) throws LiteCoreException;

    static native long getExpiration(long db, String docID) throws LiteCoreException;

    // - Creating and Updating Documents

    static native long create(long db, String docID, byte[] body, int flags) throws LiteCoreException;

    static native long create2(long db, String docID, long body, int flags) throws LiteCoreException;

    @SuppressWarnings("PMD.ExcessiveParameterList")
    static native long put(
        long db,
        byte[] body,
        String docID,
        int revFlags,
        boolean existingRevision,
        boolean allowConflict,
        String[] history,
        boolean save,
        int maxRevTreeDepth,
        int remoteDBID)
        throws LiteCoreException;

    @SuppressWarnings("PMD.ExcessiveParameterList")
    static native long put2(
        long db,
        long body, // C4Slice*
        String docID,
        int revFlags,
        boolean existingRevision,
        boolean allowConflict,
        String[] history,
        boolean save,
        int maxRevTreeDepth,
        int remoteDBID)
        throws LiteCoreException;

    // - C4Document

    private static native int getFlags(long doc);

    private static native String getDocID(long doc);

    private static native String getRevID(long doc);

    private static native long getSequence(long doc);

    // - C4Revision

    private static native String getSelectedRevID(long doc);

    private static native int getSelectedFlags(long doc);

    private static native long getSelectedSequence(long doc);

    private static native byte[] getSelectedBody(long doc);

    // return pointer to FLValue
    private static native long getSelectedBody2(long doc);

    // - Lifecycle

    private static native long get(long db, String docID, boolean mustExist) throws LiteCoreException;

    private static native long getBySequence(long db, long sequence) throws LiteCoreException;

    private static native void save(long doc, int maxRevTreeDepth) throws LiteCoreException;

    private static native void free(long doc);

    // - Revisions

    private static native boolean selectCurrentRevision(long doc);

    private static native void loadRevisionBody(long doc) throws LiteCoreException;

    private static native boolean hasRevisionBody(long doc);

    private static native boolean selectParentRevision(long doc);

    private static native boolean selectNextRevision(long doc);

    private static native void selectNextLeafRevision(
        long doc,
        boolean includeDeleted,
        boolean withBody)
        throws LiteCoreException;

    private static native boolean selectFirstPossibleAncestorOf(long doc, String revID);

    private static native boolean selectNextPossibleAncestorOf(long doc, String revID);

    private static native boolean selectCommonAncestorRevision(long doc, String revID1, String revID2);

    // - Purging and Expiration

    private static native int purgeRevision(long doc, String revID) throws LiteCoreException;

    private static native void resolveConflict(
        long doc,
        String winningRevID,
        String losingRevID,
        byte[] mergeBody,
        int mergedFlags)
        throws LiteCoreException;

    // - Creating and Updating Documents

    private static native long update(long doc, byte[] body, int flags) throws LiteCoreException;

    private static native long update2(long doc, long body, int flags) throws LiteCoreException;

    // - Fleece-related

    // doc -> pointer to C4Document
    @Nullable
    private static native String bodyAsJSON(long doc, boolean canonical) throws LiteCoreException;

    private static native boolean dictContainsBlobs(long dict, long sk); // dict -> FLSliceResult
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy