001/*
002 *  Copyright 2020 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.skill;
017
018import java.util.Collection;
019import java.util.Collections;
020import java.util.Set;
021import java.util.stream.Collectors;
022
023import org.apache.avalon.framework.service.ServiceException;
024
025import org.ametys.cms.contenttype.ContentType;
026import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
027import org.ametys.cms.contenttype.ContentTypesHelper;
028import org.ametys.cms.data.ContentValue;
029import org.ametys.cms.data.type.ModelItemTypeConstants;
030import org.ametys.cms.model.ContentElementDefinition;
031import org.ametys.cms.model.properties.AbstractProperty;
032import org.ametys.cms.model.properties.Property;
033import org.ametys.cms.repository.Content;
034import org.ametys.odf.enumeration.OdfReferenceTableHelper;
035import org.ametys.odf.program.AbstractProgram;
036import org.ametys.runtime.model.ModelItem;
037
038/**
039 * {@link Property} for acquired skills of child courses on a {@link AbstractProgram}
040 */
041public class ProgramSkillsProperty extends AbstractProperty<ContentValue, Content> implements ContentElementDefinition
042{
043    /** The name of indexing field holding the computed acquired skills */
044    public static final String PROGRAM_SKILLS_PROPERTY_NAME = "acquiredSkills";
045    
046    private ODFSkillsHelper _skillsHelper;
047    private ContentTypeExtensionPoint _contentTypeExtensionPoint;
048    private ContentTypesHelper _contentTypesHelper;
049    
050    public Object getValue(Content content)
051    {
052        if (content instanceof AbstractProgram abstractProgram)
053        {
054            Set<ContentValue> values = getSkillsHelper().getComputedSkills(abstractProgram, 2)
055                                           .stream()
056                                           .collect(Collectors.toSet());
057            
058            return values.toArray(new ContentValue[values.size()]);
059        }
060        
061        return null;
062    }
063    
064    @Override
065    public boolean isMultiple()
066    {
067        return true;
068    }
069    
070    @Override
071    protected String _getTypeId()
072    {
073        return ModelItemTypeConstants.CONTENT_ELEMENT_TYPE_ID;
074    }
075    
076    public String getContentTypeId()
077    {
078        return OdfReferenceTableHelper.SKILL;
079    }
080    
081    public Collection< ? extends ModelItem> getModelItems()
082    {
083        if (_getContentTypeExtensionPoint().hasExtension(getContentTypeId()))
084        {
085            ContentType contentType = _getContentTypeExtensionPoint().getExtension(getContentTypeId());
086            return contentType.getModelItems();
087        }
088        else
089        {
090            return Collections.singleton(_getContentTypesHelper().getTitleAttributeDefinition());
091        }
092    }
093    
094    /**
095     * Retrieves the ODF skills helper
096     * @return the ODF skills helper
097     * @throws IllegalStateException if an error occurs
098     */
099    protected ODFSkillsHelper getSkillsHelper() throws IllegalStateException
100    {
101        if (_skillsHelper == null)
102        {
103            try
104            {
105                _skillsHelper = (ODFSkillsHelper) __serviceManager.lookup(ODFSkillsHelper.ROLE);
106            }
107            catch (ServiceException e)
108            {
109                throw new IllegalStateException("Unable to lookup after the ODF skills helper component", e);
110            }
111        }
112        return _skillsHelper;
113    }
114
115    /**
116     * Retrieves the {@link ContentTypeExtensionPoint} 
117     * @return the {@link ContentTypeExtensionPoint}
118     */
119    protected ContentTypeExtensionPoint _getContentTypeExtensionPoint()
120    {
121        if (_contentTypeExtensionPoint == null)
122        {
123            try
124            {
125                _contentTypeExtensionPoint = (ContentTypeExtensionPoint) __serviceManager.lookup(ContentTypeExtensionPoint.ROLE);
126            }
127            catch (ServiceException e)
128            {
129                throw new RuntimeException("Unable to lookup after the content type extension point", e);
130            }
131        }
132        
133        return _contentTypeExtensionPoint;
134    }
135    
136    /**
137     * Retrieves the {@link ContentTypesHelper}
138     * @return the {@link ContentTypesHelper}
139     */
140    protected ContentTypesHelper _getContentTypesHelper()
141    {
142        if (_contentTypesHelper == null)
143        {
144            try
145            {
146                _contentTypesHelper = (ContentTypesHelper) __serviceManager.lookup(ContentTypesHelper.ROLE);
147            }
148            catch (ServiceException e)
149            {
150                throw new RuntimeException("Unable to lookup after the content types helper component", e);
151            }
152        }
153        
154        return _contentTypesHelper;
155    }
156}