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.search.model.impl.AbstractStaticSearchModelCriterionDefinition; 028import org.ametys.cms.search.query.AndQuery; 029import org.ametys.cms.search.query.NotQuery; 030import org.ametys.cms.search.query.OrQuery; 031import org.ametys.cms.search.query.Query; 032import org.ametys.cms.search.query.Query.Operator; 033import org.ametys.cms.search.query.StringQuery; 034import org.ametys.odf.ODFHelper; 035import org.ametys.odf.ProgramItem; 036import org.ametys.odf.course.ShareableCourseConstants; 037import org.ametys.odf.course.ShareableCourseHelper; 038import org.ametys.odf.course.ShareableCourseStatusHelper.ShareableStatus; 039import org.ametys.odf.program.Container; 040import org.ametys.odf.program.Program; 041import org.ametys.plugins.repository.AmetysObjectResolver; 042import org.ametys.runtime.model.ModelItem; 043import org.ametys.runtime.model.type.ModelItemTypeConstants; 044 045/** 046 * Search criterion for shareable course 047 */ 048public class ShareableCourseCriterionDefinition extends AbstractStaticSearchModelCriterionDefinition<String> 049{ 050 /** The ametys object resolver. */ 051 protected AmetysObjectResolver _resolver; 052 053 /** The ODF helper */ 054 protected ODFHelper _odfHelper; 055 056 /** The shareable course helper */ 057 protected ShareableCourseHelper _shareableCourseHelper; 058 059 @Override 060 public void service(ServiceManager manager) throws ServiceException 061 { 062 super.service(manager); 063 064 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 065 _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE); 066 _shareableCourseHelper = (ShareableCourseHelper) manager.lookup(ShareableCourseHelper.ROLE); 067 } 068 069 @Override 070 public Operator getOperator() 071 { 072 // Not suppose to be used 073 return Operator.EQ; 074 } 075 076 @Override 077 protected String getTypeId() 078 { 079 return ModelItemTypeConstants.STRING_TYPE_ID; 080 } 081 082 @Override 083 public Query getQuery(Object value, Operator customOperator, Map<String, Object> allValues, String language, Map<String, Object> contextualParameters) 084 { 085 if (!_shareableCourseHelper.handleShareableCourse()) 086 { 087 return null; 088 } 089 090 return _getShareableQuery(value, customOperator, allValues, language, contextualParameters); 091 } 092 093 /** 094 * Get the {@link Query} associated to shareable fields 095 * @param value The user-submitted value (or the default value if not set) for this criterion. 096 * @param customOperator In advanced search mode, the operator chosen by the user. <code>null</code> to use the criterion-defined operator (simple search mode). 097 * @param allValues All the user-submitted values. 098 * @param language The current search language. 099 * @param contextualParameters the search contextual parameters. 100 * @return {@link Query} associated to shareable fields 101 */ 102 protected Query _getShareableQuery(Object value, Operator customOperator, Map<String, Object> allValues, String language, Map<String, Object> contextualParameters) 103 { 104 List<Query> queries = new ArrayList<>(); 105 106 // Shareable course must be validated 107 queries.add(_getValidatedShareableCourseQuery()); 108 109 if (contextualParameters.containsKey("courseListId")) 110 { 111 String courseListId = (String) contextualParameters.get("courseListId"); 112 if (StringUtils.isNotBlank(courseListId)) 113 { 114 ProgramItem courseList = _resolver.resolveById(courseListId); 115 queries.addAll(_getShareableFieldQueries(courseList)); 116 } 117 } 118 119 return queries.stream() 120 .filter(q -> q != null) 121 .collect(AndQuery.collector()); 122 } 123 124 /** 125 * Get the query to get only validated shareable course 126 * @return the query 127 */ 128 protected Query _getValidatedShareableCourseQuery() 129 { 130 return new StringQuery(ShareableCourseConstants.SHAREABLE_COURSE_COMPOSITE_METADATA + ModelItem.ITEM_PATH_SEPARATOR + ShareableCourseConstants.SHAREABLE_COURSE_STATUS_METADATA, ShareableStatus.VALIDATED.name()); 131 } 132 133 /** 134 * Get query form each shareable field 135 * @param programItem the program item 136 * @return the list of query 137 */ 138 protected List<Query> _getShareableFieldQueries(ProgramItem programItem) 139 { 140 List<Query> queries = new ArrayList<>(); 141 142 Set<Program> programs = _odfHelper.getParentPrograms(programItem); 143 Set<Container> containers = _odfHelper.getParentContainers(programItem); 144 145 // Query for programs field 146 Set<String> programValues = _shareableCourseHelper.getProgramIds(programs); 147 queries.add(_getFieldQuery(programValues, ShareableCourseConstants.PROGRAMS_FIELD_ATTRIBUTE_NAME)); 148 149 // Query for periods field 150 Set<String> periodValues = _shareableCourseHelper.getPeriods(containers); 151 queries.add(_getFieldQuery(periodValues, ShareableCourseConstants.PERIODS_FIELD_ATTRIBUTE_NAME)); 152 153 // Query for degree field 154 Set<String> degreeValues = _shareableCourseHelper.getDegrees(programs); 155 queries.add(_getFieldQuery(degreeValues, ShareableCourseConstants.DEGREES_FIELD_ATTRIBUTE_NAME)); 156 157 // Query for orgunits field 158 Set<String> orgunitValues = _shareableCourseHelper.getOrgUnits(programs); 159 queries.add(_getFieldQuery(orgunitValues, ShareableCourseConstants.ORGUNITS_FIELD_ATTRIBUTE_NAME)); 160 161 return queries; 162 } 163 164 /** 165 * Get query for the shareable course field. Query is "not(field) or field = values" 166 * @param values the values 167 * @param metadataName the metadata name of the field 168 * @return the fitler query 169 */ 170 protected Query _getFieldQuery(Set<String> values, String metadataName) 171 { 172 if (values.isEmpty()) 173 { 174 return null; 175 } 176 177 Query programValuesQuery = values.stream() 178 .map(v -> new StringQuery(metadataName, v)) 179 .collect(OrQuery.collector()); 180 181 Query noProgramValueQuery = new NotQuery(new StringQuery(metadataName)); 182 183 return new OrQuery(noProgramValueQuery, programValuesQuery); 184 } 185}