001/*
002 *  Copyright 2021 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.plugins.odfweb.service.search.criterion;
017
018import java.util.Comparator;
019import java.util.List;
020import java.util.Map;
021import java.util.stream.Collectors;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.commons.lang3.LocaleUtils;
025import org.apache.commons.lang3.tuple.Pair;
026
027import org.ametys.cms.contenttype.ContentType;
028import org.ametys.cms.data.ContentValue;
029import org.ametys.core.util.I18nUtils;
030import org.ametys.core.util.LambdaUtils;
031import org.ametys.odf.program.AbstractProgram;
032import org.ametys.plugins.odfweb.service.search.ProgramSearchable;
033import org.ametys.plugins.odfweb.service.search.helper.DegreeUniversityHelper;
034import org.ametys.runtime.i18n.I18nizableText;
035import org.ametys.runtime.model.ElementDefinition;
036import org.ametys.runtime.model.Enumerator;
037import org.ametys.web.frontoffice.search.metamodel.RestrictedEnumerator;
038import org.ametys.web.frontoffice.search.metamodel.impl.ContentReferencingSearchServiceCriterionDefinition;
039import org.ametys.web.frontoffice.search.metamodel.impl.RestrictedWrappedEnumerator;
040
041/**
042 * {@link ContentReferencingSearchServiceCriterionDefinition} for a degree content attribute.
043 */
044public class DegreeUniversityCriterionDefinition extends ContentReferencingSearchServiceCriterionDefinition
045{
046    /** The attribute for degree type */
047    public static final String ATTRIBUTE_DEGREE_TYPE = "type";
048    
049    /** The value for university for degree attribute */
050    public static final String ATTRIBUTE_DEGREE_TYPE_UNIVERSITY_VALUE = "UNIVERSITY";
051
052    /** The name of the degree criterion definition */
053    public static final String DEGREE_CRITERION_DEFINITION_NAME = ProgramSearchable.PROGRAM_SEARCHEABLE_CRITERION_DEFINITION_PREFIX + AbstractProgram.DEGREE;
054    
055    /** The name of the degree university criterion definition */
056    public static final String DEGREE_UNIVERSITY_CRITERION_DEFINITION_NAME = DEGREE_CRITERION_DEFINITION_NAME + "$University";
057    
058    /** The value for university for degree attribute */
059    public static final String CRITERION_ALL_DU_VALUE = "_Ametys_Degree_All_University";
060    
061    /** The i18n utils */
062    protected I18nUtils _i18nUtils;
063    
064    /** The degree university helper */
065    protected DegreeUniversityHelper _degreeUniversityHelper;
066    
067    /**
068     * Constructor used to create a FO criterion definition referencing the degree university
069     * @param reference the item referenced by this criterion
070     * @param referencePath the path of the criterion's reference
071     * @param baseContentType the content type defining the reference
072     */
073    public DegreeUniversityCriterionDefinition(ElementDefinition reference, String referencePath, ContentType baseContentType)
074    {
075        super(reference, referencePath, baseContentType);
076    }
077    
078    @Override
079    public String getName()
080    {
081        return DEGREE_UNIVERSITY_CRITERION_DEFINITION_NAME;
082    }
083    
084    @Override
085    public I18nizableText getLabel()
086    {
087        return new I18nizableText("plugin.odf-web", "PLUGINS_ODFWEB_SEARCH_CRITERION_DEGREE_UNIVERSITY_LABEL");
088    }
089    
090    @Override
091    public boolean isEnumerated()
092    {
093        return true;
094    }
095    
096    @Override
097    public RestrictedEnumerator<ContentValue> getRestrictedEnumerator(Map<String, Object> contextualParameters)
098    {
099        Enumerator<ContentValue> enumerator = new DegreeUniversityEnumerator(this, contextualParameters);
100        return new RestrictedWrappedEnumerator<>(enumerator, getName());
101    }
102    
103    @Override
104    public Long getOrder(ContentValue contentValue)
105    {
106        if (contentValue == null)
107        {
108            return _getDegreeUniversityHelper().getDegrees(true)
109                .stream()
110                .map(c -> c.<Long>getValue("order"))
111                .filter(l -> l != null)
112                .min(Long::compare)
113                .orElse(null);
114        }
115        else
116        {
117            return super.getOrder(contentValue);
118        }
119    }
120    
121
122    
123    /**
124     * Retrieves the {@link I18nUtils} 
125     * @return the {@link I18nUtils}
126     */
127    protected I18nUtils _getI18nUtils()
128    {
129        if (_i18nUtils == null)
130        {
131            try
132            {
133                _i18nUtils = (I18nUtils) __serviceManager.lookup(I18nUtils.ROLE);
134            }
135            catch (ServiceException e)
136            {
137                throw new RuntimeException("Unable to lookup after the I18n utils component", e);
138            }
139        }
140        
141        return _i18nUtils;
142    }
143    
144    /**
145     * Retrieves the {@link DegreeUniversityHelper} 
146     * @return the {@link DegreeUniversityHelper}
147     */
148    protected DegreeUniversityHelper _getDegreeUniversityHelper()
149    {
150        if (_degreeUniversityHelper == null)
151        {
152            try
153            {
154                _degreeUniversityHelper = (DegreeUniversityHelper) __serviceManager.lookup(DegreeUniversityHelper.ROLE);
155            }
156            catch (ServiceException e)
157            {
158                throw new RuntimeException("Unable to lookup after the degree university helper", e);
159            }
160        }
161        
162        return _degreeUniversityHelper;
163    }
164    
165    static class DegreeUniversityEnumerator implements Enumerator<ContentValue>
166    {
167        DegreeUniversityCriterionDefinition _criterionDefinition;
168        Map<String, Object> _contextualParameters;
169        
170        DegreeUniversityEnumerator(DegreeUniversityCriterionDefinition criterionDefinition, Map<String, Object> contextualParameters)
171        {
172            _criterionDefinition = criterionDefinition;
173            _contextualParameters = contextualParameters;
174        }
175        
176        public Map<ContentValue, I18nizableText> getEntries() throws Exception
177        {
178            String language = (String) _contextualParameters.get("lang");
179            
180            @SuppressWarnings("synthetic-access")
181            List<Pair<ContentValue, String>> contentsAsPair = _criterionDefinition._getDegreeUniversityHelper().getDegrees(false)
182                    .stream()
183                    .map(content -> Pair.of(new ContentValue(_criterionDefinition._getAmetysObjectResolver(), content.getId()), content.getTitle(LocaleUtils.toLocale(language))))
184                    .collect(Collectors.toList());
185                
186            if (!_criterionDefinition._getDegreeUniversityHelper().getDegrees(true).isEmpty())
187            {
188                I18nizableText criterionAllDULabel = new I18nizableText("plugin.odf-web", "PLUGINS_ODFWEB_SEARCH_CRITERION_DEGREE_UNIVERSITY_FIELD_ALL");
189                contentsAsPair.add(Pair.of(null, _criterionDefinition._getI18nUtils().translate(criterionAllDULabel, language)));
190            }
191            
192            return contentsAsPair.stream()
193                .sorted(Comparator.comparing(Pair::getRight)) // sort by title
194                .collect(LambdaUtils.Collectors.toLinkedHashMap(Pair::getLeft, pair -> new I18nizableText(pair.getRight())));
195        }
196    }
197}
198