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

import static com.google.common.base.Preconditions.checkNotNull;
import static javax.jcr.version.OnParentVersionAction.ABORT;
import static javax.jcr.version.OnParentVersionAction.COMPUTE;
import static javax.jcr.version.OnParentVersionAction.COPY;
import static javax.jcr.version.OnParentVersionAction.IGNORE;
import static javax.jcr.version.OnParentVersionAction.INITIALIZE;
import static javax.jcr.version.OnParentVersionAction.VERSION;
import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
import static org.apache.jackrabbit.JcrConstants.JCR_FROZENMIXINTYPES;
import static org.apache.jackrabbit.JcrConstants.JCR_FROZENNODE;
import static org.apache.jackrabbit.JcrConstants.JCR_FROZENPRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.JCR_FROZENUUID;
import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
import static org.apache.jackrabbit.JcrConstants.JCR_PREDECESSORS;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONHISTORY;
import static org.apache.jackrabbit.JcrConstants.MIX_VERSIONABLE;
import static org.apache.jackrabbit.JcrConstants.NT_FROZENNODE;
import static org.apache.jackrabbit.JcrConstants.NT_VERSIONEDCHILD;
import static org.apache.jackrabbit.oak.plugins.version.Utils.primaryTypeOf;
import static org.apache.jackrabbit.oak.plugins.version.Utils.uuidFromNode;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.version.OnParentVersionAction;

import com.google.common.collect.Lists;
import org.apache.jackrabbit.oak.api.CommitFailedException;
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.commons.UUIDUtils;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.plugins.tree.factories.TreeFactory;
import org.apache.jackrabbit.oak.plugins.tree.impl.ImmutableTree;
import org.apache.jackrabbit.oak.plugins.tree.TreeConstants;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@code VersionableState} provides methods to create a versionable state
 * for a version based on a versionable node.
 * <p>
 * The restore implementation of this class does not handle the removeExisting
 * flag. It is expected that this is handled on a higher level. If this is not
 * done the uniqueness constraint on the jcr:uuid will kick in and fail the
 * commit.
 * </p>
 */
class VersionableState {

    private static final Logger log = LoggerFactory.getLogger(VersionableState.class);

    private static final String JCR_CHILDVERSIONHISTORY = "jcr:childVersionHistory";
    private static final Set<String> BASIC_PROPERTIES = new HashSet<String>();
    private static final Set<String> BASIC_FROZEN_PROPERTIES = new HashSet<String>();

    static {
        BASIC_PROPERTIES.add(JCR_PRIMARYTYPE);
        BASIC_PROPERTIES.add(JCR_UUID);
        BASIC_PROPERTIES.add(JCR_MIXINTYPES);
        BASIC_FROZEN_PROPERTIES.addAll(BASIC_PROPERTIES);
        BASIC_FROZEN_PROPERTIES.add(JCR_FROZENPRIMARYTYPE);
        BASIC_FROZEN_PROPERTIES.add(JCR_FROZENUUID);
        BASIC_FROZEN_PROPERTIES.add(JCR_FROZENMIXINTYPES);
    }

    private final NodeBuilder version;
    private final NodeBuilder history;
    private final NodeBuilder frozenNode;
    private final NodeBuilder versionable;
    private final ReadWriteVersionManager vMgr;
    private final ReadOnlyNodeTypeManager ntMgr;
    
    private final boolean isFrozenNodeReferenceable;

    private VersionableState(@NotNull NodeBuilder version,
                             @NotNull NodeBuilder history,
                             @NotNull NodeBuilder versionable,
                             @NotNull ReadWriteVersionManager vMgr,
                             @NotNull ReadOnlyNodeTypeManager ntMgr) {
        this.version = checkNotNull(version);
        this.history = checkNotNull(history);
        this.frozenNode = version.child(JCR_FROZENNODE);
        this.versionable = checkNotNull(versionable);
        this.vMgr = checkNotNull(vMgr);
        this.ntMgr = checkNotNull(ntMgr);
        this.isFrozenNodeReferenceable = Utils.isFrozenNodeReferenceable(ntMgr);
    }

