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