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.systemprop;
017
018import java.util.Collection;
019import java.util.LinkedHashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.configuration.Configuration;
024import org.apache.avalon.framework.configuration.ConfigurationException;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.solr.common.SolrInputDocument;
028
029import org.ametys.cms.content.indexing.solr.SolrFieldNames;
030import org.ametys.cms.data.type.indexing.IndexableElementType;
031import org.ametys.cms.model.CMSDataContext;
032import org.ametys.cms.repository.Content;
033import org.ametys.cms.repository.comment.Comment;
034import org.ametys.cms.repository.comment.CommentableContent;
035import org.ametys.cms.search.model.CriterionDefinitionAwareElementDefinition;
036import org.ametys.cms.search.model.CriterionDefinitionHelper;
037import org.ametys.cms.search.model.SystemProperty;
038import org.ametys.cms.search.query.CommentQuery;
039import org.ametys.cms.search.query.CommentQuery.CommentInclusion;
040import org.ametys.cms.search.query.Query;
041import org.ametys.cms.search.query.Query.Operator;
042import org.ametys.cms.search.solr.schema.FieldDefinition;
043import org.ametys.cms.search.solr.schema.SchemaDefinition;
044import org.ametys.runtime.i18n.I18nizableText;
045import org.ametys.runtime.model.Enumerator;
046import org.ametys.runtime.model.StaticEnumerator;
047import org.ametys.runtime.model.type.DataContext;
048import org.ametys.runtime.model.type.ModelItemTypeConstants;
049import org.ametys.runtime.plugin.component.ThreadSafeComponentManager;
050
051/**
052 * {@link SystemProperty} which represents the comments of a content.
053 */
054public class CommentsSystemProperty extends AbstractSystemProperty<Boolean, Content> implements CriterionDefinitionAwareElementDefinition<Boolean>, IndexationAwareSystemProperty<Boolean, Content>
055{
056    /** System property identifier */
057    public static final String SYSTEM_PROPERTY_ID = "comments";
058    
059    /** Solr field name. */
060    public static final String SOLR_FIELD_NAME = SYSTEM_PROPERTY_ID;
061    
062    /** The criterion definition helper */
063    protected CriterionDefinitionHelper _criterionDefinitionHelper;
064    
065    @Override
066    public void service(ServiceManager manager) throws ServiceException
067    {
068        super.service(manager);
069        _criterionDefinitionHelper = (CriterionDefinitionHelper) manager.lookup(CriterionDefinitionHelper.ROLE);
070    }
071    
072    @Override
073    public Query getQuery(Object value, Operator operator, String language, Map<String, Object> contextualParameters)
074    {
075        if ("with-comments".equals(value))
076        {
077            return new CommentQuery(CommentInclusion.VALIDATED_AND_NON_VALIDATED, operator);
078        }
079        else if ("with-validated-comments".equals(value))
080        {
081            return new CommentQuery(CommentInclusion.VALIDATED, operator);
082        }
083        else // if ("with-nonvalidated-comments".equals(value))
084        {
085            return new CommentQuery(CommentInclusion.NON_VALIDATED, operator);
086        }
087    }
088    
089    @Override
090    public IndexableElementType getDefaultCriterionType()
091    {
092        return _criterionDefinitionHelper.getCriterionDefinitionType(ModelItemTypeConstants.STRING_TYPE_ID);
093    }
094    
095    @Override
096    public String getRenderer()
097    {
098        return "Ametys.grid.GridColumnHelper.renderBooleanIcon";
099    }
100    
101    @Override
102    public Integer getColumnWidth()
103    {
104        return 40;
105    }
106    
107    public String getSolrFieldName()
108    {
109        return SOLR_FIELD_NAME;
110    }
111    
112    public String getSolrSortFieldName()
113    {
114        return SOLR_FIELD_NAME;
115    }
116    
117    public String getSolrFacetFieldName()
118    {
119        // FIXME use the default implementation;
120        // This leads to Solr error during indexation : is field 'comments_dv' is already declared by someone else ?
121        return null;
122    }
123    
124    @Override
125    public Collection<SchemaDefinition> getSchemaDefinitions()
126    {
127        Collection<SchemaDefinition> definitions = IndexationAwareSystemProperty.super.getSchemaDefinitions();
128        
129        definitions.add(new FieldDefinition(SolrFieldNames.CONTENT_COMMENTS_VALIDATED, "boolean", false, false));
130        definitions.add(new FieldDefinition(SolrFieldNames.CONTENT_COMMENTS_NONVALIDATED, "boolean", false, false));
131        
132        return definitions;
133    }
134    
135    @Override
136    public void indexValue(SolrInputDocument document, Content content, CMSDataContext context)
137    {
138        IndexationAwareSystemProperty.super.indexValue(document, content, context);
139        
140        boolean hasComment = (boolean) getValue(content);
141        if (hasComment)
142        {
143            List<Comment> comments = ((CommentableContent) content).getComments(true, true);
144            document.addField(SolrFieldNames.CONTENT_COMMENTS_VALIDATED, comments.stream().anyMatch(c -> c.isValidated()));
145            document.addField(SolrFieldNames.CONTENT_COMMENTS_NONVALIDATED, comments.stream().anyMatch(c -> !c.isValidated()));
146        }
147    }
148    
149    @Override
150    public Object getValue(Content content)
151    {
152        if (content instanceof CommentableContent commentableContent)
153        {
154            List<Comment> comments = commentableContent.getComments(true, true);
155            return Boolean.valueOf(!comments.isEmpty());
156        }
157        
158        return Boolean.valueOf(false);
159    }
160    
161    @Override
162    public Object valueToJSON(Content content, DataContext context)
163    {
164        // FIXME pourquoi ne pas retourner getRawValue directement ?
165        Map<String, Object> infos = new LinkedHashMap<>();
166        infos.put("comments", getValue(content));
167        return infos;
168    }
169    
170    @Override
171    public Enumerator<String> getDefaultCriterionEnumerator(Configuration configuration, ThreadSafeComponentManager<Enumerator> enumeratorManager) throws ConfigurationException
172    {
173        StaticEnumerator<String> enumerator = new StaticEnumerator<>();
174        enumerator.add(new I18nizableText("plugin.cms", "PLUGINS_CMS_CONTENT_COMMENTS_SEARCH_ALL"), "with-comments");
175        enumerator.add(new I18nizableText("plugin.cms", "PLUGINS_CMS_CONTENT_COMMENTS_SEARCH_VALIDATED"), "with-validated-comments");
176        enumerator.add(new I18nizableText("plugin.cms", "PLUGINS_CMS_CONTENT_COMMENTS_SEARCH_NOTVALIDATED"), "with-nonvalidated-comments");
177        return enumerator;
178    }
179    
180    @Override
181    protected String getTypeId()
182    {
183        return ModelItemTypeConstants.BOOLEAN_TYPE_ID;
184    }
185}