001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.ade.containerpage.inherited.CmsInheritanceGroupUtils; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProperty; 033import org.opencms.file.CmsPropertyDefinition; 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.shared.CmsBrokenLinkBean; 039import org.opencms.main.CmsException; 040import org.opencms.main.CmsLog; 041import org.opencms.main.OpenCms; 042import org.opencms.relations.CmsRelation; 043import org.opencms.relations.CmsRelationFilter; 044import org.opencms.util.CmsUUID; 045 046import java.util.ArrayList; 047import java.util.List; 048import java.util.Locale; 049import java.util.Set; 050 051import org.apache.commons.logging.Log; 052 053/** 054 * A helper class used to generate the necessary information for displaying links which will be broken 055 * if the user tries to delete a file in the ADE GUI.<p> 056 */ 057public class CmsBrokenLinkRenderer { 058 059 /** The logger instance for this class.*/ 060 private static final Log LOG = CmsLog.getLog(CmsBrokenLinkRenderer.class); 061 062 /** The CMS context used by the broken link renderer.<p> */ 063 private CmsObject m_cms; 064 065 /** 066 * Creates a new broken link renderer instance.<p> 067 * 068 * @param cms the current CMS context 069 */ 070 public CmsBrokenLinkRenderer(CmsObject cms) { 071 072 m_cms = cms; 073 } 074 075 /** 076 * Renders the source of a broken link as a list of CmsBrokenLinkBean instances.<p> 077 * 078 * @param target the broken link target 079 * @param source the broken link source 080 * @return the list of broken link beans to display to the user 081 * 082 * @throws CmsException if something goes wrong 083 */ 084 public List<CmsBrokenLinkBean> renderBrokenLink(CmsResource target, CmsResource source) throws CmsException { 085 086 I_CmsResourceType resType = OpenCms.getResourceManager().getResourceType(source); 087 String typeName = resType.getTypeName(); 088 if (typeName.equals(CmsResourceTypeXmlContainerPage.INHERIT_CONTAINER_CONFIG_TYPE_NAME)) { 089 return renderBrokenLinkInheritanceGroup(target, source); 090 } else if (CmsResourceTypeXmlContainerPage.GROUP_CONTAINER_TYPE_NAME.equals(typeName)) { 091 return renderBrokenLinkGroupContainer(target, source); 092 } else { 093 return renderBrokenLinkDefault(target, source); 094 } 095 } 096 097 /** 098 * The default method for rendering broken link sources.<p> 099 * 100 * @param target the link target 101 * @param source the link source 102 * @return the list of broken link beans to display to the user 103 * 104 * @throws CmsException if something goes wrong 105 */ 106 public List<CmsBrokenLinkBean> renderBrokenLinkDefault(CmsResource target, CmsResource source) throws CmsException { 107 108 List<CmsBrokenLinkBean> result = new ArrayList<CmsBrokenLinkBean>(); 109 result.add(createSitemapBrokenLinkBean(source)); 110 return result; 111 } 112 113 /** 114 * Renders the broken links for a group container.<p> 115 * 116 * @param target the broken link target 117 * @param source the broken link source 118 * 119 * @return the list of broken link beans to display to the user 120 * 121 * @throws CmsException if something goes wrong 122 */ 123 public List<CmsBrokenLinkBean> renderBrokenLinkGroupContainer(CmsResource target, CmsResource source) 124 throws CmsException { 125 126 List<CmsBrokenLinkBean> result = new ArrayList<CmsBrokenLinkBean>(); 127 CmsBrokenLinkBean brokenLinkBean = createSitemapBrokenLinkBean(source); 128 result.add(brokenLinkBean); 129 try { 130 CmsResource referencingPage = findReferencingPage(source); 131 if (referencingPage != null) { 132 String pagePath = m_cms.getRequestContext().removeSiteRoot(referencingPage.getRootPath()); 133 String title = CmsResource.getName(pagePath); 134 CmsProperty titleProp = m_cms.readPropertyObject( 135 referencingPage, 136 CmsPropertyDefinition.PROPERTY_TITLE, 137 false); 138 if (!titleProp.isNullProperty()) { 139 title = titleProp.getValue(); 140 } 141 addPageInfo(brokenLinkBean, title, pagePath); 142 } 143 } catch (CmsException e) { 144 LOG.warn(e.getLocalizedMessage(), e); 145 } 146 return result; 147 } 148 149 /** 150 * Renders broken links from an inheritance group.<p> 151 * 152 * @param target the link target 153 * @param source the link source 154 * 155 * @return the list of broken link beans to display to the user 156 * 157 * @throws CmsException if something goes wrong 158 */ 159 public List<CmsBrokenLinkBean> renderBrokenLinkInheritanceGroup(CmsResource target, CmsResource source) 160 throws CmsException { 161 162 List<CmsBrokenLinkBean> result = new ArrayList<CmsBrokenLinkBean>(); 163 try { 164 Set<String> names = CmsInheritanceGroupUtils.getNamesOfGroupsContainingResource(m_cms, source, target); 165 if (!names.isEmpty()) { 166 for (String name : names) { 167 String title = null; 168 String path = null; 169 String extraTitle = null; 170 String extraPath = null; 171 172 CmsResource group = CmsInheritanceGroupUtils.getInheritanceGroupContentByName(m_cms, name); 173 String groupParent = CmsResource.getParentFolder(source.getRootPath()); 174 CmsProperty titleProp = m_cms.readPropertyObject( 175 group, 176 CmsPropertyDefinition.PROPERTY_TITLE, 177 false); 178 title = CmsResource.getName(group.getRootPath()); 179 if (!titleProp.isNullProperty()) { 180 title = titleProp.getValue(); 181 } 182 path = m_cms.getRequestContext().removeSiteRoot(source.getRootPath()); 183 List<CmsRelation> relations = m_cms.readRelations( 184 CmsRelationFilter.relationsToStructureId(group.getStructureId())); 185 List<CmsResource> referencingPages = new ArrayList<CmsResource>(); 186 for (CmsRelation relation : relations) { 187 CmsResource relSource = relation.getSource(m_cms, CmsResourceFilter.ALL); 188 String pageParent = CmsResource.getParentFolder(relSource.getRootPath()); 189 if (CmsResourceTypeXmlContainerPage.isContainerPage(relSource) 190 && pageParent.equals(groupParent)) { 191 referencingPages.add(relSource); 192 } 193 } 194 if (!referencingPages.isEmpty()) { 195 CmsResource firstPage = referencingPages.get(0); 196 extraPath = m_cms.getRequestContext().removeSiteRoot(firstPage.getRootPath()); 197 extraTitle = m_cms.readPropertyObject( 198 firstPage, 199 CmsPropertyDefinition.PROPERTY_TITLE, 200 true).getValue(); 201 } 202 result.add( 203 createBrokenLinkBean( 204 group.getStructureId(), 205 CmsResourceTypeXmlContainerPage.INHERIT_CONTAINER_CONFIG_TYPE_NAME, 206 title, 207 path, 208 extraTitle, 209 extraPath)); 210 } 211 } else { 212 result.add(createSitemapBrokenLinkBean(source)); 213 } 214 } catch (CmsException e) { 215 result.add(createSitemapBrokenLinkBean(source)); 216 } 217 return result; 218 } 219 220 /** 221 * Adds optional page information to the broken link bean.<p> 222 * 223 * @param bean the broken link bean 224 * @param extraTitle the optional page title 225 * @param extraPath the optional page path 226 */ 227 protected void addPageInfo(CmsBrokenLinkBean bean, String extraTitle, String extraPath) { 228 229 if (extraTitle != null) { 230 bean.addInfo(messagePageTitle(), "" + extraTitle); 231 } 232 if (extraPath != null) { 233 bean.addInfo(messagePagePath(), "" + extraPath); 234 } 235 } 236 237 /** 238 * Creates a broken link bean from the necessary values.<p> 239 * 240 * @param structureId the structure id of the resource 241 * @param type the resource type 242 * @param title the title 243 * @param path the path 244 * @param extraTitle an optional additional page title 245 * @param extraPath an optional additional page path 246 * 247 * @return the created broken link bean 248 */ 249 protected CmsBrokenLinkBean createBrokenLinkBean( 250 CmsUUID structureId, 251 String type, 252 String title, 253 String path, 254 String extraTitle, 255 String extraPath) { 256 257 CmsBrokenLinkBean result = new CmsBrokenLinkBean(structureId, title, path, type); 258 addPageInfo(result, extraTitle, extraPath); 259 return result; 260 } 261 262 /** 263 * Creates a "broken link" bean based on a resource.<p> 264 * 265 * @param resource the resource 266 * @return the "broken link" bean with the data from the resource 267 * 268 * @throws CmsException if something goes wrong 269 */ 270 protected CmsBrokenLinkBean createSitemapBrokenLinkBean(CmsResource resource) throws CmsException { 271 272 CmsProperty titleProp = m_cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, true); 273 String typeName = OpenCms.getResourceManager().getResourceType(resource).getTypeName(); 274 String defaultTitle = CmsResource.getName(resource.getRootPath()); 275 String title = titleProp.getValue(defaultTitle); 276 String path = m_cms.getSitePath(resource); 277 String subtitle = path; 278 return new CmsBrokenLinkBean(resource.getStructureId(), title, subtitle, typeName); 279 } 280 281 /** 282 * Finds a page which references another resource.<p> 283 * 284 * @param source a resource 285 * @return a page which references the resource, or null if no such page was found. 286 * 287 * @throws CmsException if something goes wrong 288 */ 289 private CmsResource findReferencingPage(CmsResource source) throws CmsException { 290 291 List<CmsRelation> relationsToFile = m_cms.readRelations( 292 CmsRelationFilter.relationsToStructureId(source.getStructureId())); 293 for (CmsRelation relation : relationsToFile) { 294 try { 295 CmsResource referencingPage = relation.getSource(m_cms, CmsResourceFilter.DEFAULT); 296 if (CmsResourceTypeXmlContainerPage.isContainerPage(referencingPage)) { 297 return referencingPage; 298 } 299 } catch (CmsException e) { 300 LOG.info(e.getLocalizedMessage(), e); 301 } 302 } 303 return null; 304 } 305 306 /** 307 * Gets the workplace locale.<p> 308 * 309 * @return the workplace locale 310 */ 311 private Locale getLocale() { 312 313 return OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 314 } 315 316 /** 317 * Message accessor.<p> 318 * 319 * @return the message 320 */ 321 private String messagePagePath() { 322 323 return org.opencms.gwt.Messages.get().getBundle(getLocale()).key( 324 org.opencms.gwt.Messages.GUI_DEPENDENCY_PAGE_PATH_0); 325 } 326 327 /** 328 * Message accessor.<p> 329 * 330 * @return the message 331 */ 332 private String messagePageTitle() { 333 334 return org.opencms.gwt.Messages.get().getBundle(getLocale()).key( 335 org.opencms.gwt.Messages.GUI_DEPENDENCY_PAGE_TITLE_0); 336 } 337 338}