| /* |
| * 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 org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| /** |
| * A tree instance represents a snapshot of the {@link ContentRepository} |
| * tree at the time the instance was acquired from a {@link ContentSession}. |
| * 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. |
| * |
| * <h2>Order and orderability</h2> |
| * The children of a {@code Tree} are generally unordered. That is, the |
| * sequence of the children returned by {@link #getChildren()} may change over |
| * time as this {@code Tree} is modified either directly or through some other |
| * session. Calling {@link #orderBefore(String)} will persist the current order |
| * and maintain the order as new children are added or removed. In this case a |
| * new child will be inserted after the last child as seen by {@link #getChildren()}. |
| * |
| * <h2>State and state transitions</h2> |
| * 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> |
| * All tree instances created in the context of a content session become invalid |
| * after the content session is closed. Any method called on an invalid tree instance |
| * will throw an {@code InvalidStateException}. |
| * <p> |
| * {@link Tree} instances may become non existing after a call to |
| * {@link Root#refresh()}, {@link Root#rebase()} or {@link Root#commit()}. |
| * Any write access to non existing {@code Tree} instances will cause an |
| * {@code InvalidStateException}. |
| * |
| * <h2>Thread safety</h2> |
| * 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. |
| * |
| * <h2>Visibility and access control</h2> |
| * The data returned by this class and intermediary objects such as are access |
| * controlled governed by the {@code ContentSession} instance from which |
| * the containing {@code Root} was obtained. |
| * |
| * <h2>Existence and iterability of trees</h2> |
| * <p> |
| * The {@link #getChild(String)} method is special in that it <em>never</em> |
| * returns a {@code null} value, even if the named tree does not exist. |
| * Instead a client should use the {@link #exists()} method on the returned |
| * tree to check whether that tree exists. |
| * <p> |
| * The <em>iterability</em> of a tree is a related to existence. A node |
| * state is <em>iterable</em> if it is included in the return values of the |
| * {@link #getChildrenCount(long)} and {@link #getChildren()} methods. An iterable |
| * node is guaranteed to exist, though not all existing nodes are necessarily |
| * iterable. |
| * <p> |
| * Furthermore, a non-existing node is guaranteed to contain no properties |
| * or iterable child nodes. It can, however contain non-iterable children. |
| * Such scenarios are typically the result of access control restrictions. |
| */ |
| public interface Tree { |
| |
| /** |
| * Status of an item in a {@code Tree} |
| */ |
| enum Status { |
| /** |
| * Item is unchanged |
| */ |
| UNCHANGED, |
| |
| /** |
| * Item is new |
| */ |
| NEW, |
| |
| /** |
| * Item is modified: has added or removed children or added, removed or modified |
| * properties. |
| */ |
| MODIFIED |
| } |
| |
| /** |
| * @return the name of this {@code Tree} instance. |
| */ |
| @NotNull |
| String getName(); |
| |
| /** |
| * @return {@code true} iff this is the root |
| */ |
| boolean isRoot(); |
| |
| /** |
| * @return the absolute path of this {@code Tree} instance from its {@link Root}. |
| */ |
| @NotNull |
| String getPath(); |
| |
| /** |
| * Get the {@code Status} of this tree instance. |
| * |
| * @return The status of this tree instance. |
| */ |
| @NotNull |
| Status getStatus(); |
| |
| /** |
| * Determine whether this tree has been removed or does not exist otherwise (e.g. caused |
| * by a refresh, rebase or commit) or is not visible due to access control restriction |
| * or does not exist at all. |
| * @return {@code true} if this tree exists, {@code false} otherwise. |
| */ |
| boolean exists(); |
| |
| /** |
| * @return the possibly non existent parent of this {@code Tree}. |
| * @throws IllegalStateException if called on the root tree. |
| */ |
| @NotNull |
| Tree getParent(); |
| |
| /** |
| * Get a property state |
| * |
| * @param name The name of the property state. |
| * @return the property state with the given {@code name} or {@code null} |
| * if no such property state exists or the property is not accessible. |
| */ |
| @Nullable |
| PropertyState getProperty(@NotNull String name); |
| |
| /** |
| * Get the {@code Status} of a property state or {@code null}. |
| * |
| * @param name The 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 or if the name refers |
| * to a property that is not accessible. |
| */ |
| @Nullable |
| Status getPropertyStatus(@NotNull String name); |
| |
| /** |
| * Determine if a property state exists and is accessible. |
| * |
| * @param name The name of the property state |
| * @return {@code true} if and only if a property with the given {@code name} |
| * exists and is accessible. |
| */ |
| boolean hasProperty(@NotNull String name); |
| |
| /** |
| * Determine the number of properties accessible to the current content session. |
| * |
| * @return The number of accessible properties. |
| */ |
| long getPropertyCount(); |
| |
| /** |
| * All accessible 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 accessible property states. |
| */ |
| @NotNull |
| Iterable<? extends PropertyState> getProperties(); |
| |
| /** |
| * Get a possibly non existing child of this {@code Tree}. |
| * @param name The name of the child to retrieve. |
| * @return The child with the given {@code name}. |
| * @throws IllegalArgumentException if the given name is invalid |
| */ |
| @NotNull |
| Tree getChild(@NotNull String name) throws IllegalArgumentException; |
| |
| /** |
| * Determine if a child of this {@code Tree} instance exists. If no child |
| * exists or an existing child isn't accessible this method returns {@code false}. |
| * |
| * @param name The name of the child |
| * @return {@code true} if and only if a child with the given {@code name} |
| * exists and is accessible for the current content session. |
| */ |
| boolean hasChild(@NotNull String name); |
| |
| /** |
| * Determine the number of children of this {@code Tree} instance taking |
| * access restrictions into account. |
| * <p> |
| * If an implementation does know the exact value, it returns it (even if |
| * the value is higher than max). If the implementation does not know the |
| * exact value, and the child node count is higher than max, it may return |
| * Long.MAX_VALUE. The cost of the operation is at most O(max). |
| * |
| * @param max the maximum value |
| * @return the number of accessible children. |
| */ |
| long getChildrenCount(long max); |
| |
| /** |
| * All accessible children of this {@code Tree} instance. 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 not visible to iterators obtained from the returned iterable. |
| * |
| * @return An {@code Iterable} for all accessible children |
| */ |
| @NotNull |
| Iterable<Tree> getChildren(); |
| |
| /** |
| * Remove this tree instance. This operation never succeeds for the root tree. |
| * |
| * @return {@code true} if the node was removed; {@code false} otherwise. |
| */ |
| boolean remove(); |
| |
| /** |
| * Add a child with the given {@code name}. Does nothing if such a child |
| * already exists. |
| * |
| * @param name name of the child. A valid name does not start with a colon, |
| * is not empty and does not contain a forward slash. |
| * @return the {@code Tree} instance of the child with the given {@code name}. |
| * @throws IllegalArgumentException if {@code name} is not valid. |
| */ |
| @NotNull |
| Tree addChild(@NotNull String name) throws IllegalArgumentException; |
| |
| /** |
| * Changes the nature of this tree such that the order of the children |
| * is kept stable. The expected behavior is as follows: |
| * <p> |
| * <ol> |
| * <li>Calling {@code setOrderableChildren(true)} on a tree |
| * the first time will stabilize the order of existing children. Any |
| * subsequent {@link #addChild(String)} call is guaranteed to insert |
| * the new tree and the end of the child list.</li> |
| * <li>Calling {@code setOrderableChildren(true)} on a tree |
| * that already has its children ordered has no effect.</li> |
| * <li>Calling {@code setOrderableChildren(false)} on a tree that |
| * doesn't have ordered children has not effect</li> |
| * <li>Calling {@code setOrderableChildren(false)} on a tree |
| * with ordered children will remove the necessity to keep the child |
| * list stable. The order of children upon {@link #getChildren()} is |
| * subsequently undefined.</li> |
| * </ol> |
| * <p> |
| * Calling {@link #orderBefore(String)} on a tree, implicitly enables |
| * orderable children on the parent tree. |
| * |
| * @param enable Enable (or disable) orderable children for this tree. |
| */ |
| void setOrderableChildren(boolean enable); |
| |
| /** |
| * Orders this {@code Tree} before the sibling tree with the given |
| * {@code name}. Calling this method for the first time on this |
| * {@code Tree} or any of its siblings will persist the current order |
| * of siblings and maintain it from this point on. |
| * |
| * @param name the name of the sibling node where this tree is ordered |
| * before. This tree will become the last sibling if |
| * {@code name} is {@code null}. |
| * @return {@code false} if there is no sibling with the given |
| * {@code name} or no reordering was performed; |
| * {@code true} otherwise. |
| * @throws IllegalArgumentException if the given name is invalid |
| */ |
| boolean orderBefore(@Nullable String name); |
| |
| /** |
| * Set a property state |
| * |
| * @param property The property state to set |
| * @throws IllegalArgumentException if {@code property} has a non valid name. A valid name |
| * does not start with a colon, is not empty and does not contain a forward slash. |
| */ |
| void setProperty(@NotNull PropertyState property); |
| |
| /** |
| * Set a property state |
| * |
| * @param name The name of this property. A valid name does not start with a colon, |
| * is not empty and does not contain a forward slash. |
| * @param value The value of this property |
| * @param <T> The type of this property. Must be one of {@code String, Blob, byte[], Long, Integer, Double, Boolean, BigDecimal} |
| * @throws IllegalArgumentException if {@code T} is not one of the above types or |
| * if {@code name} is not valid. |
| */ |
| <T> void setProperty(@NotNull String name, @NotNull T value) |
| throws IllegalArgumentException; |
| |
| /** |
| * Set a property state |
| * |
| * @param name The name of this property. A valid name does not start with a colon, |
| * is not empty and does not contain a forward slash. |
| * @param value The value of this property |
| * @param type The type of this property. |
| * @param <T> The type of this property. |
| * @throws IllegalArgumentException if {@code name} is not valid. |
| */ |
| <T> void setProperty(@NotNull String name, @NotNull T value, @NotNull Type<T> type) |
| throws IllegalArgumentException; |
| |
| /** |
| * Remove the property with the given name. This method has no effect if a |
| * property of the given {@code name} does not exist. |
| * |
| * @param name The name of the property |
| */ |
| void removeProperty(@NotNull String name); |
| |
| /** |
| * Empty array of trees. |
| */ |
| Tree[] EMPTY_ARRAY = new Tree[0]; |
| |
| } |