001/* 002 * Copyright 2016 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.plugins.contentio.synchronize.systemprop; 017 018import java.util.Map; 019import java.util.Optional; 020import java.util.stream.Stream; 021 022import org.apache.cocoon.xml.AttributesImpl; 023import org.apache.cocoon.xml.XMLUtils; 024import org.xml.sax.ContentHandler; 025import org.xml.sax.SAXException; 026 027import org.ametys.cms.repository.Content; 028import org.ametys.cms.search.model.SystemProperty; 029import org.ametys.cms.search.query.Query; 030import org.ametys.cms.search.query.Query.Operator; 031import org.ametys.cms.search.systemprop.AbstractIndexableSystemProperty; 032import org.ametys.core.util.LambdaUtils; 033import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollection; 034import org.ametys.plugins.contentio.synchronize.search.query.CollectionsQuery; 035import org.ametys.runtime.i18n.I18nizableText; 036import org.ametys.runtime.model.type.DataContext; 037import org.ametys.runtime.model.type.ModelItemTypeConstants; 038 039/** 040 * {@link SystemProperty} which represents the synchronizable contents collections of a content. 041 */ 042public class CollectionsSystemProperty extends AbstractIndexableSystemProperty<String, String, Content> 043{ 044 /** Solr field name. */ 045 public static final String SOLR_FIELD_NAME = "scc"; 046 047 @Override 048 public Query getQuery(Object value, Operator operator, String language, Map<String, Object> contextualParameters) 049 { 050 String[] synchronizableContentsCollectionIds = parseStringArray(value); 051 Operator allowedOperator = _allowedOperator(operator); 052 return new CollectionsQuery(allowedOperator, synchronizableContentsCollectionIds); 053 } 054 055 // Just to avoid an exception if a not-allowed operator is passed (for instance, SEARCH, etc.) 056 // The problem is that currently, we cannot restrain the proposed operator to the UI, 057 // and the operator for STRING type are plentiful, whereas CollectionsQuery only supports EQ and NE 058 private Operator _allowedOperator(Operator requestedOperator) 059 { 060 return requestedOperator == Operator.NE 061 ? requestedOperator 062 : Operator.EQ; 063 } 064 065 @Override 066 public String getSolrFieldName() 067 { 068 return SOLR_FIELD_NAME; 069 } 070 071 @Override 072 public String getSolrSortFieldName() 073 { 074 return SOLR_FIELD_NAME; 075 } 076 077 @Override 078 public String getSolrFacetFieldName() 079 { 080 return SOLR_FIELD_NAME + "_dv"; 081 } 082 083 @Override 084 public Object getValue(Content content) 085 { 086 return content.getInternalDataHolder() 087 .getValue(SynchronizableContentsCollection.COLLECTION_ID_DATA_NAME, new String[0]); 088 } 089 090 public Object valueToJSON(Content content, DataContext context) 091 { 092 return Stream.of((String[]) getValue(content)) 093 .map(sccId -> Map.of( 094 "value", sccId, 095 "label", _getLabel(sccId) 096 )) 097 .toList(); 098 } 099 100 public void valueToSAX(ContentHandler contentHandler, Content content, DataContext context) throws SAXException 101 { 102 String[] sccIds = (String[]) getValue(content); 103 for (String sccId : sccIds) 104 { 105 AttributesImpl attrs = new AttributesImpl(); 106 attrs.addCDATAAttribute("value", sccId); 107 XMLUtils.startElement(contentHandler, "scc", attrs); 108 _getLabel(sccId).toSAX(contentHandler); 109 XMLUtils.endElement(contentHandler, "scc"); 110 } 111 } 112 113 private I18nizableText _getLabel(String sccId) 114 { 115 return Optional.of(sccId) 116 // Exception should not happen because the CollectionEnumerator does not return any exception 117 .map(LambdaUtils.wrap(getEnumerator()::getEntry)) 118 // Return the ID it self it no entry 119 .orElseGet(() -> new I18nizableText(sccId)); 120 } 121 122 @Override 123 protected String getTypeId() 124 { 125 return ModelItemTypeConstants.STRING_TYPE_ID; 126 } 127}