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}