/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.repository2.unified.jcr.transform;
import java.util.Calendar;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.pentaho.platform.api.repository2.unified.IRepositoryFileData;
import org.pentaho.platform.api.repository2.unified.data.node.DataNode;
import org.pentaho.platform.api.repository2.unified.data.node.DataNodeRef;
import org.pentaho.platform.api.repository2.unified.data.node.DataProperty;
import org.pentaho.platform.api.repository2.unified.data.node.NodeRepositoryFileData;
import org.pentaho.platform.repository2.unified.jcr.ITransformer;
import org.pentaho.platform.repository2.unified.jcr.JcrStringHelper;
import org.pentaho.platform.repository2.unified.jcr.NodeHelper;
import org.pentaho.platform.repository2.unified.jcr.PentahoJcrConstants;
import org.springframework.util.Assert;
public class NodeRepositoryFileDataTransformer implements ITransformer<NodeRepositoryFileData> {
// ~ Static fields/initializers
// ======================================================================================
// ~ Instance fields
// =================================================================================================
// ~ Constructors
// ====================================================================================================
public NodeRepositoryFileDataTransformer() {
super();
}
// ~ Methods
// =========================================================================================================
protected void createOrUpdateContentNode( final Session session, final PentahoJcrConstants pentahoJcrConstants,
final NodeRepositoryFileData data, final Node fileNode ) throws RepositoryException {
Node unstructuredNode = null;
if ( fileNode.hasNode( pentahoJcrConstants.getJCR_CONTENT() ) ) {
unstructuredNode = fileNode.getNode( pentahoJcrConstants.getJCR_CONTENT() );
} else {
unstructuredNode =
fileNode.addNode( pentahoJcrConstants.getJCR_CONTENT(), pentahoJcrConstants.getPHO_NT_INTERNALFOLDER() );
}
// clear out all nodes since it's the quickest way to guarantee that existing nodes that should be deleted are
// removed
final String pattern = session.getNamespacePrefix( PentahoJcrConstants.PHO_NS ) + ":" + "*"; //$NON-NLS-1$ //$NON-NLS-2$
NodeIterator nodes = unstructuredNode.getNodes( pattern );
while ( nodes.hasNext() ) {
nodes.nextNode().remove();
}
internalCreateOrUpdate( session, pentahoJcrConstants, unstructuredNode, data.getNode() );
}
public void createContentNode( final Session session, final PentahoJcrConstants pentahoJcrConstants,
final NodeRepositoryFileData data, final Node fileNode ) throws RepositoryException {
createOrUpdateContentNode( session, pentahoJcrConstants, data, fileNode );
}
protected void internalCreateOrUpdate( final Session session, final PentahoJcrConstants pentahoJcrConstants,
final Node jcrParentNode, final DataNode dataNode ) throws RepositoryException {
final String prefix = session.getNamespacePrefix( PentahoJcrConstants.PHO_NS ) + ":"; //$NON-NLS-1$
// get or create the node represented by dataNode
Node jcrNode = null;
String nodeName = dataNode.getName();
// Not need to check the name if we encoded it
// JcrRepositoryFileUtils.checkName( dataNode.getName() );
nodeName = JcrStringHelper.fileNameEncode( nodeName );
if ( NodeHelper.hasNode( jcrParentNode, prefix, nodeName ) ) {
jcrNode = NodeHelper.getNode( jcrParentNode, prefix, nodeName );
} else {
jcrNode = jcrParentNode.addNode( prefix + nodeName, pentahoJcrConstants.getPHO_NT_INTERNALFOLDER() );
}
// set any properties represented by dataNode
for ( DataProperty dataProp : dataNode.getProperties() ) {
String propName = dataProp.getName();
// Not need to check the name if we encoded it
// JcrRepositoryFileUtils.checkName( propName );
propName = prefix + JcrStringHelper.fileNameEncode( propName );
switch ( dataProp.getType() ) {
case STRING: {
jcrNode.setProperty( propName, dataProp.getString() );
break;
}
case BOOLEAN: {
jcrNode.setProperty( propName, dataProp.getBoolean() );
break;
}
case DOUBLE: {
jcrNode.setProperty( propName, dataProp.getDouble() );
break;
}
case LONG: {
jcrNode.setProperty( propName, dataProp.getLong() );
break;
}
case DATE: {
Calendar cal = Calendar.getInstance();
cal.setTime( dataProp.getDate() );
jcrNode.setProperty( propName, cal );
break;
}
case REF: {
jcrNode.setProperty( propName, session.getNodeByIdentifier( dataProp.getRef().getId().toString() ) );
break;
}
default: {
throw new IllegalArgumentException();
}
}
}
// now process any child nodes of dataNode
for ( DataNode child : dataNode.getNodes() ) {
internalCreateOrUpdate( session, pentahoJcrConstants, jcrNode, child );
}
}
public NodeRepositoryFileData fromContentNode( final Session session, final PentahoJcrConstants pentahoJcrConstants,
final Node fileNode ) throws RepositoryException {
Node unstructuredNode = fileNode.getNode( pentahoJcrConstants.getJCR_CONTENT() );
final String pattern = session.getNamespacePrefix( PentahoJcrConstants.PHO_NS ) + ":" + "*"; //$NON-NLS-1$ //$NON-NLS-2$
Assert.isTrue( unstructuredNode.getNodes( pattern ).getSize() == 1 );
Node jcrNode = unstructuredNode.getNodes( pattern ).nextNode();
return new NodeRepositoryFileData( internalRead( session, pentahoJcrConstants, jcrNode, null ) );
}
protected DataNode internalRead( final Session session, final PentahoJcrConstants pentahoJcrConstants,
final Node jcrNode, final DataNode parentDataNode ) throws RepositoryException {
final String prefix = session.getNamespacePrefix( PentahoJcrConstants.PHO_NS ) + ":"; //$NON-NLS-1$
final String pattern = prefix + "*"; //$NON-NLS-1$
String nodeName = JcrStringHelper.fileNameDecode( jcrNode.getName().substring( prefix.length() ) );
DataNode dataNode = parentDataNode != null ? parentDataNode.addNode( nodeName ) : new DataNode( nodeName );
dataNode.setId( jcrNode.getIdentifier() );
PropertyIterator props = jcrNode.getProperties( pattern );
while ( props.hasNext() ) {
Property prop = props.nextProperty();
String propName = JcrStringHelper.fileNameDecode( prop.getName().substring( prefix.length() ) );
switch ( prop.getType() ) {
case PropertyType.STRING: {
dataNode.setProperty( propName, prop.getString() );
break;
}
case PropertyType.BOOLEAN: {
dataNode.setProperty( propName, prop.getBoolean() );
break;
}
case PropertyType.DOUBLE: {
dataNode.setProperty( propName, prop.getDouble() );
break;
}
case PropertyType.LONG: {
dataNode.setProperty( propName, prop.getLong() );
break;
}
case PropertyType.DATE: {
dataNode.setProperty( propName, prop.getDate().getTime() );
break;
}
case PropertyType.REFERENCE: {
try {
dataNode.setProperty( propName, new DataNodeRef( prop.getNode().getIdentifier() ) );
} catch ( ItemNotFoundException e ) {
// reference is missing, replace with missing data ref
// this situation can occur if the user does not have permission to access the reference.
dataNode.setProperty( propName, new DataNodeRef( DataNodeRef.REF_MISSING ) );
}
break;
}
default: {
throw new IllegalArgumentException();
}
}
}
// iterate over children
NodeIterator nodes = jcrNode.getNodes( pattern );
while ( nodes.hasNext() ) {
Node child = nodes.nextNode();
internalRead( session, pentahoJcrConstants, child, dataNode );
}
return dataNode;
}
/**
* {@inheritDoc}
*/
public boolean canRead( final String contentType, final Class<? extends IRepositoryFileData> clazz ) {
return IRepositoryFileData.NODE_CONTENT_TYPE.equals( contentType )
&& clazz.isAssignableFrom( NodeRepositoryFileData.class );
}
/**
* {@inheritDoc}
*/
public boolean canWrite( final Class<? extends IRepositoryFileData> clazz ) {
return NodeRepositoryFileData.class.equals( clazz );
}
/**
* {@inheritDoc}
*/
public String getContentType() {
return IRepositoryFileData.NODE_CONTENT_TYPE;
}
public void updateContentNode( Session session, PentahoJcrConstants pentahoJcrConstants, NodeRepositoryFileData data,
Node fileNode ) throws RepositoryException {
createOrUpdateContentNode( session, pentahoJcrConstants, data, fileNode );
}
}