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.ametys.cms.search.query.AndQuery; 024import org.ametys.cms.search.query.ConstantNilScoreQuery; 025import org.ametys.cms.search.query.ContentTypeQuery; 026import org.ametys.cms.search.query.FullTextQuery; 027import org.ametys.cms.search.query.JoinQuery; 028import org.ametys.cms.search.query.MaxScoreOrQuery; 029import org.ametys.cms.search.query.Query; 030import org.ametys.odf.program.Program; 031import org.ametys.odf.program.ProgramFactory; 032import org.ametys.odf.program.SubProgramFactory; 033import org.ametys.odf.program.TraversableProgramPart; 034import org.ametys.web.frontoffice.search.metamodel.AdditionalParameterValueMap; 035import org.ametys.web.frontoffice.search.metamodel.Returnable; 036import org.ametys.web.frontoffice.search.metamodel.Searchable; 037import org.ametys.web.frontoffice.search.metamodel.impl.AbstractContentBasedSearchable; 038 039/** 040 * {@link Searchable} for {@link Program}s 041 */ 042public class ProgramSearchable extends AbstractContentBasedSearchable 043{ 044 /** Avalon Role */ 045 public static final String ROLE = ProgramSearchable.class.getName(); 046 047 /** The additional parameter for indicating if search has to be made also on subprograms */ 048 public static final String PARAMETER_SEARCH_ON_SUBPROGRAMS = "searchSubprogram"; 049 050 private static final String __CRITERION_DEFINITIONS_PREFIX_ID = "ProgramSearchable$"; 051 052 @Override 053 protected String associatedContentReturnableRole() 054 { 055 return ProgramReturnable.ROLE; 056 } 057 058 @Override 059 protected String getCriterionDefinitionPrefix() 060 { 061 return __CRITERION_DEFINITIONS_PREFIX_ID; 062 } 063 064 @Override 065 public Collection<Returnable> relationsWith() 066 { 067 return Arrays.asList(_associatedContentReturnable); 068 } 069 070 @Override 071 protected Collection<String> getContentTypes(AdditionalParameterValueMap additionalParameterValues) 072 { 073 return Collections.singleton(ProgramFactory.PROGRAM_CONTENT_TYPE); 074 } 075 076 @Override 077 public Optional<Query> joinQuery(Query queryOnCriterion, Collection<Returnable> returnables, AdditionalParameterValueMap additionalParameters) 078 { 079 if (returnables.contains(_associatedContentReturnable)) 080 { 081 if (_searchOnSubprograms(additionalParameters) && appliesToSubprogram(queryOnCriterion)) 082 { 083 return Optional.of(new MaxScoreOrQuery(queryOnCriterion, getProgramThroughSubprogramsQuery(queryOnCriterion))); 084 } 085 else 086 { 087 return Optional.of(queryOnCriterion); 088 } 089 } 090 else 091 { 092 return Optional.empty(); 093 } 094 } 095 096 private boolean _searchOnSubprograms(AdditionalParameterValueMap additionalParameters) 097 { 098 return additionalParameters.getValue(PARAMETER_SEARCH_ON_SUBPROGRAMS); 099 } 100 101 /** 102 * Determines if the given {@link Query} applies to Subprograms 103 * @param queryOnCriterion The query 104 * @return <code>true</code> if the given {@link Query} applies to Subprograms 105 */ 106 protected boolean appliesToSubprogram(Query queryOnCriterion) 107 { 108 return queryOnCriterion instanceof FullTextQuery; 109 } 110 111 /** 112 * Gets the {@link Query} that returns Programs by querying their SubPrograms 113 * @param queryOnCriterion The query on SubPrograms 114 * @return The {@link Query} that returns Programs 115 */ 116 protected Query getProgramThroughSubprogramsQuery(Query queryOnCriterion) 117 { 118 Query queryOnSubprograms = new AndQuery( 119 new ConstantNilScoreQuery(new ContentTypeQuery(SubProgramFactory.SUBPROGRAM_CONTENT_TYPE)), 120 queryOnCriterion 121 ); 122 return new ProgramThroughProgramPartsQuery(queryOnSubprograms); 123 } 124 125 /** 126 * A {@link Query} that returns Programs, by querying their child ProgramParts 127 */ 128 protected static class ProgramThroughProgramPartsQuery extends JoinQuery 129 { 130 /** 131 * Builds a ProgramThroughProgramPartsQuery 132 * @param subQuery The query on ProgramParts 133 */ 134 protected ProgramThroughProgramPartsQuery(Query subQuery) 135 { 136 super(subQuery, TraversableProgramPart.METADATA_CHILD_PROGRAM_PARTS); 137 } 138 } 139}