/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.content.contentdata.legacy; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.lang.builder.HashCodeBuilder; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.transform.JDOMSource; import net.sf.saxon.om.NodeInfo; import net.sf.saxon.sxpath.XPathEvaluator; import net.sf.saxon.sxpath.XPathExpression; import com.enonic.cms.framework.util.JDOMUtil; import com.enonic.cms.core.content.ContentKey; import com.enonic.cms.core.content.binary.BinaryDataAndBinary; import com.enonic.cms.core.content.binary.BinaryDataKey; import com.enonic.cms.core.content.contentdata.ContentData; public abstract class AbstractBaseLegacyContentData implements ContentData { private String contentDataXmlString; protected Document contentDataXml; protected Element contentDataEl; private String title; private List<BinaryDataAndBinary> binaryDataAndBinaries; public AbstractBaseLegacyContentData( Document contentDataXml ) { this.contentDataXml = contentDataXml; contentDataEl = contentDataXml.getRootElement(); if ( !"contentdata".equals( contentDataEl.getName() ) ) { throw new IllegalArgumentException( "Expected contentdata as root element" ); } } public Document getContentDataXml() { return contentDataXml; } private String getContentDataXmlString() { if ( contentDataXmlString == null ) { contentDataXmlString = JDOMUtil.printDocument( contentDataXml ); } return contentDataXmlString; } public String getTitle() { if ( title == null ) { title = resolveTitle(); } return title; } public Set<ContentKey> resolveRelatedContentKeys() { return new HashSet<ContentKey>(); } /** * mark references in XML to content as deleted. * * @param key key to find and remove * @return true, if something was removed */ public boolean markReferencesToContentAsDeleted( final ContentKey key ) { return false; } /** * mark references in XML to content as deleted. * * @param iterator node iterator * @param contentKey key to find and remove * @return true, if something was removed */ protected boolean markReferencesToContentAsDeleted( final Iterator iterator, final ContentKey contentKey ) { while ( iterator.hasNext() ) { final Element e = Element.class.cast( iterator.next() ); if ( e.getAttribute( "key" ).getValue().equals( contentKey.toString() ) ) { e.setAttribute( "deleted", "true" ); return true; } } return false; } public boolean hasRelatedChild( ContentKey contentKey ) { return resolveRelatedContentKeys().contains( contentKey ); } public List<BinaryDataAndBinary> getBinaryDataAndBinaryList() { if ( binaryDataAndBinaries == null ) { binaryDataAndBinaries = resolveBinaryDataAndBinaryList(); } return binaryDataAndBinaries; } protected abstract String resolveTitle(); protected abstract List<BinaryDataAndBinary> resolveBinaryDataAndBinaryList(); protected void replaceBinaryKeyPlaceHolder( Attribute attribute, List<BinaryDataKey> binaryDatas ) { String keyPlaceHolder = attribute.getValue(); Integer keyPlaceHolderIndex = resolvePlaceHolderIndex( keyPlaceHolder ); if ( keyPlaceHolderIndex == null ) { // key already set, lets return return; } BinaryDataKey key = findBinaryDataKeyByIndex( keyPlaceHolderIndex, binaryDatas ); if ( key == null ) { attribute.setValue( "#ERROR: Binary key not found" ); } else { attribute.setValue( key.toString() ); } } private BinaryDataKey findBinaryDataKeyByIndex( Integer keyPlaceHolderIndex, List<BinaryDataKey> binaryDatas ) { if ( keyPlaceHolderIndex < 0 || keyPlaceHolderIndex > binaryDatas.size() - 1 ) { return null; } return binaryDatas.get( keyPlaceHolderIndex ); } private Integer resolvePlaceHolderIndex( String keyPlaceHolder ) { if ( keyPlaceHolder == null ) { return null; } if ( !keyPlaceHolder.startsWith( "%" ) ) { return null; } return Integer.valueOf( keyPlaceHolder.substring( 1 ) ); } protected List<ContentKey> resolveContentKeysByXPath( String xPath ) { try { XPathEvaluator xpathEvaluator = new XPathEvaluator(); XPathExpression expr = xpathEvaluator.createExpression( xPath ); final JDOMSource docAsDomSource = new JDOMSource( contentDataXml ); List<ContentKey> contentKeys = new ArrayList<ContentKey>(); List nodes = expr.evaluate( docAsDomSource ); for ( Object node : nodes ) { if ( node instanceof NodeInfo ) { NodeInfo nodeInfo = (NodeInfo) node; contentKeys.add( new ContentKey( nodeInfo.getStringValue() ) ); } else { contentKeys.add( new ContentKey( String.valueOf( node ) ) ); } } return contentKeys; } catch ( Exception e ) { throw new RuntimeException( e ); } } @Override public boolean equals( Object o ) { if ( this == o ) { return true; } if ( !( o instanceof AbstractBaseLegacyContentData ) ) { return false; } AbstractBaseLegacyContentData that = (AbstractBaseLegacyContentData) o; if ( !getContentDataXmlString().equals( that.getContentDataXmlString() ) ) { return false; } return true; } @Override public int hashCode() { return new HashCodeBuilder( 317, 381 ). append( getContentDataXmlString() ). toHashCode(); } }