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}