org.opencms.site.xmlsitemap.CmsDetailPageDuplicateEliminatingSitemapGenerator Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.site.xmlsitemap;
import org.opencms.ade.configuration.CmsADEConfigData.DetailInfo;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.types.I_CmsResourceType;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.util.CmsFileUtil;
import org.opencms.util.CmsPathMap;
import org.opencms.util.CmsStringUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import org.apache.commons.logging.Log;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
/**
* Sitemap generator class which tries to eliminate duplicate detail pages for the same content and locale.
*
* In principle, any detail page for a type somewhere in the system could be used to display contents anywhere
* else in the system. This sitemap generator, instead of generating all detail page URLs that could possibly be generated,
* instead tries to find only the best candidate URL for each content / locale combination.
*/
public class CmsDetailPageDuplicateEliminatingSitemapGenerator extends CmsXmlSitemapGenerator {
/** The logger instance for this class. */
private static final Log LOG = CmsLog.getLog(CmsDetailPageDuplicateEliminatingSitemapGenerator.class);
/** The detail page information. */
protected List m_detailInfos = new ArrayList();
/** Multimap of detail infos with the detail page as key. */
private Multimap m_detailInfosByPage;
/** Cache for path maps containing the content resources. */
private HashMap> m_pathMapsByType = Maps.newHashMap();
/**
* Constructor.
*
* @param sitemapPath the sitemap path
* @throws CmsException if something goes wrong
*/
public CmsDetailPageDuplicateEliminatingSitemapGenerator(String sitemapPath)
throws CmsException {
super(sitemapPath);
List rawDetailInfo = OpenCms.getADEManager().getDetailInfo(m_guestCms);
List filteredDetailInfo = Lists.newArrayList();
for (DetailInfo item : rawDetailInfo) {
String path = item.getFolderPath();
if (OpenCms.getSiteManager().startsWithShared(path) || CmsStringUtil.isPrefixPath(m_siteRoot, path)) {
filteredDetailInfo.add(item);
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Filtered detail info: " + item);
}
}
}
m_detailInfos = filteredDetailInfo;
}
/**
* @see org.opencms.site.xmlsitemap.CmsXmlSitemapGenerator#generateSitemapBeans()
*/
@Override
public List generateSitemapBeans() throws CmsException {
List parentResult = super.generateSitemapBeans();
List result = Lists.newArrayList();
Multimap detailPageBeans = ArrayListMultimap.create();
// We want to eliminate duplicate detail pages for the same detail content and locale,
// so first we group the XML sitemap beans belonging to detail pages by their locale/content combination,
// and then we sort each group by the sitemap configuration where the detail page is coming from,
// and then only take the last element in each group.
for (CmsXmlSitemapUrlBean urlBean : parentResult) {
if (urlBean.getDetailPageResource() == null) {
result.add(urlBean);
} else {
String localeKey = urlBean.getOriginalResource().getStructureId() + "_" + urlBean.getLocale();
detailPageBeans.put(localeKey, urlBean);
}
}
Comparator pathComparator = new Comparator() {
public int compare(CmsXmlSitemapUrlBean urlbean1, CmsXmlSitemapUrlBean urlbean2) {
String subsite1 = urlbean1.getSubsite();
if (subsite1 == null) {
subsite1 = "";
}
String subsite2 = urlbean2.getSubsite();
if (subsite2 == null) {
subsite2 = "";
}
return subsite1.compareTo(subsite2);
}
};
for (String key : detailPageBeans.keySet()) {
result.add(Collections.max(detailPageBeans.get(key), pathComparator));
}
return result;
}
/**
* @see org.opencms.site.xmlsitemap.CmsXmlSitemapGenerator#addDetailLinks(org.opencms.file.CmsResource, java.util.Locale)
*/
@Override
protected void addDetailLinks(CmsResource containerPage, Locale locale) throws CmsException {
Collection detailInfos = getDetailInfosForPage(containerPage);
for (DetailInfo info : detailInfos) {
List contents = getContents(info.getFolderPath(), info.getType());
for (CmsResource detailRes : contents) {
List detailProps = m_guestCms.readPropertyObjects(detailRes, true);
String detailLink = getDetailLink(containerPage, detailRes, locale);
detailLink = CmsFileUtil.removeTrailingSeparator(detailLink);
CmsXmlSitemapUrlBean detailUrlBean = new CmsXmlSitemapUrlBean(
replaceServerUri(detailLink),
detailRes.getDateLastModified(),
getChangeFrequency(detailProps),
getPriority(detailProps));
detailUrlBean.setLocale(locale);
detailUrlBean.setOriginalResource(detailRes);
detailUrlBean.setDetailPageResource(containerPage);
detailUrlBean.setSubsite(info.getBasePath());
addResult(detailUrlBean, 2);
}
}
}
/**
* Gets the contents for the given folder path and type name.
*
* @param folderPath the content folder path
* @param type the type name
* @return the list of contents
*
* @throws CmsException if something goes wrong
*/
private List getContents(String folderPath, String type) throws CmsException {
CmsPathMap pathMap = getPathMapForType(type);
return pathMap.getChildValues(folderPath);
}
/**
* Gets the detail information for the given container page.
*
* @param containerPage the container page
* @return the detail information
*/
private Collection getDetailInfosForPage(CmsResource containerPage) {
if (m_detailInfosByPage == null) {
m_detailInfosByPage = ArrayListMultimap.create();
for (DetailInfo detailInfo : m_detailInfos) {
m_detailInfosByPage.put(detailInfo.getDetailPageInfo().getUri(), detailInfo);
}
}
String folderPath = CmsResource.getParentFolder(containerPage.getRootPath());
Collection result = m_detailInfosByPage.get(containerPage.getRootPath());
if (result.isEmpty()) {
result = m_detailInfosByPage.get(folderPath);
}
return result;
}
/**
* Gets the path map containing the contents for the given type.
*
* @param typeName the type name
* @return the path map with the content resources
*
* @throws CmsException if something goes wrong
*/
private CmsPathMap getPathMapForType(String typeName) throws CmsException {
if (!m_pathMapsByType.containsKey(typeName)) {
CmsPathMap pathMap = readPathMapForType(
OpenCms.getResourceManager().getResourceType(typeName));
m_pathMapsByType.put(typeName, pathMap);
}
return m_pathMapsByType.get(typeName);
}
/**
* Reads the contents of a given type and stores them in a path map.
*
* @param type the type for which to read the contents
* @return the path map containing the contents
*/
private CmsPathMap readPathMapForType(I_CmsResourceType type) {
List result = new ArrayList();
CmsResourceFilter filter = CmsResourceFilter.DEFAULT_FILES.addRequireType(type);
try {
List siteFiles = m_guestCms.readResources(m_siteRoot, filter, true);
result.addAll(siteFiles);
} catch (CmsException e) {
LOG.error("XML sitemap generator error: " + e.getLocalizedMessage(), e);
}
String shared = CmsFileUtil.removeTrailingSeparator(OpenCms.getSiteManager().getSharedFolder());
if (shared != null) {
try {
List sharedFiles = m_guestCms.readResources(shared, filter, true);
result.addAll(sharedFiles);
} catch (CmsException e) {
LOG.error("XML sitemap generator error: " + e.getLocalizedMessage(), e);
}
}
CmsPathMap resultMap = new CmsPathMap();
for (CmsResource resource : result) {
resultMap.add(resource.getRootPath(), resource);
}
return resultMap;
}
}