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

org.apache.jackrabbit.oak.spi.state.AbstractRebaseDiff Maven / Gradle / Ivy

There is a newer version: 1.62.0
Show newest version
/*
 * 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 static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;

import org.apache.jackrabbit.oak.api.PropertyState;

/**
 * {@code AbstractRebaseDiff} serves as base for rebase implementations.
 * It implements a {@link NodeStateDiff}, which performs the conflict
 * handling as defined in {@link org.apache.jackrabbit.oak.spi.state.NodeStore#rebase(NodeBuilder)}
 * on the Oak SPI state level.
 * 

* Intended use of this class is to re-base a branched version of the node state * tree. Given below situation: *

 *     + head (master)
 *     |
 *     | + branch
 *     |/
 *     + base
 *     |
 * 
* The current state on the master branch is {@code head} and a branch * was created at {@code base}. The current state on the branch is * {@code branch}. Re-basing {@code branch} to the current * {@code head} works as follows: *
 *     NodeState head = ...
 *     NodeState branch = ...
 *     NodeState base = ...
 *     NodeBuilder builder = new MemoryNodeBuilder(head);
 *     branch.compareAgainstBaseState(base, new MyRebaseDiff(builder));
 *     branch = builder.getNodeState();
 * 
* The result is: *
 *       + branch
 *      /
 *     + head (master)
 *     |
 * 
*

* Conflicts during rebase cause calls to the various abstracts conflict resolution * methods of this class. Concrete subclasses of this class need to implement these * methods for handling such conflicts. */ public abstract class AbstractRebaseDiff implements NodeStateDiff { private final NodeBuilder builder; protected AbstractRebaseDiff(NodeBuilder builder) { this.builder = builder; } /** * Factory method for creating a rebase handler for the named child of the passed * parent builder. * * @param builder parent builder * @param name name of the child for which to return a rebase handler * @return rebase handler for child {@code name} in {@code builder} */ protected abstract AbstractRebaseDiff createDiff(NodeBuilder builder, String name); /** * Called when the property {@code after} was added on the branch but the property * exists already in the trunk. * * @param builder parent builder * @param before existing property * @param after added property */ protected abstract void addExistingProperty(NodeBuilder builder, PropertyState before, PropertyState after); /** * Called when the property {@code after} was changed on the branch but was * deleted already in the trunk. * * @param builder parent builder * @param after changed property */ protected abstract void changeDeletedProperty(NodeBuilder builder, PropertyState after); /** * Called when the property {@code after} was changed on the branch but was * already changed to {@code before} in the trunk. * * @param builder parent property * @param before changed property in branch * @param after changed property in trunk */ protected abstract void changeChangedProperty(NodeBuilder builder, PropertyState before, PropertyState after); /** * Called when the property {@code before} was deleted in the branch but was * already deleted in the trunk. * * @param builder parent builder * @param before deleted property */ protected abstract void deleteDeletedProperty(NodeBuilder builder, PropertyState before); /** * Called when the property {@code before} was deleted in the branch but was * already changed in the trunk. * * @param builder parent builder * @param before deleted property */ protected abstract void deleteChangedProperty(NodeBuilder builder, PropertyState before); /** * Called when the node {@code after} was added on the branch but the node * exists already in the trunk. * * @param builder parent builder * @param name name of the added node * @param before existing node * @param after added added */ protected abstract void addExistingNode(NodeBuilder builder, String name, NodeState before, NodeState after); /** * Called when the node {@code after} was changed on the branch but was * deleted already in the trunk. * * @param builder parent builder * @param name name of the changed node * @param after changed node */ protected abstract void changeDeletedNode(NodeBuilder builder, String name, NodeState after); /** * Called when the node {@code before} was deleted in the branch but was * already deleted in the trunk. * * @param builder parent builder * @param before deleted node */ protected abstract void deleteDeletedNode(NodeBuilder builder, String name, NodeState before); /** * Called when the node {@code before} was deleted in the branch but was * already changed in the trunk. * * @param builder parent builder * @param before deleted node */ protected abstract void deleteChangedNode(NodeBuilder builder, String name, NodeState before); @Override public boolean propertyAdded(PropertyState after) { PropertyState other = builder.getProperty(after.getName()); if (other == null) { builder.setProperty(after); } else if (!other.equals(after)) { addExistingProperty(builder, other, after); } return true; } @Override public boolean propertyChanged(PropertyState before, PropertyState after) { PropertyState other = builder.getProperty(before.getName()); if (other == null) { changeDeletedProperty(builder, after); } else if (other.equals(before)) { builder.setProperty(after); } else if (!other.equals(after)) { changeChangedProperty(builder, before, after); } return true; } @Override public boolean propertyDeleted(PropertyState before) { PropertyState other = builder.getProperty(before.getName()); if (other == null) { deleteDeletedProperty(builder, before); } else if (other.equals(before)) { builder.removeProperty(before.getName()); } else { deleteChangedProperty(builder, before); } return true; } @Override public boolean childNodeAdded(String name, NodeState after) { if (builder.hasChildNode(name)) { after.compareAgainstBaseState(EMPTY_NODE, createDiff(builder, name)); } else { builder.setChildNode(name, after); } return true; } @Override public boolean childNodeChanged(String name, NodeState before, NodeState after) { if (builder.hasChildNode(name)) { after.compareAgainstBaseState(before, createDiff(builder, name)); } else if (after.equals(before)) { return false; } else { changeDeletedNode(builder, name, after); } return true; } @Override public boolean childNodeDeleted(String name, NodeState before) { if (!builder.hasChildNode(name)) { deleteDeletedNode(builder, name, before); } else if (before.equals(builder.child(name).getNodeState())) { builder.getChildNode(name).remove(); } else { deleteChangedNode(builder, name, before); } return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy