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