001/*
002 *  Copyright 2019 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.course.search;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.cms.contenttype.MetadataType;
028import org.ametys.cms.search.query.AndQuery;
029import org.ametys.cms.search.query.BooleanQuery;
030import org.ametys.cms.search.query.NotQuery;
031import org.ametys.cms.search.query.OrQuery;
032import org.ametys.cms.search.query.Query;
033import org.ametys.cms.search.query.Query.Operator;
034import org.ametys.cms.search.query.StringQuery;
035import org.ametys.cms.search.ui.model.impl.AbstractCustomSearchUICriterion;
036import org.ametys.odf.ODFHelper;
037import org.ametys.odf.ProgramItem;
038import org.ametys.odf.course.ShareableCourseHelper;
039import org.ametys.odf.course.ShareableCourseStatusHelper;
040import org.ametys.odf.course.ShareableCourseStatusHelper.ShareableStatus;
041import org.ametys.odf.program.Container;
042import org.ametys.odf.program.Program;
043import org.ametys.runtime.model.ModelItem;
044
045/**
046 * UI criteria for shareable course
047 */
048public class ShareableCourseSearchUICriteria extends AbstractCustomSearchUICriterion
049{
050    /** The ODF helper */
051    protected ODFHelper _odfHelper;
052    
053    /** The shareable course helper */
054    protected ShareableCourseHelper _shareableCourseHelper;
055    
056    @Override
057    public void service(ServiceManager manager) throws ServiceException
058    {
059        super.service(manager);
060        _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE);
061        _shareableCourseHelper = (ShareableCourseHelper) manager.lookup(ShareableCourseHelper.ROLE);
062    }
063    
064    public String getFieldId()
065    {
066        return "shareable.course.field";
067    }
068
069    public Operator getOperator()
070    {
071        // Not suppose to be used
072        return Operator.EQ;
073    }
074    
075    @Override
076    public MetadataType getType()
077    {
078        // Not suppose to be used
079        return MetadataType.STRING;
080    }
081
082    public Query getQuery(Object value, Operator customOperator, Map<String, Object> allValues, String language, Map<String, Object> contextualParameters)
083    {
084        if (!_shareableCourseHelper.handleShareableCourse())
085        {
086            return null;
087        }
088        
089        List<Query> queries = new ArrayList<>();
090        
091        // Query for shareable course
092        Query isShareableQuery = new BooleanQuery(ShareableCourseHelper.SHAREABLE_METADATA_NAME, true);
093        queries.add(isShareableQuery);
094        
095        // Shareable course must be validated
096        Query isValidated = new StringQuery(ShareableCourseStatusHelper.SHAREABLE_COURSE_COMPOSITE_METADATA + ModelItem.ITEM_PATH_SEPARATOR + ShareableCourseStatusHelper.SHAREABLE_COURSE_STATUS_METADATA, ShareableStatus.VALIDATED.name());
097        queries.add(isValidated);
098        
099        if (contextualParameters.containsKey("courseListId"))
100        {
101            String courseListId = (String) contextualParameters.get("courseListId");
102            if (StringUtils.isNotBlank(courseListId))
103            {
104                ProgramItem courseList = _resolver.resolveById(courseListId);
105                Set<Program> programs = _odfHelper.getParentPrograms(courseList);
106                Set<Container> containers = _odfHelper.getParentContainers(courseList);
107                
108                // Query for programs field
109                Set<String> programValues = _shareableCourseHelper.getProgramIds(programs);
110                queries.add(_getFieldQuery(programValues, ShareableCourseHelper.PROGRAMS_FIELD_METADATA_NAME));
111                
112                // Query for periods field
113                Set<String> periodValues = _shareableCourseHelper.getPeriods(containers);
114                queries.add(_getFieldQuery(periodValues, ShareableCourseHelper.PERIODS_FIELD_METADATA_NAME));
115                
116                // Query for degree field
117                Set<String> degreeValues = _shareableCourseHelper.getDegrees(programs);
118                queries.add(_getFieldQuery(degreeValues, ShareableCourseHelper.DEGREES_FIELD_METADATA_NAME));
119                
120                // Query for orgunits field
121                Set<String> orgunitValues = _shareableCourseHelper.getOrgUnits(programs);
122                queries.add(_getFieldQuery(orgunitValues, ShareableCourseHelper.ORGUNITS_FIELD_METADATA_NAME));
123            }
124        }
125        
126        return queries.stream()
127                    .filter(q -> q != null)
128                    .collect(AndQuery.collector());
129    }
130
131    /**
132     * Get query for the shareable course field. Query is "not(field) or field = values"
133     * @param values the values
134     * @param metadataName the metadata name of the field
135     * @return the fitler query
136     */
137    protected Query _getFieldQuery(Set<String> values, String metadataName)
138    {
139        if (values.isEmpty())
140        {
141            return null;
142        }
143        
144        Query programValuesQuery = values.stream()
145                .map(v -> new StringQuery(metadataName, v))
146                .collect(OrQuery.collector());
147        
148        Query noProgramValueQuery = new NotQuery(new StringQuery(metadataName));
149        
150        return new OrQuery(noProgramValueQuery, programValuesQuery);
151    }
152}