001/* 002 * Copyright 2024 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.model.properties; 017 018import java.util.Optional; 019 020import org.apache.avalon.framework.configuration.Configuration; 021import org.apache.avalon.framework.configuration.ConfigurationException; 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024 025import org.ametys.cms.data.ametysobject.ModelAwareDataAwareAmetysObject; 026import org.ametys.cms.data.type.indexing.IndexableElementType; 027import org.ametys.cms.model.CMSDataContext; 028import org.ametys.cms.search.model.CriterionDefinitionAwareElementDefinition; 029import org.ametys.cms.search.model.CriterionDefinitionHelper; 030import org.ametys.cms.search.model.IndexationAwareElementDefinition; 031import org.ametys.cms.search.model.IndexationAwareElementDefinitionHelper; 032import org.ametys.runtime.i18n.I18nizableText; 033import org.ametys.runtime.model.ElementDefinition; 034import org.ametys.runtime.model.ItemParserHelper; 035import org.ametys.runtime.model.ItemParserHelper.ConfigurationAndPluginName; 036import org.ametys.runtime.model.Model; 037 038/** 039 * Abstract implementation for a property referencing {@link ElementDefinition}s 040 * @param <T> Type of the property values 041 * @param <X> Type of ametys object supported by this property 042 */ 043public abstract class AbstractElementsReferencingProperty<T, X extends ModelAwareDataAwareAmetysObject> extends AbstractProperty<T, X> implements ReferencingProperty<T, X>, CriterionDefinitionAwareElementDefinition<T>, IndexationAwareElementDefinition<T, X> 044{ 045 /** The criterion definition helper */ 046 protected CriterionDefinitionHelper _criterionDefinitionHelper; 047 /** The indexation aware element definition helper */ 048 protected IndexationAwareElementDefinitionHelper _indexationAwareElementDefinitionHelper; 049 050 @Override 051 public void service(ServiceManager manager) throws ServiceException 052 { 053 super.service(manager); 054 _criterionDefinitionHelper = (CriterionDefinitionHelper) manager.lookup(CriterionDefinitionHelper.ROLE); 055 _indexationAwareElementDefinitionHelper = (IndexationAwareElementDefinitionHelper) manager.lookup(IndexationAwareElementDefinitionHelper.ROLE); 056 } 057 058 @Override 059 public void configure(Configuration configuration) throws ConfigurationException 060 { 061 super.configure(configuration); 062 configureReferences(configuration); 063 } 064 065 @Override 066 protected I18nizableText _parseLabel(Configuration configuration) throws ConfigurationException 067 { 068 // Do not use name as default value, to use the referenced element's one if the the concerned text is not filled 069 return ItemParserHelper.parseI18nizableText(new ConfigurationAndPluginName(configuration, getPluginName()), "label", (I18nizableText) null); 070 } 071 072 @Override 073 protected I18nizableText _parseDescription(Configuration configuration) throws ConfigurationException 074 { 075 // Do not use empty string as default value, to use the referenced element's one if the the concerned text is not filled 076 return ItemParserHelper.parseI18nizableText(new ConfigurationAndPluginName(configuration, getPluginName()), "description", (I18nizableText) null); 077 } 078 079 /** 080 * Configures the references 081 * @param configuration the property configuration 082 * @throws ConfigurationException if an error occurred 083 */ 084 protected abstract void configureReferences(Configuration configuration) throws ConfigurationException; 085 086 public void initializeAfterModelItemsInitialization() throws Exception 087 { 088 for (String reference : getReferences()) 089 { 090 Model model = getModel(); 091 if (!model.hasModelItem(reference) || !(model.getModelItem(reference) instanceof ElementDefinition)) 092 { 093 throw new ConfigurationException("'" + reference + "' is invalid for property '" + getName() + "' in model '" + model.getId() + "'. The referenced item has not been found or is a group."); 094 } 095 } 096 } 097 098 /** 099 * Retrieves the definition of the given referenced element 100 * @param reference the reference 101 * @return the referenced element's definition 102 */ 103 @SuppressWarnings("unchecked") 104 protected ElementDefinition<T> _getReferenceDefinition(String reference) 105 { 106 return (ElementDefinition<T>) getModel().getModelItem(reference); 107 } 108 109 @Override 110 public String getName() 111 { 112 return Optional.ofNullable(super.getName()) 113 // If no name has been configured, use the first referenced element's one 114 .orElseGet(() -> this._getFirstReferenceDefinition().getName()); 115 } 116 117 @Override 118 public I18nizableText getLabel() 119 { 120 return Optional.ofNullable(super.getLabel()) 121 // If no label has been configured, use the first referenced element's one 122 .orElseGet(() -> this._getFirstReferenceDefinition().getLabel()); 123 } 124 125 @Override 126 public I18nizableText getDescription() 127 { 128 return Optional.ofNullable(super.getDescription()) 129 // If no description has been configured, use the first referenced element's one 130 .orElseGet(() -> this._getFirstReferenceDefinition().getDescription()); 131 } 132 133 private String _getFirstReference() 134 { 135 return getReferences().get(0); 136 } 137 138 private ElementDefinition<T> _getFirstReferenceDefinition() 139 { 140 return _getReferenceDefinition(_getFirstReference()); 141 } 142 143 public IndexableElementType getDefaultCriterionType() 144 { 145 CMSDataContext context = CMSDataContext.newInstance() 146 .withModelItem(this); 147 148 String typeId = getType().getDefaultCriterionTypeId(context); 149 return _criterionDefinitionHelper.getCriterionDefinitionType(typeId); 150 } 151 152 public String getSolrSortFieldName() 153 { 154 return _indexationAwareElementDefinitionHelper.getDefaultSolrSortFieldName(this); 155 } 156}