/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.jackrabbit.oak.spi.state;

import java.io.IOException;
import java.io.InputStream;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;

/**
 * Storage abstraction for trees. At any given point in time the stored
 * tree is rooted at a single immutable node state.
 * <p>
 * This is a low-level interface that doesn't cover functionality like
 * merging concurrent changes or rejecting new tree states based on some
 * higher-level consistency constraints.
 */
public interface NodeStore {

    /**
     * Returns the latest state of the tree.
     *
     * @return root node state
     */
    @Nonnull
    NodeState getRoot();

    /**
     * Merges the changes from the passed {@code builder} into
     * the store.
     *
     * @param builder  the builder whose changes to apply
     * @param commitHook the commit hook to apply while merging changes
     * @param info commit info associated with this merge operation
     * @return the node state resulting from the merge.
     * @throws CommitFailedException if the merge failed
     * @throws IllegalArgumentException if the builder is not acquired
     *                                  from a root state of this store
     */
    @Nonnull
    NodeState merge(
            @Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
            @Nonnull CommitInfo info) throws CommitFailedException;

    /**
     * Rebase the changes in the passed {@code builder} on top of the current root state.
     *
     * @param builder  the builder to rebase
     * @return the node state resulting from the rebase.
     * @throws IllegalArgumentException if the builder is not acquired
     *                                  from a root state of this store
     */
    @Nonnull
    NodeState rebase(@Nonnull NodeBuilder builder);

    /**
     * Reset the passed {@code builder} by throwing away all its changes and
     * setting its base state to the current root state.
     *
     * @param builder the builder to reset
     * @return the node state resulting from the reset.
     * @throws IllegalArgumentException if the builder is not acquired
     *                                  from a root state of this store
     */
    NodeState reset(@Nonnull NodeBuilder builder);

    /**
     * Create a {@link Blob} from the given input stream. The input stream
     * is closed after this method returns.
     * @param inputStream  The input stream for the {@code Blob}
     * @return  The {@code Blob} representing {@code inputStream}
     * @throws IOException  If an error occurs while reading from the stream
     */
    @Nonnull
    Blob createBlob(InputStream inputStream) throws IOException;

    /**
     * Get a blob by its reference.
     * @param reference  reference to the blob
     * @return  blob or {@code null} if the reference does not resolve to a blob.
     * @see Blob#getReference()
     */
    @CheckForNull
    Blob getBlob(@Nonnull String reference);

    /**
     * Creates a new checkpoint of the latest root of the tree. The checkpoint
     * remains valid for at least as long as requested and allows that state
     * of the repository to be retrieved using the returned opaque string
     * reference.
     *
     * @param lifetime time (in milliseconds, &gt; 0) that the checkpoint
     *                 should remain available
     * @return string reference of this checkpoint
     */
    @Nonnull
    String checkpoint(long lifetime);

    /**
     * Retrieves the root node from a previously created repository checkpoint.
     *
     * @param checkpoint string reference of a checkpoint
     * @return the root node of the checkpoint,
     *         or {@code null} if the checkpoint is no longer available
     */
    @CheckForNull
    NodeState retrieve(@Nonnull String checkpoint);

    void release(@Nonnull String checkpoint);

}

@@ -1716,56 +1716,161 @@
 ges 
-from the passed %7B@code b
+between the%0A     * %7B@link NodeBuilder#getBaseState() base%7D and%0A     * %7B@link NodeB
 uilder
-%7D into
+#getNodeState() head%7D states
 %0A     *
+ of
  the 
+given builder to this 
 stor
@@ -1893,33 +1893,32 @@
  @param builder 
- 
 the builder whos
@@ -2538,16 +2538,17 @@
 * Rebase
+s
  the cha
@@ -2556,36 +2556,152 @@
 ges 
-in the passed %7B@code
+between the%0A     * %7B@link NodeBuilder#getBaseState() base%7D and%0A     * %7B@link NodeBuilder#getNodeState() head%7D states%0A     * of the given
  builder
 %7D on
@@ -2696,17 +2696,16 @@
  builder
-%7D
  on top 
@@ -2723,32 +2723,210 @@
 ent root state.%0A
+     * The base state of the given builder becomes the latest%0A     * %7B@link #getRoot() root%7D state of the repository, and the%0A     * head state will contain the rebased changes.%0A
      *%0A     * @p
@@ -2938,17 +2938,16 @@
 builder 
- 
 the buil

Unclear NodeStore.merge() contract