    /**
     * Creates a frozen node under the version and initializes it with the basic
     * frozen properties (jcr:frozenPrimaryType, jcr:frozenMixinTypes and
     * jcr:frozenUuid) from the given versionable node.
     *
     * @param version the parent node of the frozen node.
     * @param history the history node of the version.
     * @param versionable the versionable node.
     * @param vMgr the version manager.
     * @param ntMgr the node type manager.
     * @return a versionable state
     */
    @NotNull
    static VersionableState fromVersion(@NotNull NodeBuilder version,
                                        @NotNull NodeBuilder history,
                                        @NotNull NodeBuilder versionable,
                                        @NotNull ReadWriteVersionManager vMgr,
                                        @NotNull ReadOnlyNodeTypeManager ntMgr) {
        VersionableState state = new VersionableState(
                version, history, versionable, vMgr, ntMgr);
        return state.initFrozen(version.child(JCR_FROZENNODE),
                versionable, uuidFromNode(versionable));
    }

    /**
     * Creates a versionable state for a restore.
     *
     * @param version the version to restore.
     * @param history the history node of the version.
     * @param versionable the versionable node.
     * @param vMgr the version manager.
     * @param ntMgr the node type manager.
     * @return a versionable state.
     */
    static VersionableState forRestore(@NotNull NodeBuilder version,
                                       @NotNull NodeBuilder history,
                                       @NotNull NodeBuilder versionable,
                                       @NotNull ReadWriteVersionManager vMgr,
                                       @NotNull ReadOnlyNodeTypeManager ntMgr) {
        return new VersionableState(version, history, versionable, vMgr, ntMgr);
    }

    /**
     * Creates a frozen node and initializes it with the basic
     * frozen properties (jcr:frozenPrimaryType, jcr:frozenMixinTypes and
     * jcr:frozenUuid) from the given node.
     *
     * @return this versionable state.
     */
    private VersionableState initFrozen(NodeBuilder frozen,
                                        NodeBuilder node,
                                        String nodeId) {
        // initialize jcr:frozenNode
        if (isFrozenNodeReferenceable) {
            // OAK-9134: add uuid in older repositories with mix:referenceable in nt:frozenNode
            frozen.setProperty(JCR_UUID, UUIDUtils.generateUUID(), Type.STRING);
        }
        frozen.setProperty(JCR_PRIMARYTYPE, NT_FROZENNODE, Type.NAME);
        List<String> mixinTypes;
        if (node.hasProperty(JCR_MIXINTYPES)) {
            mixinTypes = Lists.newArrayList(node.getNames(JCR_MIXINTYPES));
        } else {
            mixinTypes = Collections.emptyList();
        }
        frozen.setProperty(JCR_FROZENUUID, nodeId, Type.STRING);
        frozen.setProperty(JCR_FROZENPRIMARYTYPE, primaryTypeOf(node), Type.NAME);
        if (mixinTypes.isEmpty()) {
            frozen.removeProperty(JCR_FROZENMIXINTYPES);
        } else {
            frozen.setProperty(JCR_FROZENMIXINTYPES, mixinTypes, Type.NAMES);
        }
        return this;
    }

    /**
     * Creates the versionable state under the version.
     *
     * @return the frozen node.
     * @throws CommitFailedException if the operation fails. E.g. because the
     *              versionable node has a property with OPV ABORT.
     */
    NodeBuilder create() throws CommitFailedException {
        try {
            createFrozen(versionable, uuidFromNode(versionable), frozenNode, VERSION);
            return frozenNode;
        } catch (RepositoryException e) {
            throw new CommitFailedException(CommitFailedException.VERSION,
                    VersionExceptionCode.UNEXPECTED_REPOSITORY_EXCEPTION.ordinal(),
                    "Unexpected RepositoryException", e);
        }
    }

