/*
 * Copyright (C) 2005-2011 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 */
package org.alfresco.repo.audit.access;
import static org.alfresco.repo.audit.model.AuditApplication.AUDIT_PATH_SEPARATOR;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.audit.model.AuditApplication;
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCancelCheckOut;
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckIn;
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckOut;
import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy;
import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
import org.alfresco.repo.copy.CopyServicePolicies.OnCopyCompletePolicy;
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnAddAspectPolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy;
import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.version.VersionServicePolicies.OnCreateVersionPolicy;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.InvalidQNameException;
import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
 * Changes made to a {@code Node} in a single transaction. For example the creation of
 * a Node also involves updating properties, but the main action remains create node.
 * 
 * @author Alan Davis
 */
/*package*/ class NodeChange implements
        BeforeDeleteNodePolicy, OnAddAspectPolicy, OnCreateNodePolicy, OnMoveNodePolicy,
        OnRemoveAspectPolicy, OnUpdatePropertiesPolicy,
        OnContentReadPolicy, OnContentUpdatePolicy,
        OnCreateVersionPolicy,
        OnCopyCompletePolicy,
        
        OnCheckOut, OnCheckIn, OnCancelCheckOut
{
    private static final String USER = "user";
    private static final String ACTION = "action";
    private static final String SUB_ACTIONS = "sub-actions";
    private static final String NODE = "node";
    private static final String PATH = "path";
    private static final String TYPE = "type";
    private static final String FROM = "from";
    private static final String TO = "to";
    private static final String ADD = "add";
    private static final String DELETE = "delete";
    private static final String COPY = "copy";
    private static final String MOVE = "move";
    private static final String PROPERTIES = "properties";
    private static final String ASPECTS = "aspects";
    private static final String VERSION_PROPERTIES = "version-properties";
    public static final String SUB_ACTION = "sub-action";
    private static final String DELETE_NODE = "deleteNode";
    private static final String CREATE_NODE = "createNode";
    private static final String MOVE_NODE = "moveNode";
    private static final String UPDATE_NODE_PROPERTIES = "updateNodeProperties";
    private static final String DELETE_NODE_ASPECT = "deleteNodeAspect";
    private static final String ADD_NODE_ASPECT = "addNodeAspect";
    private static final String CREATE_CONTENT = "createContent";
    private static final String UPDATE_CONTENT = "updateContent";
    private static final String READ_CONTENT = "readContent";
    private static final String CREATE_VERSION = "createVersion";
    private static final String COPY_NODE = "copyNode";
    private static final String CHECK_IN = "checkIn";
    private static final String CHECK_OUT = "checkOut";
    private static final String CANCEL_CHECK_OUT = "cancelCheckOut";
    private static final String INVALID_PATH_CHAR_REPLACEMENT = "-";
    
    public static Collection SUMMARY_KEYS = new ArrayList();
    static
    {
        SUMMARY_KEYS.add(buildPath(PROPERTIES, ADD));
        SUMMARY_KEYS.add(buildPath(PROPERTIES, DELETE));
        SUMMARY_KEYS.add(buildPath(PROPERTIES, FROM));
        SUMMARY_KEYS.add(buildPath(PROPERTIES, TO));
        SUMMARY_KEYS.add(buildPath(ASPECTS, ADD));
        SUMMARY_KEYS.add(buildPath(ASPECTS, DELETE));
    }
    public static final String SUB_ACTION_PREFIX = SUB_ACTION + AUDIT_PATH_SEPARATOR;
    
    private final NodeInfoFactory nodeInfoFactory;
    private final NamespaceService namespaceService;
    private NodeInfo nodeInfo;
    private String action;
    
    private boolean auditSubActions = false;
    private Set subActions = new LinkedHashSet();
    private List