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 */
016
017package org.ametys.web.synchronization;
018
019import java.util.Map;
020
021import javax.jcr.ItemNotFoundException;
022import javax.jcr.Node;
023import javax.jcr.PathNotFoundException;
024import javax.jcr.RepositoryException;
025import javax.jcr.Session;
026
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.commons.collections.PredicateUtils;
030
031import org.ametys.cms.ObservationConstants;
032import org.ametys.cms.repository.Content;
033import org.ametys.cms.repository.ModifiableContentHelper;
034import org.ametys.cms.repository.comment.Comment;
035import org.ametys.core.observation.Event;
036import org.ametys.plugins.repository.AmetysObjectResolver;
037import org.ametys.plugins.repository.RepositoryConstants;
038import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
039import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
040import org.ametys.plugins.repository.jcr.JCRAmetysObject;
041
042/**
043 * When a comment (validated) is modifier, synchronize it
044 */
045public class SynchronizeContentCommentedObserver extends AbstractSynchronizeObserver
046{
047    private static final String COMMENTS_DATA_PREFIX = RepositoryConstants.NAMESPACE_PREFIX + ":";
048    
049    /** Ametys object resolver. */
050    protected AmetysObjectResolver _ametysObjectResolver;
051    
052    @Override
053    public void service(ServiceManager manager) throws ServiceException
054    {
055        super.service(manager);
056        _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
057    }
058    
059    @Override
060    public boolean supports(Event event)
061    {
062        return event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_VALIDATED)
063            || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_UNVALIDATED)
064            || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_DELETED)
065            || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_MODIFYING)
066            || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_REACTION_CHANGED);
067    }
068    
069    @Override
070    protected void _internalObserve(Event event, Session liveSession) throws RepositoryException
071    {
072        if (event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_DELETED) || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_UNVALIDATED))
073        {
074            _synchronizeDeletedContentComment(event, liveSession);
075        }
076        else
077        {
078            _synchronizeContentComment(event, liveSession);
079        }
080        
081        if (liveSession.hasPendingChanges())
082        {
083            liveSession.save();
084        }
085    }
086    
087    /**
088     * Synchronize deleted content comment
089     * @param event the event
090     * @param liveSession the live session
091     * @throws RepositoryException if an error occurred
092     */
093    protected void _synchronizeDeletedContentComment(Event event, Session liveSession) throws RepositoryException
094    {
095        try
096        {
097            Map<String, Object> arguments = event.getArguments();
098            Content content = (Content) arguments.get(ObservationConstants.ARGS_CONTENT);
099            Comment comment = (Comment) arguments.get(ObservationConstants.ARGS_COMMENT);
100            
101            String commentId = comment != null ? comment.getId() : (String) arguments.get(ObservationConstants.ARGS_COMMENT_ID);
102            
103            Node node = ((JCRAmetysObject) content).getNode();
104            
105            // let's check that content is in live
106            Node liveContentNode = liveSession.getNodeByIdentifier(node.getIdentifier());
107            Node unversionnedMetadata = liveContentNode.getNode("ametys-internal:unversioned");
108            Node commentNode = _getCommentNode(unversionnedMetadata, commentId);
109            
110            commentNode.remove();
111        }
112        catch (PathNotFoundException e)
113        {
114            // comment does not exist in the live, do nothing
115        }
116    }
117    
118    /**
119     * Synchronize content comment
120     * @param event the event
121     * @param liveSession the live session
122     * @throws RepositoryException if an error occurred
123     */
124    protected void _synchronizeContentComment(Event event, Session liveSession) throws RepositoryException
125    {
126        Map<String, Object> arguments = event.getArguments();
127        Content content = (Content) arguments.get(ObservationConstants.ARGS_CONTENT);
128        Comment comment = (Comment) arguments.get(ObservationConstants.ARGS_COMMENT);
129        
130        ModifiableRepositoryData repositoryData = comment.getRepositoryData();
131        
132        if (!(content instanceof JCRAmetysObject) || !(repositoryData instanceof JCRRepositoryData))
133        {
134            return;
135        }
136        
137        Node node = ((JCRAmetysObject) content).getNode();
138        Node initialCommentNode = ((JCRRepositoryData) repositoryData).getNode();
139        
140        try
141        {
142            // let's check that content is in live
143            Node liveContentNode = liveSession.getNodeByIdentifier(node.getIdentifier());
144            
145            try
146            {
147                Node unversionedMetadata = liveContentNode.getNode("ametys-internal:unversioned");
148                String commentId = comment.getId();
149                Node commentNode = _getCommentNode(unversionedMetadata, commentId);
150                Node parent = commentNode.getParent();
151                commentNode.remove();
152                
153                Node clonedNode = _synchronizeComponent.addNodeWithUUID(initialCommentNode, parent, initialCommentNode.getName());
154                _synchronizeComponent.cloneNodeAndPreserveUUID(initialCommentNode, clonedNode, PredicateUtils.truePredicate(), PredicateUtils.truePredicate());
155            }
156            catch (PathNotFoundException e)
157            {
158                // comment was not already existing
159                Node clonedParentNode = _synchronizeComponent.cloneAncestorsAndPreserveUUID(initialCommentNode, liveSession);
160                Node clonedNode = _synchronizeComponent.addNodeWithUUID(initialCommentNode, clonedParentNode, initialCommentNode.getName());
161                _synchronizeComponent.cloneNodeAndPreserveUUID(initialCommentNode, clonedNode, PredicateUtils.truePredicate(), PredicateUtils.truePredicate());
162            }
163        }
164        catch (ItemNotFoundException e)
165        {
166            // content does not exist in the live workspace
167        }
168    }
169    
170    /**
171     * Get the node of the comment id
172     * @param unversionedMetadata the unversioned metadata
173     * @param commentId the comment id
174     * @return the node of the comment id
175     * @throws PathNotFoundException if an error occurred
176     * @throws RepositoryException if an error occurred
177     */
178    protected Node _getCommentNode(Node unversionedMetadata, String commentId) throws PathNotFoundException, RepositoryException
179    {
180        Node commentsNode = unversionedMetadata.getNode(COMMENTS_DATA_PREFIX + ModifiableContentHelper.METADATA_COMMENTS);
181        
182        String[] commentIdAsTab = commentId.split(Comment.ID_SEPARATOR);
183        int i = 0;
184        int lastIndex = commentIdAsTab.length - 1;
185        while (i < lastIndex)
186        {
187            Node commentNode = commentsNode.getNode(COMMENTS_DATA_PREFIX + commentIdAsTab[i]);
188            commentsNode = commentNode.getNode(COMMENTS_DATA_PREFIX + Comment.SUB_COMMENTS_DATA_NAME);
189            i++;
190        }
191        
192        return commentsNode.getNode(COMMENTS_DATA_PREFIX + commentIdAsTab[lastIndex]);
193    }
194}