/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.content.contentdata.custom.support;
import java.util.List;
import org.jdom.Content;
import org.jdom.Document;
import org.jdom.Element;
import com.enonic.esl.util.DateUtil;
import com.enonic.cms.framework.xml.XMLDocument;
import com.enonic.cms.framework.xml.XMLDocumentFactory;
import com.enonic.cms.framework.xml.XMLException;
import com.enonic.cms.core.content.contentdata.ContentDataXPathCreator;
import com.enonic.cms.core.content.contentdata.custom.BinaryDataEntry;
import com.enonic.cms.core.content.contentdata.custom.BooleanDataEntry;
import com.enonic.cms.core.content.contentdata.custom.DataEntry;
import com.enonic.cms.core.content.contentdata.custom.DataEntryType;
import com.enonic.cms.core.content.contentdata.custom.DateDataEntry;
import com.enonic.cms.core.content.contentdata.custom.KeywordsDataEntry;
import com.enonic.cms.core.content.contentdata.custom.MultipleChoiceAlternative;
import com.enonic.cms.core.content.contentdata.custom.MultipleChoiceDataEntry;
import com.enonic.cms.core.content.contentdata.custom.RelationDataEntry;
import com.enonic.cms.core.content.contentdata.custom.contentkeybased.FileDataEntry;
import com.enonic.cms.core.content.contentdata.custom.contentkeybased.ImageDataEntry;
import com.enonic.cms.core.content.contentdata.custom.contentkeybased.RelatedContentDataEntry;
import com.enonic.cms.core.content.contentdata.custom.relationdataentrylistbased.FilesDataEntry;
import com.enonic.cms.core.content.contentdata.custom.relationdataentrylistbased.ImagesDataEntry;
import com.enonic.cms.core.content.contentdata.custom.relationdataentrylistbased.RelatedContentsDataEntry;
import com.enonic.cms.core.content.contentdata.custom.stringbased.HtmlAreaDataEntry;
import com.enonic.cms.core.content.contentdata.custom.stringbased.SelectorDataEntry;
import com.enonic.cms.core.content.contentdata.custom.stringbased.TextAreaDataEntry;
import com.enonic.cms.core.content.contentdata.custom.stringbased.TextDataEntry;
import com.enonic.cms.core.content.contentdata.custom.stringbased.UrlDataEntry;
import com.enonic.cms.core.content.contentdata.custom.xmlbased.XmlDataEntry;
import com.enonic.cms.core.content.contenttype.dataentryconfig.DataEntryConfig;
import com.enonic.cms.core.content.contenttype.dataentryconfig.RelatedContentDataEntryConfig;
/**
* 07.01.11
*/
public class DataEntryXmlCreator
{
private FileDataEntryXmlCreator fileDataEntryXmlCreator;
private BinaryDataEntryXmlCreator binaryDataEntryXmlCreator;
private boolean inBlockGroup;
public DataEntryXmlCreator( FileDataEntryXmlCreator fileDataEntryXmlCreator, BinaryDataEntryXmlCreator binaryDataEntryXmlCreator,
boolean inBlockGroup )
{
this.fileDataEntryXmlCreator = fileDataEntryXmlCreator;
this.binaryDataEntryXmlCreator = binaryDataEntryXmlCreator;
this.inBlockGroup = inBlockGroup;
}
public void createEntryElement( Element dataEntrySetEl, DataEntry entry )
{
if ( entry.getType() == DataEntryType.TEXT )
{
verifyClass( entry, TextDataEntry.class );
addTextDataEntry( dataEntrySetEl, (TextDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.TEXT_AREA )
{
verifyClass( entry, TextAreaDataEntry.class );
addTextAreaDataEntry( dataEntrySetEl, (TextAreaDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.HTML_AREA )
{
verifyClass( entry, HtmlAreaDataEntry.class );
addHtmlAreaDataEntry( dataEntrySetEl, (HtmlAreaDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.XML )
{
verifyClass( entry, XmlDataEntry.class );
addXmlDataEntry( dataEntrySetEl, (XmlDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.BINARY )
{
verifyClass( entry, BinaryDataEntry.class );
binaryDataEntryXmlCreator.createAndAddElement( dataEntrySetEl, (BinaryDataEntry) entry, inBlockGroup );
}
else if ( entry.getType() == DataEntryType.FILE )
{
verifyClass( entry, FileDataEntry.class );
fileDataEntryXmlCreator.createAndAddElement( dataEntrySetEl, (FileDataEntry) entry, inBlockGroup );
}
else if ( entry.getType() == DataEntryType.RELATED_CONTENT )
{
verifyClass( entry, RelatedContentDataEntry.class );
addRelatedContentDataEntry( dataEntrySetEl, (RelatedContentDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.RELATED_CONTENTS )
{
verifyClass( entry, RelatedContentsDataEntry.class );
addRelatedContentsDataEntry( dataEntrySetEl, (RelatedContentsDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.FILES )
{
verifyClass( entry, FilesDataEntry.class );
fileDataEntryXmlCreator.createAndAddElement( dataEntrySetEl, (FilesDataEntry) entry, inBlockGroup );
}
else if ( entry.getType() == DataEntryType.IMAGE )
{
verifyClass( entry, ImageDataEntry.class );
addImageDataEntry( dataEntrySetEl, (ImageDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.IMAGES )
{
verifyClass( entry, ImagesDataEntry.class );
addImagesDataEntry( dataEntrySetEl, (ImagesDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.KEYWORDS )
{
verifyClass( entry, KeywordsDataEntry.class );
addKeywordsDataEntry( dataEntrySetEl, (KeywordsDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.URL )
{
verifyClass( entry, UrlDataEntry.class );
addUrlDataEntry( dataEntrySetEl, (UrlDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.DATE )
{
verifyClass( entry, DateDataEntry.class );
addDateDataEntry( dataEntrySetEl, (DateDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.SELECTOR )
{
verifyClass( entry, SelectorDataEntry.class );
addSelectorDataEntry( dataEntrySetEl, (SelectorDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.BOOLEAN )
{
verifyClass( entry, BooleanDataEntry.class );
addBooleanDataEntry( dataEntrySetEl, (BooleanDataEntry) entry );
}
else if ( entry.getType() == DataEntryType.MULTIPLE_CHOICE )
{
verifyClass( entry, MultipleChoiceDataEntry.class );
addMultipleChoiceDataEntry( dataEntrySetEl, (MultipleChoiceDataEntry) entry );
}
else
{
throw new IllegalArgumentException( "DataEntry type not supported: " + entry.getType() );
}
}
private void addMultipleChoiceDataEntry( Element dataEntrySetEl, MultipleChoiceDataEntry entry )
{
Element entryElem = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryElem.addContent( new Element( "text" ).setText( entry.getText() ) );
for ( MultipleChoiceAlternative alternative : entry.getAlternatives() )
{
Element alternativeElement = new Element( "alternative" );
alternativeElement.setText( alternative.getAlternativeText() );
alternativeElement.setAttribute( "correct", alternative.isCorrectAsString() );
entryElem.addContent( alternativeElement );
}
}
private void addBooleanDataEntry( Element dataEntrySetEl, BooleanDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl,
stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryEl.setText( entry.getValueAsString() );
}
private void addSelectorDataEntry( Element dataEntrySetEl, SelectorDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryEl.setText( entry.getValue() );
}
private void addDateDataEntry( Element dataEntrySetEl, DateDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryEl.setText( DateUtil.formatISODate( entry.getValue() ) );
}
private void addXmlDataEntry( Element dataEntrySetEl, XmlDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryEl.addContent( entry.getValue().getRootElement().detach() );
}
private void addRelatedContentsDataEntry( Element dataEntrySetEl, RelatedContentsDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
for ( RelationDataEntry rel : entry.getEntries() )
{
Element contentEl = new Element( "content" );
contentEl.setAttribute( "key", rel.getContentKey().toString() );
addDeletedAttribute( rel, contentEl );
entryEl.addContent( contentEl );
}
}
private void addRelatedContentDataEntry( Element dataEntrySetEl, RelatedContentDataEntry entry )
{
final RelatedContentDataEntryConfig entryConfig = (RelatedContentDataEntryConfig) entry.getConfig();
Element entryEl =
ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entryConfig.getRelativeXPath() ) );
if ( entryConfig.isMultiple() )
{
Element contentEl = new Element( "content" );
contentEl.setAttribute( "key", entry.getContentKey().toString() );
addDeletedAttribute( entry, contentEl );
entryEl.addContent( contentEl );
}
else
{
entryEl.setAttribute( "key", entry.getContentKey().toString() );
addDeletedAttribute( entry, entryEl );
}
}
private void addDeletedAttribute( final RelationDataEntry entry, final Element contentEl )
{
if ( entry.isMarkedAsDeleted() )
{
contentEl.setAttribute( "deleted", "" + entry.isMarkedAsDeleted() );
}
}
private void addUrlDataEntry( Element dataEntrySetEl, UrlDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryEl.setText( entry.getValue() );
}
private void addKeywordsDataEntry( Element dataEntrySetEl, KeywordsDataEntry entry )
{
Element keywordsEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
for ( String s : entry.getKeywords() )
{
Element keywordEl = new Element( "keyword" );
keywordEl.setText( s );
keywordsEl.addContent( keywordEl );
}
}
private void addTextAreaDataEntry( Element dataEntrySetEl, TextAreaDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
//entryEl.addContent( new CDATA( StringUtil.replaceECC( entry.getValue() ) ) );
String entryValue = entry.getValue();
entryEl.addContent( entryValue );
}
private void addHtmlAreaDataEntry( final Element dataEntrySetEl, final HtmlAreaDataEntry entry )
{
final String wrapElementName = "temp-wraped-element-if-you-can-see-me-something-went-wrong";
final Element entryEl =
ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
if ( !entry.isEmpty() )
{
final String xmlStr = ensureXmlProlog( wrapElement( entry.getValue(), wrapElementName ) );
Document document;
try
{
final XMLDocument xml = XMLDocumentFactory.create( xmlStr );
document = xml.getAsJDOMDocument();
}
catch ( XMLException e )
{
throw new RuntimeException( "Failed to parse xml when adding entry: " + entry.getName(), e );
}
final Element rootEl = document.getRootElement();
if ( rootEl.getName().equals( wrapElementName ) )
{
@SuppressWarnings({"unchecked"}) final List<Content> children = rootEl.cloneContent();
entryEl.addContent( children );
}
else
{
entryEl.addContent( (Element) rootEl.clone() );
}
}
}
private void addTextDataEntry( Element dataEntrySetEl, TextDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryEl.setText( entry.getValue() );
}
private void addImageDataEntry( Element dataEntrySetEl, ImageDataEntry entry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( entry.getConfig() ) );
entryEl.setAttribute( "key", entry.getContentKey().toString() );
addDeletedAttribute( entry, entryEl );
}
private void addImagesDataEntry( Element dataEntrySetEl, ImagesDataEntry arrayEntry )
{
Element entryEl = ContentDataXPathCreator.ensurePath( dataEntrySetEl, stripContentdataWhenNotBlockGroup( arrayEntry.getConfig() ) );
for ( ImageDataEntry entry : arrayEntry.getEntries() )
{
Element imageEl = new Element( "image" );
entryEl.addContent( imageEl );
imageEl.setAttribute( "key", entry.getContentKey().toString() );
addDeletedAttribute( entry, imageEl );
Element textEl = new Element( "text" );
imageEl.addContent( textEl );
textEl.setText( entry.getImageText() );
}
}
private void verifyClass( DataEntry entry, Class expectedClass )
{
if ( !entry.getClass().isAssignableFrom( expectedClass ) )
{
throw new IllegalArgumentException(
"Input '" + entry.getName() + "' was not of expected class " + expectedClass.getName() + ", was " +
entry.getClass().getName() );
}
}
private String wrapElement( String xmlStr, String elementToWrap )
{
if ( xmlStr.startsWith( "<?xml" ) )
{
return xmlStr;
}
StringBuffer newXml = new StringBuffer();
newXml.append( "<" ).append( elementToWrap ).append( ">" );
newXml.append( xmlStr );
newXml.append( "</" ).append( elementToWrap ).append( ">" );
return newXml.toString();
}
private String ensureXmlProlog( String xmlStr )
{
if ( xmlStr.startsWith( "<?xml" ) )
{
return xmlStr;
}
StringBuffer newXmlStr = new StringBuffer();
newXmlStr.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" );
newXmlStr.append( xmlStr );
return newXmlStr.toString();
}
private String stripContentdataWhenNotBlockGroup( DataEntryConfig dataEntryConfig )
{
return stripContentdataWhenNotBlockGroup( dataEntryConfig.getRelativeXPath() );
}
private String stripContentdataWhenNotBlockGroup( String xpath )
{
if ( !inBlockGroup && xpath.startsWith( "contentdata/" ) )
{
return xpath.substring( "contentdata/".length() );
}
else if ( !inBlockGroup && xpath.startsWith( "/contentdata/" ) )
{
return xpath.substring( "/contentdata/".length() );
}
return xpath;
}
}