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