    /**
     * Restore the versionable node to the given version.
     *
     * @param selector an optional version selector. If none is passed, this
     *                 method will use a date based version selector.
     * @return the versionable node.
     * @throws CommitFailedException if the operation fails.
     */
    public NodeBuilder restore(@Nullable VersionSelector selector)
            throws CommitFailedException {
        try {
            if (selector == null) {
                String created = version.getProperty(JCR_CREATED).getValue(Type.DATE);
                selector = new DateVersionSelector(created);
            }
            restoreFrozen(frozenNode, versionable, selector);
            restoreVersionable(versionable, version);
            return versionable;
        } catch (RepositoryException e) {
            throw new CommitFailedException(CommitFailedException.VERSION,
                    VersionExceptionCode.UNEXPECTED_REPOSITORY_EXCEPTION.ordinal(),
                    "Unexpected RepositoryException", e);
        }
    }

    //--------------------------< internal >------------------------------------

    /**
     * Restores the state from {@code src} to a child node of
     * {@code destParent} with the same name as {@code src}.
     *
     * @param src the source node.
     * @param destParent the parent of the destination node.
     * @param name the name of the source node.
     * @param selector the version selector.
     */
    private void restoreState(@NotNull NodeBuilder src,
                              @NotNull NodeBuilder destParent,
                              @NotNull String name,
                              @NotNull VersionSelector selector)
            throws RepositoryException, CommitFailedException {
        checkNotNull(name);
        checkNotNull(destParent);
        String primaryType = primaryTypeOf(src);
        if (primaryType.equals(NT_FROZENNODE)) {
            // replace with frozen state
            destParent.getChildNode(name).remove();
            restoreFrozen(src, destParent.child(name), selector);
        } else if (primaryType.equals(NT_VERSIONEDCHILD)) {
            // only perform chained restore if the node didn't exist
            // before. see 15.7.5 and RestoreTest#testRestoreName
            if (!destParent.hasChildNode(name)) {
                restoreVersionedChild(src, destParent.child(name), selector);
            }
        } else {
            // replace
            destParent.getChildNode(name).remove();
            restoreCopiedNode(src, destParent.child(name), selector);
        }
    }

    /**
     * Restore a nt:frozenNode.
     */
    private void restoreFrozen(@NotNull NodeBuilder frozen,
                               @NotNull NodeBuilder dest,
                               @NotNull VersionSelector selector)
            throws RepositoryException, CommitFailedException {

        // OAK-9459: if the NodeState is not empty, retrieve OPVs before restoring types to avoid constraint violations
        boolean frozenTypeRestored = false;
        if (!dest.hasProperty(JCR_PRIMARYTYPE)) {
            // empty NodeState
            // 15.7.2 Restoring Type and Identifier
            restoreFrozenTypeAndUUID(frozen, dest);
            frozenTypeRestored = true;
        }

        Map<PropertyState, Integer> opvs = new HashMap<>();
        for (PropertyState p : dest.getProperties()) {
            String propName = p.getName();
            if (!BASIC_PROPERTIES.contains(propName) && !frozen.hasProperty(propName)) {
                opvs.put(p, getOPV(dest, p));
            }
        }

        if (!frozenTypeRestored) {
            // 15.7.2 Restoring Type and Identifier
            restoreFrozenTypeAndUUID(frozen, dest);
        }

        // 15.7.3 Restoring Properties
        for (PropertyState p : frozen.getProperties()) {
            // ignore basic frozen properties we restored earlier
            if (!BASIC_FROZEN_PROPERTIES.contains(p.getName())) {
                int action = getOPV(dest, p);
                if (action == COPY || action == VERSION) {
                    dest.setProperty(p);
                }
            }
        }

        for (Map.Entry<PropertyState, Integer> entry : opvs.entrySet()) {
            PropertyState p = entry.getKey();
            String propName = p.getName();
            switch (entry.getValue()) {
                case COPY:
                case VERSION:
                case ABORT:
                    dest.removeProperty(propName);
                    break;
                case IGNORE:
                    // no action
                    break;
                case INITIALIZE:
                    resetToDefaultValue(dest, p);
                    break;
                case COMPUTE:
                    // only COMPUTE property definitions currently are
                    // jcr:primaryType and jcr:mixinTypes
                    // do nothing for now
                    if (!(JCR_PRIMARYTYPE.equals(propName) || JCR_MIXINTYPES.equals(propName))) {
                        log.warn("OPV.COMPUTE not implemented for restoring property: " + propName);
                    }
                    break;
            }
        }
        restoreChildren(frozen, dest, selector);
    }

