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.LinkedHashMap;
019import java.util.Map;
020import java.util.Optional;
021
022import org.apache.avalon.framework.configuration.Configuration;
023import org.apache.avalon.framework.configuration.ConfigurationException;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.xml.AttributesImpl;
027import org.apache.cocoon.xml.XMLUtils;
028import org.xml.sax.ContentHandler;
029import org.xml.sax.SAXException;
030
031import org.ametys.cms.languages.Language;
032import org.ametys.cms.languages.LanguageEnumerator;
033import org.ametys.cms.languages.LanguagesManager;
034import org.ametys.cms.repository.Content;
035import org.ametys.cms.search.model.SystemProperty;
036import org.ametys.cms.search.query.ContentLanguageQuery;
037import org.ametys.cms.search.query.Query;
038import org.ametys.cms.search.query.Query.Operator;
039import org.ametys.core.model.type.ModelItemTypeHelper;
040import org.ametys.core.util.I18nUtils;
041import org.ametys.runtime.model.Enumerator;
042import org.ametys.runtime.model.type.DataContext;
043import org.ametys.runtime.model.type.ModelItemTypeConstants;
044import org.ametys.runtime.plugin.component.ThreadSafeComponentManager;
045
046/**
047 * {@link SystemProperty} which represents the language of a Content.
048 */
049public class LanguageSystemProperty extends AbstractIndexableSystemProperty<String, String, Content>
050{
051    /** Solr field name. */
052    public static final String SOLR_FIELD_NAME = "contentLanguage";
053    
054    /** The language manager. */
055    protected LanguagesManager _languageManager;
056    
057    /** The i18n utils. */
058    protected I18nUtils _i18nUtils;
059    
060    @Override
061    public void service(ServiceManager manager) throws ServiceException
062    {
063        super.service(manager);
064        _languageManager = (LanguagesManager) manager.lookup(LanguagesManager.ROLE);
065        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
066    }
067    
068    @Override
069    public Query getQuery(Object value, Operator operator, String language, Map<String, Object> contextualParameters)
070    {
071        if (_criterionDefinitionHelper.isQueryValueEmpty(value))
072        {
073            return new ContentLanguageQuery();
074        }
075        else if (value instanceof String[] values)
076        {
077            return new ContentLanguageQuery(operator, values);
078        }
079        else
080        {
081            String langValue = "CURRENT".equals(value) ? language : (String) value;
082            return new ContentLanguageQuery(operator, langValue);
083        }
084    }
085    
086    @Override
087    public String getRenderer()
088    {
089        return "Ametys.plugins.cms.search.SearchGridHelper.renderLanguage";
090    }
091    
092    @Override
093    public String getConverter()
094    {
095        return "Ametys.plugins.cms.search.SearchGridHelper.convertLanguage";
096    }
097    
098    @Override
099    public Integer getColumnWidth()
100    {
101        return 70;
102    }
103    
104    @Override
105    public String getSolrFieldName()
106    {
107        return SOLR_FIELD_NAME;
108    }
109    
110    @Override
111    public String getSolrSortFieldName()
112    {
113        return SOLR_FIELD_NAME + "_sort";
114    }
115    
116    @Override
117    public String getSolrFacetFieldName()
118    {
119        return SOLR_FIELD_NAME + "_dv";
120    }
121    
122    @Override
123    public Object getValue(Content content)
124    {
125        return content.getLanguage();
126    }
127    
128    public Object valueToJSON(Content content, DataContext context)
129    {
130        String languageCode = (String) getValue(content);
131        Map<String, Object> infos = new LinkedHashMap<>();
132        
133        infos.put("code", languageCode);
134        
135        if (languageCode != null)
136        {
137            Language language = _languageManager.getLanguage(languageCode);
138            if (language != null)
139            {
140                infos.put("icon", language.getSmallIcon());
141                infos.put("label", language.getLabel());
142            }
143        }
144        
145        return infos;
146    }
147    
148    public void valueToSAX(ContentHandler contentHandler, Content content, DataContext context) throws SAXException
149    {
150        Language language = Optional.of(content)
151                .map(this::getValue)
152                .map(String.class::cast)
153                .map(_languageManager::getLanguage)
154                .orElse(null);
155        
156        if (language != null)
157        {
158            AttributesImpl attr = ModelItemTypeHelper.getXMLAttributesFromDataContext(context);
159            attr.addCDATAAttribute("code", language.getCode());
160            XMLUtils.startElement(contentHandler, getName(),  attr);
161            language.getLabel().toSAX(contentHandler);
162            XMLUtils.endElement(contentHandler, getName());
163        }
164    }
165    
166    @Override
167    protected Object getSortValue(Content content)
168    {
169        Language language = Optional.of(content)
170                .map(this::getValue)
171                .map(String.class::cast)
172                .map(_languageManager::getLanguage)
173                .orElse(null);
174        
175        if (language != null)
176        {
177            return _i18nUtils.translate(language.getLabel(), language.getCode());
178        }
179        
180        return null;
181    }
182    
183    @Override
184    public Enumerator<String> getDefaultCriterionEnumerator(Configuration configuration, ThreadSafeComponentManager<Enumerator> enumeratorManager) throws ConfigurationException
185    {
186        String role = "enumerator";
187        enumeratorManager.addComponent(getPluginName(), null, role, LanguageEnumerator.class, configuration);
188        
189        try
190        {
191            enumeratorManager.initialize();
192            return enumeratorManager.lookup(role);
193        }
194        catch (Exception e)
195        {
196            throw new ConfigurationException("Unable to initialize the language enumerator for system property '" + getName() + "'.", configuration, e);
197        }
198    }
199    
200    @Override
201    protected String getTypeId()
202    {
203        return ModelItemTypeConstants.STRING_TYPE_ID;
204    }
205}