001/* 002 * Copyright 2022 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.odf.program.properties; 017 018import java.lang.reflect.Array; 019import java.util.Arrays; 020import java.util.List; 021 022import org.apache.avalon.framework.configuration.Configuration; 023import org.apache.avalon.framework.configuration.ConfigurationException; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.commons.lang3.StringUtils; 027 028import org.ametys.cms.contenttype.ContentType; 029import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 030import org.ametys.cms.data.type.ModelItemTypeExtensionPoint; 031import org.ametys.cms.data.type.indexing.IndexableElementType; 032import org.ametys.cms.model.CMSDataContext; 033import org.ametys.cms.model.properties.AbstractProperty; 034import org.ametys.cms.model.properties.Property; 035import org.ametys.cms.repository.Content; 036import org.ametys.cms.search.model.CriterionDefinitionAwareElementDefinition; 037import org.ametys.cms.search.model.CriterionDefinitionHelper; 038import org.ametys.cms.search.model.IndexationAwareElementDefinition; 039import org.ametys.cms.search.model.IndexationAwareElementDefinitionHelper; 040import org.ametys.odf.ODFHelper; 041import org.ametys.odf.program.Program; 042import org.ametys.odf.program.ProgramFactory; 043import org.ametys.odf.program.SubProgram; 044import org.ametys.runtime.model.ModelItem; 045import org.ametys.runtime.model.type.ElementType; 046 047/** 048 * {@link Property} for attribute name of the parent {@link Program} of a {@link SubProgram} 049 */ 050public class SubProgramParentProgramProperty extends AbstractProperty<Object, Content> implements CriterionDefinitionAwareElementDefinition<Object>, IndexationAwareElementDefinition<Object, Content> 051{ 052 /** The ODF Helper */ 053 protected ODFHelper _odfHelper; 054 055 /** The Content Type Extension Point */ 056 protected ContentTypeExtensionPoint _ctypeEP; 057 058 /** The Content Attribute Type Extension Point */ 059 protected ModelItemTypeExtensionPoint _contentAttributeTypeEP; 060 061 /** The criterion definition helper */ 062 protected CriterionDefinitionHelper _criterionDefinitionHelper; 063 064 /** The indexation aware element definition helper */ 065 protected IndexationAwareElementDefinitionHelper _indexationAwareElementDefinitionHelper; 066 067 /** The program attribute name to index for subProgram */ 068 protected String _programAttributeName; 069 070 /** The program attribute type to index for subProgram */ 071 protected String _programAttributeType; 072 073 @Override 074 public void service(ServiceManager manager) throws ServiceException 075 { 076 super.service(manager); 077 _contentAttributeTypeEP = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_CONTENT_ATTRIBUTE); 078 _ctypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 079 _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE); 080 _criterionDefinitionHelper = (CriterionDefinitionHelper) manager.lookup(CriterionDefinitionHelper.ROLE); 081 _indexationAwareElementDefinitionHelper = (IndexationAwareElementDefinitionHelper) manager.lookup(IndexationAwareElementDefinitionHelper.ROLE); 082 } 083 084 @Override 085 public void configure(Configuration configuration) throws ConfigurationException 086 { 087 super.configure(configuration); 088 089 _programAttributeType = configuration.getAttribute("type"); 090 if (StringUtils.isBlank(_programAttributeType)) 091 { 092 throw new ConfigurationException("Attribute 'type' is mandatory for " + SubProgramParentProgramProperty.class.getName()); 093 } 094 095 _programAttributeName = configuration.getChild("program-attribute-name").getValue(); 096 if (StringUtils.isBlank(_programAttributeName)) 097 { 098 throw new ConfigurationException("Child 'program-attribute-name' is mandatory for " + SubProgramParentProgramProperty.class.getName()); 099 } 100 } 101 102 @Override 103 public Object getValue(Content content) 104 { 105 if (content instanceof SubProgram subProgram) 106 { 107 List<Object> values = _odfHelper.getParentPrograms(subProgram) 108 .stream() 109 .map(this::_getValues) 110 .flatMap(List::stream) 111 .toList(); 112 113 ContentType programCType = _ctypeEP.getExtension(ProgramFactory.PROGRAM_CONTENT_TYPE); 114 ModelItem modelItem = programCType.getModelItem(_programAttributeName); 115 ElementType attributeType = (ElementType) _contentAttributeTypeEP.getExtension(modelItem.getType().getId()); 116 117 return !values.isEmpty() ? values.toArray((Object[]) Array.newInstance(attributeType.getManagedClass(), values.size())) : null; 118 } 119 120 return null; 121 } 122 123 private List<Object> _getValues(Program program) 124 { 125 if (program.isMultiple(_programAttributeName)) 126 { 127 Object[] values = program.getValue(_programAttributeName); 128 129 return values != null ? Arrays.asList(values) : List.of(); 130 } 131 else 132 { 133 Object value = program.getValue(_programAttributeName); 134 return value != null ? List.of(value) : List.of(); 135 } 136 } 137 138 @Override 139 public boolean isMultiple() 140 { 141 return true; 142 } 143 144 @Override 145 protected String getTypeId() 146 { 147 return _programAttributeType; 148 } 149 150 public IndexableElementType getDefaultCriterionType() 151 { 152 CMSDataContext context = CMSDataContext.newInstance() 153 .withModelItem(this); 154 155 String typeId = getType().getDefaultCriterionTypeId(context); 156 return _criterionDefinitionHelper.getCriterionDefinitionType(typeId); 157 } 158 159 public String getSolrSortFieldName() 160 { 161 return _indexationAwareElementDefinitionHelper.getDefaultSolrSortFieldName(this); 162 } 163}