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