001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.widgets; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProperty; 033import org.opencms.file.CmsPropertyDefinition; 034import org.opencms.file.CmsResource; 035import org.opencms.i18n.CmsMessages; 036import org.opencms.json.JSONArray; 037import org.opencms.json.JSONException; 038import org.opencms.json.JSONObject; 039import org.opencms.loader.CmsTemplateLoaderFacade; 040import org.opencms.main.CmsException; 041import org.opencms.main.CmsLog; 042import org.opencms.main.OpenCms; 043import org.opencms.util.CmsStringUtil; 044import org.opencms.workplace.CmsDialog; 045import org.opencms.workplace.CmsWorkplaceMessages; 046import org.opencms.xml.containerpage.I_CmsFormatterBean; 047import org.opencms.xml.types.A_CmsXmlContentValue; 048import org.opencms.xml.types.CmsXmlDisplayFormatterValue; 049 050import java.util.ArrayList; 051import java.util.Arrays; 052import java.util.Collections; 053import java.util.Comparator; 054import java.util.HashSet; 055import java.util.List; 056import java.util.Locale; 057import java.util.Set; 058 059import org.apache.commons.logging.Log; 060 061import com.google.common.collect.Sets; 062 063/** 064 * Widget to select a type and formatter combination.<p> 065 */ 066public class CmsDisplayTypeSelectWidget extends CmsSelectWidget { 067 068 /** 069 * Formatter option comparator, sorting by type name and rank.<p> 070 */ 071 class FormatterComparator implements Comparator<FormatterOption> { 072 073 /** 074 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 075 */ 076 public int compare(FormatterOption o1, FormatterOption o2) { 077 078 return o1.m_typeName.equals(o2.m_typeName) ? o2.m_rank - o1.m_rank : o1.m_typeName.compareTo(o2.m_typeName); 079 } 080 } 081 082 /** 083 * Formatter select option.<p> 084 */ 085 class FormatterOption { 086 087 /** the display type. */ 088 String m_displayType; 089 090 /** The option key. */ 091 String m_key; 092 093 /** The option label. */ 094 String m_label; 095 096 /** The formatter rank. */ 097 int m_rank; 098 099 /** The type name. */ 100 String m_typeName; 101 102 /** 103 * Constructor.<p> 104 * 105 * @param key the option key 106 * @param typeName the type name 107 * @param displayType the display type 108 * @param label the option label 109 * @param rank the formatter rank 110 */ 111 FormatterOption(String key, String typeName, String displayType, String label, int rank) { 112 113 m_key = key; 114 m_typeName = typeName; 115 m_displayType = displayType; 116 m_label = label; 117 m_rank = rank; 118 } 119 } 120 121 /** The match display types key. */ 122 public static final String MATCH_TYPES_KEY = "matchTypes"; 123 124 /** The logger instance for this class. */ 125 private static final Log LOG = CmsLog.getLog(CmsDisplayTypeSelectWidget.class); 126 127 /** The display types split regex. */ 128 private static final String TYPES_SPLITTER = " *, *"; 129 130 /** The display container type configuration. */ 131 private String m_displayContainerTypeConfig; 132 133 /** Flag indicating display types should be matched. */ 134 private boolean m_matchTypes; 135 136 /** The configuration String. */ 137 private String m_config; 138 139 /** 140 * @see org.opencms.widgets.A_CmsSelectWidget#getConfiguration() 141 */ 142 @Override 143 public String getConfiguration() { 144 145 return m_config; 146 } 147 148 /** 149 * @see org.opencms.widgets.A_CmsSelectWidget#getConfiguration(org.opencms.file.CmsObject, org.opencms.xml.types.A_CmsXmlContentValue, org.opencms.i18n.CmsMessages, org.opencms.file.CmsResource, java.util.Locale) 150 */ 151 @Override 152 public String getConfiguration( 153 CmsObject cms, 154 A_CmsXmlContentValue schemaType, 155 CmsMessages messages, 156 CmsResource resource, 157 Locale contentLocale) { 158 159 List<FormatterOption> options = getFormatterOptions(cms, resource); 160 JSONObject config = new JSONObject(); 161 try { 162 String path; 163 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(schemaType.getPath())) { 164 path = CmsStringUtil.joinPaths(schemaType.getPath(), schemaType.getName()); 165 } else { 166 path = schemaType.getName(); 167 } 168 169 config.put("valuePath", path); 170 config.put("matchTypes", m_matchTypes); 171 config.put("emptyLabel", messages.key(Messages.GUI_DISPLAYTYPE_SELECT_0)); 172 JSONArray optionArray = new JSONArray(); 173 for (FormatterOption option : options) { 174 JSONObject opt = new JSONObject(); 175 try { 176 opt.put("value", option.m_key); 177 opt.put("label", option.m_label); 178 opt.put("displayType", option.m_displayType); 179 optionArray.put(opt); 180 } catch (JSONException e) { 181 LOG.error(e.getLocalizedMessage(), e); 182 } 183 } 184 config.put("options", optionArray); 185 } catch (JSONException e) { 186 LOG.error(e.getLocalizedMessage(), e); 187 } 188 return config.toString(); 189 } 190 191 /** 192 * @see org.opencms.widgets.CmsSelectWidget#getWidgetName() 193 */ 194 @Override 195 public String getWidgetName() { 196 197 return CmsDisplayTypeSelectWidget.class.getName(); 198 } 199 200 /** 201 * @see org.opencms.widgets.CmsSelectWidget#newInstance() 202 */ 203 @Override 204 public I_CmsWidget newInstance() { 205 206 return new CmsDisplayTypeSelectWidget(); 207 } 208 209 /** 210 * @see org.opencms.widgets.A_CmsSelectWidget#setConfiguration(java.lang.String) 211 */ 212 @Override 213 public void setConfiguration(String configuration) { 214 215 m_config = configuration; 216 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(configuration)) { 217 String[] conf = configuration.split("\\|"); 218 for (int i = 0; i < conf.length; i++) { 219 if (MATCH_TYPES_KEY.equals(conf[i])) { 220 m_matchTypes = true; 221 } else { 222 m_displayContainerTypeConfig = conf[i]; 223 } 224 225 } 226 } 227 } 228 229 /** 230 * @see org.opencms.widgets.A_CmsSelectWidget#parseSelectOptions(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog, org.opencms.widgets.I_CmsWidgetParameter) 231 */ 232 @Override 233 protected List<CmsSelectWidgetOption> parseSelectOptions( 234 CmsObject cms, 235 I_CmsWidgetDialog widgetDialog, 236 I_CmsWidgetParameter param) { 237 238 CmsResource resource = null; 239 List<CmsSelectWidgetOption> result = new ArrayList<CmsSelectWidgetOption>(); 240 try { 241 if (widgetDialog instanceof CmsDummyWidgetDialog) { 242 resource = ((CmsDummyWidgetDialog)widgetDialog).getResource(); 243 } else if (widgetDialog instanceof CmsDialog) { 244 String sitePath = ((CmsDialog)widgetDialog).getParamResource(); 245 if (sitePath != null) { 246 247 resource = cms.readResource(sitePath); 248 249 } 250 } 251 for (FormatterOption option : getFormatterOptions(cms, resource)) { 252 result.add(new CmsSelectWidgetOption(option.m_key, false, option.m_label)); 253 } 254 } catch (Exception e) { 255 LOG.error(e.getLocalizedMessage(), e); 256 } 257 return result; 258 } 259 260 /** 261 * Evaluates the display type of the given formatter.<p> 262 * 263 * @param formatter the formatter configuration bean 264 * 265 * @return the display type 266 */ 267 private String getDisplayType(I_CmsFormatterBean formatter) { 268 269 return formatter.getDisplayType(); 270 } 271 272 /** 273 * Returns the available formatter options.<p> 274 * 275 * @param cms the cms context 276 * @param resource the edited resource 277 * 278 * @return the formatter options 279 */ 280 private List<FormatterOption> getFormatterOptions(CmsObject cms, CmsResource resource) { 281 282 List<FormatterOption> options = new ArrayList<FormatterOption>(); 283 Set<String> containerTypes = new HashSet<>(); 284 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_displayContainerTypeConfig)) { 285 String types = null; 286 287 if (CmsPropertyDefinition.PROPERTY_TEMPLATE_DISPLAY_TYPES.equals(m_displayContainerTypeConfig)) { 288 try { 289 CmsProperty prop = cms.readPropertyObject( 290 resource, 291 CmsPropertyDefinition.PROPERTY_TEMPLATE_DISPLAY_TYPES, 292 true); 293 String propValue = prop.getValue(); 294 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(propValue)) { 295 types = propValue; 296 } else { 297 // look up template property 298 try { 299 CmsTemplateLoaderFacade loaderFacade = OpenCms.getResourceManager().getTemplateLoaderFacade( 300 cms, 301 null, 302 resource, 303 CmsPropertyDefinition.PROPERTY_TEMPLATE); 304 CmsResource template = loaderFacade.getLoaderStartResource(); 305 if (template != null) { 306 prop = cms.readPropertyObject( 307 template, 308 CmsPropertyDefinition.PROPERTY_TEMPLATE_DISPLAY_TYPES, 309 false); 310 propValue = prop.getValue(); 311 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(propValue)) { 312 types = propValue; 313 } 314 } 315 } catch (Exception ex) { 316 LOG.debug(ex.getMessage(), ex); 317 } 318 } 319 } catch (CmsException e) { 320 LOG.warn(e.getLocalizedMessage(), e); 321 } 322 } else { 323 types = m_displayContainerTypeConfig; 324 } 325 if (types != null) { 326 containerTypes.addAll(Arrays.asList(types.split(TYPES_SPLITTER))); 327 } 328 } 329 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration(cms, resource.getRootPath()); 330 331 if (config != null) { 332 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 333 for (I_CmsFormatterBean formatter : config.getDisplayFormatters(cms)) { 334 if (!containerTypes.isEmpty()) { 335 if (Sets.intersection(containerTypes, formatter.getContainerTypes()).isEmpty()) { 336 continue; 337 } 338 } 339 for (String typeName : formatter.getResourceTypeNames()) { 340 String label = formatter.getNiceName(wpLocale) 341 + " (" 342 + CmsWorkplaceMessages.getResourceTypeName(wpLocale, typeName) 343 + ")"; 344 options.add( 345 new FormatterOption( 346 typeName + CmsXmlDisplayFormatterValue.SEPARATOR + formatter.getId(), 347 typeName, 348 getDisplayType(formatter), 349 label, 350 formatter.getRank())); 351 } 352 } 353 } 354 Collections.sort(options, new FormatterComparator()); 355 return options; 356 } 357}