001/* 002 * Copyright 2023 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.Collection; 019import java.util.Collections; 020import java.util.Map; 021import java.util.Optional; 022import java.util.Set; 023import java.util.stream.Stream; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.xml.sax.ContentHandler; 028import org.xml.sax.SAXException; 029 030import org.ametys.cms.contenttype.ContentType; 031import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 032import org.ametys.cms.contenttype.ContentTypesHelper; 033import org.ametys.cms.data.ContentValue; 034import org.ametys.cms.data.ametysobject.ModelAwareDataAwareAmetysObject; 035import org.ametys.cms.data.type.ModelItemTypeConstants; 036import org.ametys.cms.model.ContentElementDefinition; 037import org.ametys.cms.repository.ModifiableContent; 038import org.ametys.core.util.XMLUtils; 039import org.ametys.runtime.model.DefinitionContext; 040import org.ametys.runtime.model.ModelItem; 041 042/** 043 * Abstract class for content property 044 * @param <X> type of ametys object supported by this property 045 */ 046public abstract class AbstractContentProperty<X extends ModelAwareDataAwareAmetysObject> extends AbstractProperty<ContentValue, X> implements ContentElementDefinition 047{ 048 private ContentTypeExtensionPoint _contentTypeExtensionPoint; 049 private ContentTypesHelper _contentTypesHelper; 050 051 @Override 052 public void service(ServiceManager manager) throws ServiceException 053 { 054 super.service(manager); 055 _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 056 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 057 } 058 059 @Override 060 protected String getTypeId() 061 { 062 return ModelItemTypeConstants.CONTENT_ELEMENT_TYPE_ID; 063 } 064 065 public void setContentTypeId(String contentTypeId) 066 { 067 throw new UnsupportedOperationException("Setting the content type is not supported on " + getClass() + ", it is defined by the property itself."); 068 } 069 070 public Collection< ? extends ModelItem> getModelItems() 071 { 072 if (_contentTypeExtensionPoint.hasExtension(getContentTypeId())) 073 { 074 ContentType contentType = _contentTypeExtensionPoint.getExtension(getContentTypeId()); 075 return contentType.getModelItems(); 076 } 077 else 078 { 079 return Collections.singleton(_contentTypesHelper.getTitleAttributeDefinition()); 080 } 081 } 082 083 @Override 084 protected Map<String, Object> _toJSON(DefinitionContext context) 085 { 086 Map<String, Object> result = super._toJSON(context); 087 result.put("contentType", getContentTypeId()); 088 return result; 089 } 090 091 @Override 092 public void toSAX(ContentHandler contentHandler, DefinitionContext context) throws SAXException 093 { 094 super.toSAX(contentHandler, context); 095 XMLUtils.createElementIfNotNull(contentHandler, "contentType", getContentTypeId()); 096 } 097 098 @Override 099 public Object getValue(X dataHolder) 100 { 101 Set<? extends ModifiableContent> contents = _getLinkedContents(dataHolder); 102 103 return isMultiple() 104 ? _transformToContentValueArray(contents) 105 : Optional.ofNullable(contents) 106 .map(Set::stream) 107 .orElseGet(Stream::empty) 108 .findFirst() 109 .map(ContentValue::new) 110 .orElse(null); 111 } 112 113 /** 114 * Get the linked contents to index. 115 * @param dataHolder The data holder 116 * @return The linked contents 117 */ 118 protected abstract Set<? extends ModifiableContent> _getLinkedContents(X dataHolder); 119 120 private ContentValue[] _transformToContentValueArray(Set<? extends ModifiableContent> contents) 121 { 122 if (contents == null) 123 { 124 return null; 125 } 126 127 return contents.stream() 128 .map(ContentValue::new) 129 .toArray(ContentValue[]::new); 130 } 131}