    /**
     * Restores the basic frozen properties (jcr:primaryType, jcr:mixinTypes
     * and jcr:uuid).
     */
    private void restoreFrozenTypeAndUUID(@NotNull NodeBuilder frozen,
                                          @NotNull NodeBuilder dest) {
        dest.setProperty(JCR_PRIMARYTYPE,
                frozen.getName(JCR_FROZENPRIMARYTYPE), Type.NAME);
        String id = frozen.getProperty(JCR_FROZENUUID).getValue(Type.STRING);
        if (id.indexOf('/') == -1) {
            // only restore jcr:uuid if id is in fact a uuid
            dest.setProperty(JCR_UUID, id, Type.STRING);
        }
        if (frozen.hasProperty(JCR_FROZENMIXINTYPES)) {
            dest.setProperty(JCR_MIXINTYPES,
                    frozen.getNames(JCR_FROZENMIXINTYPES), Type.NAMES);
        }
    }

    /**
     * Restore a copied node.
     */
    private void restoreCopiedNode(NodeBuilder src,
                                   NodeBuilder dest,
                                   VersionSelector selector)
            throws RepositoryException, CommitFailedException {
        if (primaryTypeOf(src).equals(NT_FROZENNODE)) {
            restoreFrozenTypeAndUUID(src, dest);
            copyProperties(src, dest, new OPVProvider() {
                @Override
                public int getAction(NodeBuilder src,
                                     NodeBuilder dest,
                                     PropertyState prop)
                        throws RepositoryException {
                    // copy back, except for basic frozen props
                    if (BASIC_FROZEN_PROPERTIES.contains(prop.getName())) {
                        return IGNORE;
                    } else {
                        return COPY;
                    }
                }
            }, true);
        } else {
            copyProperties(src, dest, OPVForceCopy.INSTANCE, false);
        }
        restoreChildren(src, dest, selector);
    }

    /**
     * Restore an nt:versionedChild node.
     */
    private void restoreVersionedChild(NodeBuilder versionedChild,
                                       NodeBuilder dest,
                                       VersionSelector selector)
            throws RepositoryException, CommitFailedException {
        // 15.7.5 Chained Versions on Restore
        PropertyState id = versionedChild.getProperty(JCR_CHILDVERSIONHISTORY);
        if (id == null) {
            throw new RepositoryException("Mandatory property " +
                    JCR_CHILDVERSIONHISTORY + " is missing.");
        }
        vMgr.restore(id.getValue(Type.REFERENCE), selector, dest);
    }

    /**
     * Restores children of a {@code src}.
     */
    private void restoreChildren(NodeBuilder src,
                                 NodeBuilder dest,
                                 VersionSelector selector)
            throws RepositoryException, CommitFailedException {
        // 15.7.6 Restoring Child Nodes
        for (String name : src.getChildNodeNames()) {
            NodeBuilder srcChild = src.getChildNode(name);
            int action = getOPV(dest, srcChild, name);
            if (action == COPY) {
                // replace on destination
                dest.getChildNode(name).remove();
                restoreCopiedNode(srcChild, dest.child(name), selector);
            } else if (action == VERSION) {
                restoreState(srcChild, dest, name, selector);
            }
        }
        for (String name : dest.getChildNodeNames()) {
            if (src.hasChildNode(name)) {
                continue;
            }
            NodeBuilder destChild = dest.getChildNode(name);
            int action = getOPV(dest, destChild, name);
            if (action == COPY || action == VERSION || action == ABORT) {
                dest.getChildNode(name).remove();
            } else if (action == IGNORE) {
                // no action
            } else if (action == INITIALIZE) {
                log.warn("OPV.INITIALIZE not implemented for restoring child nodes.");
            } else if (action == COMPUTE) {
                // there are currently no child node definitions
                // with OPV compute
                log.warn("OPV.COMPUTE not implemented for restoring child nodes: ");
            }
        }
    }

