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