001/* 002 * Copyright 2015 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.cocoon; 017 018import java.io.IOException; 019import java.util.Collections; 020import java.util.List; 021import java.util.Map; 022import java.util.Optional; 023import java.util.Set; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.cocoon.ProcessingException; 028import org.apache.cocoon.generation.ServiceableGenerator; 029import org.apache.cocoon.xml.AttributesImpl; 030import org.apache.cocoon.xml.XMLUtils; 031import org.xml.sax.SAXException; 032 033import org.ametys.cms.contenttype.ContentTypesHelper; 034import org.ametys.cms.search.model.SearchModel; 035import org.ametys.cms.search.solr.SolrContentQueryHelper; 036import org.ametys.cms.search.ui.model.ColumnHelper; 037import org.ametys.cms.search.ui.model.ColumnHelper.Column; 038import org.ametys.cms.search.ui.model.SearchUIModelExtensionPoint; 039import org.ametys.core.util.ServerCommHelper; 040import org.ametys.runtime.i18n.I18nizableText; 041import org.ametys.runtime.model.ModelViewItem; 042import org.ametys.runtime.model.ViewHelper; 043import org.ametys.runtime.model.ViewItem; 044import org.ametys.runtime.model.ViewItemAccessor; 045import org.ametys.runtime.model.ViewItemContainer; 046 047/** 048 * SAX the columns of a search tool model. 049 */ 050public class ModelColumnsGenerator extends ServiceableGenerator 051{ 052 /** The extenstion point for search UI */ 053 protected SearchUIModelExtensionPoint _searchModelManager; 054 /** The servercomm helper */ 055 protected ServerCommHelper _serverCommHelper; 056 /** The content type helper. */ 057 protected ContentTypesHelper _cTypeHelper; 058 /** The helper for columns */ 059 protected ColumnHelper _columnHelper; 060 061 @Override 062 public void service(ServiceManager smanager) throws ServiceException 063 { 064 super.service(smanager); 065 _searchModelManager = (SearchUIModelExtensionPoint) smanager.lookup(SearchUIModelExtensionPoint.ROLE); 066 _serverCommHelper = (ServerCommHelper) manager.lookup(ServerCommHelper.ROLE); 067 _cTypeHelper = (ContentTypesHelper) smanager.lookup(ContentTypesHelper.ROLE); 068 _columnHelper = (ColumnHelper) smanager.lookup(ColumnHelper.ROLE); 069 } 070 071 @Override 072 public void generate() throws IOException, SAXException, ProcessingException 073 { 074 Map<String, Object> jsParameters = _serverCommHelper.getJsParameters(); 075 076 contentHandler.startDocument(); 077 saxColumns(jsParameters); 078 contentHandler.endDocument(); 079 } 080 081 /** 082 * Get search model. 083 * @param jsParameters JS parameters 084 * @return the search model 085 */ 086 protected SearchModel getSearchModel(Map<String, Object> jsParameters) 087 { 088 String modelId = (String) jsParameters.get("model"); 089 return _searchModelManager.getExtension(modelId); 090 } 091 092 /** 093 * Sax search columns. 094 * @param jsParameters JS parameters 095 * @throws SAXException if an error occurs 096 */ 097 protected void saxColumns(Map<String, Object> jsParameters) throws SAXException 098 { 099 @SuppressWarnings("unchecked") 100 Map<String, Object> contextualParameters = (Map<String, Object>) jsParameters.get("contextualParameters"); 101 102 SearchModel model = getSearchModel(jsParameters); 103 List<Column> columns = _getColumns(model, jsParameters, contextualParameters); 104 ViewItemContainer resultItems = model.getResultItems(contextualParameters); 105 106 XMLUtils.startElement(contentHandler, "columns"); 107 _saxColumns(resultItems, columns); 108 XMLUtils.endElement(contentHandler, "columns"); 109 } 110 111 private List<Column> _getColumns(SearchModel model, Map<String, Object> jsParameters, Map<String, Object> contextualParameters) 112 { 113 Set<String> cTypes; 114 if ("search-ui.solr".equals(jsParameters.get("model"))) 115 { 116 cTypes = SolrContentQueryHelper.getContentTypes(jsParameters); 117 } 118 else 119 { 120 cTypes = model.getContentTypes(contextualParameters); 121 } 122 Set<String> cTypeIds = _cTypeHelper.getCommonAncestors(cTypes); 123 List<Column> columns = getColumnsFromParameters(jsParameters, cTypeIds); 124 return columns; 125 } 126 127 private void _saxColumns(ViewItemAccessor viewItemAccessor, List<Column> columns) throws SAXException 128 { 129 for (ViewItem viewItem : viewItemAccessor.getViewItems()) 130 { 131 if (viewItem instanceof ViewItemAccessor itemAccessor && !itemAccessor.getViewItems().isEmpty()) 132 { 133 _saxColumns(itemAccessor, columns); 134 } 135 else if (viewItem instanceof ModelViewItem modelViewItem) 136 { 137 String modelViewItemPath = ViewHelper.getModelViewItemPath(modelViewItem); 138 Optional<Column> column = columns.stream() 139 .filter(c -> c.getId().equals(modelViewItemPath)) 140 .findFirst(); 141 142 if (columns.isEmpty() || column.isPresent()) 143 { 144 AttributesImpl attrs = new AttributesImpl(); 145 attrs.addCDATAAttribute("id", ViewHelper.getModelViewItemPath(modelViewItem)); 146 attrs.addCDATAAttribute("type", modelViewItem.getDefinition().getType().getId()); 147 148 XMLUtils.startElement(contentHandler, "column", attrs); 149 150 column.flatMap(Column::getLabel) 151 .map(I18nizableText::new) 152 .orElseGet(modelViewItem::getLabel) 153 .toSAX(contentHandler); 154 155 XMLUtils.endElement(contentHandler, "column"); 156 } 157 } 158 } 159 } 160 161 /** 162 * Get the columns from JS parameters 163 * @param jsParameters The JS parameters 164 * @param contentTypes The content type 165 * @return the requested columns 166 */ 167 @SuppressWarnings("unchecked") 168 protected List<Column> getColumnsFromParameters(Map<String, Object> jsParameters, Set<String> contentTypes) 169 { 170 Map<String, Object> values = (Map<String, Object>) jsParameters.get("values"); 171 172 if (values != null && values.containsKey("columns")) 173 { 174 Object columnsAsObj = values.get("columns"); 175 if (columnsAsObj instanceof String) 176 { 177 return _columnHelper.getColumns((String) columnsAsObj, contentTypes); 178 } 179 else 180 { 181 return _columnHelper.getColumns((List<String>) columnsAsObj, contentTypes); 182 } 183 } 184 return Collections.EMPTY_LIST; 185 } 186}