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.ui.util; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsProperty; 032import org.opencms.file.CmsPropertyDefinition; 033import org.opencms.file.CmsRequestContext; 034import org.opencms.file.CmsResource; 035import org.opencms.file.CmsResourceFilter; 036import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 037import org.opencms.file.types.I_CmsResourceType; 038import org.opencms.gwt.CmsIconUtil; 039import org.opencms.gwt.CmsPropertyEditorHelper; 040import org.opencms.gwt.CmsTemplateFinder; 041import org.opencms.gwt.shared.CmsListInfoBean; 042import org.opencms.gwt.shared.property.CmsPropertiesBean; 043import org.opencms.gwt.shared.property.CmsPropertyChangeSet; 044import org.opencms.i18n.CmsMessages; 045import org.opencms.main.CmsException; 046import org.opencms.main.CmsLog; 047import org.opencms.main.OpenCms; 048import org.opencms.util.CmsMacroResolver; 049import org.opencms.util.CmsUUID; 050import org.opencms.xml.content.CmsXmlContentProperty; 051import org.opencms.xml.content.CmsXmlContentPropertyHelper; 052 053import java.util.ArrayList; 054import java.util.LinkedHashMap; 055import java.util.List; 056import java.util.Locale; 057import java.util.Map; 058 059import org.apache.commons.logging.Log; 060 061import com.google.common.collect.Lists; 062 063/** 064 * Helper class for creating a new resource using the New dialog.<p> 065 */ 066public class CmsNewResourceBuilder { 067 068 /** 069 * Interface for callbacks which should be notified when this helper has created a resource.<p> 070 */ 071 public static interface I_Callback { 072 073 /** 074 * Error handler.<p> 075 * 076 * @param e the exception which was thrown 077 */ 078 void onError(Exception e); 079 080 /** 081 * This should be called after the resource is fully created and its properties have been set.<p> 082 * 083 * @param builder the resource builder 084 */ 085 void onResourceCreated(CmsNewResourceBuilder builder); 086 } 087 088 /** 089 * Property helper subclass which is responsible for loading the initial property data to display in the property 090 * dialog for a resource to be created in the New dialog.<p> 091 */ 092 public class PropertyEditorHelper extends CmsPropertyEditorHelper { 093 094 /** 095 * Creates a new instance.<p> 096 * 097 * @param cms the CMS cntext 098 */ 099 public PropertyEditorHelper(CmsObject cms) { 100 101 super(cms); 102 } 103 104 /** 105 * Loads the data needed for editing the properties of a resource.<p> 106 * 107 * @param id the structure id of the resource (ignored) 108 * 109 * @return the data needed for editing the properties 110 * 111 * @throws CmsException if something goes wrong 112 */ 113 @SuppressWarnings("synthetic-access") 114 @Override 115 public CmsPropertiesBean loadPropertyData(CmsUUID id) throws CmsException { 116 117 CmsObject cms = m_cms; 118 String originalSiteRoot = cms.getRequestContext().getSiteRoot(); 119 CmsPropertiesBean result = new CmsPropertiesBean(); 120 121 result.setReadOnly(false); 122 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(m_type); 123 List<CmsProperty> typeDefaultProperties = type.getConfiguredDefaultProperties(); 124 result.setFolder(type.isFolder()); 125 result.setContainerPage(m_type.equals(CmsResourceTypeXmlContainerPage.getStaticTypeName())); 126 String sitePath = OpenCms.getResourceManager().getNameGenerator().getNewFileName( 127 m_cms, 128 m_pathWithPattern, 129 5, 130 m_explorerNameGeneration); 131 String rootPath = m_cms.getRequestContext().addSiteRoot(sitePath); 132 133 Map<String, CmsXmlContentProperty> propertyConfig = OpenCms.getADEManager().lookupConfiguration( 134 cms, 135 rootPath).getPropertyConfigurationAsMap(); 136 Map<String, CmsXmlContentProperty> defaultProperties = getDefaultPropertiesForType(m_type); 137 Map<String, CmsXmlContentProperty> mergedConfig = new LinkedHashMap<String, CmsXmlContentProperty>(); 138 mergedConfig.putAll(defaultProperties); 139 mergedConfig.putAll(propertyConfig); 140 propertyConfig = mergedConfig; 141 142 // Resolve macros in the property configuration 143 propertyConfig = CmsXmlContentPropertyHelper.resolveMacrosInProperties( 144 propertyConfig, 145 CmsMacroResolver.newWorkplaceLocaleResolver(cms)); 146 CmsPropertyEditorHelper.updateWysiwygConfig(propertyConfig, cms, null); 147 148 result.setPropertyDefinitions(new LinkedHashMap<String, CmsXmlContentProperty>(propertyConfig)); 149 try { 150 cms.getRequestContext().setSiteRoot(""); 151 String parentPath = CmsResource.getParentFolder(rootPath); 152 CmsResource parent = cms.readResource(parentPath, CmsResourceFilter.IGNORE_EXPIRATION); 153 List<CmsProperty> parentProperties = cms.readPropertyObjects(parent, true); 154 List<CmsProperty> ownProperties = typeDefaultProperties; 155 result.setOwnProperties(convertProperties(ownProperties)); 156 result.setInheritedProperties(convertProperties(parentProperties)); 157 result.setPageInfo(getPageInfo(sitePath)); 158 List<CmsPropertyDefinition> propDefs = cms.readAllPropertyDefinitions(); 159 List<String> propNames = new ArrayList<String>(); 160 for (CmsPropertyDefinition propDef : propDefs) { 161 propNames.add(propDef.getName()); 162 } 163 CmsTemplateFinder templateFinder = new CmsTemplateFinder(cms); 164 result.setTemplates(templateFinder.getTemplates()); 165 result.setAllProperties(propNames); 166 result.setStructureId(id); 167 result.setSitePath(sitePath); 168 return result; 169 } finally { 170 cms.getRequestContext().setSiteRoot(originalSiteRoot); 171 } 172 } 173 174 /** 175 * Gets the page info bean.<p> 176 * 177 * @param sitePath the site path 178 * @return the page info bean 179 */ 180 private CmsListInfoBean getPageInfo(String sitePath) { 181 182 CmsListInfoBean listInfo = new CmsListInfoBean(); 183 listInfo.setResourceState(CmsResource.STATE_NEW); 184 listInfo.setTitle(CmsResource.getName(sitePath)); 185 listInfo.setSubTitle(sitePath); 186 187 String key = OpenCms.getWorkplaceManager().getExplorerTypeSetting(m_type).getKey(); 188 Locale currentLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 189 CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(currentLocale); 190 String resTypeNiceName = messages.key(key); 191 listInfo.addAdditionalInfo( 192 messages.key(org.opencms.workplace.commons.Messages.GUI_LABEL_TYPE_0), 193 resTypeNiceName); 194 listInfo.setBigIconClasses(CmsIconUtil.getIconClasses(m_type, sitePath, false)); 195 listInfo.setResourceType(m_type); 196 return listInfo; 197 } 198 } 199 200 /** The logger instance for this class. */ 201 private static final Log LOG = CmsLog.getLog(CmsNewResourceBuilder.class); 202 203 /** The CMS context. */ 204 CmsObject m_cms; 205 206 /** The resource type name. */ 207 String m_type; 208 209 /** The list of registered callbacks. */ 210 private List<I_Callback> m_callbacks = Lists.newArrayList(); 211 212 /** The created resource (null until this helper has finished creating the resource). */ 213 private CmsResource m_createdResource; 214 215 /** True if explorer name generation is enabled. */ 216 private boolean m_explorerNameGeneration; 217 218 /** The model resource. */ 219 private CmsResource m_modelResource; 220 221 /** The path with name pattern at which the resource should be created. */ 222 private String m_pathWithPattern; 223 224 /** The property changes to save (may be null). */ 225 private CmsPropertyChangeSet m_propChanges; 226 227 /** 228 * Creates a new instance.<p> 229 * 230 * @param cms the CMS context 231 * @throws CmsException if something goes wrong 232 */ 233 public CmsNewResourceBuilder(CmsObject cms) 234 throws CmsException { 235 236 m_cms = OpenCms.initCmsObject(cms); 237 } 238 239 /** 240 * Adds a callback to be notified when the resource is created.<p> 241 * 242 * @param callback the callback 243 */ 244 public void addCallback(I_Callback callback) { 245 246 m_callbacks.add(callback); 247 } 248 249 /** 250 * Triggers the resource creation.<p> 251 * 252 * @return the created resource 253 * 254 * @throws CmsException if something goes wrong 255 */ 256 public CmsResource createResource() throws CmsException { 257 258 String path = OpenCms.getResourceManager().getNameGenerator().getNewFileName( 259 m_cms, 260 m_pathWithPattern, 261 5, 262 m_explorerNameGeneration); 263 Locale contentLocale = OpenCms.getLocaleManager().getDefaultLocale(m_cms, CmsResource.getFolderPath(path)); 264 CmsRequestContext context = m_cms.getRequestContext(); 265 if (m_modelResource != null) { 266 context.setAttribute(CmsRequestContext.ATTRIBUTE_MODEL, m_modelResource.getRootPath()); 267 } 268 context.setAttribute(CmsRequestContext.ATTRIBUTE_NEW_RESOURCE_LOCALE, contentLocale); 269 CmsResource res = m_cms.createResource( 270 path, 271 OpenCms.getResourceManager().getResourceType(m_type), 272 null, 273 new ArrayList<CmsProperty>()); 274 if (m_propChanges != null) { 275 CmsPropertyEditorHelper helper = new CmsPropertyEditorHelper(m_cms); 276 helper.overrideStructureId(res.getStructureId()); 277 helper.saveProperties(m_propChanges); 278 } 279 // Path or other metadata may have changed 280 m_createdResource = m_cms.readResource(res.getStructureId(), CmsResourceFilter.IGNORE_EXPIRATION); 281 try { 282 m_cms.unlockResource(m_createdResource); 283 } catch (CmsException e) { 284 LOG.info(e.getLocalizedMessage(), e); 285 } 286 for (I_Callback callback : m_callbacks) { 287 callback.onResourceCreated(this); 288 } 289 return m_createdResource; 290 } 291 292 /** 293 * Gets the created resource.<p> 294 * 295 * This will null before the resource creation process. 296 * 297 * @return the created resource 298 */ 299 public CmsResource getCreatedResource() { 300 301 return m_createdResource; 302 } 303 304 /** 305 * Loads the property data with which the property dialog for the new resource should be initialized.<p> 306 * 307 * @return the properties bean 308 */ 309 public CmsPropertiesBean getPropertyData() { 310 311 CmsPropertyEditorHelper helper = new PropertyEditorHelper(m_cms); 312 try { 313 CmsPropertiesBean data = helper.loadPropertyData(CmsUUID.getNullUUID()); 314 return data; 315 } catch (Exception e) { 316 throw new RuntimeException(e); 317 } 318 } 319 320 /** 321 * Creates a resource, but doesn't throw any exceptions.<p> 322 * 323 * Exceptions will be passed to the onError method of registered callbacks.<p> 324 * 325 * @return the created resource 326 */ 327 public CmsResource safeCreateResource() { 328 329 try { 330 return createResource(); 331 } catch (Exception e) { 332 for (I_Callback callback : m_callbacks) { 333 callback.onError(e); 334 } 335 return null; 336 } 337 } 338 339 /** 340 * Sets the Explorer name generation mode.<p> 341 * 342 * @param explorerNameGenerationMode the explorer name generation mode 343 */ 344 public void setExplorerNameGeneration(boolean explorerNameGenerationMode) { 345 346 m_explorerNameGeneration = explorerNameGenerationMode; 347 } 348 349 /** 350 * Sets the locale.<p> 351 * 352 * @param locale the locale 353 */ 354 public void setLocale(Locale locale) { 355 356 m_cms.getRequestContext().setLocale(locale); 357 358 } 359 360 /** 361 * Sets the model resource.<p> 362 * 363 * @param modelResource the model resource 364 */ 365 public void setModel(CmsResource modelResource) { 366 367 m_modelResource = modelResource; 368 } 369 370 /** 371 * Sets the creation path containing a number pattern.<p> 372 * 373 * @param destination the creation path 374 */ 375 public void setPatternPath(String destination) { 376 377 m_pathWithPattern = destination; 378 } 379 380 /** 381 * Sets the property changes.<p> 382 * 383 * @param propertyChanges the property changes 384 */ 385 public void setPropertyChanges(CmsPropertyChangeSet propertyChanges) { 386 387 m_propChanges = propertyChanges; 388 } 389 390 /** 391 * Sets the site root of the CMS context.<p> 392 * 393 * @param siteRoot the site root 394 */ 395 public void setSiteRoot(String siteRoot) { 396 397 m_cms.getRequestContext().setSiteRoot(siteRoot); 398 } 399 400 /** 401 * Sets the resource type name.<p> 402 * 403 * @param type the resource type name 404 */ 405 public void setType(String type) { 406 407 m_type = type; 408 } 409}