    /**
     * 15.7.7 Simple vs. Full Versioning after Restore
     */
    private void restoreVersionable(@NotNull NodeBuilder versionable,
                                    @NotNull NodeBuilder version) {
        checkNotNull(versionable).setProperty(JCR_ISCHECKEDOUT,
                false, Type.BOOLEAN);
        versionable.setProperty(JCR_VERSIONHISTORY,
                uuidFromNode(history), Type.REFERENCE);
        versionable.setProperty(JCR_BASEVERSION,
                uuidFromNode(version), Type.REFERENCE);
        versionable.setProperty(JCR_PREDECESSORS,
                Collections.<String>emptyList(), Type.REFERENCES);
    }

    private void resetToDefaultValue(NodeBuilder dest, PropertyState p)
            throws RepositoryException {
        Tree tree = TreeFactory.createReadOnlyTree(dest.getNodeState());
        PropertyDefinition def = ntMgr.getDefinition(tree, p, true);
        Value[] values = def.getDefaultValues();
        if (values != null) {
            if (p.isArray()) {
                p = PropertyStates.createProperty(p.getName(), values);
                dest.setProperty(p);
            } else if (values.length > 0) {
                p = PropertyStates.createProperty(p.getName(), values[0]);
                dest.setProperty(p);
            }
        }
    }

    private void createFrozen(NodeBuilder src, String srcId, NodeBuilder dest, int opva)
            throws CommitFailedException, RepositoryException {
        initFrozen(dest, src, srcId);
        OPVProvider opvProvider;
        if (opva == OnParentVersionAction.COPY) {
            opvProvider = OPVForceCopy.INSTANCE;
        } else {
            opvProvider = new OPVVersion();
        }
        copyProperties(src, dest, opvProvider, true);

        // add the frozen children and histories
        for (String name : src.getChildNodeNames()) {
            if (NodeStateUtils.isHidden(name)) {
                continue;
            }
            NodeBuilder child = src.getChildNode(name);
            String childId = getChildId(srcId, child, name);
            int opv = getOPV(src, child, name);

            if (opv == OnParentVersionAction.ABORT) {
                throw new CommitFailedException(CommitFailedException.VERSION,
                        VersionExceptionCode.OPV_ABORT_ITEM_PRESENT.ordinal(),
                        "Checkin aborted due to OPV abort in " + name);
            }
            if (opv == OnParentVersionAction.VERSION) {
                if (ntMgr.isNodeType(TreeFactory.createReadOnlyTree(child.getNodeState()), MIX_VERSIONABLE)) {
                    // create frozen versionable child
                    versionedChild(child, dest.child(name));
                } else {
                    // else copy
                    createFrozen(child, childId, dest.child(name), COPY);
                }
            } else if (opv == COPY) {
                createFrozen(child, childId, dest.child(name), COPY);
            }
        }
    }

    private void versionedChild(NodeBuilder src, NodeBuilder dest) {
        String ref = src.getProperty(JCR_VERSIONHISTORY).getValue(Type.REFERENCE);
        dest.setProperty(JCR_PRIMARYTYPE, NT_VERSIONEDCHILD, Type.NAME);
        dest.setProperty(JCR_CHILDVERSIONHISTORY, ref, Type.REFERENCE);
    }

