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.web.frontoffice.search.instance.model; 017 018import java.util.List; 019import java.util.Map; 020import java.util.stream.Collectors; 021 022import org.slf4j.Logger; 023import org.slf4j.LoggerFactory; 024 025import org.ametys.cms.search.advanced.WrappedValue; 026import org.ametys.web.frontoffice.search.metamodel.SearchCriterionDefinition; 027 028/** 029 * The mode of a {@link FOSearchCriterion} 030 */ 031public enum FOSearchCriterionMode 032{ 033 /** 034 * The criterion is static, i.e. valued by the webmaster and is not a proposed criterion to the final user. 035 */ 036 STATIC 037 { 038 @Override 039 public FoWrappedValue getValue(FOSearchCriterion searchCriterion, Map<String, Object> userCriteria, Map<String, Object> contextualParameters) 040 { 041 Object staticValue = searchCriterion.getStaticValue().get(); 042 FoWrappedValue result = new FoWrappedValue(staticValue); 043 __LOGGER.debug("Value for static criterion '{}': {}", searchCriterion.getId(), result); 044 return result; 045 } 046 }, 047 048 /** 049 * The criterion is proposed to the final user. 050 */ 051 USER_INPUT 052 { 053 @Override 054 public FoWrappedValue getValue(FOSearchCriterion searchCriterion, Map<String, Object> userCriteria, Map<String, Object> contextualParameters) 055 { 056 String criterionId = searchCriterion.getId(); 057 Object val = userCriteria.get(criterionId); 058 SearchCriterionDefinition criterionDefinition = searchCriterion.getCriterionDefinition(); 059 if (val != null) 060 { 061 boolean requestEmptyValue = val.equals(NONE_VALUE) 062 && !searchCriterion.isMandatory() 063 && criterionDefinition.isEnumerated(); 064 065 FoWrappedValue result = new FoWrappedValue(val, requestEmptyValue); 066 __LOGGER.debug("Value from user for criterion '{}': {}", criterionId, result); 067 return result; 068 } 069 070 // val is null 071 // no need to build a collection of all existing entries of the enumerated values as all are allowed, and empty is allowed too => avoid an unnecessary query on the indexed field 072 __LOGGER.debug("Value from user for criterion '{}': null", criterionId); 073 return new FoWrappedValue(null); 074 } 075 }, 076 077 /** 078 * The criterion is proposed to the final user, with a restricted enumeration of choices. 079 */ 080 RESTRICTED_USER_INPUT 081 { 082 @Override 083 public FoWrappedValue getValue(FOSearchCriterion searchCriterion, Map<String, Object> userCriteria, Map<String, Object> contextualParameters) 084 { 085 String criterionId = searchCriterion.getId(); 086 Object val = userCriteria.get(criterionId); 087 if (val != null) 088 { 089 boolean requestEmptyValue = val.equals(NONE_VALUE) && !searchCriterion.isMandatory(); 090 FoWrappedValue result = new FoWrappedValue(val, requestEmptyValue); 091 __LOGGER.debug("Value from user for (restricted) criterion '{}': {}", criterionId, result); 092 return result; 093 } 094 else 095 { 096 // The criterion was not filled by the visitor 097 // Consider it as the 'All' option to filter results matching with at least one value in the restricted values 098 List<Object> vals = searchCriterion 099 .getRestrictedValues() 100 .get() 101 .values() 102 .keySet() 103 .stream() 104 .collect(Collectors.toList()); 105 106 boolean requestEmptyValue = !searchCriterion.isMandatory(); 107 FoWrappedValue result = new FoWrappedValue(vals, requestEmptyValue); 108 __LOGGER.debug("Value for criterion '{}' (computed because not filled by user but is restricted): {}", criterionId, result); 109 return result; 110 } 111 } 112 }, 113 114 /** 115 * The criterion is proposed for content profiled by user group tag. 116 */ 117 PROFILED_GROUPS_TAGS_INPUT 118 { 119 @Override 120 public FoWrappedValue getValue(FOSearchCriterion searchCriterion, Map<String, Object> userCriteria, Map<String, Object> contextualParameters) 121 { 122 return new FoWrappedValue(PROFILED_GROUPS_TAGS_VALUE); 123 } 124 }; 125 126 /** The none value */ 127 public static final String NONE_VALUE = "__ametys_none"; 128 129 /** The profiled groups tags value */ 130 public static final String PROFILED_GROUPS_TAGS_VALUE = "__ametys_profiled_groups_tags"; 131 132 static final Logger __LOGGER = LoggerFactory.getLogger(FOSearchCriterionMode.class); 133 134 /** 135 * Gets the value from the {@link FOSearchCriterion criterion} and the final user criteria. 136 * @param searchCriterion The {@link FOSearchCriterion} which is in this mode 137 * @param finalUserCriteria The criteria from the final user 138 * @param contextualParameters The contextual parameters 139 * @return the value 140 */ 141 public abstract FoWrappedValue getValue(FOSearchCriterion searchCriterion, Map<String, Object> finalUserCriteria, Map<String, Object> contextualParameters); 142 143 /** 144 * <code>true</code> if the criterion is static 145 * @return <code>true</code> if the criterion is static 146 */ 147 public boolean isStatic() 148 { 149 return this.equals(STATIC) || this.equals(PROFILED_GROUPS_TAGS_INPUT); 150 } 151 152 /** 153 * A {@link WrappedValue}, being the return type of {@link FOSearchCriterionMode#getValue}. It can notify for enumerated criteria if empty value need to be requested, through {@link #requestEmptyValue()} 154 */ 155 public static final class FoWrappedValue extends WrappedValue 156 { 157 private final boolean _requestEmptyValue; 158 159 private FoWrappedValue(Object value) 160 { 161 super(value); 162 _requestEmptyValue = false; 163 } 164 165 private FoWrappedValue(Object values, boolean requestEmptyValue) 166 { 167 super(values); 168 _requestEmptyValue = requestEmptyValue; 169 } 170 171 /** 172 * <code>true</code> if the wrapped value is from enumerated and no mandatory data. The caller has selected none value or all value for restricted user input. 173 * @return <code>true</code> if the wrapped value is from enumerated and no mandatory data. The caller has selected none value or all value for restricted user input. 174 */ 175 public boolean requestEmptyValue() 176 { 177 return _requestEmptyValue; 178 } 179 180 @Override 181 public String toString() 182 { 183 return super.toString() + "{requestEmptyValue:" + _requestEmptyValue + "}"; 184 } 185 } 186}