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 Map<String, CmsXmlContentProperty> propertyConfig; 133 Map<String, CmsXmlContentProperty> defaultProperties = getDefaultPropertiesForType(m_type); 134 Map<String, CmsXmlContentProperty> mergedConfig = OpenCms.getADEManager().lookupConfiguration( 135 cms, 136 rootPath).getPropertyConfiguration(defaultProperties); 137 propertyConfig = mergedConfig; 138 139 // Resolve macros in the property configuration 140 propertyConfig = CmsXmlContentPropertyHelper.resolveMacrosInProperties( 141 propertyConfig, 142 CmsMacroResolver.newWorkplaceLocaleResolver(cms)); 143 CmsPropertyEditorHelper.updateWysiwygConfig(propertyConfig, cms, null); 144 145 result.setPropertyDefinitions(new LinkedHashMap<String, CmsXmlContentProperty>(propertyConfig)); 146 try { 147 cms.getRequestContext().setSiteRoot(""); 148 String parentPath = CmsResource.getParentFolder(rootPath); 149 CmsResource parent = cms.readResource(parentPath, CmsResourceFilter.IGNORE_EXPIRATION); 150 List<CmsProperty> parentProperties = cms.readPropertyObjects(parent, true); 151 List<CmsProperty> ownProperties = typeDefaultProperties; 152 result.setOwnProperties(convertProperties(ownProperties)); 153 result.setInheritedProperties(convertProperties(parentProperties)); 154 result.setPageInfo(getPageInfo(sitePath)); 155 List<CmsPropertyDefinition> propDefs = cms.readAllPropertyDefinitions(); 156 List<String> propNames = new ArrayList<String>(); 157 for (CmsPropertyDefinition propDef : propDefs) { 158 propNames.add(propDef.getName()); 159 } 160 CmsTemplateFinder templateFinder = new CmsTemplateFinder(cms); 161 result.setTemplates(templateFinder.getTemplates()); 162 result.setAllProperties(propNames); 163 result.setStructureId(id); 164 result.setSitePath(sitePath); 165 return result; 166 } finally { 167 cms.getRequestContext().setSiteRoot(originalSiteRoot); 168 } 169 } 170 171 /** 172 * Gets the page info bean.<p> 173 * 174 * @param sitePath the site path 175 * @return the page info bean 176 */ 177 private CmsListInfoBean getPageInfo(String sitePath) { 178 179 CmsListInfoBean listInfo = new CmsListInfoBean(); 180 listInfo.setResourceState(CmsResource.STATE_NEW); 181 listInfo.setTitle(CmsResource.getName(sitePath)); 182 listInfo.setSubTitle(sitePath); 183 184 String key = OpenCms.getWorkplaceManager().getExplorerTypeSetting(m_type).getKey(); 185 Locale currentLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 186 CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(currentLocale); 187 String resTypeNiceName = messages.key(key); 188 listInfo.addAdditionalInfo( 189 messages.key(org.opencms.workplace.commons.Messages.GUI_LABEL_TYPE_0), 190 resTypeNiceName); 191 listInfo.setBigIconClasses(CmsIconUtil.getIconClasses(m_type, sitePath, false)); 192 listInfo.setResourceType(m_type); 193 return listInfo; 194 } 195 } 196 197 /** The logger instance for this class. */ 198 private static final Log LOG = CmsLog.getLog(CmsNewResourceBuilder.class); 199 200 /** The CMS context. */ 201 CmsObject m_cms; 202 203 /** The resource type name. */ 204 String m_type; 205 206 /** The list of registered callbacks. */ 207 private List<I_Callback> m_callbacks = Lists.newArrayList(); 208 209 /** The created resource (null until this helper has finished creating the resource). */ 210 private CmsResource m_createdResource; 211 212 /** True if explorer name generation is enabled. */ 213 private boolean m_explorerNameGeneration; 214 215 /** The model resource. */ 216 private CmsResource m_modelResource; 217 218 /** The path with name pattern at which the resource should be created. */ 219 private String m_pathWithPattern; 220 221 /** The property changes to save (may be null). */ 222 private CmsPropertyChangeSet m_propChanges; 223 224 /** 225 * Creates a new instance.<p> 226 * 227 * @param cms the CMS context 228 * @throws CmsException if something goes wrong 229 */ 230 public CmsNewResourceBuilder(CmsObject cms) 231 throws CmsException { 232 233 m_cms = OpenCms.initCmsObject(cms); 234 } 235 236 /** 237 * Adds a callback to be notified when the resource is created.<p> 238 * 239 * @param callback the callback 240 */ 241 public void addCallback(I_Callback callback) { 242 243 m_callbacks.add(callback); 244 } 245 246 /** 247 * Triggers the resource creation.<p> 248 * 249 * @return the created resource 250 * 251 * @throws CmsException if something goes wrong 252 */ 253 public CmsResource createResource() throws CmsException { 254 255 String path = OpenCms.getResourceManager().getNameGenerator().getNewFileName( 256 m_cms, 257 m_pathWithPattern, 258 5, 259 m_explorerNameGeneration); 260 Locale contentLocale = OpenCms.getLocaleManager().getDefaultLocale(m_cms, CmsResource.getFolderPath(path)); 261 CmsRequestContext context = m_cms.getRequestContext(); 262 if (m_modelResource != null) { 263 context.setAttribute(CmsRequestContext.ATTRIBUTE_MODEL, m_modelResource.getRootPath()); 264 } 265 context.setAttribute(CmsRequestContext.ATTRIBUTE_NEW_RESOURCE_LOCALE, contentLocale); 266 CmsResource res = m_cms.createResource( 267 path, 268 OpenCms.getResourceManager().getResourceType(m_type), 269 null, 270 new ArrayList<CmsProperty>()); 271 if (m_propChanges != null) { 272 CmsPropertyEditorHelper helper = new CmsPropertyEditorHelper(m_cms); 273 helper.overrideStructureId(res.getStructureId()); 274 helper.saveProperties(m_propChanges); 275 } 276 // Path or other metadata may have changed 277 m_createdResource = m_cms.readResource(res.getStructureId(), CmsResourceFilter.IGNORE_EXPIRATION); 278 try { 279 m_cms.unlockResource(m_createdResource); 280 } catch (CmsException e) { 281 LOG.info(e.getLocalizedMessage(), e); 282 } 283 for (I_Callback callback : m_callbacks) { 284 callback.onResourceCreated(this); 285 } 286 return m_createdResource; 287 } 288 289 /** 290 * Gets the created resource.<p> 291 * 292 * This will null before the resource creation process. 293 * 294 * @return the created resource 295 */ 296 public CmsResource getCreatedResource() { 297 298 return m_createdResource; 299 } 300 301 /** 302 * Loads the property data with which the property dialog for the new resource should be initialized.<p> 303 * 304 * @return the properties bean 305 */ 306 public CmsPropertiesBean getPropertyData() { 307 308 CmsPropertyEditorHelper helper = new PropertyEditorHelper(m_cms); 309 try { 310 CmsPropertiesBean data = helper.loadPropertyData(CmsUUID.getNullUUID()); 311 return data; 312 } catch (Exception e) { 313 throw new RuntimeException(e); 314 } 315 } 316 317 /** 318 * Creates a resource, but doesn't throw any exceptions.<p> 319 * 320 * Exceptions will be passed to the onError method of registered callbacks.<p> 321 * 322 * @return the created resource 323 */ 324 public CmsResource safeCreateResource() { 325 326 try { 327 return createResource(); 328 } catch (Exception e) { 329 for (I_Callback callback : m_callbacks) { 330 callback.onError(e); 331 } 332 return null; 333 } 334 } 335 336 /** 337 * Sets the Explorer name generation mode.<p> 338 * 339 * @param explorerNameGenerationMode the explorer name generation mode 340 */ 341 public void setExplorerNameGeneration(boolean explorerNameGenerationMode) { 342 343 m_explorerNameGeneration = explorerNameGenerationMode; 344 } 345 346 /** 347 * Sets the locale.<p> 348 * 349 * @param locale the locale 350 */ 351 public void setLocale(Locale locale) { 352 353 m_cms.getRequestContext().setLocale(locale); 354 355 } 356 357 /** 358 * Sets the model resource.<p> 359 * 360 * @param modelResource the model resource 361 */ 362 public void setModel(CmsResource modelResource) { 363 364 m_modelResource = modelResource; 365 } 366 367 /** 368 * Sets the creation path containing a number pattern.<p> 369 * 370 * @param destination the creation path 371 */ 372 public void setPatternPath(String destination) { 373 374 m_pathWithPattern = destination; 375 } 376 377 /** 378 * Sets the property changes.<p> 379 * 380 * @param propertyChanges the property changes 381 */ 382 public void setPropertyChanges(CmsPropertyChangeSet propertyChanges) { 383 384 m_propChanges = propertyChanges; 385 } 386 387 /** 388 * Sets the site root of the CMS context.<p> 389 * 390 * @param siteRoot the site root 391 */ 392 public void setSiteRoot(String siteRoot) { 393 394 m_cms.getRequestContext().setSiteRoot(siteRoot); 395 } 396 397 /** 398 * Sets the resource type name.<p> 399 * 400 * @param type the resource type name 401 */ 402 public void setType(String type) { 403 404 m_type = type; 405 } 406}