/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.content.imports;
import java.util.List;
import java.util.Map;
import com.enonic.cms.core.content.ContentEntity;
import com.enonic.cms.core.content.ContentKey;
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.CustomContentData;
import com.enonic.cms.core.content.contentdata.custom.DataEntry;
import com.enonic.cms.core.content.contentdata.custom.DataEntrySet;
import com.enonic.cms.core.content.contentdata.custom.DateDataEntry;
import com.enonic.cms.core.content.contentdata.custom.GroupDataEntry;
import com.enonic.cms.core.content.contentdata.custom.KeywordsDataEntry;
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.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.ContentTypeConfig;
import com.enonic.cms.core.content.contenttype.CtyImportBlockConfig;
import com.enonic.cms.core.content.contenttype.CtyImportMappingConfig;
import com.enonic.cms.core.content.contenttype.CtySetConfig;
import com.enonic.cms.core.content.contenttype.dataentryconfig.DataEntryConfig;
import com.enonic.cms.core.content.contenttype.dataentryconfig.RelatedContentDataEntryConfig;
import com.enonic.cms.core.content.imports.sourcevalueholders.AbstractSourceValue;
/**
* Apr 17, 2009
*/
public class ImportDataEntryParser
{
private RelatedContentFinder relatedContentFinder;
private ContentTypeConfig contentTypeConfig;
public ImportDataEntryParser( RelatedContentFinder relatedContentFinder, ContentTypeConfig contentTypeConfig )
{
this.relatedContentFinder = relatedContentFinder;
this.contentTypeConfig = contentTypeConfig;
}
public CustomContentData parseToCustomContentData( final ImportDataEntry importData, final ContentEntity existingContent )
{
final CustomContentData contentData = new CustomContentData( contentTypeConfig );
parseSet( importData, contentData, true );
parseBlocks( importData, contentData, new BlockIndexResolver( existingContent ) );
return contentData;
}
private void parseBlocks( final ImportDataEntry importDataEntry, final CustomContentData contentData,
final BlockIndexResolver blockIndexResolver )
{
for ( final Map.Entry<CtyImportBlockConfig, ImportDataEntry> blockConfigAndValue : importDataEntry.getBlockConfigAndValue().entries() )
{
final CtyImportBlockConfig blockImportConfig = blockConfigAndValue.getKey();
final CtySetConfig blockConfig = contentTypeConfig.getSetConfig( blockImportConfig.getDestination() );
final ImportDataEntry blockImportDataEntry = blockConfigAndValue.getValue();
String syncInputName = null;
if ( blockImportConfig.hasSyncSetting() )
{
final CtyImportMappingConfig mappingConfigForSync = blockImportConfig.getSyncMapping();
syncInputName = mappingConfigForSync.getDestination();
}
final int blockGroupIndex =
blockIndexResolver.resolve( blockConfig.getName(), syncInputName, blockImportDataEntry.getSyncValue() );
final DataEntrySet blockEntrySet = getNewGroupBlock( contentData, blockConfig, blockGroupIndex );
parseSet( blockImportDataEntry, blockEntrySet, false );
}
}
private void parseSet( final ImportDataEntry importData, final DataEntrySet entrySet, final boolean allowBlockCreation )
{
int nextBinaryKeyPlaceHolderIndex = 0;
for ( final Map.Entry<CtyImportMappingConfig, AbstractSourceValue> configAndValue : importData.getConfigAndValueMap().entrySet() )
{
final DataEntryConfig dataEntryConfig = contentTypeConfig.getInputConfig( configAndValue.getKey().getDestination() );
DataEntrySet dataEntrySet;
final boolean inBlockGroup = dataEntryConfig.getSetConfig().getGroupXPath() != null;
if ( inBlockGroup && allowBlockCreation )
{
dataEntrySet = getBlockGroup( entrySet, dataEntryConfig.getSetConfig() );
}
else
{
dataEntrySet = entrySet;
}
final DataEntry dataEntry = dataEntrySet.getEntry( dataEntryConfig.getName() );
boolean dataEntryAlreadyExist = dataEntry != null;
if ( dataEntryAlreadyExist && inBlockGroup && allowBlockCreation )
{
/* Entry already exist in block group - create a new one */
dataEntrySet = getNewBlockGroup( entrySet, dataEntryConfig.getSetConfig() );
dataEntryAlreadyExist = false;
}
if ( !dataEntryAlreadyExist )
{
final DataEntry newDataEntry = getNewDataEntry( dataEntryConfig, configAndValue, nextBinaryKeyPlaceHolderIndex );
dataEntrySet.add( newDataEntry );
}
}
}
private DataEntrySet getBlockGroup( final DataEntrySet entrySet, final CtySetConfig setConfig )
{
final List<GroupDataEntry> groups = entrySet.getGroupDataSets( setConfig.getName() );
if ( groups.isEmpty() )
{
return getNewGroupBlock( entrySet, setConfig, 1 );
}
return groups.get( groups.size() - 1 );
}
private DataEntrySet getNewBlockGroup( final DataEntrySet entrySet, final CtySetConfig setConfig )
{
final List<GroupDataEntry> groups = entrySet.getGroupDataSets( setConfig.getName() );
return getNewGroupBlock( entrySet, setConfig, groups.size() + 1 );
}
private DataEntrySet getNewGroupBlock( final DataEntrySet entrySet, final CtySetConfig setConfig, final int blockGroupIndex )
{
final GroupDataEntry group = new GroupDataEntry( setConfig.getName(), setConfig.getGroupXPath(), blockGroupIndex );
entrySet.add( group );
return group;
}
private DataEntry getNewDataEntry( final DataEntryConfig dataEntryConfig,
final Map.Entry<CtyImportMappingConfig, AbstractSourceValue> configAndValue,
int nextBinaryKeyPlaceHolderIndex )
{
final CtyImportMappingConfig mappingConfig = configAndValue.getKey();
final AbstractSourceValue value = configAndValue.getValue();
switch ( dataEntryConfig.getType() )
{
// String based types
case TEXT:
return new TextDataEntry( dataEntryConfig, ImportValueFormater.getText( value ) );
case TEXT_AREA:
return new TextAreaDataEntry( dataEntryConfig, ImportValueFormater.getTextArea( value ) );
case XML:
return new XmlDataEntry( dataEntryConfig, ImportValueFormater.getXml( value ) );
case HTMLAREA:
return new HtmlAreaDataEntry( dataEntryConfig, ImportValueFormater.getHtmlArea( value ) );
case URL:
return new UrlDataEntry( dataEntryConfig, ImportValueFormater.getUrl( value ) );
case RADIOBUTTON:
case DROPDOWN:
return new SelectorDataEntry( dataEntryConfig, ImportValueFormater.getSelector( value ) );
// Content Key based types
case IMAGE:
return new ImageDataEntry( dataEntryConfig, ImportValueFormater.getContentKey( value ) );
case FILE:
return new FileDataEntry( dataEntryConfig, ImportValueFormater.getContentKey( value ) );
case RELATEDCONTENT:
return getRelatedContentEntry( dataEntryConfig, configAndValue );
// Other types
case CHECKBOX:
return new BooleanDataEntry( dataEntryConfig, ImportValueFormater.getBoolean( value ) );
case DATE:
return new DateDataEntry( dataEntryConfig, ImportValueFormater.getDate( value, mappingConfig.getFormat() ) );
case BINARY:
final String binaryName = ImportValueFormater.getAdditionalValue( value, "<unknown>" );
return new BinaryDataEntry( dataEntryConfig, "%" + String.valueOf( nextBinaryKeyPlaceHolderIndex++ ),
ImportValueFormater.getBinary( value ), binaryName );
case KEYWORDS:
return new KeywordsDataEntry( dataEntryConfig, ImportValueFormater.getKeywords( value ) );
// Unsupported types
case MULTIPLE_CHOICE: // ???
case FILES: // Discontinuted
case IMAGES: // Discontinuted
default:
throw new ImportException( "Import of data entrys of type \"" + dataEntryConfig.getType() + "\" is not supported." );
}
}
private DataEntry getRelatedContentEntry( final DataEntryConfig dataEntryConfig,
final Map.Entry<CtyImportMappingConfig, AbstractSourceValue> configAndValue )
{
final RelatedContentDataEntryConfig relConfig = (RelatedContentDataEntryConfig) dataEntryConfig;
final CtyImportMappingConfig importMappingConfig = configAndValue.getKey();
final boolean lookupRelatedContent = importMappingConfig.getRelatedContentType() != null;
final AbstractSourceValue sourceValue = configAndValue.getValue();
if ( relConfig.isMultiple() )
{
/* Multiple content */
List<ContentKey> contentKeys;
if ( lookupRelatedContent )
{
contentKeys = relatedContentFinder.getContentKeys( configAndValue );
}
else
{
contentKeys = ImportValueFormater.getContentKeys( sourceValue );
}
final RelatedContentsDataEntry relatedContents = new RelatedContentsDataEntry( dataEntryConfig );
for ( ContentKey contentKey : contentKeys )
{
relatedContents.add( new RelatedContentDataEntry( dataEntryConfig, contentKey ) );
}
return relatedContents;
}
else
{
/* Single content */
ContentKey contentKey;
if ( lookupRelatedContent )
{
contentKey = relatedContentFinder.getContentKey( configAndValue );
}
else
{
contentKey = ImportValueFormater.getContentKey( sourceValue );
}
return new RelatedContentDataEntry( dataEntryConfig, contentKey );
}
}
}