001/* 002 * Copyright 2025 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.systemprop; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.List; 021 022import org.apache.solr.common.SolrInputDocument; 023 024import org.ametys.cms.data.ametysobject.ModelAwareDataAwareAmetysObject; 025import org.ametys.cms.data.type.indexing.IndexableElementType; 026import org.ametys.cms.model.CMSDataContext; 027import org.ametys.cms.model.properties.AbstractIndexableStaticProperty; 028import org.ametys.cms.search.solr.schema.CopyFieldDefinition; 029import org.ametys.cms.search.solr.schema.FieldDefinition; 030import org.ametys.cms.search.solr.schema.SchemaDefinition; 031 032/** 033 * Abstract class for single indexation aware system property 034 * @param <T> type of the property values 035 * @param <C> type of criterion 036 * @param <X> type of ametys object supported by this property 037 */ 038public abstract class AbstractIndexableSystemProperty<T, C, X extends ModelAwareDataAwareAmetysObject> extends AbstractIndexableStaticProperty<T, C, X> implements IndexationAwareSystemProperty<T, X> 039{ 040 @Override 041 protected String _getNameConfigurationAttribute() 042 { 043 return "id"; 044 } 045 046 @Override 047 public void indexValue(SolrInputDocument document, X ametysObject, CMSDataContext context) 048 { 049 Object value = getValue(ametysObject); 050 if (value == null) 051 { 052 // Nothing to index 053 return; 054 } 055 056 String solrFieldName = getSolrFieldName(); 057 if (solrFieldName == null) 058 { 059 // Nothing to index 060 return; 061 } 062 063 IndexableElementType<T> type = getType(); 064 if (type.getManagedClass().isInstance(value)) 065 { 066 Object valueToIndex = type.getSingleValueToIndex(type.getManagedClass().cast(value)); 067 document.addField(solrFieldName, valueToIndex); 068 } 069 else if (type.getManagedClassArray().isInstance(value)) 070 { 071 T[] values = type.getManagedClassArray().cast(value); 072 for (T singleValue : values) 073 { 074 Object valueToIndex = type.getSingleValueToIndex(singleValue); 075 document.addField(solrFieldName, valueToIndex); 076 } 077 } 078 079 // Index sort field 080 Object sortValue = getSortValue(ametysObject); 081 String solrSortFieldName = getSolrSortFieldName(); 082 if (isSortable() && sortValue != null && solrSortFieldName != null && !solrFieldName.equals(solrSortFieldName)) 083 { 084 document.setField(solrSortFieldName, sortValue); 085 } 086 } 087 088 /** 089 * Get the sort value represented by this field in the given result ametys object. 090 * @param ametysObject the result ametys object. 091 * @return the content sort value, must be scalar (String, long, double, Date). 092 */ 093 protected Object getSortValue(X ametysObject) 094 { 095 Object value = getValue(ametysObject); 096 if (value == null) 097 { 098 return null; 099 } 100 101 IndexableElementType<T> type = getType(); 102 if (type.getManagedClassArray().isInstance(value)) 103 { 104 T[] values = type.getManagedClassArray().cast(value); 105 return values.length > 0 ? values[0] : value; 106 } 107 else 108 { 109 return value; 110 } 111 } 112 113 public Collection<SchemaDefinition> getSchemaDefinitions() 114 { 115 List<SchemaDefinition> definitions = new ArrayList<>(); 116 117 String solrFieldName = getSolrFieldName(); 118 String sortFieldName = getSolrSortFieldName(); 119 String facetFieldName = getSolrFacetFieldName(); 120 121 boolean multiple = isMultiple(); 122 String type = getType().getSchemaType(); 123 if (solrFieldName != null && type != null) 124 { 125 definitions.add(new FieldDefinition(solrFieldName, type, multiple, false)); 126 127 if (sortFieldName != null && !sortFieldName.equals(solrFieldName)) 128 { 129 definitions.add(new FieldDefinition(sortFieldName, type, false, false)); 130 } 131 132 if (facetFieldName != null && !facetFieldName.equals(solrFieldName)) 133 { 134 // By default the index value in field name will be automatically copy in facet field 135 // So we do not need the index facet field manually 136 definitions.add(new FieldDefinition(facetFieldName, type, multiple, true)); 137 definitions.add(new CopyFieldDefinition(solrFieldName, facetFieldName)); 138 } 139 } 140 141 return definitions; 142 } 143 144 /** 145 * Get the value as a array of String 146 * @param value The value as an object to parse 147 * @return The values as a String array 148 */ 149 protected String[] parseStringArray(Object value) 150 { 151 return value instanceof String 152 ? new String[] {(String) value} 153 : (String[]) value; 154 } 155}