/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.content;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.enonic.vertical.adminweb.handlers.xmlbuilders.ContentBaseXMLBuilder;
import com.enonic.cms.framework.util.JDOMUtil;
import com.enonic.cms.core.content.access.ContentAccessEntity;
import com.enonic.cms.core.content.binary.BinaryDataKey;
import com.enonic.cms.core.content.category.CategoryEntity;
import com.enonic.cms.core.content.category.CategoryKey;
import com.enonic.cms.core.content.contentdata.ContentData;
import com.enonic.cms.core.content.contentdata.ContentDataParser;
import com.enonic.cms.core.content.contenttype.ContentTypeEntity;
import com.enonic.cms.core.language.LanguageEntity;
import com.enonic.cms.core.language.LanguageKey;
import com.enonic.cms.core.security.group.GroupEntity;
import com.enonic.cms.core.security.user.UserEntity;
import com.enonic.cms.core.security.user.UserKey;
import com.enonic.cms.store.dao.CategoryDao;
import com.enonic.cms.store.dao.ContentDao;
import com.enonic.cms.store.dao.ContentVersionDao;
import com.enonic.cms.store.dao.GroupDao;
import com.enonic.cms.store.dao.LanguageDao;
import com.enonic.cms.store.dao.UserDao;
public class ContentParser
{
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormat.forPattern( "yyyy-MM-dd HH:mm" );
/**
* Whether to parse contentdata from xml data or not. If false, contentdata is loaded from storage instead. Default is true.
*/
private boolean parseContentData = true;
private boolean parseContentCreatedAt = false;
private ContentDao contentDao;
private ContentVersionDao contentVersionDao;
private CategoryDao categoryDao;
private UserDao userDao;
private GroupDao groupDao;
private LanguageDao languageDao;
private Element contentEl;
private List<BinaryDataKey> binaryDatas;
private static final String COMMENT_XML_KEY = "comment";
public ContentParser( ContentDao contentDao, ContentVersionDao contentVersionDao, CategoryDao categoryDao, GroupDao groupDao,
UserDao userDao, LanguageDao languageDao, String contentXml )
{
this.contentDao = contentDao;
this.contentVersionDao = contentVersionDao;
this.userDao = userDao;
this.categoryDao = categoryDao;
this.groupDao = groupDao;
this.languageDao = languageDao;
if ( contentXml != null )
{
Document doc = getContentElement( contentXml );
this.contentEl = doc.getRootElement();
if ( !"content".equals( this.contentEl.getName() ) )
{
throw new IllegalArgumentException(
"Root element in content XML expected to be named 'content': " + this.contentEl.getName() );
}
}
}
public void setBinaryDatas( List<BinaryDataKey> list )
{
this.binaryDatas = list;
}
public void setParseContentData( boolean value )
{
this.parseContentData = value;
}
public void setParseContentCreatedAt( boolean parseContentCreatedAt )
{
this.parseContentCreatedAt = parseContentCreatedAt;
}
public ContentAndVersion parseContentAndVersion( Element contentEl )
{
this.contentEl = contentEl;
return parseContentAndVersion();
}
public ContentAndVersion parseContentAndVersion()
{
ContentEntity content = parseContent();
ContentVersionEntity version = parseContentVersion( content );
return new ContentAndVersion( content, version );
}
private ContentEntity parseContent()
{
ContentEntity content = new ContentEntity();
content.setName( parseContentName() );
content.setKey( parseContentKey() );
content.setAvailableFrom( parsePublishFrom() );
content.setAvailableTo( parsePublishTo() );
content.setPriority( parsePriority() );
CategoryEntity category = parseCategory();
if ( category == null )
{
throw new IllegalArgumentException( "Given contentXml did not define category" );
}
content.setCategory( category );
LanguageEntity language = parseLanguage();
if ( language == null )
{
// set language to category's language if not given in xml
language = category.getLanguage();
}
content.setLanguage( language );
content.setOwner( parseOwner() );
content.setAssignee( parseAssignee() );
content.setAssignmentDueDate( parseDueDate() );
content.setAssignmentDescription( parseAssignmentComment() );
content.setAssigner( parseAssigner() );
content.addContentAccessRights( parseContentAccessRights() );
if ( parseContentCreatedAt )
{
content.setCreatedAt( parseCreatedAt() );
}
return content;
}
private String parseAssignmentComment()
{
Element assignmentCommentElement = contentEl.getChild( ContentBaseXMLBuilder.ASSIGNMENT_DESCRIPTION_XML_KEY );
if ( assignmentCommentElement == null )
{
return null;
}
String assignmentComment = assignmentCommentElement.getValue();
if ( StringUtils.isBlank( assignmentComment ) )
{
return "";
}
return assignmentComment;
}
private String parseContentName()
{
Element contentNameElement = contentEl.getChild( "name" );
if ( contentNameElement == null )
{
return null;
}
String contentName = contentNameElement.getValue();
if ( StringUtils.isBlank( contentName ) )
{
return "";
}
return contentName;
}
private String parseComment()
{
Element contentNameElement = contentEl.getChild( ContentBaseXMLBuilder.COMMENT_XML_KEY );
if ( contentNameElement == null )
{
return null;
}
String description = contentNameElement.getValue();
if ( StringUtils.isBlank( description ) )
{
return "";
}
return description;
}
public ContentVersionEntity parseContentVersion( ContentEntity content )
{
ContentVersionEntity version = new ContentVersionEntity();
version.setKey( parseContentVersionKey() );
version.setContent( content );
version.setStatus( ContentStatus.get( parseStatus() ) );
version.setModifiedBy( parseModifier() );
version.setChangeComment( parseComment() );
ContentData contentData = parseContentData( content, version );
version.setContentData( contentData );
Set<ContentKey> relatedcontentKeys = contentData.resolveRelatedContentKeys();
for ( ContentKey relatedContentKey : relatedcontentKeys )
{
ContentEntity relatedContent = contentDao.findByKey( relatedContentKey );
if ( relatedContent != null )
{
version.addRelatedChild( relatedContent );
}
}
return version;
}
private ContentData parseContentData( ContentEntity content, ContentVersionEntity version )
{
ContentData contentData = null;
if ( parseContentData )
{
contentData = parseContentData( content.getCategory().getContentType() );
}
else if ( version.getKey() != null )
{
ContentVersionEntity persistedVersion = contentVersionDao.findByKey( version.getKey() );
if ( persistedVersion != null )
{
contentData = persistedVersion.getContentData();
}
}
return contentData;
}
public List<ContentAccessEntity> parseContentAccessRights()
{
List<ContentAccessEntity> list = new ArrayList<ContentAccessEntity>();
Element accessrightsEl = contentEl.getChild( "accessrights" );
if ( accessrightsEl == null )
{
return list;
}
//noinspection unchecked
List<Element> accessrighElList = accessrightsEl.getChildren( "accessright" );
for ( Element accessrightEl : accessrighElList )
{
ContentAccessEntity accessRight = parseContentAccessRight( accessrightEl );
if ( accessRight != null )
{
list.add( accessRight );
}
}
return list;
}
private ContentAccessEntity parseContentAccessRight( Element accessRightEl )
{
GroupEntity group = parseGroup( accessRightEl.getAttributeValue( "groupkey" ) );
if ( group == null )
{
return null;
}
ContentAccessEntity contentAccess = new ContentAccessEntity();
contentAccess.setGroup( group );
contentAccess.setReadAccess( parseBoolean( accessRightEl.getAttributeValue( "read" ), false ) );
contentAccess.setUpdateAccess( parseBoolean( accessRightEl.getAttributeValue( "update" ), false ) );
contentAccess.setDeleteAccess( parseBoolean( accessRightEl.getAttributeValue( "delete" ), false ) );
return contentAccess;
}
private GroupEntity parseGroup( String groupKeyStr )
{
return groupDao.find( groupKeyStr );
}
private ContentData parseContentData( ContentTypeEntity contentType )
{
Element contentdataEl = contentEl.getChild( "contentdata" );
if ( contentdataEl == null )
{
return null;
}
Document doc = new Document( (Element) contentdataEl.detach() );
return ContentDataParser.parse( doc, contentType, binaryDatas );
}
private CategoryEntity parseCategory()
{
Element categorynameEl = contentEl.getChild( "categoryname" );
if ( categorynameEl == null )
{
return null;
}
String categoryKeyStr = categorynameEl.getAttributeValue( "key" );
if ( categoryKeyStr == null )
{
return null;
}
CategoryKey categoryKey = new CategoryKey( categoryKeyStr );
return categoryDao.findByKey( categoryKey );
}
private UserEntity parseOwner()
{
Element ownerEl = contentEl.getChild( "owner" );
if ( ownerEl == null )
{
return null;
}
String ownerKeyStr = ownerEl.getAttributeValue( "key" );
if ( ownerKeyStr == null )
{
return null;
}
UserKey userKey = new UserKey( ownerKeyStr );
return userDao.findByKey( userKey.toString() );
}
private UserEntity parseAssigner()
{
Element assignerEl = contentEl.getChild( ContentBaseXMLBuilder.ASSIGNER_XML_KEY );
if ( assignerEl == null )
{
return null;
}
String assignerKeyString = assignerEl.getAttributeValue( "key" );
if ( assignerKeyString == null )
{
return null;
}
UserKey userKey = new UserKey( assignerKeyString );
return userDao.findByKey( userKey );
}
private UserEntity parseAssignee()
{
Element assigneeEl = contentEl.getChild( ContentBaseXMLBuilder.ASSIGNEE_XML_KEY );
if ( assigneeEl == null )
{
return null;
}
String assigneeKeyString = assigneeEl.getAttributeValue( "key" );
if ( assigneeKeyString == null )
{
return null;
}
UserKey userKey = new UserKey( assigneeKeyString );
return userDao.findByKey( userKey );
}
private UserEntity parseModifier()
{
Element modifierEl = contentEl.getChild( "modifier" );
if ( modifierEl == null )
{
return null;
}
String modifierKeyStr = modifierEl.getAttributeValue( "key" );
if ( modifierKeyStr == null )
{
return null;
}
UserKey userKey = new UserKey( modifierKeyStr );
return userDao.findByKey( userKey.toString() );
}
private LanguageEntity parseLanguage()
{
String languageKeyStr = contentEl.getAttributeValue( "languagekey" );
if ( StringUtils.isBlank( languageKeyStr ) )
{
return null;
}
return languageDao.findByKey( new LanguageKey( languageKeyStr ) );
}
private ContentKey parseContentKey()
{
String string = contentEl.getAttributeValue( "key" );
Integer intValue = parseInteger( string, null );
if ( intValue == null )
{
return null;
}
return new ContentKey( intValue );
}
private ContentVersionKey parseContentVersionKey()
{
String string = contentEl.getAttributeValue( "versionkey" );
Integer intValue = parseInteger( string, null );
if ( intValue == null )
{
return null;
}
return new ContentVersionKey( intValue );
}
private Date parseCreatedAt()
{
String dateString = contentEl.getAttributeValue( "created" );
return parseDate( dateString );
}
private Date parsePublishFrom()
{
String dateString = contentEl.getAttributeValue( "publishfrom" );
return parseDate( dateString );
}
private Date parsePublishTo()
{
String dateString = contentEl.getAttributeValue( "publishto" );
return parseDate( dateString );
}
private Date parseDueDate()
{
Element dueDate = contentEl.getChild( ContentBaseXMLBuilder.ASSIGNMENT_DUEDATE_XML_KEY );
if ( dueDate != null )
{
String dateString = dueDate.getValue();
return parseDate( dateString );
}
return null;
}
private Integer parseStatus()
{
String statusString = contentEl.getAttributeValue( "status" );
return parseInteger( statusString, null );
}
private Integer parsePriority()
{
String priorityStr = contentEl.getAttributeValue( "priority" );
return parseInteger( priorityStr, 0 );
}
private Date parseDate( String dateString )
{
if ( dateString == null || dateString.trim().length() == 0 )
{
return null;
}
final DateTime date = DATE_TIME_FORMATTER.parseDateTime( dateString );
return date.toDate();
}
private Integer parseInteger( String str, Integer defaultValue )
{
if ( str == null || str.trim().length() == 0 )
{
return defaultValue;
}
return Integer.valueOf( str );
}
private Boolean parseBoolean( String value, Boolean defaultValue )
{
if ( value == null )
{
return defaultValue;
}
else if ( "true".equals( value ) )
{
return Boolean.TRUE;
}
else if ( "false".equals( value ) )
{
return Boolean.FALSE;
}
return defaultValue;
}
private static Document getContentElement( String contentXml )
{
try
{
return JDOMUtil.parseDocument( contentXml );
}
catch ( Exception e )
{
throw new RuntimeException( "Failed to parse contentXml", e );
}
}
}