001/* 002 * Copyright 2015 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.cms.search.ui.model; 017 018import java.util.Collection; 019import java.util.Collections; 020import java.util.HashSet; 021import java.util.LinkedHashMap; 022import java.util.Map; 023import java.util.Set; 024 025import org.apache.avalon.framework.configuration.Configuration; 026import org.apache.avalon.framework.configuration.ConfigurationException; 027import org.apache.avalon.framework.configuration.DefaultConfiguration; 028import org.apache.avalon.framework.context.Context; 029import org.apache.avalon.framework.context.ContextException; 030import org.apache.avalon.framework.context.Contextualizable; 031import org.apache.avalon.framework.service.ServiceException; 032import org.apache.avalon.framework.service.ServiceManager; 033import org.apache.avalon.framework.service.Serviceable; 034import org.slf4j.Logger; 035 036import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 037import org.ametys.cms.search.model.SearchCriterion; 038import org.ametys.cms.search.query.Query.Operator; 039import org.ametys.runtime.i18n.I18nizableText; 040import org.ametys.runtime.plugin.component.LogEnabled; 041 042/** 043 * Abstract class for SearchUIModel. 044 */ 045public abstract class AbstractSearchUIModel implements SearchUIModel, LogEnabled, Serviceable, Contextualizable 046{ 047 /** The content type extension point */ 048 protected ContentTypeExtensionPoint _cTypeEP; 049 /** The search model helper. */ 050 protected SearchUIModelHelper _searchModelHelper; 051 /** The logger. */ 052 protected Logger _logger; 053 /** The service manager */ 054 protected ServiceManager _manager; 055 /** The context. */ 056 protected Context _context; 057 058 /** The content types of this search model. */ 059 protected Set<String> _cTypes; 060 /** The content types excluded from this search model. */ 061 protected Set<String> _excludedCTypes; 062 063 /** The search criteria in simple mode, indexed by ID. */ 064 protected Map<String, SearchUICriterion> _searchCriteria; 065 /** The search criteria in advanced mode, indexed by ID. */ 066 protected Map<String, SearchUICriterion> _advancedSearchCriteria; 067 /** The search criteria used as facets, indexed by ID. */ 068 protected Map<String, SearchUICriterion> _facetedCriteria; 069 /** The result columns, indexed by ID. */ 070 protected Map<String, SearchUIColumn> _columns; 071 072 public void setLogger(final Logger logger) 073 { 074 _logger = logger; 075 } 076 077 /** 078 * Get the logger. 079 * @return the logger. 080 */ 081 protected final Logger getLogger() 082 { 083 return _logger; 084 } 085 086 @Override 087 public void contextualize(Context context) throws ContextException 088 { 089 _context = context; 090 } 091 092 @Override 093 public void service(ServiceManager manager) throws ServiceException 094 { 095 _cTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 096 _searchModelHelper = (SearchUIModelHelper) manager.lookup(SearchUIModelHelper.ROLE); 097 _manager = manager; 098 } 099 100 @Override 101 public Set<String> getContentTypes(Map<String, Object> contextualParameters) 102 { 103 return Collections.unmodifiableSet(_cTypes); 104 } 105 106 /** 107 * Set the content types. 108 * @param cTypes The content types. 109 */ 110 public void setContentTypes(Set<String> cTypes) 111 { 112 _cTypes = new HashSet<>(cTypes); 113 } 114 115 @Override 116 public Set<String> getExcludedContentTypes(Map<String, Object> contextualParameters) 117 { 118 return Collections.unmodifiableSet(_excludedCTypes); 119 } 120 121 /** 122 * Set the excluded content types. 123 * @param cTypes The excluded content types. 124 */ 125 public void setExcludedContentTypes(Set<String> cTypes) 126 { 127 _excludedCTypes = new HashSet<>(cTypes); 128 } 129 130 @Override 131 public Map<String, SearchUICriterion> getCriteria(Map<String, Object> contextualParameters) 132 { 133 return Collections.unmodifiableMap(_searchCriteria); 134 } 135 136 /** 137 * Set the criteria in simple mode. 138 * @param criteria A collection of search criteria. 139 */ 140 public void setCriteria(Collection<SearchUICriterion> criteria) 141 { 142 _searchCriteria = new LinkedHashMap<>(); 143 for (SearchCriterion criterion : criteria) 144 { 145 _searchCriteria.put(criterion.getId(), (SearchUICriterion) criterion); 146 } 147 } 148 149 @Override 150 public Map<String, SearchUICriterion> getAdvancedCriteria(Map<String, Object> contextualParameters) 151 { 152 return Collections.unmodifiableMap(_advancedSearchCriteria); 153 } 154 155 /** 156 * Set the criteria in advanced mode. 157 * @param criteria A collection of search criteria. 158 */ 159 public void setAdvancedCriteria(Collection<SearchUICriterion> criteria) 160 { 161 _advancedSearchCriteria = new LinkedHashMap<>(); 162 for (SearchUICriterion criterion : criteria) 163 { 164 _advancedSearchCriteria.put(criterion.getId(), criterion); 165 } 166 } 167 168 @Override 169 public Map<String, SearchUICriterion> getFacetedCriteria(Map<String, Object> contextualParameters) 170 { 171 return Collections.unmodifiableMap(_facetedCriteria); 172 } 173 174 /** 175 * Set the criteria to use as facets. 176 * @param criteria A collection of search criteria. 177 */ 178 public void setFacetedCriteria(Collection<SearchCriterion> criteria) 179 { 180 _facetedCriteria = new LinkedHashMap<>(); 181 for (SearchCriterion criterion : criteria) 182 { 183 _facetedCriteria.put(criterion.getId(), (SearchUICriterion) criterion); 184 } 185 } 186 187 @Override 188 public Map<String, SearchUIColumn> getResultFields(Map<String, Object> contextualParameters) 189 { 190 return Collections.unmodifiableMap(_columns); 191 } 192 193 /** 194 * Set the result columns. 195 * @param fields A collection of search columns. 196 */ 197 public void setResultFields(Collection<SearchUIColumn> fields) 198 { 199 _columns = new LinkedHashMap<>(); 200 for (SearchUIColumn column : fields) 201 { 202 _columns.put(column.getId(), column); 203 } 204 } 205 206 @Override 207 public int getPageSize(Map<String, Object> contextualParameters) 208 { 209 // Use the default value or unlimited. 210 return -1; 211 } 212 213 @Override 214 public String getWorkspace(Map<String, Object> contextualParameters) 215 { 216 // Use the default workspace. 217 return null; 218 } 219 220 @Override 221 public String getSearchUrl(Map<String, Object> contextualParameters) 222 { 223 return "search/list.json"; 224 } 225 226 @Override 227 public String getSearchUrlPlugin(Map<String, Object> contextualParameters) 228 { 229 return "cms"; 230 } 231 232 @Override 233 public String getExportCSVUrl(Map<String, Object> contextualParameters) 234 { 235 return "search/export.csv"; 236 } 237 238 @Override 239 public String getExportCSVUrlPlugin(Map<String, Object> contextualParameters) 240 { 241 return "cms"; 242 } 243 244 @Override 245 public String getExportXMLUrl(Map<String, Object> contextualParameters) 246 { 247 return "search/export.xml"; 248 } 249 250 @Override 251 public String getExportXMLUrlPlugin(Map<String, Object> contextualParameters) 252 { 253 return "cms"; 254 } 255 256 @Override 257 public String getPrintUrl(Map<String, Object> contextualParameters) 258 { 259 return "search/print.html"; 260 } 261 262 @Override 263 public String getPrintUrlPlugin(Map<String, Object> contextualParameters) 264 { 265 return "cms"; 266 } 267 268 /** 269 * Get the configuration of a metadata criteria component. 270 * @param contentTypeId the content type ID. 271 * @param path the field path. 272 * @param operator the criteria operator, can be null. 273 * @return the configuration to provide to the metadata criteria component. 274 * @throws ConfigurationException if an error occurs. 275 */ 276 protected Configuration getIndexingFieldCriteriaConfiguration(String contentTypeId, String path, Operator operator) throws ConfigurationException 277 { 278 return getIndexingFieldCriteriaConfiguration(contentTypeId, path, operator, null); 279 } 280 281 /** 282 * Get the configuration of a metadata criteria component. 283 * @param contentTypeId the content type ID. 284 * @param path the field path. 285 * @param operator the criteria operator, can be null. 286 * @param group The group. Can ne null. 287 * @return the configuration to provide to the metadata criteria component. 288 * @throws ConfigurationException if an error occurs. 289 */ 290 protected Configuration getIndexingFieldCriteriaConfiguration(String contentTypeId, String path, Operator operator, I18nizableText group) throws ConfigurationException 291 { 292 return getIndexingFieldCriteriaConfiguration(new DefaultConfiguration("criteria"), contentTypeId, path, operator, group); 293 } 294 295 /** 296 * Get the configuration of a metadata criteria component. 297 * @param originalConf the original criteria configuration. 298 * @param contentTypeId the content type ID. 299 * @param path the field path, separated by '/'. 300 * @param operator the criteria operator, can be null. 301 * @param group The group. Can ne null. 302 * @return the configuration to provide to the metadata criterion component. 303 * @throws ConfigurationException if an error occurs. 304 */ 305 protected Configuration getIndexingFieldCriteriaConfiguration(Configuration originalConf, String contentTypeId, String path, Operator operator, I18nizableText group) throws ConfigurationException 306 { 307 DefaultConfiguration conf = new DefaultConfiguration(originalConf); 308 309 DefaultConfiguration metaConf = new DefaultConfiguration("field"); 310 conf.addChild(metaConf); 311 metaConf.setAttribute("path", path); 312 313 if (operator != null) 314 { 315 DefaultConfiguration opConf = new DefaultConfiguration("test-operator"); 316 conf.addChild(opConf); 317 opConf.setValue(operator.getName()); 318 } 319 320 addContentTypesConfiguration(conf, contentTypeId); 321 322 if (group != null) 323 { 324 DefaultConfiguration groupConf = new DefaultConfiguration("group"); 325 groupConf.setAttribute("i18n", group.isI18n()); 326 groupConf.setValue(group.isI18n() ? group.getCatalogue() + ":" + group.getKey() : group.getLabel()); 327 conf.addChild(groupConf); 328 } 329 330 return conf; 331 } 332 333 /** 334 * Get the configuration of a system criteria component. 335 * @param contentTypeId the content type ID. 336 * @param property the system property. 337 * @return the configuration to provide to the system criterion component. 338 */ 339 protected Configuration getSystemCriteriaConfiguration(String contentTypeId, String property) 340 { 341 return getSystemCriteriaConfiguration(contentTypeId, property, null); 342 } 343 344 /** 345 * Get the configuration of a system criteria component. 346 * @param contentTypeId the content type ID. 347 * @param property the system property. 348 * @param group The group. Can ne null. 349 * @return the configuration to provide to the system criterion component. 350 */ 351 protected Configuration getSystemCriteriaConfiguration(String contentTypeId, String property, I18nizableText group) 352 { 353 try 354 { 355 return getSystemCriteriaConfiguration(new DefaultConfiguration("criteria"), contentTypeId, property, group); 356 } 357 catch (ConfigurationException e) 358 { 359 // Ignore, just can't happen. 360 return null; 361 } 362 } 363 364 /** 365 * Get the configuration of a system criteria component. 366 * @param originalConf the original column configuration. 367 * @param contentTypeId the content type ID. 368 * @param property the system property. 369 * @param group The group. Can ne null. 370 * @return the configuration to provide to the system criterion component. 371 * @throws ConfigurationException if an error occurs. 372 */ 373 protected Configuration getSystemCriteriaConfiguration(Configuration originalConf, String contentTypeId, String property, I18nizableText group) throws ConfigurationException 374 { 375 DefaultConfiguration conf = new DefaultConfiguration(originalConf); 376 377 DefaultConfiguration propConf = new DefaultConfiguration("systemProperty"); 378 propConf.setAttribute("name", property); 379 conf.addChild(propConf); 380 381 addContentTypesConfiguration(conf, contentTypeId); 382 383 if (group != null) 384 { 385 DefaultConfiguration groupConf = new DefaultConfiguration("group"); 386 groupConf.setAttribute("i18n", group.isI18n()); 387 groupConf.setValue(group.isI18n() ? group.getCatalogue() + ":" + group.getKey() : group.getLabel()); 388 conf.addChild(groupConf); 389 } 390 391 return conf; 392 } 393 394 /** 395 * Get the configuration of a custom criteria component. 396 * @param originalConf the original column configuration. 397 * @param contentTypeId the content type ID. 398 * @param customCriterionId the custom criterion id 399 * @param group The group. Can be null. 400 * @return the configuration to provide to the custom criterion component. 401 * @throws ConfigurationException if an error occurs. 402 */ 403 protected Configuration getCustomCriteriaConfiguration(Configuration originalConf, String contentTypeId, String customCriterionId, I18nizableText group) throws ConfigurationException 404 { 405 DefaultConfiguration conf = new DefaultConfiguration(originalConf); 406 407 DefaultConfiguration customCriterionConf = new DefaultConfiguration("customCriterion"); 408 customCriterionConf.setAttribute("id", customCriterionId); 409 conf.addChild(customCriterionConf); 410 411 addContentTypesConfiguration(conf, contentTypeId); 412 413 if (group != null) 414 { 415 DefaultConfiguration groupConf = new DefaultConfiguration("group"); 416 groupConf.setAttribute("i18n", group.isI18n()); 417 groupConf.setValue(group.isI18n() ? group.getCatalogue() + ":" + group.getKey() : group.getLabel()); 418 conf.addChild(groupConf); 419 } 420 421 return conf; 422 } 423 424 /** 425 * Get the configuration of a metadata column component. 426 * @param contentTypeId the content type ID. 427 * @param metadataPath the metadata path. 428 * @return the configuration to provide to the metadata column component. 429 * @throws ConfigurationException if an error occurs. 430 */ 431 protected Configuration getMetadataColumnConfiguration(String contentTypeId, String metadataPath) throws ConfigurationException 432 { 433 return getMetadataColumnConfiguration(new DefaultConfiguration("column"), contentTypeId, metadataPath); 434 } 435 436 /** 437 * Get the configuration of a metadata column component. 438 * @param originalConf the original column configuration. 439 * @param contentTypeId the content type ID, may be null. 440 * @param metadataPath the metadata path. 441 * @return the configuration to provide to the metadata column component. 442 * @throws ConfigurationException if an error occurs. 443 */ 444 protected Configuration getMetadataColumnConfiguration(Configuration originalConf, String contentTypeId, String metadataPath) throws ConfigurationException 445 { 446 DefaultConfiguration conf = new DefaultConfiguration(originalConf); 447 448 DefaultConfiguration metaConf = new DefaultConfiguration("metadata"); 449 conf.addChild(metaConf); 450 metaConf.setAttribute("path", metadataPath); 451 452 addContentTypesConfiguration(conf, contentTypeId); 453 454 return conf; 455 } 456 457 /** 458 * Get the configuration of a system column component. 459 * @param contentTypeId the content type ID. 460 * @param property the system property. 461 * @return the configuration to provide to the system column component. 462 * @throws ConfigurationException if an error occurs. 463 */ 464 protected Configuration getSystemColumnConfiguration(String contentTypeId, String property) throws ConfigurationException 465 { 466 return getSystemColumnConfiguration(new DefaultConfiguration("column"), contentTypeId, property); 467 } 468 469 /** 470 * Get the configuration of a system column component. 471 * @param originalConf the original column configuration. 472 * @param contentTypeId the content type ID. 473 * @param property the system property. 474 * @return the configuration to provide to the system column component. 475 * @throws ConfigurationException if an error occurs. 476 */ 477 protected Configuration getSystemColumnConfiguration(Configuration originalConf, String contentTypeId, String property) throws ConfigurationException 478 { 479 DefaultConfiguration conf = originalConf != null ? new DefaultConfiguration(originalConf) : new DefaultConfiguration("column"); 480 481 DefaultConfiguration propConf = new DefaultConfiguration("systemProperty"); 482 propConf.setAttribute("name", property); 483 conf.addChild(propConf); 484 485 addContentTypesConfiguration(conf, contentTypeId); 486 487 return conf; 488 } 489 490 /** 491 * Add the content types configuration. 492 * @param conf The configuration to write to. 493 * @param contentTypeId The "base" content type ID, may be null. 494 */ 495 protected void addContentTypesConfiguration(DefaultConfiguration conf, String contentTypeId) 496 { 497 Set<String> contentTypes = _searchModelHelper.getAllContentTypes(this, Collections.emptyMap()); 498 DefaultConfiguration cTypesConf = new DefaultConfiguration("contentTypes"); 499 conf.addChild(cTypesConf); 500 for (String contentType : contentTypes) 501 { 502 DefaultConfiguration cTypeConf = new DefaultConfiguration("type"); 503 cTypeConf.setAttribute("id", contentType); 504 cTypesConf.addChild(cTypeConf); 505 } 506 507 if (contentTypeId != null) 508 { 509 cTypesConf.setAttribute("baseId", contentTypeId); 510 } 511 } 512 513}