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.plugins.odfweb.service.search; 017 018import java.util.Arrays; 019import java.util.Collection; 020import java.util.Collections; 021import java.util.Optional; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025 026import org.ametys.cms.search.query.AndQuery; 027import org.ametys.cms.search.query.ConstantNilScoreQuery; 028import org.ametys.cms.search.query.ContentTypeQuery; 029import org.ametys.cms.search.query.IsolateQuery; 030import org.ametys.cms.search.query.JoinQuery; 031import org.ametys.cms.search.query.MaxScoreOrQuery; 032import org.ametys.cms.search.query.Query; 033import org.ametys.odf.program.Program; 034import org.ametys.odf.program.ProgramFactory; 035import org.ametys.odf.program.SubProgramFactory; 036import org.ametys.odf.program.TraversableProgramPart; 037import org.ametys.plugins.odfweb.service.search.criterion.DegreeUniversityAttributeContentSearchCriterionDefinition; 038import org.ametys.plugins.odfweb.service.search.helper.DegreeUniversityHelper; 039import org.ametys.web.frontoffice.search.metamodel.AdditionalParameterValueMap; 040import org.ametys.web.frontoffice.search.metamodel.Returnable; 041import org.ametys.web.frontoffice.search.metamodel.SearchCriterionDefinition; 042import org.ametys.web.frontoffice.search.metamodel.Searchable; 043import org.ametys.web.frontoffice.search.metamodel.impl.AbstractContentBasedSearchable; 044 045/** 046 * {@link Searchable} for {@link Program}s 047 */ 048public class ProgramSearchable extends AbstractContentBasedSearchable 049{ 050 /** Avalon Role */ 051 public static final String ROLE = ProgramSearchable.class.getName(); 052 053 /** The additional parameter for indicating if search has to be made also on subprograms */ 054 public static final String PARAMETER_SEARCH_ON_SUBPROGRAMS = "searchSubprogram"; 055 056 /** The prefix for program searchable */ 057 public static final String CRITERION_DEFINITIONS_PREFIX_ID = "ProgramSearchable$"; 058 059 /** The prefix for indexing field in program searcheable */ 060 public static final String PROGRAM_SEARCHEABLE_INDEXING_FIELD_PREFIX = CRITERION_DEFINITIONS_PREFIX_ID + "indexingField$" + ProgramFactory.PROGRAM_CONTENT_TYPE + "$"; 061 062 /** The ODF search helper */ 063 protected ODFSearchHelper _odfSearchHelper; 064 065 /** The degree university helper */ 066 protected DegreeUniversityHelper _degreeUniversityHelper; 067 068 @Override 069 public void service(ServiceManager manager) throws ServiceException 070 { 071 super.service(manager); 072 _odfSearchHelper = (ODFSearchHelper) manager.lookup(ODFSearchHelper.ROLE); 073 _degreeUniversityHelper = (DegreeUniversityHelper) manager.lookup(DegreeUniversityHelper.ROLE); 074 } 075 076 @Override 077 protected String associatedContentReturnableRole() 078 { 079 return ProgramReturnable.ROLE; 080 } 081 082 @Override 083 protected String getCriterionDefinitionPrefix() 084 { 085 return CRITERION_DEFINITIONS_PREFIX_ID; 086 } 087 088 @Override 089 public Collection<Returnable> relationsWith() 090 { 091 return Arrays.asList(_associatedContentReturnable); 092 } 093 094 @Override 095 protected Collection<String> getContentTypes(AdditionalParameterValueMap additionalParameterValues) 096 { 097 return Collections.singleton(ProgramFactory.PROGRAM_CONTENT_TYPE); 098 } 099 100 @Override 101 public Optional<Query> joinQuery(Query queryOnCriterion, SearchCriterionDefinition criterion, Collection<Returnable> returnables, AdditionalParameterValueMap additionalParameters) 102 { 103 if (returnables.contains(_associatedContentReturnable)) 104 { 105 if (_searchOnSubprograms(additionalParameters) && appliesToSubprogram(criterion)) 106 { 107 return Optional.of(new MaxScoreOrQuery(new IsolateQuery(queryOnCriterion), getProgramThroughSubprogramsQuery(queryOnCriterion))); 108 } 109 else 110 { 111 return Optional.of(queryOnCriterion); 112 } 113 } 114 else 115 { 116 return Optional.empty(); 117 } 118 } 119 120 private boolean _searchOnSubprograms(AdditionalParameterValueMap additionalParameters) 121 { 122 return additionalParameters.getValue(PARAMETER_SEARCH_ON_SUBPROGRAMS); 123 } 124 125 /** 126 * Determines if the given {@link SearchCriterionDefinition} applies to Subprograms 127 * @param criterion the criterion 128 * @return <code>true</code> if the given {@link SearchCriterionDefinition} applies to Subprograms 129 */ 130 protected boolean appliesToSubprogram(SearchCriterionDefinition criterion) 131 { 132 return _odfSearchHelper.isCriterionOnBothProgramAndSubProgram(criterion); 133 } 134 135 /** 136 * Gets the {@link Query} that returns Programs by querying their SubPrograms 137 * @param queryOnCriterion The query on SubPrograms 138 * @return The {@link Query} that returns Programs 139 */ 140 protected Query getProgramThroughSubprogramsQuery(Query queryOnCriterion) 141 { 142 Query queryOnSubprograms = new AndQuery( 143 new ConstantNilScoreQuery(new ContentTypeQuery(SubProgramFactory.SUBPROGRAM_CONTENT_TYPE)), 144 queryOnCriterion 145 ); 146 return new ProgramThroughProgramPartsQuery(queryOnSubprograms); 147 } 148 149 @Override 150 public Collection<SearchCriterionDefinition> getCriteria(AdditionalParameterValueMap additionalParameterValues) 151 { 152 Collection<SearchCriterionDefinition> criteria = super.getCriteria(additionalParameterValues); 153 154 DegreeUniversityAttributeContentSearchCriterionDefinition degreeUniversityCriterionDefinition = _degreeUniversityHelper.getDegreeUniversityCriterionDefinition(this); 155 if (degreeUniversityCriterionDefinition != null) 156 { 157 criteria.add(degreeUniversityCriterionDefinition); 158 } 159 160 return criteria; 161 } 162 163 /** 164 * A {@link Query} that returns Programs, by querying their child ProgramParts 165 */ 166 protected static class ProgramThroughProgramPartsQuery extends JoinQuery 167 { 168 /** 169 * Builds a ProgramThroughProgramPartsQuery 170 * @param subQuery The query on ProgramParts 171 */ 172 protected ProgramThroughProgramPartsQuery(Query subQuery) 173 { 174 super(subQuery, TraversableProgramPart.CHILD_PROGRAM_PARTS); 175 } 176 } 177}