Author: tomekr
Date: Fri Apr 28 07:15:00 2017
New Revision: 1792992
URL: http://svn.apache.org/viewvc?rev=1792992&view=rev
Log:
OAK-6132: Backport oak-upgrade to 1.0 and 1.2
-backported NodeBuilderTree
Added:
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/AbstractMutableTree.java
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/NodeBuilderTree.java
Added:
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/AbstractMutableTree.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/AbstractMutableTree.java?rev=1792992&view=auto
==============================================================================
---
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/AbstractMutableTree.java
(added)
+++
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/AbstractMutableTree.java
Fri Apr 28 07:15:00 2017
@@ -0,0 +1,224 @@
+/*
+ * 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.upgrade.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Lists.newArrayListWithCapacity;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static
org.apache.jackrabbit.oak.plugins.tree.TreeConstants.OAK_CHILD_ORDER;
+import static org.apache.jackrabbit.oak.spi.state.NodeStateUtils.isHidden;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.core.HiddenTree;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.plugins.tree.AbstractTree;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+
+/**
+ * {@code AbstractMutableTree} extends {@code AbstractTree} with
implementations
+ * for most write methods of {@code Tree}. Furthermore it handles the ordering
+ * of siblings.
+ */
+public abstract class AbstractMutableTree extends AbstractTree {
+
+ protected AbstractMutableTree(@Nonnull String name, @Nonnull NodeBuilder
nodeBuilder) {
+ super(name, nodeBuilder);
+ }
+
+ protected abstract AbstractMutableTree getParentOrNull();
+
+ protected abstract NodeBuilder getNodeBuilder();
+
+ @Override
+ @Nonnull
+ public AbstractMutableTree getParent() {
+ AbstractMutableTree parent = getParentOrNull();
+ checkState(parent != null, "root tree does not have a parent");
+ return parent;
+ }
+
+ @Override
+ @Nonnull
+ public Tree getChild(@Nonnull String name) throws IllegalArgumentException
{
+ if (!isHidden(name)) {
+ return createChild(name);
+ } else {
+ return new HiddenTree(this, name);
+ }
+ }
+
+ @Override
+ public boolean remove() {
+ String name = getName();
+ AbstractMutableTree parent = getParentOrNull();
+ if (parent != null && parent.hasChild(name)) {
+ getNodeBuilder().remove();
+ NodeBuilder parentBuilder = parent.getNodeBuilder();
+ PropertyState order = parentBuilder.getProperty(OAK_CHILD_ORDER);
+ if (order != null) {
+ List<String> names = newArrayListWithCapacity(order.count());
+ for (String n : order.getValue(NAMES)) {
+ if (!n.equals(name)) {
+ names.add(n);
+ }
+ }
+ parentBuilder.setProperty(OAK_CHILD_ORDER, names, NAMES);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Nonnull
+ @Override
+ public Tree addChild(@Nonnull String name) throws IllegalArgumentException
{
+ checkArgument(!isHidden(name));
+ if (!hasChild(name)) {
+ NodeBuilder nodeBuilder = getNodeBuilder();
+ nodeBuilder.setChildNode(name);
+ PropertyState order = nodeBuilder.getProperty(OAK_CHILD_ORDER);
+ if (order != null) {
+ List<String> names = newArrayListWithCapacity(order.count() +
1);
+ for (String n : order.getValue(NAMES)) {
+ if (!n.equals(name)) {
+ names.add(n);
+ }
+ }
+ names.add(name);
+ nodeBuilder.setProperty(OAK_CHILD_ORDER, names, NAMES);
+ }
+ }
+ return createChild(name);
+ }
+
+
+ @Override
+ public void setOrderableChildren(boolean enable) {
+ if (enable) {
+ updateChildOrder(true);
+ } else {
+ getNodeBuilder().removeProperty(OAK_CHILD_ORDER);
+ }
+ }
+
+ /**
+ * Updates the child order to match any added or removed child nodes that
+ * are not yet reflected in the {@link
org.apache.jackrabbit.oak.plugins.tree.TreeConstants#OAK_CHILD_ORDER}
+ * property. If the {@code force} flag is set, the child order is set
+ * in any case, otherwise only if the node already is orderable.
+ *
+ * @param force whether to add child order information if it doesn't exist
+ */
+ protected void updateChildOrder(boolean force) {
+ if (force || hasOrderableChildren()) {
+ getNodeBuilder().setProperty(PropertyStates.createProperty(
+ OAK_CHILD_ORDER, getChildNames(), Type.NAMES));
+ }
+ }
+
+ @Override
+ public boolean orderBefore(@Nullable String name) {
+ String thisName = getName();
+ AbstractMutableTree parent = getParentOrNull();
+ if (parent == null) {
+ return false; // root does not have siblings
+ } else if (thisName.equals(name)) {
+ return false; // same node
+ }
+
+ // perform the reorder
+ List<String> names = newArrayListWithCapacity(10000);
+ NodeBuilder builder = parent.getNodeBuilder();
+ boolean found = false;
+
+ // first try reordering based on the (potentially out-of-sync)
+ // child order property in the parent node
+ for (String n : builder.getNames(OAK_CHILD_ORDER)) {
+ if (n.equals(name) && parent.hasChild(name)) {
+ names.add(thisName);
+ found = true;
+ }
+ if (!n.equals(thisName)) {
+ names.add(n);
+ }
+ }
+
+ // if the target node name was not found in the parent's child order
+ // property, we need to fall back to recreating the child order list
+ if (!found) {
+ names.clear();
+ for (String n : parent.getChildNames()) {
+ if (n.equals(name)) {
+ names.add(thisName);
+ found = true;
+ }
+ if (!n.equals(thisName)) {
+ names.add(n);
+ }
+ }
+ }
+
+ if (name == null) {
+ names.add(thisName);
+ found = true;
+ }
+
+ if (found) {
+ builder.setProperty(OAK_CHILD_ORDER, names, NAMES);
+ return true;
+ } else {
+ // no such sibling (not existing or not accessible)
+ return false;
+ }
+ }
+
+ @Override
+ public void setProperty(@Nonnull PropertyState property) {
+ checkArgument(!isHidden(checkNotNull(property).getName()));
+ getNodeBuilder().setProperty(property);
+ }
+
+ @Override
+ public <T> void setProperty(@Nonnull String name, @Nonnull T value) throws
IllegalArgumentException {
+ checkArgument(!isHidden(checkNotNull(name)));
+ getNodeBuilder().setProperty(name, checkNotNull(value));
+ }
+
+ @Override
+ public <T> void setProperty(@Nonnull String name, @Nonnull T value,
@Nonnull Type<T> type)
+ throws IllegalArgumentException {
+ checkArgument(!isHidden(checkNotNull(name)));
+ getNodeBuilder().setProperty(name, checkNotNull(value),
checkNotNull(type));
+ }
+
+ @Override
+ public void removeProperty(@Nonnull String name) {
+ getNodeBuilder().removeProperty(checkNotNull(name));
+ }
+}
\ No newline at end of file
Added:
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/NodeBuilderTree.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/NodeBuilderTree.java?rev=1792992&view=auto
==============================================================================
---
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/NodeBuilderTree.java
(added)
+++
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/tree/NodeBuilderTree.java
Fri Apr 28 07:15:00 2017
@@ -0,0 +1,84 @@
+/*
+ * 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.upgrade.tree;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+
+/**
+ * A mutable {@code Tree} implementation based on an underlying
+ * {@code NodeBuilder}, which tracks all changes recorded through
+ * this tree's mutator methods.
+ */
+public final class NodeBuilderTree extends AbstractMutableTree {
+
+ private final NodeBuilderTree parent;
+
+ private final String name;
+
+ private final NodeBuilder nodeBuilder;
+
+ /**
+ * Create a new {@code AbstractTree} instance
+ *
+ * @param nodeBuilder {@code NodeBuilder} for the underlying node state
+ * @param name name of the tree
+ */
+ public NodeBuilderTree(@Nonnull String name, @Nonnull NodeBuilder
nodeBuilder) {
+ this(null, nodeBuilder, name);
+ }
+
+ protected NodeBuilderTree(@Nullable NodeBuilderTree parent, @Nonnull
NodeBuilder nodeBuilder,
+ @Nonnull String name) {
+ super(name, nodeBuilder);
+ this.parent = parent;
+ this.name = name;
+ this.nodeBuilder = nodeBuilder;
+ }
+
+ @Override
+ @CheckForNull
+ protected AbstractMutableTree getParentOrNull() {
+ return parent;
+ }
+
+ @Nonnull
+ @Override
+ protected NodeBuilder getNodeBuilder() {
+ return nodeBuilder;
+ }
+
+ @Nonnull
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ @Nonnull
+ protected NodeBuilderTree createChild(@Nonnull String name) throws
IllegalArgumentException {
+ return new NodeBuilderTree(this,
nodeBuilder.getChildNode(checkNotNull(name)), name);
+ }
+
+}
\ No newline at end of file