001/*
002 *  Copyright 2024 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.odf.catalog;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021
022import org.ametys.cms.repository.Content;
023import org.ametys.odf.ProgramItem;
024import org.ametys.odf.course.Course;
025import org.ametys.odf.data.EducationalPath;
026import org.ametys.odf.data.type.EducationalPathRepositoryElementType;
027import org.ametys.plugins.repository.data.holder.impl.DataHolderHelper;
028import org.ametys.runtime.plugin.component.AbstractLogEnabled;
029
030/**
031 * Copy updater to update the educational path values of courses after a catalog copy
032 */
033public class EducationalPathCopyUpdater extends AbstractLogEnabled implements CopyCatalogUpdater
034{
035    @Override
036    // Be careful ! For now this method only update educational paths of courses
037    public void updateContents(String initialCatalogName, String newCatalogName, Map<Content, Content> copiedContents, Content targetParentContent)
038    {
039        for (Content copiedContent : copiedContents.values())
040        {
041            if (copiedContent instanceof Course course)
042            {
043                Map<String, Object> educationalPathAttributes = DataHolderHelper.findEditableItemsByType(course, EducationalPathRepositoryElementType.EDUCATIONAL_PATH_ELEMENT_TYPE_ID);
044                for (Map.Entry<String, Object> entry : educationalPathAttributes.entrySet())
045                {
046                    String dataPath = entry.getKey();
047                    Object value = entry.getValue();
048                    
049                    if (value instanceof EducationalPath path)
050                    {
051                        EducationalPath copiedPath = _getUpdatedEducationalPath(course, path, copiedContents);
052                        course.setValue(dataPath, copiedPath);
053                    }
054                    else if (value instanceof EducationalPath[] paths)
055                    {
056                        List<EducationalPath> newPaths = new ArrayList<>();
057                        for (EducationalPath path : paths)
058                        {
059                            EducationalPath copiedPath = _getUpdatedEducationalPath(course, path, copiedContents);
060                            if (copiedPath == null)
061                            {
062                                newPaths.add(copiedPath);
063                            }
064                        }
065                        
066                        course.setValue(dataPath, newPaths.toArray(EducationalPath[]::new));
067                    }
068                }
069                
070                if (course.needsSave())
071                {
072                    course.saveChanges();
073                }
074            }
075        }
076    }
077    
078    private EducationalPath _getUpdatedEducationalPath(Content content, EducationalPath initialPath, Map<Content, Content> copiedContents)
079    {
080        List<ProgramItem> programItems = new ArrayList<>();
081        for (String programItemId : initialPath.getProgramItemIds())
082        {
083            ProgramItem copiedProgramItem = copiedContents.entrySet()
084                                                          .stream()
085                                                          .filter(entry -> programItemId.equals(entry.getKey().getId()))
086                                                          .map(Map.Entry::getValue)
087                                                          .filter(ProgramItem.class::isInstance)
088                                                          .findFirst()
089                                                          .map(ProgramItem.class::cast)
090                                                          .orElse(null);
091            if (copiedProgramItem == null)
092            {
093                getLogger().warn("No corresponding content found with id '{}' in copied catalog. Unable to update the educational path value for content '{}'", programItemId, content.getId());
094                return null;
095            }
096            
097            programItems.add(copiedProgramItem);
098        }
099        
100        return EducationalPath.of(programItems.toArray(ProgramItem[]::new));
101    }
102}