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.model;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.HashMap;
021import java.util.HashSet;
022import java.util.List;
023import java.util.Map;
024import java.util.Set;
025
026import org.ametys.cms.search.ui.model.SearchUIColumn;
027import org.ametys.runtime.model.DefinitionContext;
028import org.ametys.runtime.model.View;
029import org.ametys.runtime.model.ViewHelper;
030import org.ametys.runtime.model.ViewItem;
031import org.ametys.runtime.model.ViewItemAccessor;
032import org.ametys.runtime.model.ViewItemContainer;
033
034/**
035 * Default implementation of a {@link SearchModel}.
036 */
037public class DefaultSearchModel implements SearchModel
038{
039    /** The content types of this search model. */
040    private Set<String> _contentTypes = new HashSet<>();
041    /** The content types excluded from this search model. */
042    private Set<String> _excludedContentTypes = new HashSet<>();
043    
044    /** The simple criteria */
045    private ViewItemContainer _criteria = new View();
046    /** The faceted criteria */
047    private ViewItemContainer _facetedCriteria = new View();
048    /** The result items */
049    private ViewItemContainer _resultItems = new View();
050    /** the workspace */
051    private String _workspace;
052    
053    /**
054     * Default constructor.
055     */
056    public DefaultSearchModel()
057    {
058        // Do nothing
059    }
060    
061    /**
062     * Constructor by copying an existing {@link SearchModel}.
063     * @param searchModelToCopy The {@link SearchModel} to copy
064     * @param contextualParameters The contextual parameters
065     */
066    public DefaultSearchModel(SearchModel searchModelToCopy, Map<String, Object> contextualParameters)
067    {
068        setContentTypes(new HashSet<>(searchModelToCopy.getContentTypes(contextualParameters)));
069        setExcludedContentTypes(new HashSet<>(searchModelToCopy.getExcludedContentTypes(contextualParameters)));
070        
071        View criteria = new View();
072        ViewItemContainer criteriaToCopy = searchModelToCopy.getCriteria(contextualParameters);
073        List<ViewItem> criteriaViewItems = ViewHelper.copyViewItems(criteriaToCopy.getViewItems());
074        criteria.addViewItems(criteriaViewItems);
075        setCriteria(criteria);
076        
077        View facetedCriteria = new View();
078        ViewItemContainer facetedCriteriaToCopy = searchModelToCopy.getFacetedCriteria(contextualParameters);
079        List<ViewItem> facetedCriteriaViewItems = ViewHelper.copyViewItems(facetedCriteriaToCopy.getViewItems());
080        facetedCriteria.addViewItems(facetedCriteriaViewItems);
081        setFacetedCriteria(facetedCriteria);
082        
083        View resultItems = new View();
084        ViewItemContainer resultItemsToCopy = searchModelToCopy.getResultItems(contextualParameters);
085        List<ViewItem> resultViewItems = ViewHelper.copyViewItems(resultItemsToCopy.getViewItems());
086        resultItems.addViewItems(resultViewItems);
087        setResultItems(resultItems);
088        
089        setWorkspace(searchModelToCopy.getWorkspace(contextualParameters));
090    }
091    
092    public Set<String> getContentTypes(Map<String, Object> contextualParameters)
093    {
094        return Collections.unmodifiableSet(_contentTypes);
095    }
096    
097    /**
098     * Set the content types of the models
099     * @param cTypes The content types.
100     */
101    public void setContentTypes(Set<String> cTypes)
102    {
103        _contentTypes = new HashSet<>(cTypes);
104    }
105    
106    public Set<String> getExcludedContentTypes(Map<String, Object> contextualParameters)
107    {
108        return Collections.unmodifiableSet(_excludedContentTypes);
109    }
110    
111    /**
112     * Set the content types to exclude
113     * @param cTypes The content types to exclude
114     */
115    public void setExcludedContentTypes(Set<String> cTypes)
116    {
117        _excludedContentTypes = new HashSet<>(cTypes);
118    }
119    
120    public ViewItemContainer getCriteria(Map<String, Object> contextualParameters)
121    {
122        return _criteria;
123    }
124    
125    /**
126     * Add criteria to the simple criteria. The created criteria reference the given paths 
127     * @param criterionDefinitionHelper the criterion definition helper
128     * @param contextualParameters the contextual parameters
129     * @param references the paths to the items the criteria will reference 
130     */
131    public void addCriteria(SearchModelCriterionDefinitionHelper criterionDefinitionHelper, Map<String, Object> contextualParameters, String... references)
132    {
133        for (String reference : references)
134        {
135            SearchModelCriterionDefinition criterion = criterionDefinitionHelper.createReferencingCriterionDefinition(this, reference, getContentTypes(contextualParameters));
136            addCriterion(criterion, contextualParameters);
137        }
138    }
139    
140    /**
141     * Set the criteria
142     * @param criteria The criteria to set
143     */
144    public void setCriteria(ViewItemContainer criteria)
145    {
146        _criteria = criteria;
147    }
148    
149    public ViewItemContainer getFacetedCriteria(Map<String, Object> contextualParameters)
150    {
151        return _facetedCriteria;
152    }
153    
154    /**
155     * Add criteria to the faceted criteria. The created criteria reference the given paths 
156     * @param criterionDefinitionHelper the criterion definition helper
157     * @param contextualParameters the contextual parameters
158     * @param references the paths to the items the criteria will reference 
159     */
160    public void addFacetedCriteria(SearchModelCriterionDefinitionHelper criterionDefinitionHelper, Map<String, Object> contextualParameters, String... references)
161    {
162        for (String reference : references)
163        {
164            SearchModelCriterionDefinition criterion = criterionDefinitionHelper.createReferencingCriterionDefinition(this, reference, getContentTypes(contextualParameters));
165            addFacetedCriterion(criterion, contextualParameters);
166        }
167    }
168
169    /**
170     * Set the faceted criteria
171     * @param criteria The faceted criteria to set
172     */
173    public void setFacetedCriteria(ViewItemContainer criteria)
174    {
175        _facetedCriteria = criteria;
176    }
177    
178    public ViewItemContainer getResultItems(Map<String, Object> contextualParameters)
179    {
180        return _resultItems;
181    }
182    
183    /**
184     * Set the result items
185     * @param resultItems The result items to set
186     */
187    public void setResultItems(ViewItemContainer resultItems)
188    {
189        _resultItems = resultItems;
190    }
191    
192    public String getWorkspace(Map<String, Object> contextualParameters)
193    {
194        return _workspace;
195    }
196    
197    /**
198     * Set the workspace
199     * @param workspace The workspace to set
200     */
201    public void setWorkspace(String workspace)
202    {
203        _workspace = workspace;
204    }
205    
206    public Map<String, Object> toJSON(Map<String, Object> contextualParameters)
207    {
208        Map<String, Object> jsonObject = new HashMap<>();
209        
210        jsonObject.put("workspace", getWorkspace(contextualParameters));
211        
212        ViewItemContainer criteria = getCriteria(contextualParameters);
213        Map<String, Object> criteriaToJSON = ViewHelper.viewItemsToJSON(criteria.getViewItems(), DefinitionContext.newInstance());
214        jsonObject.put("simple-criteria", criteriaToJSON);
215        
216        jsonObject.put("columns", resultItemsToJSON(contextualParameters));
217        jsonObject.put("hasFacets", !getFacetedCriteria(contextualParameters).getViewItems().isEmpty());
218        
219        return jsonObject;
220    }
221    
222    public List<Object> resultItemsToJSON(Map<String, Object> contextualParameters)
223    {
224        ViewItemContainer resultItems = getResultItems(contextualParameters);
225        return _resultItemsToJSON(resultItems);
226    }
227    
228    /**
229     * Converts the search model's result items on a JSON map
230     * @param viewItemAccessor The result items
231     * @return the result items as a JSON map
232     */
233    protected List<Object> _resultItemsToJSON(ViewItemAccessor viewItemAccessor)
234    {
235        List<Object> jsonObject = new ArrayList<>();
236        
237        for (ViewItem viewItem : viewItemAccessor.getViewItems())
238        {
239            if (viewItem instanceof SearchUIColumn searchUIColumn)
240            {
241                jsonObject.add(searchUIColumn.toJSON(DefinitionContext.newInstance()));
242            }
243            else if (viewItem instanceof ViewItemAccessor itemAccessor)
244            {
245                jsonObject.addAll(_resultItemsToJSON(itemAccessor));
246            }
247        }
248        
249        return jsonObject;
250    }
251}