001/* 002 * Copyright 2010 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.web.repository.site; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Comparator; 021import java.util.List; 022import java.util.stream.Collectors; 023import java.util.stream.Stream; 024 025import org.apache.avalon.framework.configuration.Configurable; 026import org.apache.avalon.framework.configuration.Configuration; 027import org.apache.avalon.framework.configuration.ConfigurationException; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.apache.avalon.framework.thread.ThreadSafe; 032import org.apache.excalibur.source.SourceResolver; 033 034import org.ametys.core.util.I18nUtils; 035import org.ametys.core.util.I18nizableTextKeyComparator; 036import org.ametys.runtime.i18n.I18nizableText; 037import org.ametys.runtime.model.CategorizedElementDefinitionHelper; 038import org.ametys.runtime.model.CategorizedElementDefinitionWrapperComparator; 039import org.ametys.runtime.model.ElementDefinition; 040import org.ametys.runtime.model.View; 041import org.ametys.runtime.plugin.component.PluginAware; 042import org.ametys.web.site.SiteConfigurationExtensionPoint; 043import org.ametys.web.site.SiteParameterWrapper; 044 045/** 046 * Type of site which is retrieved from a XML configuration. 047 */ 048public class DefaultSiteType implements SiteType, Configurable, PluginAware, ThreadSafe, Serviceable 049{ 050 private static final String __FAMILY_ID = "SiteTypes"; 051 052 private static final String __GENERAL_INFORMATIONS_I18N_KEY = "PLUGINS_WEB_SITE_INFORMATION_CATEGORY"; 053 054 /** Plugin name. */ 055 protected String _pluginName; 056 /** Site type id. */ 057 protected String _id; 058 /** Site type name. */ 059 protected String _name; 060 /** Label. */ 061 protected I18nizableText _label; 062 /** Description. */ 063 protected I18nizableText _description; 064 /** Glyph icon */ 065 protected String _iconGlyph; 066 /** Small icon URI 16x16. */ 067 protected String _smallIcon; 068 /** Medium icon URI 32x32. */ 069 protected String _mediumIcon; 070 /** Large icon URI 48x48. */ 071 protected String _largeIcon; 072 /** The model items of this site type */ 073 protected List<ElementDefinition> _parameters = new ArrayList<>(); 074 /** The site type view, built from site parameter categories and groups */ 075 protected View _view; 076 077 /** The source resolver */ 078 protected SourceResolver _srcResolver; 079 /** The site configuration extension point */ 080 protected SiteConfigurationExtensionPoint _siteConfigurationExtensionPoint; 081 /** Component gathering utility methods for internationalizable text translation {@link I18nUtils} */ 082 protected I18nUtils _i18nUtils; 083 084 /** The parameter wrappers available for this site type **/ 085 private Collection<SiteParameterWrapper> _parameterWrappers = new ArrayList<>(); 086 087 public void service(ServiceManager smanager) throws ServiceException 088 { 089 _srcResolver = (SourceResolver) smanager.lookup(SourceResolver.ROLE); 090 _siteConfigurationExtensionPoint = (SiteConfigurationExtensionPoint) smanager.lookup(SiteConfigurationExtensionPoint.ROLE); 091 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 092 } 093 094 public void configure(Configuration configuration) throws ConfigurationException 095 { 096 _name = configuration.getChild("name").getValue(); 097 098 _label = _parseI18nizableText(configuration, "label"); 099 _description = _parseI18nizableText(configuration, "description"); 100 101 _iconGlyph = configuration.getChild("icons").getChild("glyph").getValue(null); 102 103 _smallIcon = _parseIcon(configuration.getChild("icons"), "small"); 104 _mediumIcon = _parseIcon(configuration.getChild("icons"), "medium"); 105 _largeIcon = _parseIcon(configuration.getChild("icons"), "large"); 106 } 107 108 public String getId() 109 { 110 return _id; 111 } 112 113 public String getFamilyId() 114 { 115 return __FAMILY_ID; 116 } 117 118 public String getName() 119 { 120 return _name; 121 } 122 123 public I18nizableText getLabel() 124 { 125 return _label; 126 } 127 128 public I18nizableText getDescription() 129 { 130 return _description; 131 } 132 133 public String getIconGlyph() 134 { 135 return _iconGlyph; 136 } 137 138 public String getLargeIcon() 139 { 140 return _largeIcon; 141 } 142 143 public String getMediumIcon() 144 { 145 return _mediumIcon; 146 } 147 148 public String getSmallIcon() 149 { 150 return _smallIcon; 151 } 152 153 public String getPluginName() 154 { 155 return _pluginName; 156 } 157 158 public void setPluginInfo(String pluginName, String featureName, String id) 159 { 160 _id = id; 161 _pluginName = pluginName; 162 } 163 164 public Collection<ElementDefinition> getModelItems() 165 { 166 if (_parameters.isEmpty()) 167 { 168 _parameters = _getParameterWrappers() 169 .map(SiteParameterWrapper::getDefinition) 170 .collect(Collectors.toList()); 171 } 172 173 return _parameters; 174 } 175 176 public View getView() 177 { 178 if (_view == null) 179 { 180 Collection<SiteParameterWrapper> wrappers = _getParameterWrappers() 181 .filter(wrapper -> !Site.ILLUSTRATION_PARAMETER.equals(wrapper.getDefinition().getName())) 182 .collect(Collectors.toList()); 183 184 Comparator<I18nizableText> categoriesComparator = new I18nizableTextTranslationComparator(); 185 Comparator<I18nizableText> groupsComparator = new I18nizableTextKeyComparator(); 186 Comparator<SiteParameterWrapper> elementsComparator = new SiteConfigurationParametersComparator(); 187 188 _view = CategorizedElementDefinitionHelper.buildViewFromCategories(wrappers, categoriesComparator, groupsComparator, elementsComparator); 189 } 190 191 return _view; 192 } 193 194 private Stream<SiteParameterWrapper> _getParameterWrappers() 195 { 196 if (_parameterWrappers.isEmpty()) 197 { 198 for (String extensionId : _siteConfigurationExtensionPoint.getExtensionsIds()) 199 { 200 SiteParameterWrapper wrapper = _siteConfigurationExtensionPoint.getExtension(extensionId); 201 // Filter site parameters for this type 202 if (wrapper.isInSiteType(this.getName())) 203 { 204 @SuppressWarnings("unchecked") 205 SiteParameterWrapper copy = new SiteParameterWrapper<>(wrapper); 206 207 // Set the model to each definition 208 copy.getDefinition().setModel(this); 209 210 _parameterWrappers.add(copy); 211 } 212 } 213 } 214 215 return _parameterWrappers.stream(); 216 } 217 218 /** 219 * Parse an i18n text. 220 * @param config the configuration to use. 221 * @param name the child name. 222 * @return the i18n text. 223 * @throws ConfigurationException if the configuration is not valid. 224 */ 225 protected I18nizableText _parseI18nizableText(Configuration config, String name) throws ConfigurationException 226 { 227 return I18nizableText.parseI18nizableText(config.getChild(name), "plugin." + _pluginName, ""); 228 } 229 230 /** 231 * Parse an icon path 232 * @param configuration the configuration to use 233 * @param name the child name. 234 * @return The icon path 235 * @throws ConfigurationException if the configuration is not valid. 236 */ 237 protected String _parseIcon (Configuration configuration, String name) throws ConfigurationException 238 { 239 Configuration iconConfig = configuration.getChild(name, false); 240 if (iconConfig != null) 241 { 242 String pluginName = iconConfig.getAttribute("plugin", _pluginName); 243 return "/plugins/" + pluginName + "/resources/" + iconConfig.getValue(); 244 } 245 246 return "/plugins/web/resources/img/sitetype/icon-" + name + ".png"; 247 } 248 249 /** 250 * I18nizableText comparator for site parameters 251 * General information category is the first one, then sort the I18nizableText with their translation 252 */ 253 class I18nizableTextTranslationComparator implements Comparator<I18nizableText> 254 { 255 @Override 256 public int compare(I18nizableText t1, I18nizableText t2) 257 { 258 // The general informations category always goes first 259 if (t1.getKey().equals(__GENERAL_INFORMATIONS_I18N_KEY)) 260 { 261 if (t2.getKey().equals(__GENERAL_INFORMATIONS_I18N_KEY)) 262 { 263 return 0; 264 } 265 return -1; 266 } 267 268 if (t2.getKey().equals(__GENERAL_INFORMATIONS_I18N_KEY)) 269 { 270 return 1; 271 } 272 273 String tt1 = _i18nUtils.translate(t1); 274 if (tt1 == null) 275 { 276 return -1; 277 } 278 279 String tt2 = _i18nUtils.translate(t2); 280 if (tt2 == null) 281 { 282 return 1; 283 } 284 285 return tt1.compareTo(tt2); 286 } 287 } 288 289 /** 290 * Comparator for the site parameter wrappers using their position 291 * If no position is set, keep the order of arrival in the configuration 292 */ 293 class SiteConfigurationParametersComparator extends CategorizedElementDefinitionWrapperComparator<SiteParameterWrapper> 294 { 295 @Override 296 protected int compareWrappersWithSamePositions(SiteParameterWrapper wrapper1, SiteParameterWrapper wrapper2) 297 { 298 // Keep the order of arrival in the configuration 299 return 1; 300 } 301 } 302}