summaryrefslogtreecommitdiff
path: root/ucb/source/ucp/hierarchy/hierarchycontent.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/hierarchy/hierarchycontent.cxx')
-rw-r--r--ucb/source/ucp/hierarchy/hierarchycontent.cxx1641
1 files changed, 1641 insertions, 0 deletions
diff --git a/ucb/source/ucp/hierarchy/hierarchycontent.cxx b/ucb/source/ucp/hierarchy/hierarchycontent.cxx
new file mode 100644
index 000000000000..db48c0e15b96
--- /dev/null
+++ b/ucb/source/ucp/hierarchy/hierarchycontent.cxx
@@ -0,0 +1,1641 @@
+/*************************************************************************
+ *
+ * $RCSfile: hierarchycontent.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: kso $ $Date: 2000-10-16 14:54:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ - optimize transfer command. "Move" should be implementable much more
+ efficient!
+
+ **************************************************************************
+
+ - Root Folder vs. 'normal' Folder
+ - root doesn't support command 'delete'
+ - root doesn't support command 'insert'
+ - root needs not created via XContentCreator - queryContent with root
+ folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0
+ - root has no parent.
+
+ *************************************************************************/
+
+#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#endif
+#ifndef _COM_SUN_STAR_BEANS_XPROPERTYACCESS_HPP_
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#endif
+#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
+#include <com/sun/star/sdbc/XRow.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_INSERTCOMMANDARGUMENT_HPP_
+#include <com/sun/star/ucb/InsertCommandArgument.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_OPENCOMMANDARGUMENT2_HPP_
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_XCOMMANDINFO_HPP_
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_XPERSISTENTPROPERTYSET_HPP_
+#include <com/sun/star/ucb/XPersistentPropertySet.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_NAMECLASH_HPP_
+#include <com/sun/star/ucb/NameClash.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_TRANSFERINFO_HPP_
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#endif
+#ifndef _VOS_DIAGNOSE_HXX_
+#include <vos/diagnose.hxx>
+#endif
+#ifndef _UCBHELPER_CONTENTIDENTIFIER_HXX
+#include <ucbhelper/contentidentifier.hxx>
+#endif
+#ifndef _UCBHELPER_PROPERTYVALUESET_HXX
+#include <ucbhelper/propertyvalueset.hxx>
+#endif
+
+#ifndef _HIERARCHYCONTENT_HXX
+#include "hierarchycontent.hxx"
+#endif
+#ifndef _HIERARCHYPROVIDER_HXX
+#include "hierarchyprovider.hxx"
+#endif
+#ifndef _DYNAMICRESULTSET_HXX
+#include "dynamicresultset.hxx"
+#endif
+
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::uno;
+using namespace cppu;
+using namespace rtl;
+
+using namespace hierarchy_ucp;
+
+//=========================================================================
+//=========================================================================
+//
+// HierarchyContent Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+// static ( "virtual" ctor )
+HierarchyContent* HierarchyContent::create(
+ const Reference< XMultiServiceFactory >& rxSMgr,
+ ::ucb::ContentProviderImplHelper* pProvider,
+ const Reference< XContentIdentifier >& Identifier )
+{
+ // Fail, if content does not exist.
+ HierarchyContentProperties aProps;
+ if ( !loadData( rxSMgr, Identifier, aProps ) )
+ return 0;
+
+ return new HierarchyContent( rxSMgr, pProvider, Identifier, aProps );
+}
+
+//=========================================================================
+// static ( "virtual" ctor )
+HierarchyContent* HierarchyContent::create(
+ const Reference< XMultiServiceFactory >& rxSMgr,
+ ::ucb::ContentProviderImplHelper* pProvider,
+ const Reference< XContentIdentifier >& Identifier,
+ const ContentInfo& Info )
+{
+ if ( !Info.Type.getLength() )
+ return 0;
+
+ if ( ( Info.Type.compareToAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) != 0 ) &&
+ ( Info.Type.compareToAscii( HIERARCHY_LINK_CONTENT_TYPE ) != 0 ) )
+ return 0;
+
+#if 0
+ // Fail, if content does exist.
+ if ( hasData( rxSMgr, Identifier ) )
+ return 0;
+#endif
+
+ return new HierarchyContent( rxSMgr, pProvider, Identifier, Info );
+}
+
+//=========================================================================
+HierarchyContent::HierarchyContent(
+ const Reference< XMultiServiceFactory >& rxSMgr,
+ ::ucb::ContentProviderImplHelper* pProvider,
+ const Reference< XContentIdentifier >& Identifier,
+ const HierarchyContentProperties& rProps )
+: ContentImplHelper( rxSMgr, pProvider, Identifier ),
+ m_aProps( rProps ),
+ m_eState( PERSISTENT )
+{
+ setKind( Identifier );
+}
+
+//=========================================================================
+HierarchyContent::HierarchyContent(
+ const Reference< XMultiServiceFactory >& rxSMgr,
+ ::ucb::ContentProviderImplHelper* pProvider,
+ const Reference< XContentIdentifier >& Identifier,
+ const ContentInfo& Info )
+: ContentImplHelper( rxSMgr, pProvider, Identifier, sal_False ),
+ m_eState( TRANSIENT )
+{
+ if ( Info.Type.compareToAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) == 0 )
+ {
+ // New folder...
+ m_aProps.aContentType = Info.Type;
+// m_aProps.aTitle =
+ m_aProps.bIsFolder = sal_True;
+ m_aProps.bIsDocument = sal_False;
+ }
+ else
+ {
+ VOS_ENSURE(
+ Info.Type.compareToAscii( HIERARCHY_LINK_CONTENT_TYPE ) == 0,
+ "HierarchyContent::HierarchyContent - Wrong content info!" );
+
+ // New link...
+ m_aProps.aContentType = Info.Type;
+// m_aProps.aTitle =
+ m_aProps.bIsFolder = sal_False;
+ m_aProps.bIsDocument = sal_True;
+ }
+
+ setKind( Identifier );
+}
+
+//=========================================================================
+// virtual
+HierarchyContent::~HierarchyContent()
+{
+}
+
+//=========================================================================
+//
+// XInterface methods.
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL HierarchyContent::acquire()
+ throw( RuntimeException )
+{
+ ContentImplHelper::acquire();
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL HierarchyContent::release()
+ throw( RuntimeException )
+{
+ ContentImplHelper::release();
+}
+
+//=========================================================================
+// virtual
+Any SAL_CALL HierarchyContent::queryInterface( const Type & rType )
+ throw ( RuntimeException )
+{
+ Any aRet;
+
+ if ( isFolder() )
+ aRet = cppu::queryInterface( rType,
+ static_cast< XContentCreator * >( this ) );
+
+ return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
+}
+
+//=========================================================================
+//
+// XTypeProvider methods.
+//
+//=========================================================================
+
+XTYPEPROVIDER_COMMON_IMPL( HierarchyContent );
+
+//=========================================================================
+// virtual
+Sequence< Type > SAL_CALL HierarchyContent::getTypes()
+ throw( RuntimeException )
+{
+ static OTypeCollection* pCollection = NULL;
+
+ if ( !pCollection )
+ {
+ osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
+ if ( !pCollection )
+ {
+ if ( isFolder() )
+ {
+ static OTypeCollection aCollection(
+ CPPU_TYPE_REF( XTypeProvider ),
+ CPPU_TYPE_REF( XServiceInfo ),
+ CPPU_TYPE_REF( XComponent ),
+ CPPU_TYPE_REF( XContent ),
+ CPPU_TYPE_REF( XCommandProcessor ),
+ CPPU_TYPE_REF( XPropertiesChangeNotifier ),
+ CPPU_TYPE_REF( XCommandInfoChangeNotifier ),
+ CPPU_TYPE_REF( XPropertyContainer ),
+ CPPU_TYPE_REF( XPropertySetInfoChangeNotifier ),
+ CPPU_TYPE_REF( XChild ),
+ CPPU_TYPE_REF( XContentCreator ) ); // !!
+ pCollection = &aCollection;
+ }
+ else
+ {
+ static OTypeCollection aCollection(
+ CPPU_TYPE_REF( XTypeProvider ),
+ CPPU_TYPE_REF( XServiceInfo ),
+ CPPU_TYPE_REF( XComponent ),
+ CPPU_TYPE_REF( XContent ),
+ CPPU_TYPE_REF( XCommandProcessor ),
+ CPPU_TYPE_REF( XPropertiesChangeNotifier ),
+ CPPU_TYPE_REF( XCommandInfoChangeNotifier ),
+ CPPU_TYPE_REF( XPropertyContainer ),
+ CPPU_TYPE_REF( XPropertySetInfoChangeNotifier ),
+ CPPU_TYPE_REF( XChild ) );
+ pCollection = &aCollection;
+ }
+ }
+ }
+
+ return (*pCollection).getTypes();
+}
+
+//=========================================================================
+//
+// XServiceInfo methods.
+//
+//=========================================================================
+
+// virtual
+OUString SAL_CALL HierarchyContent::getImplementationName()
+ throw( RuntimeException )
+{
+ return OUString::createFromAscii( "HierarchyContent" );
+}
+
+//=========================================================================
+// virtual
+Sequence< OUString > SAL_CALL HierarchyContent::getSupportedServiceNames()
+ throw( RuntimeException )
+{
+ Sequence< OUString > aSNS( 1 );
+
+ if ( m_eKind == LINK )
+ aSNS.getArray()[ 0 ] = OUString::createFromAscii(
+ HIERARCHY_LINK_CONTENT_SERVICE_NAME );
+ else if ( m_eKind == FOLDER )
+ aSNS.getArray()[ 0 ] = OUString::createFromAscii(
+ HIERARCHY_FOLDER_CONTENT_SERVICE_NAME );
+ else
+ aSNS.getArray()[ 0 ] = OUString::createFromAscii(
+ HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME );
+
+ return aSNS;
+}
+
+//=========================================================================
+//
+// XContent methods.
+//
+//=========================================================================
+
+// virtual
+OUString SAL_CALL HierarchyContent::getContentType()
+ throw( RuntimeException )
+{
+ return m_aProps.aContentType;
+}
+
+//=========================================================================
+// virtual
+Reference< XContentIdentifier > SAL_CALL HierarchyContent::getIdentifier()
+ throw( RuntimeException )
+{
+ // Transient?
+ if ( m_eState == TRANSIENT )
+ {
+ // Transient contents have no identifier.
+ return Reference< XContentIdentifier >();
+ }
+
+ return ContentImplHelper::getIdentifier();
+}
+
+//=========================================================================
+//
+// XCommandProcessor methods.
+//
+//=========================================================================
+
+// virtual
+Any SAL_CALL HierarchyContent::execute( const Command& aCommand,
+ sal_Int32 CommandId,
+ const Reference<
+ XCommandEnvironment >& Environment )
+ throw( Exception, CommandAbortedException, RuntimeException )
+{
+ Any aRet;
+
+ if ( aCommand.Name.compareToAscii( "getPropertyValues" ) == 0 )
+ {
+ //////////////////////////////////////////////////////////////////
+ // getPropertyValues
+ //////////////////////////////////////////////////////////////////
+
+ Sequence< Property > Properties;
+ if ( !( aCommand.Argument >>= Properties ) )
+ {
+ VOS_ENSURE( sal_False, "Wrong argument type!" );
+ return Any();
+ }
+
+ aRet <<= getPropertyValues( Properties );
+ }
+ else if ( aCommand.Name.compareToAscii( "setPropertyValues" ) == 0 )
+ {
+ //////////////////////////////////////////////////////////////////
+ // setPropertyValues
+ //////////////////////////////////////////////////////////////////
+
+ Sequence< PropertyValue > aProperties;
+ if ( !( aCommand.Argument >>= aProperties ) )
+ {
+ VOS_ENSURE( sal_False, "Wrong argument type!" );
+ return Any();
+ }
+
+ if ( !aProperties.getLength() )
+ {
+ VOS_ENSURE( sal_False, "No properties!" );
+ return Any();
+ }
+
+ setPropertyValues( aProperties );
+ }
+ else if ( aCommand.Name.compareToAscii( "getPropertySetInfo" ) == 0 )
+ {
+ //////////////////////////////////////////////////////////////////
+ // getPropertySetInfo
+ //////////////////////////////////////////////////////////////////
+
+ aRet <<= getPropertySetInfo();
+ }
+ else if ( aCommand.Name.compareToAscii( "getCommandInfo" ) == 0 )
+ {
+ //////////////////////////////////////////////////////////////////
+ // getCommandInfo
+ //////////////////////////////////////////////////////////////////
+
+ aRet <<= getCommandInfo();
+ }
+ else if ( isFolder() && ( aCommand.Name.compareToAscii( "open" ) == 0 ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // open command for a folder content
+ //////////////////////////////////////////////////////////////////
+
+ OpenCommandArgument2 aOpenCommand;
+ if ( aCommand.Argument >>= aOpenCommand )
+ {
+ Reference< XDynamicResultSet > xSet
+ = new DynamicResultSet( m_xSMgr, this, aOpenCommand );
+ aRet <<= xSet;
+ }
+ else
+ {
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::execute - invalid parameter!" );
+ throw CommandAbortedException();
+ }
+ }
+ else if ( aCommand.Name.compareToAscii( "insert" ) == 0 )
+ {
+ //////////////////////////////////////////////////////////////////
+ // insert
+ // ( Not available at root folder and at persistent objects )
+ //////////////////////////////////////////////////////////////////
+
+ InsertCommandArgument aArg;
+ if ( aCommand.Argument >>= aArg )
+ {
+ sal_Int32 nNameClash = aArg.ReplaceExisting
+ ? NameClash::OVERWRITE
+ : NameClash::ERROR;
+ insert( nNameClash );
+ }
+ else
+ {
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::execute - invalid parameter!" );
+ throw CommandAbortedException();
+ }
+ }
+ else if ( aCommand.Name.compareToAscii( "delete" ) == 0 )
+ {
+ //////////////////////////////////////////////////////////////////
+ // delete
+ // ( Not available at root folder and at non-persistent objects )
+ //////////////////////////////////////////////////////////////////
+
+ sal_Bool bDeletePhysical = sal_False;
+ aCommand.Argument >>= bDeletePhysical;
+ destroy( bDeletePhysical );
+
+ // Remove own and all children's persistent data.
+ removeData();
+
+ // Remove own and all children's Additional Core Properties.
+ removeAdditionalPropertySet( sal_True );
+ }
+ else if ( aCommand.Name.compareToAscii( "transfer" ) == 0 )
+ {
+ //////////////////////////////////////////////////////////////////
+ // transfer
+ // ( Not available at link objects )
+ //////////////////////////////////////////////////////////////////
+
+ TransferInfo aInfo;
+ if ( aCommand.Argument >>= aInfo )
+ {
+ transfer( aInfo );
+ }
+ else
+ {
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::execute - invalid parameter!" );
+ throw CommandAbortedException();
+ }
+ }
+ else
+ {
+ //////////////////////////////////////////////////////////////////
+ // Unknown command
+ //////////////////////////////////////////////////////////////////
+
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::execute - unknown command!" );
+ throw CommandAbortedException();
+ }
+
+ return aRet;
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL HierarchyContent::abort( sal_Int32 CommandId )
+ throw( RuntimeException )
+{
+ // @@@ Generally, no action takes much time...
+}
+
+//=========================================================================
+//
+// XContentCreator methods.
+//
+//=========================================================================
+
+// virtual
+Sequence< ContentInfo > SAL_CALL
+HierarchyContent::queryCreatableContentsInfo()
+ throw( RuntimeException )
+{
+ if ( isFolder() )
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ Sequence< ContentInfo > aSeq( 2 );
+
+ // Folder.
+ aSeq.getArray()[ 0 ].Type
+ = OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE );
+ aSeq.getArray()[ 0 ].Attributes = 0;
+
+ Sequence< Property > aFolderProps( 1 );
+ aFolderProps.getArray()[ 0 ] = Property(
+ OUString::createFromAscii( "Title" ),
+ -1,
+ getCppuType( static_cast< const OUString * >( 0 ) ),
+ PropertyAttribute::BOUND );
+ aSeq.getArray()[ 0 ].Properties = aFolderProps;
+
+ // Link.
+ aSeq.getArray()[ 1 ].Type
+ = OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE );
+ aSeq.getArray()[ 1 ].Attributes = 0;
+
+ Sequence< Property > aLinkProps( 2 );
+ aLinkProps.getArray()[ 0 ] = Property(
+ OUString::createFromAscii( "Title" ),
+ -1,
+ getCppuType( static_cast< const OUString * >( 0 ) ),
+ PropertyAttribute::BOUND );
+ aLinkProps.getArray()[ 1 ] = Property(
+ OUString::createFromAscii( "TargetURL" ),
+ -1,
+ getCppuType( static_cast< const OUString * >( 0 ) ),
+ PropertyAttribute::BOUND );
+ aSeq.getArray()[ 1 ].Properties = aLinkProps;
+
+ return aSeq;
+ }
+ else
+ {
+ VOS_ENSURE( sal_False,
+ "queryCreatableContentsInfo called on non-folder object!" );
+
+ return Sequence< ContentInfo >( 0 );
+ }
+}
+
+//=========================================================================
+// virtual
+Reference< XContent > SAL_CALL HierarchyContent::createNewContent(
+ const ContentInfo& Info )
+ throw( RuntimeException )
+{
+ if ( isFolder() )
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ if ( !Info.Type.getLength() )
+ return Reference< XContent >();
+
+ if ( ( Info.Type.compareToAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) != 0 )
+ &&
+ ( Info.Type.compareToAscii( HIERARCHY_LINK_CONTENT_TYPE ) != 0 ) )
+ return Reference< XContent >();
+
+ OUString aURL = m_xIdentifier->getContentIdentifier();
+
+ VOS_ENSURE( aURL.getLength() > 0,
+ "HierarchyContent::createNewContent - empty identifier!" );
+
+ if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
+ aURL += OUString::createFromAscii( "/" );
+
+ if ( Info.Type.compareToAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) == 0 )
+ aURL += OUString::createFromAscii( "New_Folder" );
+ else
+ aURL += OUString::createFromAscii( "New_Link" );
+
+ Reference< XContentIdentifier > xId(
+ new ::ucb::ContentIdentifier( m_xSMgr, aURL ) );
+
+ return create( m_xSMgr, m_xProvider.getBodyPtr(), xId, Info );
+ }
+ else
+ {
+ VOS_ENSURE( sal_False,
+ "createNewContent called on non-folder object!" );
+ return Reference< XContent >();
+ }
+}
+
+//=========================================================================
+// virtual
+OUString HierarchyContent::getParentURL()
+{
+ OUString aURL = m_xIdentifier->getContentIdentifier();
+
+ // Am I the root folder?
+ if ( m_eKind == ROOT )
+ return OUString();
+
+ sal_Int32 nPos = aURL.lastIndexOf( '/' );
+
+ if ( nPos == ( aURL.getLength() - 1 ) )
+ {
+ // Trailing slash found. Skip.
+ nPos = aURL.lastIndexOf( '/', nPos );
+ }
+
+ if ( nPos != -1 )
+ {
+ OUString aParentURL = aURL.copy( 0, nPos );
+ return aParentURL;
+ }
+
+ return OUString();
+}
+
+//=========================================================================
+//static
+sal_Bool HierarchyContent::hasData(
+ const Reference< XMultiServiceFactory >& rxSMgr,
+ const Reference< XContentIdentifier >& Identifier )
+{
+ OUString aURL = Identifier->getContentIdentifier();
+
+// if ( aURL.compareToAscii( HIERARCHY_ROOT_FOLDER_URL,
+// HIERARCHY_ROOT_FOLDER_URL_LENGTH ) != 0 )
+// {
+// // Illegal identifier!
+// return sal_False;
+// }
+
+ // Am I the root folder?
+ if ( aURL.getLength() == HIERARCHY_ROOT_FOLDER_URL_LENGTH )
+ {
+ // hasData must always return 'true' for root folder
+ // even if no persistent data exist!!!
+ return sal_True;
+ }
+
+ HierarchyEntry aEntry( rxSMgr, aURL );
+ HierarchyEntryData aData;
+
+ return aEntry.hasData();
+}
+
+//=========================================================================
+//static
+sal_Bool HierarchyContent::loadData(
+ const Reference< XMultiServiceFactory >& rxSMgr,
+ const Reference< XContentIdentifier >& Identifier,
+ HierarchyContentProperties& rProps )
+{
+ OUString aURL = Identifier->getContentIdentifier();
+
+// if ( aURL.compareToAscii( HIERARCHY_ROOT_FOLDER_URL,
+// HIERARCHY_ROOT_FOLDER_URL_LENGTH ) != 0 )
+// {
+// // Illegal identifier!
+// return sal_False;
+// }
+
+ // Am I the root folder?
+ if ( aURL.getLength() == HIERARCHY_ROOT_FOLDER_URL_LENGTH )
+ {
+ // loadData must always return 'true' for root folder
+ // even if no persistent data exist!!! --> Fill props!!!
+
+ rProps.aContentType = OUString::createFromAscii(
+ HIERARCHY_FOLDER_CONTENT_TYPE );
+// rProps.aTitle = OUString();
+// rProps.aTargetURL = OUString();
+ rProps.bIsFolder = sal_True;
+ rProps.bIsDocument = sal_False;
+ }
+ else
+ {
+
+ HierarchyEntry aEntry( rxSMgr, aURL );
+ if ( !aEntry.getData( rProps ) )
+ return sal_False;
+
+ if ( rProps.aTargetURL.getLength() > 0 )
+ {
+ rProps.aContentType = OUString::createFromAscii(
+ HIERARCHY_LINK_CONTENT_TYPE );
+ rProps.bIsFolder = sal_False;
+ rProps.bIsDocument = sal_True;
+ }
+ else
+ {
+ rProps.aContentType = OUString::createFromAscii(
+ HIERARCHY_FOLDER_CONTENT_TYPE );
+ rProps.bIsFolder = sal_True;
+ rProps.bIsDocument = sal_False;
+ }
+ }
+ return sal_True;
+}
+
+//=========================================================================
+sal_Bool HierarchyContent::storeData()
+{
+ HierarchyEntry aEntry( m_xSMgr, m_xIdentifier->getContentIdentifier() );
+ return aEntry.setData( m_aProps, sal_True );
+}
+
+//=========================================================================
+sal_Bool HierarchyContent::renameData(
+ const Reference< XContentIdentifier >& xOldId,
+ const Reference< XContentIdentifier >& xNewId )
+{
+ HierarchyEntry aEntry( m_xSMgr, xOldId->getContentIdentifier() );
+ return aEntry.move( xNewId->getContentIdentifier() );
+}
+
+//=========================================================================
+sal_Bool HierarchyContent::removeData()
+{
+ HierarchyEntry aEntry( m_xSMgr, m_xIdentifier->getContentIdentifier() );
+ return aEntry.remove();
+}
+
+//=========================================================================
+void HierarchyContent::setKind(
+ const Reference< XContentIdentifier >& Identifier )
+{
+ if ( m_aProps.bIsFolder )
+ {
+ // Am I the root folder?
+ if ( Identifier->getContentIdentifier().compareToAscii(
+ HIERARCHY_ROOT_FOLDER_URL ) == 0 )
+ m_eKind = ROOT;
+ else
+ m_eKind = FOLDER;
+ }
+ else
+ m_eKind = LINK;
+}
+
+//=========================================================================
+Reference< XContentIdentifier > HierarchyContent::getIdentifierFromTitle()
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ // Assemble new content identifier...
+
+ OUString aURL( m_xIdentifier->getContentIdentifier() );
+ sal_Int32 nPos = aURL.lastIndexOf( '/' );
+
+ if ( nPos == ( aURL.getLength() - 1 ) )
+ {
+ // Trailing slash found. Skip.
+ nPos = aURL.lastIndexOf( '/', nPos );
+ }
+
+ if ( nPos == -1 )
+ {
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::getIdentifierFromTitle - Invalid URL!" );
+ return Reference< XContentIdentifier >();
+ }
+
+ OUString aNewURL = aURL.copy( 0, nPos + 1 );
+ aNewURL += HierarchyContentProvider::encodeSegment( m_aProps.aTitle );
+
+ return Reference< XContentIdentifier >(
+ new ::ucb::ContentIdentifier( m_xSMgr, aNewURL ) );
+}
+
+//=========================================================================
+void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren )
+{
+ if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) )
+ return;
+
+ // Obtain a list with a snapshot of all currently instanciated contents
+ // from provider and extract the contents which are direct children
+ // of this content.
+
+ ::ucb::ContentRefList aAllContents;
+ m_xProvider->queryExistingContents( aAllContents );
+
+ OUString aURL = m_xIdentifier->getContentIdentifier();
+ sal_Int32 nPos = aURL.lastIndexOf( '/' );
+
+ if ( nPos != ( aURL.getLength() - 1 ) )
+ {
+ // No trailing slash found. Append.
+ aURL += OUString::createFromAscii( "/" );
+ }
+
+ sal_Int32 nLen = aURL.getLength();
+
+ ::ucb::ContentRefList::const_iterator it = aAllContents.begin();
+ ::ucb::ContentRefList::const_iterator end = aAllContents.end();
+
+ while ( it != end )
+ {
+ ::ucb::ContentImplHelperRef xChild = (*it);
+ OUString aChildURL = xChild->getIdentifier()->getContentIdentifier();
+
+ // Is aURL a prefix of aChildURL?
+ if ( ( aChildURL.getLength() > nLen ) &&
+ ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
+ {
+ sal_Int32 nPos = nLen;
+ nPos = aChildURL.indexOf( '/', nPos );
+
+ if ( ( nPos == -1 ) ||
+ ( nPos == ( aChildURL.getLength() - 1 ) ) )
+ {
+ // No further slashes/ only a final slash. It's a child!
+ rChildren.push_back(
+ HierarchyContentRef(
+ static_cast< HierarchyContent * >(
+ xChild.getBodyPtr() ) ) );
+ }
+ }
+ ++it;
+ }
+}
+
+//=========================================================================
+sal_Bool HierarchyContent::exchangeIdentity(
+ const Reference< XContentIdentifier >& xNewId )
+{
+ if ( !xNewId.is() )
+ return sal_False;
+
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ Reference< XContent > xThis = this;
+
+ // Already persistent?
+ if ( m_eState != PERSISTENT )
+ {
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::exchangeIdentity - Not persistent!" );
+ return sal_False;
+ }
+
+ // Am I the root folder?
+ if ( m_eKind == ROOT )
+ {
+ VOS_ENSURE( sal_False, "HierarchyContent::exchangeIdentity - "
+ "Not supported by root folder!" );
+ return sal_False;
+ }
+
+ // Exchange own identitity.
+
+ // Fail, if a content with given id already exists.
+ if ( !hasData( xNewId ) )
+ {
+ OUString aOldURL = m_xIdentifier->getContentIdentifier();
+
+ if ( exchange( xNewId ) )
+ {
+ if ( m_eKind == FOLDER )
+ {
+ // Process instanciated children...
+
+ HierarchyContentRefList aChildren;
+ queryChildren( aChildren );
+
+ HierarchyContentRefList::const_iterator it = aChildren.begin();
+ HierarchyContentRefList::const_iterator end = aChildren.end();
+
+ while ( it != end )
+ {
+ HierarchyContentRef xChild = (*it);
+
+ // Create new content identifier for the child...
+ Reference< XContentIdentifier > xOldChildId
+ = xChild->getIdentifier();
+ OUString aOldChildURL = xOldChildId->getContentIdentifier();
+ OUString aNewChildURL
+ = aOldChildURL.replaceAt(
+ 0,
+ aOldURL.getLength(),
+ xNewId->getContentIdentifier() );
+ Reference< XContentIdentifier > xNewChildId
+ = new ::ucb::ContentIdentifier( m_xSMgr, aNewChildURL );
+
+ if ( !xChild->exchangeIdentity( xNewChildId ) )
+ return sal_False;
+
+ ++it;
+ }
+ }
+ return sal_True;
+ }
+ }
+
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::exchangeIdentity - "
+ "Panic! Cannot exchange identity!" );
+ return sal_False;
+}
+
+//=========================================================================
+// static
+Reference< XRow > HierarchyContent::getPropertyValues(
+ const Reference< XMultiServiceFactory >& rSMgr,
+ const Sequence< Property >& rProperties,
+ const HierarchyContentProperties& rData,
+ const vos::ORef< ucb::ContentProviderImplHelper >& rProvider,
+ const OUString& rContentId )
+{
+ // Note: Empty sequence means "get values of all supported properties".
+
+ vos::ORef< ::ucb::PropertyValueSet > xRow
+ = new ::ucb::PropertyValueSet( rSMgr );
+
+ sal_Int32 nCount = rProperties.getLength();
+ if ( nCount )
+ {
+ Reference< XPropertySet > xAdditionalPropSet;
+ sal_Bool bTriedToGetAdditonalPropSet = sal_False;
+
+ const Property* pProps = rProperties.getConstArray();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const Property& rProp = pProps[ n ];
+
+ // Process Core properties.
+
+ if ( rProp.Name.compareToAscii( "ContentType" ) == 0 )
+ {
+ xRow->appendString ( rProp, rData.aContentType );
+ }
+ else if ( rProp.Name.compareToAscii( "Title" ) == 0 )
+ {
+ xRow->appendString ( rProp, rData.aTitle );
+ }
+ else if ( rProp.Name.compareToAscii( "IsDocument" ) == 0 )
+ {
+ xRow->appendBoolean( rProp, rData.bIsDocument );
+ }
+ else if ( rProp.Name.compareToAscii( "IsFolder" ) == 0 )
+ {
+ xRow->appendBoolean( rProp, rData.bIsFolder );
+ }
+ else if ( rProp.Name.compareToAscii( "TargetURL" ) == 0 )
+ {
+ // TargetURL is only supported by links.
+
+ if ( rData.bIsDocument )
+ xRow->appendString( rProp, rData.aTargetURL );
+ else
+ xRow->appendVoid( rProp );
+ }
+
+ else
+ {
+ // Not a Core Property! Maybe it's an Additional Core Property?!
+
+ if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
+ {
+ xAdditionalPropSet
+ = Reference< XPropertySet >(
+ rProvider->getAdditionalPropertySet( rContentId,
+ sal_False ),
+ UNO_QUERY );
+ bTriedToGetAdditonalPropSet = sal_True;
+ }
+
+ if ( xAdditionalPropSet.is() )
+ {
+ if ( !xRow->appendPropertySetValue(
+ xAdditionalPropSet,
+ rProp ) )
+ {
+ // Append empty entry.
+ xRow->appendVoid( rProp );
+ }
+ }
+ else
+ {
+ // Append empty entry.
+ xRow->appendVoid( rProp );
+ }
+ }
+ }
+ }
+ else
+ {
+ // Append all Core Properties.
+ xRow->appendString (
+ Property( OUString::createFromAscii( "ContentType" ),
+ -1,
+ getCppuType( static_cast< const OUString * >( 0 ) ),
+ PropertyAttribute::BOUND | PropertyAttribute::READONLY ),
+ rData.aContentType );
+ xRow->appendString (
+ Property( OUString::createFromAscii( "Title" ),
+ -1,
+ getCppuType( static_cast< const OUString * >( 0 ) ),
+ PropertyAttribute::BOUND ),
+ rData.aTitle );
+ xRow->appendBoolean(
+ Property( OUString::createFromAscii( "IsDocument" ),
+ -1,
+ getCppuBooleanType(),
+ PropertyAttribute::BOUND | PropertyAttribute::READONLY ),
+ rData.bIsDocument );
+ xRow->appendBoolean(
+ Property( OUString::createFromAscii( "IsFolder" ),
+ -1,
+ getCppuBooleanType(),
+ PropertyAttribute::BOUND | PropertyAttribute::READONLY ),
+ rData.bIsFolder );
+
+ if ( rData.bIsDocument )
+ xRow->appendString(
+ Property( OUString::createFromAscii( "TargetURL" ),
+ -1,
+ getCppuType( static_cast< const OUString * >( 0 ) ),
+ PropertyAttribute::BOUND ),
+ rData.aTargetURL );
+
+ // Append all Additional Core Properties.
+
+ Reference< XPropertySet > xSet(
+ rProvider->getAdditionalPropertySet( rContentId, sal_False ),
+ UNO_QUERY );
+ xRow->appendPropertySet( xSet );
+ }
+
+ return Reference< XRow >( xRow.getBodyPtr() );
+}
+
+//=========================================================================
+Reference< XRow > HierarchyContent::getPropertyValues(
+ const Sequence< Property >& rProperties )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ return getPropertyValues( m_xSMgr,
+ rProperties,
+ m_aProps,
+ m_xProvider,
+ m_xIdentifier->getContentIdentifier() );
+}
+
+//=========================================================================
+void HierarchyContent::setPropertyValues(
+ const Sequence< PropertyValue >& rValues )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+
+ Sequence< PropertyChangeEvent > aChanges( rValues.getLength() );
+ sal_Int32 nChanged = 0;
+
+ PropertyChangeEvent aEvent;
+ aEvent.Source = static_cast< OWeakObject * >( this );
+ aEvent.Further = sal_False;
+// aEvent.PropertyName =
+ aEvent.PropertyHandle = -1;
+// aEvent.OldValue =
+// aEvent.NewValue =
+
+ const PropertyValue* pValues = rValues.getConstArray();
+ sal_Int32 nCount = rValues.getLength();
+
+ Reference< XPersistentPropertySet > xAdditionalPropSet;
+ sal_Bool bTriedToGetAdditonalPropSet = sal_False;
+
+ sal_Bool bExchange = sal_False;
+
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const PropertyValue& rValue = pValues[ n ];
+
+ if ( rValue.Name.compareToAscii( "ContentType" ) == 0 )
+ {
+ // Read-only property!
+ }
+ else if ( rValue.Name.compareToAscii( "IsDocument" ) == 0 )
+ {
+ // Read-only property!
+ }
+ else if ( rValue.Name.compareToAscii( "IsFolder" ) == 0 )
+ {
+ // Read-only property!
+ }
+ else if ( rValue.Name.compareToAscii( "Title" ) == 0 )
+ {
+ OUString aNewValue;
+ if ( rValue.Value >>= aNewValue )
+ {
+ // No empty titles!
+ if ( aNewValue.getLength() > 0 )
+ {
+ if ( aNewValue != m_aProps.aTitle )
+ {
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+ m_aProps.aTitle = aNewValue;
+
+ // modified title -> modified URL -> exchange !
+ if ( m_eState == PERSISTENT )
+ bExchange = sal_True;
+
+ aGuard.clear();
+
+ aEvent.PropertyName = rValue.Name;
+ aEvent.OldValue = makeAny( m_aProps.aTitle );
+ aEvent.NewValue = makeAny( aNewValue );
+
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nChanged++;
+ }
+ }
+ }
+ }
+ else if ( rValue.Name.compareToAscii( "TargetURL" ) == 0 )
+ {
+ // TargetURL is only supported by links.
+
+ if ( m_eKind == LINK )
+ {
+ OUString aNewValue;
+ if ( rValue.Value >>= aNewValue )
+ {
+ // No empty target URL's!
+ if ( aNewValue.getLength() > 0 )
+ {
+ if ( aNewValue != m_aProps.aTargetURL )
+ {
+ osl::ClearableGuard< osl::Mutex > aGuard(
+ m_aMutex );
+ m_aProps.aTargetURL = aNewValue;
+ aGuard.clear();
+
+ aEvent.PropertyName = rValue.Name;
+ aEvent.OldValue = makeAny( m_aProps.aTargetURL );
+ aEvent.NewValue = makeAny( aNewValue );
+
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nChanged++;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Not a Core Property! Maybe it's an Additional Core Property?!
+
+ if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
+ {
+ xAdditionalPropSet = getAdditionalPropertySet( sal_False );
+ bTriedToGetAdditonalPropSet = sal_True;
+ }
+
+ if ( xAdditionalPropSet.is() )
+ {
+ try
+ {
+ Any aOldValue = xAdditionalPropSet->getPropertyValue(
+ rValue.Name );
+ xAdditionalPropSet->setPropertyValue(
+ rValue.Name, rValue.Value );
+
+ if ( aOldValue != rValue.Value )
+ {
+ aEvent.PropertyName = rValue.Name;
+ aEvent.OldValue = aOldValue;
+ aEvent.NewValue = rValue.Value;
+
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nChanged++;
+ }
+ }
+ catch ( UnknownPropertyException )
+ {
+ }
+ catch ( WrappedTargetException )
+ {
+ }
+ catch ( PropertyVetoException )
+ {
+ }
+ catch ( IllegalArgumentException )
+ {
+ }
+ }
+ }
+ }
+
+ // @@@ What, if exchange fails??? Rollback of Title prop? Old title is
+ // contained in aChanges...
+ if ( bExchange )
+ {
+ Reference< XContentIdentifier > xOldId = m_xIdentifier;
+ Reference< XContentIdentifier > xNewId = getIdentifierFromTitle();
+
+ if ( exchangeIdentity( xNewId ) )
+ {
+ // Adapt persistent data.
+ renameData( xOldId, xNewId );
+
+ // Adapt Additional Core Properties.
+ renameAdditionalPropertySet(
+ xOldId->getContentIdentifier(),
+ xNewId->getContentIdentifier(),
+ sal_True );
+ }
+ }
+
+ if ( nChanged > 0 )
+ {
+ // Save changes, if content was already made persistent.
+ if ( m_eState == PERSISTENT )
+ storeData();
+
+ aGuard.clear();
+ aChanges.realloc( nChanged );
+ notifyPropertiesChange( aChanges );
+ }
+}
+
+//=========================================================================
+void HierarchyContent::insert( sal_Int32 nNameClashResolve )
+ throw( CommandAbortedException )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+
+ // Transient?
+ if ( m_eState != TRANSIENT )
+ {
+ VOS_ENSURE( sal_False, "HierarchyContent::insert - Not transient!" );
+ throw CommandAbortedException();
+ }
+
+ // Am I the root folder?
+ if ( m_eKind == ROOT )
+ {
+ VOS_ENSURE( sal_False, "HierarchyContent::insert - "
+ "Not supported by root folder!" );
+ throw CommandAbortedException();
+ }
+
+ // Check, if all required properties were set.
+ if ( m_aProps.aTitle.getLength() == 0 )
+ {
+ VOS_ENSURE( sal_False, "HierarchyContent::insert - No Title!" );
+ throw CommandAbortedException();
+ }
+
+ // Assemble new content identifier...
+
+ Reference< XContentIdentifier > xId = getIdentifierFromTitle();
+ if ( !xId.is() )
+ throw CommandAbortedException();
+
+ if ( hasData( xId ) )
+ {
+ // Handle name clash...
+
+ switch ( nNameClashResolve )
+ {
+ // fail.
+ case NameClash::ERROR:
+ throw CommandAbortedException();
+
+ // replace existing object.
+ case NameClash::OVERWRITE:
+ break;
+
+ // "invent" a new valid title.
+ case NameClash::RENAME:
+ {
+ sal_Int32 nTry = 0;
+
+ do
+ {
+ OUString aNewId = xId->getContentIdentifier();
+ aNewId += OUString::createFromAscii( "_" );
+ aNewId += OUString::valueOf( ++nTry );
+ xId = new ::ucb::ContentIdentifier( m_xSMgr, aNewId );
+ }
+ while ( hasData( xId ) && ( nTry < 100000 ) );
+
+ if ( nTry == 100000 )
+ {
+ VOS_ENSURE( sal_False,
+ "HierarchyContent::insert - "
+ "Unable to resolve name clash" );
+ throw CommandAbortedException();
+ }
+ else
+ {
+ m_aProps.aTitle += OUString::createFromAscii( "_" );
+ m_aProps.aTitle += OUString::valueOf( nTry );
+ }
+ break;
+ }
+
+ // keep existing sub-objects, transfer non-clashing sub-objects.
+ case NameClash::KEEP:
+ // @@@
+
+ default:
+ throw CommandAbortedException();
+ }
+ }
+
+ m_xIdentifier = xId;
+
+ if ( !storeData() )
+ throw CommandAbortedException();
+
+ m_eState = PERSISTENT;
+
+ aGuard.clear();
+ inserted();
+}
+
+//=========================================================================
+void HierarchyContent::destroy( sal_Bool bDeletePhysical )
+ throw( CommandAbortedException )
+{
+ // @@@ take care about bDeletePhysical -> trashcan support
+
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ Reference< XContent > xThis = this;
+
+ // Persistent?
+ if ( m_eState != PERSISTENT )
+ {
+ VOS_ENSURE( sal_False, "HierarchyContent::destroy - Not persistent!" );
+ throw CommandAbortedException();
+ }
+
+ // Am I the root folder?
+ if ( m_eKind == ROOT )
+ {
+ VOS_ENSURE( sal_False, "HierarchyContent::destroy - "
+ "Not supported by root folder!" );
+ throw CommandAbortedException();
+ }
+
+ m_eState = DEAD;
+ deleted();
+
+ if ( m_eKind == FOLDER )
+ {
+ // Process instanciated children...
+
+ HierarchyContentRefList aChildren;
+ queryChildren( aChildren );
+
+ HierarchyContentRefList::const_iterator it = aChildren.begin();
+ HierarchyContentRefList::const_iterator end = aChildren.end();
+
+ while ( it != end )
+ {
+ (*it)->destroy( bDeletePhysical );
+ ++it;
+ }
+ }
+}
+
+//=========================================================================
+void HierarchyContent::transfer( const TransferInfo& rInfo )
+ throw( CommandAbortedException )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+
+ // Persistent?
+ if ( m_eState != PERSISTENT )
+ {
+ VOS_ENSURE( sal_False, "HierarchyContent::transfer - Not persistent!" );
+ throw CommandAbortedException();
+ }
+
+ if ( rInfo.SourceURL.getLength() == 0 )
+ throw CommandAbortedException();
+
+ // Is source a hierarchy content?
+ if ( rInfo.SourceURL.compareToAscii(
+ HIERARCHY_ROOT_FOLDER_URL, HIERARCHY_ROOT_FOLDER_URL_LENGTH ) != 0 )
+ throw CommandAbortedException();
+
+ // Is source not a parent of me / not me?
+ OUString aId = m_xIdentifier->getContentIdentifier();
+ sal_Int32 nPos = aId.lastIndexOf( '/' );
+ if ( nPos != ( aId.getLength() - 1 ) )
+ {
+ // No trailing slash found. Append.
+ aId += OUString::createFromAscii( "/" );
+ }
+
+ if ( rInfo.SourceURL.getLength() <= aId.getLength() )
+ {
+ if ( aId.compareTo(
+ rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
+ throw CommandAbortedException();
+ }
+
+ try
+ {
+ //////////////////////////////////////////////////////////////////
+ // 0) Obtain content object for source.
+ //////////////////////////////////////////////////////////////////
+
+ Reference< XContentIdentifier > xId =
+ new ::ucb::ContentIdentifier( m_xSMgr, rInfo.SourceURL );
+
+ // Note: The static cast is okay here, because its sure that
+ // m_xProvider is always the HierarchyContentProvider.
+ vos::ORef< HierarchyContent > xSource
+ = static_cast< HierarchyContent * >(
+ m_xProvider->queryContent( xId ).get() );
+ if ( !xSource.isValid() )
+ throw CommandAbortedException();
+
+ //////////////////////////////////////////////////////////////////
+ // 1) Create new child content.
+ //////////////////////////////////////////////////////////////////
+
+ OUString aType = xSource->isFolder()
+ ? OUString::createFromAscii(
+ HIERARCHY_FOLDER_CONTENT_TYPE )
+ : OUString::createFromAscii(
+ HIERARCHY_LINK_CONTENT_TYPE );
+ ContentInfo aInfo;
+ aInfo.Type = aType;
+ aInfo.Attributes = 0;
+
+ // Note: The static cast is okay here, because its sure that
+ // createNewContent always creates a HierarchyContent.
+ vos::ORef< HierarchyContent > xTarget
+ = static_cast< HierarchyContent * >(
+ createNewContent( aInfo ).get() );
+ if ( !xTarget.isValid() )
+ throw CommandAbortedException();
+
+ //////////////////////////////////////////////////////////////////
+ // 2) Copy data from source content to child content.
+ //////////////////////////////////////////////////////////////////
+
+ Sequence< Property > aProps
+ = xSource->getPropertySetInfo()->getProperties();
+ sal_Int32 nCount = aProps.getLength();
+
+ if ( nCount )
+ {
+ sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 );
+
+ // Get all source values.
+ Reference< XRow > xRow = xSource->getPropertyValues( aProps );
+
+ Sequence< PropertyValue > aValues( nCount );
+ PropertyValue* pValues = aValues.getArray();
+
+ const Property* pProps = aProps.getConstArray();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const Property& rProp = pProps[ n ];
+ PropertyValue& rValue = pValues[ n ];
+
+ rValue.Name = rProp.Name;
+ rValue.Handle = rProp.Handle;
+
+ if ( !bHadTitle && rProp.Name.compareToAscii( "Title" ) == 0 )
+ {
+ // Set new title instead of original.
+ bHadTitle = sal_True;
+ rValue.Value <<= rInfo.NewTitle;
+ }
+ else
+ rValue.Value
+ = xRow->getObject( n + 1, Reference< XNameAccess >() );
+
+ rValue.State = PropertyState_DIRECT_VALUE;
+
+ if ( rProp.Attributes & PropertyAttribute::REMOVABLE )
+ {
+ // Add Additional Core Property.
+ try
+ {
+ xTarget->addProperty( rProp.Name,
+ rProp.Attributes,
+ rValue.Value );
+ }
+ catch ( PropertyExistException & )
+ {
+ }
+ catch ( IllegalTypeException & )
+ {
+ }
+ catch ( IllegalArgumentException & )
+ {
+ }
+ }
+ }
+
+ // Set target values.
+ xTarget->setPropertyValues( aValues );
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // 3) Commit (insert) child.
+ //////////////////////////////////////////////////////////////////
+
+ xTarget->insert( rInfo.NameClash );
+
+ //////////////////////////////////////////////////////////////////
+ // 4) Transfer (copy) children of source.
+ //////////////////////////////////////////////////////////////////
+
+ if ( xSource->isFolder() )
+ {
+ HierarchyEntry aFolder( m_xSMgr, xId->getContentIdentifier() );
+ HierarchyEntry::iterator it;
+
+ while ( aFolder.next( it ) )
+ {
+ const HierarchyEntryData& rResult = *it;
+
+ OUString aChildId = xId->getContentIdentifier();
+ if ( ( aChildId.lastIndexOf( '/' ) + 1 )
+ != aChildId.getLength() )
+ aChildId += OUString::createFromAscii( "/" );
+
+ aChildId += HierarchyContentProvider::encodeSegment(
+ rResult.aTitle );
+
+ Reference< XContentIdentifier > xChildId
+ = new ::ucb::ContentIdentifier( m_xSMgr, aChildId );
+
+ vos::ORef< HierarchyContent > xChild
+ = static_cast< HierarchyContent * >(
+ m_xProvider->queryContent( xChildId ).get() );
+
+ TransferInfo aInfo;
+ aInfo.MoveData = sal_False;
+ aInfo.NewTitle = OUString();
+ aInfo.SourceURL = aChildId;
+ aInfo.NameClash = rInfo.NameClash;
+
+ // Transfer child to target.
+ xTarget->transfer( aInfo );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // 5) Destroy source ( when moving only ) .
+ //////////////////////////////////////////////////////////////////
+
+ if ( rInfo.MoveData )
+ {
+ xSource->destroy( sal_True );
+
+ // Remove all persistent data of source and its children.
+ xSource->removeData();
+
+ // Remove own and all children's Additional Core Properties.
+ xSource->removeAdditionalPropertySet( sal_True );
+ }
+ }
+ catch ( IllegalIdentifierException & )
+ {
+ // queryContent
+ VOS_ENSURE( sal_False, "HierarchyContent::transfer - "
+ "Caught IllegalIdentifierException!" );
+ throw CommandAbortedException();
+ }
+}
+