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 GmbH & Co. KG, 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.jsp.decorator; 029 030import org.opencms.cache.CmsVfsMemoryObjectCache; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsResource; 033import org.opencms.file.CmsResourceFilter; 034import org.opencms.file.types.CmsResourceTypePlain; 035import org.opencms.loader.CmsLoaderException; 036import org.opencms.main.CmsException; 037import org.opencms.main.CmsLog; 038import org.opencms.main.OpenCms; 039import org.opencms.module.CmsModule; 040import org.opencms.util.CmsStringUtil; 041 042import java.util.ArrayList; 043import java.util.Collections; 044import java.util.Iterator; 045import java.util.List; 046import java.util.Locale; 047 048import org.apache.commons.logging.Log; 049 050/** 051 * This class defines text decoration to be made by the postprocessor.<p> 052 * 053 * @since 6.1.3 054 */ 055public class CmsDecorationDefintion { 056 057 /** The log object for this class. */ 058 private static final Log LOG = CmsLog.getLog(CmsDecorationDefintion.class); 059 060 /** The name of the configuration file holding all word substitutions. */ 061 private String m_configurationFile; 062 063 /** Flag, signaling if the first occurance of a word must be marked differntly. */ 064 private boolean m_markFirst; 065 066 /** The name of the substitution. */ 067 private String m_name; 068 069 /** The post to be added after the occurance of a word. */ 070 private String m_postText; 071 072 /** The post to be added after the occurance of a word on its first occurance. */ 073 private String m_postTextFirst; 074 075 /** The prefix to be added in front of the occurance of a word. */ 076 private String m_preText; 077 078 /** The prefix to be added in front of the occurance of a word on its first occurance. */ 079 private String m_preTextFirst; 080 081 /** 082 * Constructor, creates a new empty CmsDecorationDefintion.<p> 083 */ 084 public CmsDecorationDefintion() { 085 086 m_configurationFile = null; 087 m_markFirst = false; 088 m_name = null; 089 m_postText = null; 090 m_postTextFirst = null; 091 m_preText = null; 092 m_preTextFirst = null; 093 } 094 095 /** 096 * Constructor, creates a new CmsDecorationDefintion with given values.<p> 097 * 098 * @param name the name of the decoration defintinion 099 * @param preText the preText to be used 100 * @param postText the postText to be used 101 * @param preTextFirst the preTextFirst to be used 102 * @param postTextFirst the postTextFirst to be used 103 * @param markFrist the flag to use different decorations for the first occurance 104 * @param configurationFile the name of the configuration file 105 */ 106 public CmsDecorationDefintion( 107 String name, 108 String preText, 109 String postText, 110 String preTextFirst, 111 String postTextFirst, 112 boolean markFrist, 113 String configurationFile) { 114 115 m_configurationFile = configurationFile; 116 m_markFirst = markFrist; 117 m_name = name; 118 m_postText = postText; 119 m_postTextFirst = postTextFirst; 120 m_preText = preText; 121 m_preTextFirst = preTextFirst; 122 } 123 124 /** 125 * Returns all different decoration configuration names (like "abbr" or "acronym") that 126 * are in the config file pointed to by module parameter "configfile".<p> 127 * 128 * @param cms needed to access the decoration definition XML content 129 * 130 * @return all different decoration configuration names (like "abbr" or "acronym") that 131 * are in the config file pointed to by module parameter "configfile" 132 * 133 * @throws CmsException if sth goes wrong 134 */ 135 public static List<String> getDecorationDefinitionNames(CmsObject cms) throws CmsException { 136 137 List<String> result = new ArrayList<String>(); 138 CmsModule module = OpenCms.getModuleManager().getModule("com.alkacon.opencms.extendeddecorator"); 139 String configFile = module.getParameter("configfile"); 140 if (CmsStringUtil.isEmpty(configFile)) { 141 LOG.error(Messages.get().getBundle().key(Messages.LOG_ERROR_CONFIG_MISSING_0)); 142 } else { 143 CmsDecoratorConfiguration config = new CmsDecoratorConfiguration(cms, configFile); 144 List<CmsDecorationDefintion> decorationDefinitions = config.getDecorationDefinitions(); 145 Iterator<CmsDecorationDefintion> it = decorationDefinitions.iterator(); 146 CmsDecorationDefintion decDef; 147 while (it.hasNext()) { 148 decDef = it.next(); 149 result.add(decDef.getName()); 150 } 151 152 } 153 154 return result; 155 } 156 157 /** 158 * Creates a CmsDecorationBundle of text decoration to be used by the decorator.<p> 159 * 160 * @param cms the CmsObject 161 * @param locale the locale to build the decoration bundle for. If no locale is given, a bundle of all locales is build 162 * @return CmsDecorationBundle including all decoration lists that match the locale 163 * @throws CmsException if something goes wrong 164 */ 165 public CmsDecorationBundle createDecorationBundle(CmsObject cms, Locale locale) throws CmsException { 166 167 // get configfile basename and the list of all decoration map files 168 List<CmsResource> decorationMapFiles = getDecorationMapFiles(cms); 169 if (LOG.isDebugEnabled()) { 170 LOG.debug( 171 Messages.get().getBundle().key( 172 Messages.LOG_DECORATION_DEFINITION_MAP_FILES_2, 173 decorationMapFiles, 174 locale)); 175 } 176 177 // create decoration maps 178 List<CmsDecorationMap> decorationMaps = getDecorationMaps(cms, decorationMapFiles); 179 if (LOG.isDebugEnabled()) { 180 LOG.debug( 181 Messages.get().getBundle().key(Messages.LOG_DECORATION_DEFINITION_MAPS_2, decorationMaps, locale)); 182 } 183 184 // now that we have all decoration maps we can build the decoration bundle 185 // the bundele is depending on the locale, if a locale is given, only those decoration maps that contain the 186 // locale (or no locale at all) must be used. If no locale is given, all decoration maps are 187 // put into the decoration bundle 188 return createDecorationBundle(decorationMaps, locale); 189 } 190 191 /** 192 * Creates a CmsDecorationBundle of text decoration to be used by the decorator based on a list of decoration maps.<p> 193 * 194 * @param decorationMaps the decoration maps to build the bundle from 195 * @param locale the locale to build the decoration bundle for. If no locale is given, a bundle of all locales is build 196 * @return CmsDecorationBundle including all decoration lists that match the locale 197 */ 198 public CmsDecorationBundle createDecorationBundle(List<CmsDecorationMap> decorationMaps, Locale locale) { 199 200 CmsDecorationBundle decorationBundle = new CmsDecorationBundle(locale); 201 // sort the bundles 202 Collections.sort(decorationMaps); 203 // now process the decoration maps to see which of those must be added to the bundle 204 Iterator<CmsDecorationMap> i = decorationMaps.iterator(); 205 while (i.hasNext()) { 206 CmsDecorationMap decMap = i.next(); 207 // a decoration map must be added to the bundle if one of the following conditions match: 208 // 1) the bundle has no locale 209 // 2) the bundle has a locale and the locale of the map is equal or a sublocale 210 // 3) the bundle has a locale and the map has no locale 211 if ((locale == null) 212 || ((decMap.getLocale() == null)) 213 || (locale.getDisplayLanguage().equals(decMap.getLocale().getDisplayLanguage()))) { 214 decorationBundle.putAll(decMap.getDecorationMap()); 215 if (LOG.isDebugEnabled()) { 216 LOG.debug( 217 Messages.get().getBundle().key( 218 Messages.LOG_DECORATION_DEFINITION_CREATE_BUNDLE_2, 219 decMap.getName(), 220 locale)); 221 } 222 } 223 } 224 return decorationBundle; 225 } 226 227 /** 228 * Returns the configurationFile.<p> 229 * 230 * 231 * @return the configurationFile 232 */ 233 public String getConfigurationFile() { 234 235 return m_configurationFile; 236 } 237 238 /** 239 * Returns the name.<p> 240 * 241 * @return the name 242 */ 243 public String getName() { 244 245 return m_name; 246 } 247 248 /** 249 * Returns the postText.<p> 250 * 251 * @return the postText 252 */ 253 public String getPostText() { 254 255 return m_postText; 256 } 257 258 /** 259 * Returns the postTextFirst.<p> 260 * 261 * @return the postTextFirst 262 */ 263 public String getPostTextFirst() { 264 265 return m_postTextFirst; 266 } 267 268 /** 269 * Returns the preText.<p> 270 * 271 * @return the preText 272 */ 273 public String getPreText() { 274 275 return m_preText; 276 } 277 278 /** 279 * Returns the preTextFirst.<p> 280 * 281 * @return the preTextFirst 282 */ 283 public String getPreTextFirst() { 284 285 return m_preTextFirst; 286 } 287 288 /** 289 * Returns the markFirst flag.<p> 290 * 291 * @return the markFirst flag 292 */ 293 public boolean isMarkFirst() { 294 295 return m_markFirst; 296 } 297 298 /** 299 * Sets the configurationFile.<p> 300 * 301 * @param configurationFile the configurationFile to set 302 */ 303 public void setConfigurationFile(String configurationFile) { 304 305 m_configurationFile = configurationFile; 306 } 307 308 /** 309 * Sets the markFirst flag.<p> 310 * 311 * @param markFirst the markFirst flag to set 312 */ 313 public void setMarkFirst(boolean markFirst) { 314 315 m_markFirst = markFirst; 316 } 317 318 /** 319 * Sets the name.<p> 320 * 321 * @param name the name to set 322 */ 323 public void setName(String name) { 324 325 m_name = name; 326 } 327 328 /** 329 * Sets the postText.<p> 330 * 331 * @param postText the postText to set 332 */ 333 public void setPostText(String postText) { 334 335 m_postText = postText; 336 } 337 338 /** 339 * Sets the postTextFirst.<p> 340 * 341 * @param postTextFirst the postTextFirst to set 342 */ 343 public void setPostTextFirst(String postTextFirst) { 344 345 m_postTextFirst = postTextFirst; 346 } 347 348 /** 349 * Sets the preText.<p> 350 * 351 * @param preText the preText to set 352 */ 353 public void setPreText(String preText) { 354 355 m_preText = preText; 356 } 357 358 /** 359 * Sets the preTextFirst.<p> 360 * 361 * @param preTextFirst the preTextFirst to set 362 */ 363 public void setPreTextFirst(String preTextFirst) { 364 365 m_preTextFirst = preTextFirst; 366 } 367 368 /** 369 * @see java.lang.Object#toString() 370 */ 371 @Override 372 public String toString() { 373 374 StringBuffer buf = new StringBuffer(); 375 buf.append(this.getClass().getName()); 376 buf.append(" [name = '"); 377 buf.append(m_name); 378 buf.append("', markFirst = '"); 379 buf.append(m_markFirst); 380 buf.append("', preText = '"); 381 buf.append(m_preText); 382 buf.append("', postText = '"); 383 buf.append(m_postText); 384 buf.append("', preTextFirst = '"); 385 buf.append(m_preTextFirst); 386 buf.append("', postTextFirst = '"); 387 buf.append(m_postTextFirst); 388 buf.append("', configFile = "); 389 buf.append(m_configurationFile); 390 buf.append("]"); 391 return buf.toString(); 392 } 393 394 /** 395 * Gets the list of all decoartion map files that match to the current basename.<p> 396 * 397 * @param cms the CmsObject 398 * @return list of CmsResources of the decoration map files 399 * @throws CmsException if something goes wrong. 400 */ 401 private List<CmsResource> getDecorationMapFiles(CmsObject cms) throws CmsException { 402 403 List<CmsResource> files = new ArrayList<CmsResource>(); 404 405 // calcualte the basename for the decoration map files 406 // the basename is the filename without the fileextension and any "_locale" postfixes 407 // e.g. decoration_en.csv will generate "decoration" as basename 408 StringBuffer baseFilename = new StringBuffer(); 409 baseFilename.append(CmsResource.getParentFolder(m_configurationFile)); 410 String filename = cms.readResource(m_configurationFile).getName(); 411 // get rid of the fileextension if there is one 412 if (filename.lastIndexOf(".") > -1) { 413 filename = filename.substring(0, filename.lastIndexOf(".")); 414 } 415 // extract the basename 416 if (filename.lastIndexOf("_") > -1) { 417 filename = filename.substring(0, filename.lastIndexOf("_")); 418 } 419 baseFilename.append(filename); 420 String basename = baseFilename.toString(); 421 422 // get all config files which belong to this basename 423 int plainId; 424 try { 425 plainId = OpenCms.getResourceManager().getResourceType( 426 CmsResourceTypePlain.getStaticTypeName()).getTypeId(); 427 } catch (CmsLoaderException e) { 428 // this should really never happen 429 plainId = CmsResourceTypePlain.getStaticTypeId(); 430 } 431 List<CmsResource> resources = cms.readResources( 432 CmsResource.getParentFolder(m_configurationFile), 433 CmsResourceFilter.DEFAULT); 434 Iterator<CmsResource> i = resources.iterator(); 435 while (i.hasNext()) { 436 CmsResource res = i.next(); 437 if (cms.getSitePath(res).startsWith(basename) && (res.getTypeId() == plainId)) { 438 files.add(res); 439 } 440 } 441 442 return files; 443 } 444 445 /** 446 * Creates a list of decoration map objects from a given list of decoration files.<p> 447 * 448 * @param cms the CmsObject 449 * @param decorationListFiles the list of decoration files 450 * @return list of decoration map objects 451 */ 452 private List<CmsDecorationMap> getDecorationMaps(CmsObject cms, List<CmsResource> decorationListFiles) { 453 454 List<CmsDecorationMap> decorationMaps = new ArrayList<CmsDecorationMap>(); 455 Iterator<CmsResource> i = decorationListFiles.iterator(); 456 while (i.hasNext()) { 457 CmsResource res = i.next(); 458 try { 459 CmsDecorationMap decMap = (CmsDecorationMap)CmsVfsMemoryObjectCache.getVfsMemoryObjectCache().getCachedObject( 460 cms, 461 res.getRootPath()); 462 if (decMap == null) { 463 decMap = new CmsDecorationMap(cms, res, this); 464 CmsVfsMemoryObjectCache.getVfsMemoryObjectCache().putCachedObject(cms, res.getRootPath(), decMap); 465 } 466 467 decorationMaps.add(decMap); 468 } catch (CmsException e) { 469 if (LOG.isErrorEnabled()) { 470 LOG.error( 471 Messages.get().getBundle().key( 472 Messages.LOG_DECORATION_DEFINITION_CREATE_MAP_2, 473 res.getName(), 474 e)); 475 } 476 } 477 } 478 return decorationMaps; 479 } 480 481}