001/*
002 *  Copyright 2022 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.program.properties;
017
018import java.lang.reflect.Array;
019import java.util.Arrays;
020import java.util.List;
021
022import org.apache.avalon.framework.configuration.Configuration;
023import org.apache.avalon.framework.configuration.ConfigurationException;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.commons.lang3.StringUtils;
027
028import org.ametys.cms.contenttype.ContentType;
029import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
030import org.ametys.cms.data.type.ModelItemTypeExtensionPoint;
031import org.ametys.cms.model.properties.AbstractIndexableStaticProperty;
032import org.ametys.cms.model.properties.Property;
033import org.ametys.cms.repository.Content;
034import org.ametys.odf.ODFHelper;
035import org.ametys.odf.program.Program;
036import org.ametys.odf.program.ProgramFactory;
037import org.ametys.odf.program.SubProgram;
038import org.ametys.runtime.model.ModelItem;
039import org.ametys.runtime.model.type.ElementType;
040
041/**
042 * {@link Property} for attribute name of the parent {@link Program} of a {@link SubProgram}
043 */
044public class SubProgramParentProgramProperty extends AbstractIndexableStaticProperty<Object, Object, Content>
045{
046    /** The ODF Helper */
047    protected ODFHelper _odfHelper;
048    
049    /** The Content Type Extension Point */
050    protected ContentTypeExtensionPoint _ctypeEP;
051    
052    /** The Content Attribute Type Extension Point */
053    protected ModelItemTypeExtensionPoint _contentAttributeTypeEP;
054    
055    /** The program attribute name to index for subProgram */
056    protected String _programAttributeName;
057    
058    /** The program attribute type to index for subProgram */
059    protected String _programAttributeType;
060    
061    @Override
062    public void service(ServiceManager manager) throws ServiceException
063    {
064        super.service(manager);
065        _contentAttributeTypeEP = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_CONTENT_ATTRIBUTE);
066        _ctypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE);
067        _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE);
068    }
069    
070    @Override
071    public void configure(Configuration configuration) throws ConfigurationException
072    {
073        super.configure(configuration);
074        
075        _programAttributeType = configuration.getAttribute("type");
076        if (StringUtils.isBlank(_programAttributeType))
077        {
078            throw new ConfigurationException("Attribute 'type' is mandatory for " + SubProgramParentProgramProperty.class.getName());
079        }
080        
081        _programAttributeName = configuration.getChild("program-attribute-name").getValue();
082        if (StringUtils.isBlank(_programAttributeName))
083        {
084            throw new ConfigurationException("Child 'program-attribute-name' is mandatory for " + SubProgramParentProgramProperty.class.getName());
085        }
086    }
087    
088    @Override
089    public Object getValue(Content content)
090    {
091        if (content instanceof SubProgram subProgram)
092        {
093            List<Object> values = _odfHelper.getParentPrograms(subProgram)
094                .stream()
095                .map(this::_getValues)
096                .flatMap(List::stream)
097                .toList();
098            
099            ContentType programCType = _ctypeEP.getExtension(ProgramFactory.PROGRAM_CONTENT_TYPE);
100            ModelItem modelItem = programCType.getModelItem(_programAttributeName);
101            ElementType attributeType = (ElementType) _contentAttributeTypeEP.getExtension(modelItem.getType().getId());
102            
103            return !values.isEmpty() ? values.toArray((Object[]) Array.newInstance(attributeType.getManagedClass(), values.size())) : null;
104        }
105        
106        return null;
107    }
108    
109    private List<Object> _getValues(Program program)
110    {
111        if (program.isMultiple(_programAttributeName))
112        {
113            Object[] values = program.getValue(_programAttributeName);
114            
115            return values != null ? Arrays.asList(values) : List.of();
116        }
117        else
118        {
119            Object value = program.getValue(_programAttributeName);
120            return value != null ? List.of(value) : List.of();
121        }
122    }
123    
124    @Override
125    public boolean isMultiple()
126    {
127        return true;
128    }
129    
130    @Override
131    protected String getTypeId()
132    {
133        return _programAttributeType;
134    }
135}