/*
 * 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.api;

import java.util.List;

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

/**
 * A tree instance represents a snapshot of the {@code ContentRepository}
 * tree at the time the instance was acquired. Tree instances may
 * become invalid over time due to garbage collection of old content, at
 * which point an outdated snapshot will start throwing
 * {@code IllegalStateException}s to indicate that the snapshot is no
 * longer available.
 * <p>
 * A tree instance belongs to the client and its state is only modified
 * in response to method calls made by the client. The various accessors
 * on this interface mirror these of the underlying {@code NodeState}
 * interface. However, since instances of this class are mutable return
 * values may change between invocations.
 * <p>
 * Tree instances are not thread-safe for write access, so writing clients
 * need to ensure that they are not accessed concurrently from multiple
 * threads. Instances are however thread-safe for read access, so
 * implementations need to ensure that all reading clients see a
 * coherent state.
 */
public interface Tree {

    /**
     * Status of an item in a {@code Tree}
     */
    enum Status {
        /**
         * Item is persisted
         */
        EXISTING,

        /**
         * Item is new
         */
        NEW,

        /**
         * Item is modified: has added or removed children or added, removed or modified
         * properties.
         */
        MODIFIED,

        /**
         * Item is removed
         */
        REMOVED
    }

    /**
     * @return  the name of this {@code Tree} instance.
     */
    @Nonnull
    String getName();

    /**
     * @return {@code true} iff this is the root
     */
    boolean isRoot();

    /**
     * @return  path of this {@code Tree} instance relative to its {@link Root}.
     */
    @Nonnull
    String getPath();

    /**
     * @return the parent of this {@code Tree} instance. This method returns
     * {@code null} if the parent is not accessible or if no parent exists (root
     * node).
     */
    @CheckForNull
    Tree getParent();

    /**
     * Get a property state
     * @param name name of the property state
     * @return  the property state with the given {@code name} or {@code null}
     *          if no such property state exists.
     */
    @CheckForNull
    PropertyState getProperty(String name);

    /**
     * Get the {@code Status} of a property state
     * @param name  name of the property state
     * @return  the status of the property state with the given {@code name}
     *          or {@code null} in no such property state exists.
     */
    @CheckForNull
    Status getPropertyStatus(String name);

    /**
     * Determine if a property state exists
     * @param name  name of the property state
     * @return  {@code true} if and only if a property with the given {@code name}
     *          exists.
     */
    boolean hasProperty(String name);

    /**
     * Determine the number of properties.
     * @return  number of properties
     */
    long getPropertyCount();

    /**
     * All property states. The returned {@code Iterable} has snapshot semantics. That
     * is, it reflect the state of this {@code Tree} instance at the time of the
     * call. Later changes to this instance are no visible to iterators obtained from
     * the returned iterable.
     * @return  An {@code Iterable} for all property states
     */
    @Nonnull
    Iterable<? extends PropertyState> getProperties();

    /**
     * Get a child of this {@code Tree} instance
     * @param name  name of the child
     * @return  the child with the given {@code name} or {@code null} if no such child
     * exists.
     */
    @CheckForNull
    Tree getChild(String name);

    /**
     * Get the {@code Status} of this tree
     * @return  the status of this tree
     */
    @Nonnull
    Status getStatus();

    /**
     * Determine if a child of this {@code Tree} instance exists.
     * @param name  name of the child
     * @return  {@code true} if and only if a child with the given {@code name}
     *          exists.
     */
    boolean hasChild(String name);

    /**
     * Determine the number of children of this {@code Tree} instance.
     * @return  number of children
     */
    long getChildrenCount();

    /**
     * All children of this {@code Tree} instance. The returned {@code Iterable}
     * has snapshot semantics. That is, it reflect the state of this {@code Tree}
     * instance. instance at the time of the call. Later changes to this instance are no
     * visible to iterators obtained from the returned iterable.
     * @return  An {@code Iterable} for all children
     */
    @Nonnull
    Iterable<Tree> getChildren();

    /**
     * Add a child with the given {@code name}. Does nothing if such a child
     * already exists.
     *
     * @param name name of the child
     * @return the {@code Tree} instance of the child with the given {@code name}.
     */
    @Nonnull
    Tree addChild(String name);

    /**
     * Remove this sub tree if not root.
     * @return  {@code false} iff this is the root.
     */
    boolean remove();

    /**
     * Set a single valued property state
     *
     * @param name The name of this property
     * @param value The value of this property
     * @return the affected property state
     */
    @Nonnull
    PropertyState setProperty(String name, CoreValue value);

    /**
     * Set a multivalued valued property state
     *
     * @param name The name of this property
     * @param values The value of this property
     * @return the affected property state
     */
    @Nonnull
    PropertyState setProperty(String name, List<CoreValue> values);

    /**
     * Remove a property
     * @param name name of the property
     */
    void removeProperty(String name);

}

@@ -2995,32 +2995,39 @@
  property state%0A
+     *%0A
      * @param na
@@ -3021,32 +3021,36 @@
   * @param name 
+The 
 name of the prop
@@ -3051,32 +3051,33 @@
 e property state
+.
 %0A     * @return 
@@ -3072,25 +3072,24 @@
   * @return 
- 
 the property
@@ -3145,25 +3145,16 @@
 %7D%0A     *
-         
  if no s
@@ -3170,32 +3170,66 @@
 rty state exists
+ or the property is not accessible
 .%0A     */%0A    @C
@@ -3654,16 +3654,42 @@
 e exists
+ and is accessible.%0A     *
 %0A     * 
@@ -3692,32 +3692,35 @@
   * @param name 
+The
  name of the pro
@@ -3738,33 +3738,32 @@
 %0A     * @return 
- 
 %7B@code true%7D if 
@@ -3827,32 +3827,50 @@
           exists
+ and is accessible
 .%0A     */%0A    bo

Define behavior of Tree#getProperty(String) in case of lack of access OAK-195: State that Tree#hasProperty returns false of the property is not accessible