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