    /**
     * Returns the id of the {@code child} node. The id is the value of the
     * jcr:uuid property of the child node if present, or the concatenation of
     * the {@code parentId} and the {@code name} of the child node.
     *
     * @param parentId the parentId.
     * @param child the child node.
     * @param name the name of the child node.
     * @return the identifier of the child node.
     */
    private String getChildId(String parentId, NodeBuilder child, String name) {
        if (child.hasProperty(JCR_UUID)) {
            return uuidFromNode(child);
        } else {
            return parentId + "/" + name;
        }
    }

    private void copyProperties(NodeBuilder src,
                                NodeBuilder dest,
                                OPVProvider opvProvider,
                                boolean ignoreTypeAndUUID)
            throws RepositoryException, CommitFailedException {
        // add the properties
        for (PropertyState prop : src.getProperties()) {
            int opv = opvProvider.getAction(src, dest, prop);

            String propName = prop.getName();
            if (opv == OnParentVersionAction.ABORT) {
                throw new CommitFailedException(CommitFailedException.VERSION,
                        VersionExceptionCode.OPV_ABORT_ITEM_PRESENT.ordinal(),
                        "Checkin aborted due to OPV abort in " + propName);
            }
            if (ignoreTypeAndUUID && BASIC_PROPERTIES.contains(propName)) {
                continue;
            }
            if (isHiddenProperty(propName)) {
                continue;
            }
            if (opv == OnParentVersionAction.VERSION
                    || opv == COPY) {
                dest.setProperty(prop);
            }
        }
    }

    private static boolean isHiddenProperty(@NotNull String propName) {
        return NodeStateUtils.isHidden(propName) && !TreeConstants.OAK_CHILD_ORDER.equals(propName);
    }

    private int getOPV(NodeBuilder parent, NodeBuilder child, String childName)
            throws RepositoryException {
        // ignore hidden tree
        if (childName.startsWith(":")) {
            return IGNORE;
        }
        ImmutableTree parentTree = new ImmutableTree(parent.getNodeState());
        NodeState childState;
        if (NT_FROZENNODE.equals(child.getName(JCR_PRIMARYTYPE))) {
            // need to translate into a regular node to get proper OPV value
            NodeBuilder builder = new MemoryNodeBuilder(EmptyNodeState.EMPTY_NODE);
            builder.setProperty(JCR_PRIMARYTYPE, child.getName(JCR_FROZENPRIMARYTYPE), Type.NAME);
            builder.setProperty(JCR_MIXINTYPES, child.getNames(JCR_MIXINTYPES), Type.NAMES);
            childState = builder.getNodeState();
        } else {
            childState = child.getNodeState();
        }
        ImmutableTree childTree = new ImmutableTree(parentTree, childName, childState);
        return ntMgr.getDefinition(parentTree, childTree).getOnParentVersion();
    }

    private int getOPV(NodeBuilder node, PropertyState property)
            throws RepositoryException {
        if (property.getName().charAt(0) == ':') {
            // FIXME: handle child order properly
            return OnParentVersionAction.COPY;
        } else {
            return ntMgr.getDefinition(TreeFactory.createReadOnlyTree(node.getNodeState()),
                    property, false).getOnParentVersion();
        }
    }

    private interface OPVProvider {

        int getAction(NodeBuilder src,
                NodeBuilder dest,
                PropertyState prop)
                throws RepositoryException;
    }

    private static final class OPVForceCopy implements OPVProvider {

        private static final OPVProvider INSTANCE = new OPVForceCopy();

        @Override
        public int getAction(NodeBuilder src,
                             NodeBuilder dest,
                             PropertyState prop) {
            return COPY;
        }
    }

    private final class OPVVersion implements OPVProvider {

        @Override
        public int getAction(NodeBuilder src,
                             NodeBuilder dest,
                             PropertyState prop)
                throws RepositoryException {
            String propName = prop.getName();
            if (BASIC_FROZEN_PROPERTIES.contains(propName)) {
                // OAK-940: do not overwrite basic frozen properties
                return IGNORE;
            } else if (isHiddenProperty(propName)) {
                // don't copy hidden properties except for :childOrder
                return IGNORE;
            }
            return getOPV(src, prop);
        }
    }
}
