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