001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.web.synchronization;
017
018import java.util.Map;
019
020import javax.jcr.ItemNotFoundException;
021import javax.jcr.Node;
022import javax.jcr.PathNotFoundException;
023import javax.jcr.RepositoryException;
024import javax.jcr.Session;
025
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.commons.collections.PredicateUtils;
029
030import org.ametys.cms.ObservationConstants;
031import org.ametys.cms.repository.Content;
032import org.ametys.cms.repository.DefaultContent;
033import org.ametys.cms.repository.ReactionableObject.ReactionType;
034import org.ametys.core.observation.Event;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.plugins.repository.RepositoryConstants;
037import org.ametys.plugins.repository.jcr.JCRAmetysObject;
038
039/**
040 * Observer to synchronize the content reactions 
041 *
042 */
043public class SynchronizeContentReactionObserver extends AbstractSynchronizeObserver
044{
045    /** Ametys object resolver. */
046    protected AmetysObjectResolver _ametysObjectResolver;
047
048    @Override
049    public void service(ServiceManager manager) throws ServiceException
050    {
051        super.service(manager);
052        _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
053    }
054    
055    @Override
056    public boolean supports(Event event)
057    {
058        return event.getId().equals(ObservationConstants.EVENT_CONTENT_REACTION_CHANGED);
059    }
060    
061    @Override
062    protected void _internalObserve(Event event, Session liveSession) throws RepositoryException
063    {
064        _synchronizeContentReaction(event, liveSession);
065        
066        if (liveSession.hasPendingChanges())
067        {
068            liveSession.save();
069        }
070    }
071    
072    /**
073     * Synchronize content comment
074     * @param event the event
075     * @param liveSession the live session
076     * @throws RepositoryException if an error occurred
077     */
078    protected void _synchronizeContentReaction(Event event, Session liveSession) throws RepositoryException
079    {
080        Map<String, Object> arguments = event.getArguments();
081        Content content = (Content) arguments.get(ObservationConstants.ARGS_CONTENT);
082        ReactionType reactionType = (ReactionType) arguments.get(ObservationConstants.ARGS_REACTION_TYPE);
083        
084        if (content instanceof DefaultContent)
085        {
086            Node node = ((JCRAmetysObject) content).getNode();
087            Node unversionnedMetadata = node.getNode("ametys-internal:unversioned");
088            Node initialReactionNode = _getReactionNode(unversionnedMetadata, reactionType);
089            
090            try
091            {
092                // let's check that content is in live
093                Node liveContentNode = liveSession.getNodeByIdentifier(node.getIdentifier());
094                
095                try
096                {
097                    Node liveUnversionnedMetadata = liveContentNode.getNode("ametys-internal:unversioned");
098                    Node liveReactionNode = _getReactionNode(liveUnversionnedMetadata, reactionType);
099                    
100                    // Remove existing reactions
101                    liveReactionNode.remove();
102                    
103                    // Clone reactions
104                    Node clonedNode = _synchronizeComponent.addNodeWithUUID(initialReactionNode, liveUnversionnedMetadata, initialReactionNode.getName());
105                    _synchronizeComponent.cloneNodeAndPreserveUUID(initialReactionNode, clonedNode, PredicateUtils.truePredicate(), PredicateUtils.truePredicate());
106                }
107                catch (PathNotFoundException e)
108                {
109                    // Reaction node does not exist yet in Live
110                    Node clonedParentNode = _synchronizeComponent.cloneAncestorsAndPreserveUUID(initialReactionNode, liveSession);
111                    Node clonedNode = _synchronizeComponent.addNodeWithUUID(initialReactionNode, clonedParentNode, initialReactionNode.getName());
112                    _synchronizeComponent.cloneNodeAndPreserveUUID(initialReactionNode, clonedNode, PredicateUtils.truePredicate(), PredicateUtils.truePredicate());
113                }
114            }
115            catch (ItemNotFoundException e)
116            {
117                // content does not exist in the live workspace, nothing to do
118            }
119        }
120    }
121    
122    private Node _getReactionNode(Node unversionnedMetadata, ReactionType reactionType) throws PathNotFoundException, RepositoryException
123    {
124        return unversionnedMetadata.getNode(RepositoryConstants.NAMESPACE_PREFIX + ':' + reactionType.name().toLowerCase());
125    }
126}