001/*
002 *  Copyright 2025 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.content;
017
018import java.util.HashSet;
019import java.util.Map;
020import java.util.Optional;
021import java.util.Set;
022import java.util.stream.Collectors;
023
024import org.apache.avalon.framework.context.Context;
025import org.apache.avalon.framework.context.ContextException;
026import org.apache.avalon.framework.context.Contextualizable;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.avalon.framework.service.Serviceable;
030import org.apache.cocoon.components.ContextHelper;
031
032import org.ametys.cms.data.ContentValue;
033import org.ametys.cms.repository.Content;
034import org.ametys.odf.ODFHelper;
035import org.ametys.odf.program.Container;
036import org.ametys.odf.program.Program;
037import org.ametys.plugins.repository.UnknownAmetysObjectException;
038import org.ametys.runtime.i18n.I18nizableText;
039import org.ametys.runtime.model.Enumerator;
040
041/**
042 * {@link Enumerator} for previous/next available years of a year container
043 */
044public class YearsEnumerator implements Enumerator<ContentValue>, Serviceable, Contextualizable
045{
046    private Context _context;
047    private ODFHelper _odfHelper;
048
049    public void contextualize(Context context) throws ContextException
050    {
051        _context = context;
052    }
053    
054    public void service(ServiceManager manager) throws ServiceException
055    {
056        _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE);
057    }
058    
059    // DO NOT call getEntries().get(value)
060    // In case of a copy, the value is not yet updated but can not be part of available years. The copy should not failed.
061    // The value is removed after content's copy or updated after catalog's copy 
062    public I18nizableText getEntry(ContentValue value) throws Exception
063    {
064        try
065        {
066            return _getDisplayName((Container) value.getContent());
067        }
068        catch (UnknownAmetysObjectException e)
069        {
070            // Ignore.
071        }
072        
073        return null;
074    }
075
076    public Map<ContentValue, I18nizableText> getEntries() throws Exception
077    {
078        Optional<Container> container = Optional.of(_context)
079                                                .map(ContextHelper::getRequest)
080                                                .map(r -> r.getAttribute(Content.class.getName()))
081                                                .filter(Container.class::isInstance)
082                                                .map(Container.class::cast);
083        
084        if (container.isEmpty())
085        {
086            // Not in a container context
087            return Map.of();
088        }
089        
090        Container containerObj = container.get();
091        if (!_odfHelper.isContainerOfTypeYear(containerObj))
092        {
093            // Not a year container
094            return Map.of();
095        }
096        
097        Set<Program> parentPrograms = _odfHelper.getParentPrograms(containerObj);
098        
099        Set<Container> years = new HashSet<>();
100        for (Program program : parentPrograms)
101        {
102            years.addAll(_odfHelper.getYears(program));
103        }
104        
105        // Remove the current year
106        years.remove(containerObj);
107        
108        return years.stream().collect(Collectors.toMap(ContentValue::new, this::_getDisplayName));
109    }
110    
111    private I18nizableText _getDisplayName(Container container)
112    {
113        StringBuilder displayName = new StringBuilder();
114        
115        // Display code
116        displayName.append("[");
117        displayName.append(container.getDisplayCode());
118        displayName.append("] ");
119        
120        displayName.append(container.getTitle());
121        
122        return new I18nizableText(displayName.toString());
123    }
124}