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