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