001/*
002 *  Copyright 2020 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.plugins.odfsync.apogee.scc;
017
018import java.util.Optional;
019import java.util.Set;
020
021import org.apache.avalon.framework.component.Component;
022import org.apache.avalon.framework.context.Context;
023import org.apache.avalon.framework.context.ContextException;
024import org.apache.avalon.framework.context.Contextualizable;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028import org.apache.cocoon.components.ContextHelper;
029import org.apache.cocoon.environment.Request;
030import org.slf4j.Logger;
031
032import org.ametys.cms.repository.Content;
033import org.ametys.cms.repository.ModifiableContent;
034import org.ametys.cms.repository.ModifiableDefaultContent;
035import org.ametys.odf.ODFHelper;
036import org.ametys.odf.ProgramItem;
037import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollectionDAO;
038import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollectionHelper;
039
040/**
041 * Helper for Apogee Synchronizable Contents Collections.
042 */
043public class ApogeeSynchronizableContentsCollectionHelper implements Serviceable, Component, Contextualizable
044{
045    /** The Avalon Role */
046    public static final String ROLE = ApogeeSynchronizableContentsCollectionHelper.class.getName();
047 
048    /** Request attribute name to store handle contents during import or synchronization. */
049    public static final String HANDLE_CONTENTS = AbstractApogeeSynchronizableContentsCollection.class.getName() + "$handleContents";
050    
051    /** SCC DAO */
052    protected SynchronizableContentsCollectionHelper _sccHelper;
053    
054    /** The ODF Helper */
055    protected ODFHelper _odfHelper;
056    
057    /** SCC DAO */
058    protected SynchronizableContentsCollectionDAO _sccDAO;
059    
060    /** Context */
061    protected Context _context;
062    
063    @Override
064    public void service(ServiceManager smanager) throws ServiceException
065    {
066        _odfHelper = (ODFHelper) smanager.lookup(ODFHelper.ROLE);
067        _sccHelper = (SynchronizableContentsCollectionHelper) smanager.lookup(SynchronizableContentsCollectionHelper.ROLE);
068        _sccDAO = (SynchronizableContentsCollectionDAO) smanager.lookup(SynchronizableContentsCollectionDAO.ROLE);
069    }
070    
071    public void contextualize(Context context) throws ContextException
072    {
073        _context = context;
074    }
075    
076    /**
077     * Synchronize the content or its children if the content has no Apogee SCC
078     * @param content the content
079     * @param logger the logger
080     */
081    public void synchronizeContent(ModifiableContent content, Logger logger)
082    {
083        Optional<AbstractApogeeSynchronizableContentsCollection> childSCC = getContentSCC(content, logger);
084        // The content has a SCC, so synchronize it
085        if (childSCC.isPresent())
086        {
087            try
088            {
089                childSCC.get().synchronizeContent((ModifiableDefaultContent) content, logger);
090            }
091            catch (Exception e)
092            {
093                logger.error("An error occurred synchronized content '{}' ({}) from SCC '{}'", content.getTitle(), content.getId(), childSCC.get().getId(), e);
094            }
095        }
096        // The content is manually created, so search in deeper children
097        else if (addToHandleContents(content.getId()))
098        {
099            for (ProgramItem syncChild : _odfHelper.getChildProgramItems((ProgramItem) content))
100            {
101                synchronizeContent((ModifiableDefaultContent) syncChild, logger);
102            }
103        }
104    }
105    
106    /**
107     * Get the Apogee SCC for the content if it exists
108     * @param content The content to search on
109     * @param logger the logger
110     * @return the Apogee SCC
111     */
112    public Optional<AbstractApogeeSynchronizableContentsCollection> getContentSCC(Content content, Logger logger)
113    {
114        try
115        {
116            return _sccHelper.getSynchronizableCollectionIds(content)
117                .stream()
118                .map(_sccDAO::getSynchronizableContentsCollection)
119                .filter(AbstractApogeeSynchronizableContentsCollection.class::isInstance)
120                .map(AbstractApogeeSynchronizableContentsCollection.class::cast)
121                .findFirst();
122        }
123        catch (Exception e)
124        {
125            logger.error("An error occurred getting ametys-internal:scc property", e);
126        }
127        
128        return Optional.empty();
129    }
130    
131    /**
132     * Add the content ID to the handle contents list.
133     * @param contentId Content ID
134     * @return <code>true</code> if the content ID have been added, <code>false</code> is returned if the content ID already exists in the handle contents list.
135     */
136    public boolean addToHandleContents(String contentId)
137    {
138        Request request = ContextHelper.getRequest(_context);
139        @SuppressWarnings("unchecked")
140        Set<String> handleContents = (Set<String>) request.getAttribute(HANDLE_CONTENTS);
141        boolean added = handleContents.add(contentId);
142        request.setAttribute(HANDLE_CONTENTS, handleContents);
143        return added;
144    }
145}