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.gwt; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.types.CmsResourceTypeUnknownFile; 033import org.opencms.file.types.CmsResourceTypeUnknownFolder; 034import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 035import org.opencms.gwt.shared.CmsGwtConstants; 036import org.opencms.jsp.CmsJspNavBuilder; 037import org.opencms.main.CmsEvent; 038import org.opencms.main.I_CmsEventListener; 039import org.opencms.main.OpenCms; 040import org.opencms.util.CmsStringUtil; 041import org.opencms.workplace.CmsWorkplace; 042import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 043import org.opencms.workplace.explorer.CmsIconRule; 044 045import java.util.ArrayList; 046import java.util.HashMap; 047import java.util.List; 048import java.util.Map; 049import java.util.Map.Entry; 050 051/** 052 * Utility class to generate the resource icon CSS.<p> 053 * 054 * @since 8.0.0 055 */ 056public final class CmsIconUtil implements I_CmsEventListener { 057 058 /** 059 * Inner helper class for building the CSS rules.<p> 060 */ 061 static class CssBuilder { 062 063 /** The buffer into which the CSS is written. */ 064 private StringBuffer m_buffer = new StringBuffer(1024); 065 066 /** 067 * Builds the CSS for all resource types.<p> 068 * 069 * @return a string containing the CSS rules for all resource types 070 */ 071 public String buildResourceIconCss() { 072 073 for (CmsExplorerTypeSettings type : OpenCms.getWorkplaceManager().getExplorerTypeSettings()) { 074 addCssForType(type); 075 } 076 return m_buffer.toString(); 077 } 078 079 /** 080 * Writes the CSS for a single icon rule to a buffer.<p> 081 * 082 * @param typeName the name of the resource type 083 * @param rule the icon rule 084 */ 085 private void addCssForIconRule(String typeName, CmsIconRule rule) { 086 087 String extension = rule.getExtension(); 088 if (rule.getBigIcon() != null) { 089 IconCssRuleBuilder cssBig = new IconCssRuleBuilder(); 090 cssBig.addSelectorForSubType(typeName, extension, false); 091 cssBig.setImageUri(getIconUri(rule.getBigIcon())); 092 cssBig.writeCss(m_buffer); 093 094 IconCssRuleBuilder cssSmall = new IconCssRuleBuilder(); 095 cssSmall.addSelectorForSubType(typeName, extension, true); 096 cssSmall.setImageUri(getIconUri(rule.getIcon())); 097 cssSmall.writeCss(m_buffer); 098 099 } else { 100 IconCssRuleBuilder css = new IconCssRuleBuilder(); 101 css.addSelectorForSubType(typeName, extension, false); 102 css.addSelectorForSubType(typeName, extension, true); 103 css.setImageUri(getIconUri(rule.getIcon())); 104 css.writeCss(m_buffer); 105 106 } 107 } 108 109 /** 110 * Helper method for appending the CSS for a single resource type to a buffer.<p> 111 * 112 * @param explorerType the explorer type for which the CSS should be generated 113 */ 114 private void addCssForType(CmsExplorerTypeSettings explorerType) { 115 116 String typeName = explorerType.getName(); 117 if (explorerType.getBigIconStyle() == null) { 118 if (explorerType.getBigIcon() != null) { 119 IconCssRuleBuilder css = new IconCssRuleBuilder(); 120 css.setImageUri(getIconUri(explorerType.getBigIcon())); 121 css.addSelectorForType(typeName, false); 122 css.writeCss(m_buffer); 123 124 IconCssRuleBuilder cssSmall = new IconCssRuleBuilder(); 125 cssSmall.setImageUri(getIconUri(explorerType.getIcon())); 126 cssSmall.addSelectorForType(typeName, true); 127 cssSmall.writeCss(m_buffer); 128 } else if (explorerType.getOriginalIcon() != null) { 129 IconCssRuleBuilder css = new IconCssRuleBuilder(); 130 css.setImageUri(getIconUri(explorerType.getIcon())); 131 css.addSelectorForType(typeName, true); 132 css.addSelectorForType(typeName, false); 133 css.writeCss(m_buffer); 134 } 135 } 136 Map<String, CmsIconRule> iconRules = explorerType.getIconRules(); 137 for (Map.Entry<String, CmsIconRule> entry : iconRules.entrySet()) { 138 CmsIconRule rule = entry.getValue(); 139 addCssForIconRule(typeName, rule); 140 } 141 } 142 143 /** 144 * Converts an icon file name to a full icon URI.<p> 145 * 146 * @param icon the file name of the icon 147 * 148 * @return the full icon uri 149 */ 150 private String getIconUri(String icon) { 151 152 return CmsWorkplace.getResourceUri(CmsWorkplace.RES_PATH_FILETYPES + icon); 153 } 154 155 } 156 157 /** 158 * Helper class for creating the text of the CSS rule for a single icon based on resource type and file suffix.<p> 159 */ 160 static class IconCssRuleBuilder { 161 162 /** The uri of the icon image. */ 163 private String m_imageUri = "INVALID_ICON"; 164 165 /** The list of selector strings. */ 166 private List<String> m_selectors = new ArrayList<String>(); 167 168 /** 169 * Adds a selector for a resource type and a file suffix.<p> 170 * 171 * @param type the resource type name 172 * @param suffix the file suffix 173 * @param small true if the selector should be for the small icon 174 */ 175 public void addSelectorForSubType(String type, String suffix, boolean small) { 176 177 String template = " .%1$s.%2$s.%3$s"; 178 String selector = String.format( 179 template, 180 CmsGwtConstants.TYPE_ICON_CLASS, 181 getResourceTypeIconClass(type, small), 182 getResourceSubTypeIconClass(type, suffix, small)); 183 m_selectors.add(selector); 184 } 185 186 /** 187 * Adds a selector for a resource type.<p> 188 * 189 * @param type the name of the resource type 190 * @param small true if the selector should be for the small icon 191 */ 192 public void addSelectorForType(String type, boolean small) { 193 194 String template = " div.%1$s.%2$s, span.%1$s.%2$s"; 195 String selector = String.format( 196 template, 197 CmsGwtConstants.TYPE_ICON_CLASS, 198 getResourceTypeIconClass(type, small)); 199 m_selectors.add(selector); 200 } 201 202 /** 203 * Sets the URI of the icon image file.<p> 204 * 205 * @param imageUri the URI of the icon image file 206 */ 207 public void setImageUri(String imageUri) { 208 209 m_imageUri = imageUri; 210 } 211 212 /** 213 * Writes the CSS to a string buffer.<p> 214 * 215 * @param buffer the string buffer to which the 216 */ 217 public void writeCss(StringBuffer buffer) { 218 219 buffer.append(CmsStringUtil.listAsString(m_selectors, ", ")); 220 buffer.append(" { background-image: url(\""); 221 buffer.append(m_imageUri); 222 buffer.append("\");} "); 223 } 224 } 225 226 /** Pseudo type icon. */ 227 public static final String ICON_MODEL_GROUP_BIG = CmsGwtConstants.TYPE_ICON_CLASS + " oc-icon-24-modelgroup_copy"; 228 229 /** Pseudo type icon. */ 230 public static final String ICON_MODEL_GROUP_COPY_BIG = CmsGwtConstants.TYPE_ICON_CLASS 231 + " " 232 + CmsExplorerTypeSettings.ICON_STYLE_MODEL_GROUP_COPY_BIG; 233 234 /** Pseudo type icon. */ 235 public static final String ICON_MODEL_GROUP_COPY_SMALL = CmsGwtConstants.TYPE_ICON_CLASS 236 + " " 237 + CmsExplorerTypeSettings.ICON_STYLE_MODEL_GROUP_COPY_SMALL; 238 239 /** Pseudo type icon. */ 240 public static final String ICON_NAV_LEVEL_BIG = CmsGwtConstants.TYPE_ICON_CLASS 241 + " " 242 + CmsExplorerTypeSettings.ICON_STYLE_NAV_LEVEL_BIG; 243 244 /** Pseudo type icon. */ 245 public static final String ICON_NAV_LEVEL_SMALL = CmsGwtConstants.TYPE_ICON_CLASS 246 + " " 247 + CmsExplorerTypeSettings.ICON_STYLE_NAV_LEVEL_SMALL; 248 249 /** The big resource not found icon name. */ 250 public static final String NOT_FOUND_ICON_BIG = CmsGwtConstants.TYPE_ICON_CLASS + " oc-icon-24-warning"; 251 252 /** The small resource not found icon name. */ 253 public static final String NOT_FOUND_ICON_SMALL = CmsGwtConstants.TYPE_ICON_CLASS + " oc-icon-16-warning"; 254 255 /** The suffix for the CSS classes for small icons. */ 256 public static final String SMALL_SUFFIX = "_small"; 257 258 /** Type for resource not found. */ 259 public static final String TYPE_RESOURCE_NOT_FOUND = "cms_resource_not_found"; 260 261 /** The cached CSS. */ 262 private static String m_cachedCss; 263 264 /** The extension icon mapping. */ 265 private static Map<String, String> m_extensionIconMapping; 266 267 /** Flag indicating the 'clear caches' event listener has been registered. */ 268 private static boolean m_listenerRegistered; 269 270 /** 271 * Constructor.<p> 272 */ 273 private CmsIconUtil() { 274 275 } 276 277 /** 278 * Builds the CSS for all resource types.<p> 279 * 280 * @return a string containing the CSS rules for all resource types 281 */ 282 public static String buildResourceIconCss() { 283 284 if (!m_listenerRegistered) { 285 registerListener(); 286 } 287 if (m_cachedCss == null) { 288 rebuildCss(); 289 } 290 return m_cachedCss; 291 } 292 293 /** 294 * Returns the resource type name used to display the resource icon. 295 * This may differ from the actual resource type in case of navigation level folders and model groups.<p> 296 * 297 * @param cms the cms context 298 * @param resource the resource 299 * 300 * @return the display type name 301 */ 302 public static String getDisplayType(CmsObject cms, CmsResource resource) { 303 304 String result; 305 if (CmsJspNavBuilder.isNavLevelFolder(cms, resource)) { 306 result = CmsGwtConstants.TYPE_NAVLEVEL; 307 } else if (CmsResourceTypeXmlContainerPage.isModelCopyGroup(cms, resource)) { 308 result = CmsGwtConstants.TYPE_MODELGROUP_COPY; 309 } else { 310 result = OpenCms.getResourceManager().getResourceType(resource).getTypeName(); 311 } 312 return result; 313 } 314 315 /** 316 * Returns the extension icon mapping used when uploading files.<p> 317 * 318 * @return the extension icon mapping 319 */ 320 public static Map<String, String> getExtensionIconMapping() { 321 322 if (m_extensionIconMapping == null) { 323 m_extensionIconMapping = new HashMap<String, String>(); 324 for (Entry<String, String> entry : OpenCms.getResourceManager().getExtensionMapping().entrySet()) { 325 m_extensionIconMapping.put( 326 entry.getKey(), 327 getIconClasses(entry.getValue(), "_." + entry.getKey(), false)); 328 } 329 m_extensionIconMapping.put("", getIconClasses("plain", null, false)); 330 } 331 // returning a copy of the icon map, as GWT will not work with unmodifiable maps 332 return new HashMap<String, String>(m_extensionIconMapping); 333 } 334 335 /** 336 * Returns the resource type icon CSS classes for the given type.<p> 337 * Use within ADE context only.<p> 338 * 339 * @param typeSettings the explorer type settings 340 * @param resourceName the resource name 341 * @param small <code>true</code> to get the small icon classes 342 * 343 * @return the icon CSS classes 344 */ 345 public static String getIconClasses(CmsExplorerTypeSettings typeSettings, String resourceName, boolean small) { 346 347 String result = null; 348 if (typeSettings == null) { 349 typeSettings = OpenCms.getWorkplaceManager().getExplorerTypeSetting( 350 (resourceName != null) && CmsResource.isFolder(resourceName) 351 ? CmsResourceTypeUnknownFile.RESOURCE_TYPE_NAME 352 : CmsResourceTypeUnknownFolder.RESOURCE_TYPE_NAME); 353 } 354 if (!typeSettings.getIconRules().isEmpty() && (resourceName != null)) { 355 String extension = CmsResource.getExtension(resourceName); 356 if (extension != null) { 357 // check for a matching sub type icon rule 358 CmsIconRule rule = typeSettings.getIconRules().get(extension); 359 if (rule != null) { 360 result = small ? rule.getSmallIconStyle() : rule.getBigIconStyle(); 361 } 362 } 363 } 364 if (result == null) { 365 if (small && (typeSettings.getSmallIconStyle() != null)) { 366 result = typeSettings.getSmallIconStyle(); 367 } else if (small && (typeSettings.getIcon() == null)) { 368 result = CmsExplorerTypeSettings.ICON_STYLE_DEFAULT_SMALL; 369 } else if (!small && (typeSettings.getBigIconStyle() != null)) { 370 result = typeSettings.getBigIconStyle(); 371 } else if (!small && (typeSettings.getBigIcon() == null)) { 372 result = CmsExplorerTypeSettings.ICON_STYLE_DEFAULT_BIG; 373 } 374 375 if (result != null) { 376 result = CmsGwtConstants.TYPE_ICON_CLASS + " " + result; 377 } else { 378 result = getResourceIconClasses(typeSettings.getName(), resourceName, small); 379 } 380 } 381 return result; 382 } 383 384 /** 385 * Returns the resource type icon CSS classes for the given type.<p> 386 * Use within ADE context only.<p> 387 * 388 * @param resourceType the resource type name 389 * @param resourceName the resource name 390 * @param small <code>true</code> to get the small icon classes 391 * 392 * @return the icon CSS classes 393 */ 394 public static String getIconClasses(String resourceType, String resourceName, boolean small) { 395 396 String result; 397 if (resourceType.equals(CmsGwtConstants.TYPE_NAVLEVEL)) { 398 if (small) { 399 result = ICON_NAV_LEVEL_SMALL; 400 } else { 401 result = ICON_NAV_LEVEL_BIG; 402 } 403 } else if (resourceType.equals(CmsGwtConstants.TYPE_MODELGROUP_COPY)) { 404 if (small) { 405 result = ICON_MODEL_GROUP_COPY_SMALL; 406 } else { 407 result = ICON_MODEL_GROUP_COPY_BIG; 408 } 409 } else if (resourceType.equals(TYPE_RESOURCE_NOT_FOUND)) { 410 if (small) { 411 result = NOT_FOUND_ICON_SMALL; 412 } else { 413 result = NOT_FOUND_ICON_BIG; 414 } 415 } else { 416 result = getIconClasses( 417 OpenCms.getWorkplaceManager().getExplorerTypeSetting(resourceType), 418 resourceName, 419 small); 420 } 421 return result; 422 } 423 424 /** 425 * Returns the CSS class for a given resource type name and file name extension.<p> 426 * 427 * @param resourceTypeName the resource type name 428 * @param suffix the file name extension 429 * @param small if true, get the icon class for the small icon, else for the biggest one available 430 * 431 * @return the CSS class for the type and extension 432 */ 433 static String getResourceSubTypeIconClass(String resourceTypeName, String suffix, boolean small) { 434 435 StringBuffer buffer = new StringBuffer(CmsGwtConstants.TYPE_ICON_CLASS).append("_").append( 436 resourceTypeName.hashCode()).append("_").append(suffix); 437 if (small) { 438 buffer.append(SMALL_SUFFIX); 439 } 440 return buffer.toString(); 441 } 442 443 /** 444 * Returns the CSS class for the given resource type.<p> 445 * 446 * @param resourceTypeName the resource type name 447 * @param small if true, get the icon class for the small icon, else for the biggest one available 448 * 449 * @return the CSS class 450 */ 451 static String getResourceTypeIconClass(String resourceTypeName, boolean small) { 452 453 StringBuffer sb = new StringBuffer(CmsGwtConstants.TYPE_ICON_CLASS); 454 sb.append("_").append(resourceTypeName.hashCode()); 455 if (small) { 456 sb.append(SMALL_SUFFIX); 457 } 458 return sb.toString(); 459 } 460 461 /** 462 * Returns the CSS class for the given filename.<p> 463 * 464 * @param resourceTypeName the resource type name 465 * @param fileName the filename 466 * @param small if true, get the CSS class for the small icon, else for the biggest one available 467 * 468 * @return the CSS class 469 */ 470 private static String getFileTypeIconClass(String resourceTypeName, String fileName, boolean small) { 471 472 if ((fileName != null) && fileName.contains(".")) { 473 int last = fileName.lastIndexOf("."); 474 if (fileName.length() > (last + 1)) { 475 String suffix = fileName.substring(fileName.lastIndexOf(".") + 1); 476 return getResourceSubTypeIconClass(resourceTypeName, suffix, small); 477 } 478 } 479 return ""; 480 481 } 482 483 /** 484 * Returns the CSS classes of the resource icon for the given resource type and filename.<p> 485 * 486 * Use this the resource type and filename is known.<p> 487 * 488 * @param resourceTypeName the resource type name 489 * @param fileName the filename 490 * @param small if true, get the icon classes for the small icon, else for the biggest one available 491 * 492 * @return the CSS classes 493 */ 494 private static String getResourceIconClasses(String resourceTypeName, String fileName, boolean small) { 495 496 StringBuffer sb = new StringBuffer(CmsGwtConstants.TYPE_ICON_CLASS); 497 sb.append(" ").append(getResourceTypeIconClass(resourceTypeName, small)).append(" ").append( 498 getFileTypeIconClass(resourceTypeName, fileName, small)); 499 return sb.toString(); 500 } 501 502 /** 503 * Rebuilds the icon CSS.<p> 504 */ 505 private static synchronized void rebuildCss() { 506 507 if (m_cachedCss == null) { 508 CssBuilder builder = new CssBuilder(); 509 m_cachedCss = builder.buildResourceIconCss(); 510 } 511 } 512 513 /** 514 * Registers the 'clear caches' event listener.<p> 515 */ 516 private static synchronized void registerListener() { 517 518 if (!m_listenerRegistered) { 519 OpenCms.getEventManager().addCmsEventListener( 520 new CmsIconUtil(), 521 new int[] {I_CmsEventListener.EVENT_CLEAR_CACHES}); 522 m_listenerRegistered = true; 523 } 524 } 525 526 /** 527 * @see org.opencms.main.I_CmsEventListener#cmsEvent(org.opencms.main.CmsEvent) 528 */ 529 public void cmsEvent(CmsEvent event) { 530 531 m_cachedCss = null; 532 } 533}