/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.resource.xml;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Multimap;
import com.enonic.esl.util.DigestUtil;
import com.enonic.cms.framework.xml.XMLBuilder;
import com.enonic.cms.framework.xml.XMLDocument;
import com.enonic.cms.core.CmsDateAndTimeFormats;
import com.enonic.cms.core.resource.ResourceBase;
import com.enonic.cms.core.resource.ResourceFile;
import com.enonic.cms.core.resource.ResourceFolder;
import com.enonic.cms.core.resource.ResourceKey;
import com.enonic.cms.core.resource.ResourceReferencer;
import com.enonic.cms.core.structure.SiteKey;
public final class ResourceXmlCreator
{
private boolean includeFullPath = true;
/**
* Zero means all levels are included.
*/
private int maxLevels = 0;
private HashMap<ResourceKey, Long> usageCountMap = null;
private boolean includeData = false;
private boolean listFolders = true;
private boolean listResources = true;
private boolean includeHidden = false;
private Multimap<ResourceKey, ResourceReferencer> usedByMap = null;
public void setIncludeFullPath( boolean includeFullPath )
{
this.includeFullPath = includeFullPath;
}
/**
* Set number of levels to include. 1 means that only top level is included, and so on. Default is zero, which
* means that all levels are included.
*/
public void setMaxLevels( int maxLevels )
{
this.maxLevels = maxLevels;
}
public void setUsageCountMap( HashMap<ResourceKey, Long> usageCountMap )
{
this.usageCountMap = usageCountMap;
}
public void setIncludeData( boolean includeData )
{
this.includeData = includeData;
}
public void setListFolders( boolean listFolders )
{
this.listFolders = listFolders;
}
public void setListResources( boolean listResources )
{
this.listResources = listResources;
}
public void setIncludeHidden( boolean includeHidden )
{
this.includeHidden = includeHidden;
}
public void setUsedByMap( Multimap<ResourceKey, ResourceReferencer> usedByMap )
{
this.usedByMap = usedByMap;
}
public XMLDocument createResourceXml( ResourceFile resourceFile )
{
XMLBuilder builder = new XMLBuilder();
addResource( builder, resourceFile );
return builder.getDocument();
}
public XMLDocument createResourceTreeXml( ResourceFolder root )
{
XMLBuilder builder = new XMLBuilder( "resources" );
addRootAttributes( builder, root );
addSubItems( builder, root, 1 );
return builder.getDocument();
}
private void addSubItems( XMLBuilder builder, ResourceFolder root, int level )
{
if ( listFolders )
{
for ( ResourceFolder f : root.getFolders() )
{
addFolder( builder, f, level );
}
}
if ( listResources )
{
for ( ResourceFile f : root.getFiles() )
{
addResource( builder, f );
}
}
}
private void addFolder( XMLBuilder builder, ResourceFolder f, int level )
{
if ( f.isHidden() && !includeHidden )
{
return;
}
builder.startElement( "folder" );
addFolderAttributes( builder, f );
if ( level == maxLevels )
{
builder.setAttribute( "maxLevelReached", true );
}
else
{
addSubItems( builder, f, level + 1 );
}
builder.endElement();
}
private void addResource( XMLBuilder builder, ResourceFile f )
{
if ( f.isHidden() && !includeHidden )
{
return;
}
builder.startElement( "resource" );
addResourceAttributes( builder, f );
if ( includeData )
{
builder.startElement( "data" );
builder.addContentAsCDATA( f.getDataAsString() );
builder.endElement();
}
if ( usedByMap != null )
{
addUsedBy( builder, ResourceKey.from( f.getPath() ) );
}
builder.endElement();
}
private void addRootAttributes( XMLBuilder builder, ResourceFolder f )
{
builder.setAttribute( "root", f.getPath() );
builder.setAttribute( "maxLevels", maxLevels );
}
private void addFolderAttributes( XMLBuilder builder, ResourceFolder f )
{
addCommonAttributes( builder, f );
if ( usageCountMap != null )
{
Long count = 0L;
for ( Map.Entry<ResourceKey, Long> entry : usageCountMap.entrySet() )
{
if ( entry.getKey().startsWith( f.getPath() ) )
{
count += entry.getValue();
}
}
builder.setAttribute( "usageCount", count );
}
}
private void addResourceAttributes( XMLBuilder builder, ResourceFile f )
{
addCommonAttributes( builder, f );
builder.setAttribute( "size", f.getSize() );
builder.setAttribute( "mimeType", f.getMimeType() );
if ( usageCountMap != null )
{
ResourceKey resourceKey = ResourceKey.from( f.getPath() );
Long count = usageCountMap.containsKey( resourceKey ) ? usageCountMap.get( resourceKey ) : 0;
builder.setAttribute( "usageCount", count );
}
}
private void addCommonAttributes( XMLBuilder builder, ResourceBase f )
{
builder.setAttribute( "name", f.getName() );
builder.setAttribute( "lastModified", CmsDateAndTimeFormats.printAs_XML_TIMESTAMP( f.getLastModified().getTime() ) );
if ( includeFullPath )
{
builder.setAttribute( "hashedFullPath", DigestUtil.generateMD5( f.getPath() ) );
builder.setAttribute( "fullPath", f.getPath() );
}
if ( includeHidden && f.isHidden() )
{
builder.setAttribute( "hidden", true );
}
}
private void addUsedBy( XMLBuilder builder, ResourceKey resourceKey )
{
SortBySiteBuilderWrapper sortBySiteWrapper = new SortBySiteBuilderWrapper( usedByMap.get( resourceKey ) );
builder.startElement( "usedBy" );
addSiteRefUsage( builder, sortBySiteWrapper );
addContentTypeUsage( builder, sortBySiteWrapper );
builder.endElement();
}
private void addSiteRefUsage( XMLBuilder builder, SortBySiteBuilderWrapper sortBySiteWrapper )
{
Set<Map.Entry<SiteKey, String>> sites = sortBySiteWrapper.getSites().entrySet();
if ( sites.size() == 0 )
{
return;
}
List<ResourceReferencer> refs = sortBySiteWrapper.getSiteUsage();
for ( Map.Entry<SiteKey, String> site : sites )
{
builder.startElement( "site" );
builder.setAttribute( "key", site.getKey().toInt() );
builder.setAttribute( "name", site.getValue() );
builder.setAttribute( "defaultCss", isSiteRef( refs, site.getKey() ) );
addContentObjectUsage( builder, sortBySiteWrapper, site.getKey() );
addPageTemplateUsage( builder, sortBySiteWrapper, site.getKey() );
builder.endElement();
}
}
private boolean isSiteRef( List<ResourceReferencer> refs, SiteKey siteKey )
{
for ( ResourceReferencer ref : refs )
{
if ( ref.getSiteKey().equals( siteKey ) )
{
return true;
}
}
return false;
}
private void addContentObjectUsage( XMLBuilder builder, SortBySiteBuilderWrapper sortBySiteWrapper, SiteKey siteKey )
{
List<ResourceReferencer> refs = sortBySiteWrapper.getContentObjectUsage( siteKey );
if ( refs.size() == 0 )
{
return;
}
builder.startElement( "contentObjects" );
for ( ResourceReferencer ref : refs )
{
addReferencer( builder, "contentObject", ref );
}
builder.endElement();
}
private void addPageTemplateUsage( XMLBuilder builder, SortBySiteBuilderWrapper sortBySiteWrapper, SiteKey siteKey )
{
List<ResourceReferencer> refs = sortBySiteWrapper.getPageTemplateUsage( siteKey );
if ( refs.size() == 0 )
{
return;
}
builder.startElement( "pageTemplates" );
for ( ResourceReferencer ref : refs )
{
addReferencer( builder, "pageTemplate", ref );
}
builder.endElement();
}
private void addContentTypeUsage( XMLBuilder builder, SortBySiteBuilderWrapper sortBySiteWrapper )
{
List<ResourceReferencer> refs = sortBySiteWrapper.getContentTypeUsage();
if ( refs.size() == 0 )
{
return;
}
builder.startElement( "contentTypes" );
for ( ResourceReferencer ref : refs )
{
addReferencer( builder, "contentType", ref );
}
builder.endElement();
}
private void addReferencer( XMLBuilder builder, String elementName, ResourceReferencer ref )
{
builder.startElement( elementName );
builder.setAttribute( "key", ref.getKey() );
builder.setAttribute( "name", ref.getName() );
builder.endElement();
}
}