bump product version to 7.2.5.1
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchycontent.cxx
blob76391b4bfc51c80a45915554a7882405042b8554
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
22 TODO
23 **************************************************************************
25 - optimize transfer command. "Move" should be implementable much more
26 efficient!
28 **************************************************************************
30 - Root Folder vs. 'normal' Folder
31 - root doesn't support command 'delete'
32 - root doesn't support command 'insert'
33 - root needs not created via XContentCreator - queryContent with root
34 folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0
35 - root has no parent.
37 *************************************************************************/
38 #include <osl/diagnose.h>
40 #include <rtl/ustring.hxx>
41 #include <com/sun/star/beans/IllegalTypeException.hpp>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/beans/PropertyExistException.hpp>
44 #include <com/sun/star/beans/PropertyState.hpp>
45 #include <com/sun/star/lang/IllegalAccessException.hpp>
46 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
47 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
48 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
49 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
50 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
51 #include <com/sun/star/ucb/NameClash.hpp>
52 #include <com/sun/star/ucb/NameClashException.hpp>
53 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
54 #include <com/sun/star/ucb/TransferInfo.hpp>
55 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
56 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
57 #include <com/sun/star/ucb/XCommandInfo.hpp>
58 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
59 #include <com/sun/star/uno/Any.hxx>
60 #include <com/sun/star/uno/Sequence.hxx>
61 #include <comphelper/propertysequence.hxx>
62 #include <comphelper/sequence.hxx>
63 #include <cppuhelper/queryinterface.hxx>
64 #include <ucbhelper/contentidentifier.hxx>
65 #include <ucbhelper/propertyvalueset.hxx>
66 #include <ucbhelper/cancelcommandexecution.hxx>
67 #include <ucbhelper/macros.hxx>
68 #include "hierarchycontent.hxx"
69 #include "hierarchyprovider.hxx"
70 #include "dynamicresultset.hxx"
71 #include "hierarchyuri.hxx"
73 #include "../inc/urihelper.hxx"
75 using namespace com::sun::star;
76 using namespace hierarchy_ucp;
79 // HierarchyContent Implementation.
82 // static ( "virtual" ctor )
83 rtl::Reference<HierarchyContent> HierarchyContent::create(
84 const uno::Reference< uno::XComponentContext >& rxContext,
85 HierarchyContentProvider* pProvider,
86 const uno::Reference< ucb::XContentIdentifier >& Identifier )
88 // Fail, if content does not exist.
89 HierarchyContentProperties aProps;
90 if ( !loadData( rxContext, pProvider, Identifier, aProps ) )
91 return nullptr;
93 return new HierarchyContent( rxContext, pProvider, Identifier, aProps );
97 // static ( "virtual" ctor )
98 rtl::Reference<HierarchyContent> HierarchyContent::create(
99 const uno::Reference< uno::XComponentContext >& rxContext,
100 HierarchyContentProvider* pProvider,
101 const uno::Reference< ucb::XContentIdentifier >& Identifier,
102 const ucb::ContentInfo& Info )
104 if ( Info.Type.isEmpty() )
105 return nullptr;
107 if ( Info.Type != HIERARCHY_FOLDER_CONTENT_TYPE && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
108 return nullptr;
110 return new HierarchyContent( rxContext, pProvider, Identifier, Info );
114 HierarchyContent::HierarchyContent(
115 const uno::Reference< uno::XComponentContext >& rxContext,
116 HierarchyContentProvider* pProvider,
117 const uno::Reference< ucb::XContentIdentifier >& Identifier,
118 const HierarchyContentProperties& rProps )
119 : ContentImplHelper( rxContext, pProvider, Identifier ),
120 m_aProps( rProps ),
121 m_eState( PERSISTENT ),
122 m_pProvider( pProvider ),
123 m_bCheckedReadOnly( false ),
124 m_bIsReadOnly( true )
126 setKind( Identifier );
130 HierarchyContent::HierarchyContent(
131 const uno::Reference< uno::XComponentContext >& rxContext,
132 HierarchyContentProvider* pProvider,
133 const uno::Reference< ucb::XContentIdentifier >& Identifier,
134 const ucb::ContentInfo& Info )
135 : ContentImplHelper( rxContext, pProvider, Identifier ),
136 m_aProps( Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE ? HierarchyEntryData::FOLDER : HierarchyEntryData::LINK ),
137 m_eState( TRANSIENT ),
138 m_pProvider( pProvider ),
139 m_bCheckedReadOnly( false ),
140 m_bIsReadOnly( true )
142 setKind( Identifier );
146 // virtual
147 HierarchyContent::~HierarchyContent()
152 // XInterface methods.
155 // virtual
156 void SAL_CALL HierarchyContent::acquire()
157 noexcept
159 ContentImplHelper::acquire();
163 // virtual
164 void SAL_CALL HierarchyContent::release()
165 noexcept
167 ContentImplHelper::release();
171 // virtual
172 uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType )
174 uno::Any aRet = ContentImplHelper::queryInterface( rType );
176 if ( !aRet.hasValue() )
178 // Note: isReadOnly may be relative expensive. So avoid calling it
179 // unless it is really necessary.
180 aRet = cppu::queryInterface(
181 rType, static_cast< ucb::XContentCreator * >( this ) );
182 if ( aRet.hasValue() )
184 if ( !isFolder() || isReadOnly() )
185 return uno::Any();
189 return aRet;
193 // XTypeProvider methods.
196 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent );
199 // virtual
200 uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes()
202 if ( isFolder() && !isReadOnly() )
204 static cppu::OTypeCollection s_aFolderTypes(
205 CPPU_TYPE_REF( lang::XTypeProvider ),
206 CPPU_TYPE_REF( lang::XServiceInfo ),
207 CPPU_TYPE_REF( lang::XComponent ),
208 CPPU_TYPE_REF( ucb::XContent ),
209 CPPU_TYPE_REF( ucb::XCommandProcessor ),
210 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
211 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
212 CPPU_TYPE_REF( beans::XPropertyContainer ),
213 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
214 CPPU_TYPE_REF( container::XChild ),
215 CPPU_TYPE_REF( ucb::XContentCreator ) );
218 return s_aFolderTypes.getTypes();
220 else
222 static cppu::OTypeCollection s_aDocumentTypes(
223 CPPU_TYPE_REF( lang::XTypeProvider ),
224 CPPU_TYPE_REF( lang::XServiceInfo ),
225 CPPU_TYPE_REF( lang::XComponent ),
226 CPPU_TYPE_REF( ucb::XContent ),
227 CPPU_TYPE_REF( ucb::XCommandProcessor ),
228 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
229 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
230 CPPU_TYPE_REF( beans::XPropertyContainer ),
231 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
232 CPPU_TYPE_REF( container::XChild ) );
234 return s_aDocumentTypes.getTypes();
239 // XServiceInfo methods.
242 // virtual
243 OUString SAL_CALL HierarchyContent::getImplementationName()
245 return "com.sun.star.comp.ucb.HierarchyContent";
249 // virtual
250 uno::Sequence< OUString > SAL_CALL
251 HierarchyContent::getSupportedServiceNames()
253 uno::Sequence< OUString > aSNS( 1 );
255 if ( m_eKind == LINK )
256 aSNS.getArray()[ 0 ] = "com.sun.star.ucb.HierarchyLinkContent";
257 else if ( m_eKind == FOLDER )
258 aSNS.getArray()[ 0 ] = "com.sun.star.ucb.HierarchyFolderContent";
259 else
260 aSNS.getArray()[ 0 ] = "com.sun.star.ucb.HierarchyRootFolderContent";
262 return aSNS;
266 // XContent methods.
269 // virtual
270 OUString SAL_CALL HierarchyContent::getContentType()
272 return m_aProps.getContentType();
276 // virtual
277 uno::Reference< ucb::XContentIdentifier > SAL_CALL
278 HierarchyContent::getIdentifier()
280 // Transient?
281 if ( m_eState == TRANSIENT )
283 // Transient contents have no identifier.
284 return uno::Reference< ucb::XContentIdentifier >();
287 return ContentImplHelper::getIdentifier();
291 // XCommandProcessor methods.
294 // virtual
295 uno::Any SAL_CALL HierarchyContent::execute(
296 const ucb::Command& aCommand,
297 sal_Int32 /*CommandId*/,
298 const uno::Reference< ucb::XCommandEnvironment >& Environment )
300 uno::Any aRet;
302 if ( aCommand.Name == "getPropertyValues" )
305 // getPropertyValues
308 uno::Sequence< beans::Property > Properties;
309 if ( !( aCommand.Argument >>= Properties ) )
311 ucbhelper::cancelCommandExecution(
312 uno::makeAny( lang::IllegalArgumentException(
313 "Wrong argument type!",
314 static_cast< cppu::OWeakObject * >( this ),
315 -1 ) ),
316 Environment );
317 // Unreachable
320 aRet <<= getPropertyValues( Properties );
322 else if ( aCommand.Name == "setPropertyValues" )
325 // setPropertyValues
328 uno::Sequence< beans::PropertyValue > aProperties;
329 if ( !( aCommand.Argument >>= aProperties ) )
331 ucbhelper::cancelCommandExecution(
332 uno::makeAny( lang::IllegalArgumentException(
333 "Wrong argument type!",
334 static_cast< cppu::OWeakObject * >( this ),
335 -1 ) ),
336 Environment );
337 // Unreachable
340 if ( !aProperties.hasElements() )
342 ucbhelper::cancelCommandExecution(
343 uno::makeAny( lang::IllegalArgumentException(
344 "No properties!",
345 static_cast< cppu::OWeakObject * >( this ),
346 -1 ) ),
347 Environment );
348 // Unreachable
351 aRet <<= setPropertyValues( aProperties, Environment );
353 else if ( aCommand.Name == "getPropertySetInfo" )
356 // getPropertySetInfo
359 aRet <<= getPropertySetInfo( Environment );
361 else if ( aCommand.Name == "getCommandInfo" )
364 // getCommandInfo
367 aRet <<= getCommandInfo( Environment );
369 else if ( aCommand.Name == "open" && isFolder() )
372 // open command for a folder content
375 ucb::OpenCommandArgument2 aOpenCommand;
376 if ( !( aCommand.Argument >>= aOpenCommand ) )
378 ucbhelper::cancelCommandExecution(
379 uno::makeAny( lang::IllegalArgumentException(
380 "Wrong argument type!",
381 static_cast< cppu::OWeakObject * >( this ),
382 -1 ) ),
383 Environment );
384 // Unreachable
387 uno::Reference< ucb::XDynamicResultSet > xSet
388 = new DynamicResultSet( m_xContext, this, aOpenCommand );
389 aRet <<= xSet;
391 else if ( aCommand.Name == "insert" && ( m_eKind != ROOT ) && !isReadOnly() )
394 // insert
395 // ( Not available at root folder )
398 ucb::InsertCommandArgument aArg;
399 if ( !( aCommand.Argument >>= aArg ) )
401 ucbhelper::cancelCommandExecution(
402 uno::makeAny( lang::IllegalArgumentException(
403 "Wrong argument type!",
404 static_cast< cppu::OWeakObject * >( this ),
405 -1 ) ),
406 Environment );
407 // Unreachable
410 sal_Int32 nNameClash = aArg.ReplaceExisting
411 ? ucb::NameClash::OVERWRITE
412 : ucb::NameClash::ERROR;
413 insert( nNameClash, Environment );
415 else if ( aCommand.Name == "delete" && ( m_eKind != ROOT ) && !isReadOnly() )
418 // delete
419 // ( Not available at root folder )
422 bool bDeletePhysical = false;
423 aCommand.Argument >>= bDeletePhysical;
424 destroy( bDeletePhysical, Environment );
426 // Remove own and all children's persistent data.
427 if ( !removeData() )
429 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
431 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
432 }));
433 ucbhelper::cancelCommandExecution(
434 ucb::IOErrorCode_CANT_WRITE,
435 aArgs,
436 Environment,
437 "Cannot remove persistent data!",
438 this );
439 // Unreachable
442 // Remove own and all children's Additional Core Properties.
443 removeAdditionalPropertySet();
445 else if ( aCommand.Name == "transfer" && isFolder() && !isReadOnly() )
448 // transfer
449 // ( Not available at link objects )
452 ucb::TransferInfo aInfo;
453 if ( !( aCommand.Argument >>= aInfo ) )
455 OSL_FAIL( "Wrong argument type!" );
456 ucbhelper::cancelCommandExecution(
457 uno::makeAny( lang::IllegalArgumentException(
458 "Wrong argument type!",
459 static_cast< cppu::OWeakObject * >( this ),
460 -1 ) ),
461 Environment );
462 // Unreachable
465 transfer( aInfo, Environment );
467 else if ( aCommand.Name == "createNewContent" && isFolder() && !isReadOnly() )
470 // createNewContent
471 // ( Not available at link objects )
474 ucb::ContentInfo aInfo;
475 if ( !( aCommand.Argument >>= aInfo ) )
477 OSL_FAIL( "Wrong argument type!" );
478 ucbhelper::cancelCommandExecution(
479 uno::makeAny( lang::IllegalArgumentException(
480 "Wrong argument type!",
481 static_cast< cppu::OWeakObject * >( this ),
482 -1 ) ),
483 Environment );
484 // Unreachable
487 aRet <<= createNewContent( aInfo );
489 else
492 // Unsupported command
495 ucbhelper::cancelCommandExecution(
496 uno::makeAny( ucb::UnsupportedCommandException(
497 OUString(),
498 static_cast< cppu::OWeakObject * >( this ) ) ),
499 Environment );
500 // Unreachable
503 return aRet;
507 // virtual
508 void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ )
510 // @@@ Generally, no action takes much time...
514 // XContentCreator methods.
517 // virtual
518 uno::Sequence< ucb::ContentInfo > SAL_CALL
519 HierarchyContent::queryCreatableContentsInfo()
521 return m_aProps.getCreatableContentsInfo();
525 // virtual
526 uno::Reference< ucb::XContent > SAL_CALL
527 HierarchyContent::createNewContent( const ucb::ContentInfo& Info )
529 if ( isFolder() )
531 osl::Guard< osl::Mutex > aGuard( m_aMutex );
533 if ( Info.Type.isEmpty() )
534 return uno::Reference< ucb::XContent >();
536 bool bCreateFolder = Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE;
538 if ( !bCreateFolder && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
539 return uno::Reference< ucb::XContent >();
541 OUString aURL = m_xIdentifier->getContentIdentifier();
543 OSL_ENSURE( !aURL.isEmpty(),
544 "HierarchyContent::createNewContent - empty identifier!" );
546 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
547 aURL += "/";
549 if ( bCreateFolder )
550 aURL += "New_Folder";
551 else
552 aURL += "New_Link";
554 uno::Reference< ucb::XContentIdentifier > xId
555 = new ::ucbhelper::ContentIdentifier( aURL );
557 return create( m_xContext, m_pProvider, xId, Info );
559 else
561 OSL_FAIL( "createNewContent called on non-folder object!" );
562 return uno::Reference< ucb::XContent >();
567 // virtual
568 OUString HierarchyContent::getParentURL()
570 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
571 return aUri.getParentUri();
575 //static
576 bool HierarchyContent::hasData(
577 const uno::Reference< uno::XComponentContext >& rxContext,
578 HierarchyContentProvider* pProvider,
579 const uno::Reference< ucb::XContentIdentifier >& Identifier )
581 OUString aURL = Identifier->getContentIdentifier();
583 // Am I a root folder?
584 HierarchyUri aUri( aURL );
585 if ( aUri.isRootFolder() )
587 // hasData must always return 'true' for root folder
588 // even if no persistent data exist!!!
589 return true;
592 return HierarchyEntry( rxContext, pProvider, aURL ).hasData();
596 //static
597 bool HierarchyContent::loadData(
598 const uno::Reference< uno::XComponentContext >& rxContext,
599 HierarchyContentProvider* pProvider,
600 const uno::Reference< ucb::XContentIdentifier >& Identifier,
601 HierarchyContentProperties& rProps )
603 OUString aURL = Identifier->getContentIdentifier();
605 // Am I a root folder?
606 HierarchyUri aUri( aURL );
607 if ( aUri.isRootFolder() )
609 rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER );
611 else
613 HierarchyEntry aEntry( rxContext, pProvider, aURL );
614 HierarchyEntryData aData;
615 if ( !aEntry.getData( aData ) )
616 return false;
618 rProps = HierarchyContentProperties( aData );
620 return true;
624 bool HierarchyContent::storeData()
626 HierarchyEntry aEntry(
627 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
628 return aEntry.setData( m_aProps.getHierarchyEntryData() );
632 void HierarchyContent::renameData(
633 const uno::Reference< ucb::XContentIdentifier >& xOldId,
634 const uno::Reference< ucb::XContentIdentifier >& xNewId )
636 HierarchyEntry aEntry(
637 m_xContext, m_pProvider, xOldId->getContentIdentifier() );
638 aEntry.move( xNewId->getContentIdentifier(),
639 m_aProps.getHierarchyEntryData() );
643 bool HierarchyContent::removeData()
645 HierarchyEntry aEntry(
646 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
647 return aEntry.remove();
651 void HierarchyContent::setKind(
652 const uno::Reference< ucb::XContentIdentifier >& Identifier )
654 if ( m_aProps.getIsFolder() )
656 // Am I a root folder?
657 HierarchyUri aUri( Identifier->getContentIdentifier() );
658 if ( aUri.isRootFolder() )
659 m_eKind = ROOT;
660 else
661 m_eKind = FOLDER;
663 else
664 m_eKind = LINK;
668 bool HierarchyContent::isReadOnly()
670 if ( !m_bCheckedReadOnly )
672 osl::Guard< osl::Mutex > aGuard( m_aMutex );
673 if ( !m_bCheckedReadOnly )
675 m_bCheckedReadOnly = true;
676 m_bIsReadOnly = true;
678 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
679 uno::Reference< lang::XMultiServiceFactory > xConfigProv
680 = m_pProvider->getConfigProvider( aUri.getService() );
681 if ( xConfigProv.is() )
683 uno::Sequence< OUString > aNames
684 = xConfigProv->getAvailableServiceNames();
685 m_bIsReadOnly = comphelper::findValue(aNames, "com.sun.star.ucb.HierarchyDataReadWriteAccess") == -1;
690 return m_bIsReadOnly;
694 uno::Reference< ucb::XContentIdentifier >
695 HierarchyContent::makeNewIdentifier( const OUString& rTitle )
697 osl::Guard< osl::Mutex > aGuard( m_aMutex );
699 // Assemble new content identifier...
700 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
701 OUString aNewURL = aUri.getParentUri() + "/";
702 aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle );
704 return uno::Reference< ucb::XContentIdentifier >(
705 new ::ucbhelper::ContentIdentifier( aNewURL ) );
709 void HierarchyContent::queryChildren( HierarchyContentRefVector& rChildren )
711 if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) )
712 return;
714 // Obtain a list with a snapshot of all currently instantiated contents
715 // from provider and extract the contents which are direct children
716 // of this content.
718 ::ucbhelper::ContentRefList aAllContents;
719 m_xProvider->queryExistingContents( aAllContents );
721 OUString aURL = m_xIdentifier->getContentIdentifier();
722 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
724 if ( nURLPos != ( aURL.getLength() - 1 ) )
726 // No trailing slash found. Append.
727 aURL += "/";
730 sal_Int32 nLen = aURL.getLength();
732 for ( const auto& rContent : aAllContents )
734 ::ucbhelper::ContentImplHelperRef xChild = rContent;
735 OUString aChildURL
736 = xChild->getIdentifier()->getContentIdentifier();
738 // Is aURL a prefix of aChildURL?
739 if ( ( aChildURL.getLength() > nLen ) &&
740 ( aChildURL.startsWith( aURL ) ) )
742 sal_Int32 nPos = aChildURL.indexOf( '/', nLen );
744 if ( ( nPos == -1 ) ||
745 ( nPos == ( aChildURL.getLength() - 1 ) ) )
747 // No further slashes/ only a final slash. It's a child!
748 rChildren.emplace_back(
749 static_cast< HierarchyContent * >( xChild.get() ) );
756 bool HierarchyContent::exchangeIdentity(
757 const uno::Reference< ucb::XContentIdentifier >& xNewId )
759 if ( !xNewId.is() )
760 return false;
762 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
764 uno::Reference< ucb::XContent > xThis = this;
766 // Already persistent?
767 if ( m_eState != PERSISTENT )
769 OSL_FAIL( "HierarchyContent::exchangeIdentity - Not persistent!" );
770 return false;
773 // Am I the root folder?
774 if ( m_eKind == ROOT )
776 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
777 "Not supported by root folder!" );
778 return false;
781 // Exchange own identity.
783 // Fail, if a content with given id already exists.
784 if ( !hasData( xNewId ) )
786 OUString aOldURL = m_xIdentifier->getContentIdentifier();
788 aGuard.clear();
789 if ( exchange( xNewId ) )
791 if ( m_eKind == FOLDER )
793 // Process instantiated children...
795 HierarchyContentRefVector aChildren;
796 queryChildren( aChildren );
798 for ( const auto& rChild : aChildren )
800 HierarchyContentRef xChild = rChild;
802 // Create new content identifier for the child...
803 uno::Reference< ucb::XContentIdentifier > xOldChildId
804 = xChild->getIdentifier();
805 OUString aOldChildURL
806 = xOldChildId->getContentIdentifier();
807 OUString aNewChildURL
808 = aOldChildURL.replaceAt(
810 aOldURL.getLength(),
811 xNewId->getContentIdentifier() );
812 uno::Reference< ucb::XContentIdentifier > xNewChildId
813 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
815 if ( !xChild->exchangeIdentity( xNewChildId ) )
816 return false;
819 return true;
823 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
824 "Panic! Cannot exchange identity!" );
825 return false;
829 // static
830 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
831 const uno::Reference< uno::XComponentContext >& rxContext,
832 const uno::Sequence< beans::Property >& rProperties,
833 const HierarchyContentProperties& rData,
834 HierarchyContentProvider* pProvider,
835 const OUString& rContentId )
837 // Note: Empty sequence means "get values of all supported properties".
839 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
840 = new ::ucbhelper::PropertyValueSet( rxContext );
842 if ( rProperties.hasElements() )
844 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
845 bool bTriedToGetAdditionalPropSet = false;
847 for ( const beans::Property& rProp : rProperties )
849 // Process Core properties.
851 if ( rProp.Name == "ContentType" )
853 xRow->appendString ( rProp, rData.getContentType() );
855 else if ( rProp.Name == "Title" )
857 xRow->appendString ( rProp, rData.getTitle() );
859 else if ( rProp.Name == "IsDocument" )
861 xRow->appendBoolean( rProp, rData.getIsDocument() );
863 else if ( rProp.Name == "IsFolder" )
865 xRow->appendBoolean( rProp, rData.getIsFolder() );
867 else if ( rProp.Name == "CreatableContentsInfo" )
869 xRow->appendObject(
870 rProp, uno::makeAny( rData.getCreatableContentsInfo() ) );
872 else if ( rProp.Name == "TargetURL" )
874 // TargetURL is only supported by links.
876 if ( rData.getIsDocument() )
877 xRow->appendString( rProp, rData.getTargetURL() );
878 else
879 xRow->appendVoid( rProp );
881 else
883 // Not a Core Property! Maybe it's an Additional Core Property?!
885 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
887 xAdditionalPropSet =
888 pProvider->getAdditionalPropertySet( rContentId,
889 false );
890 bTriedToGetAdditionalPropSet = true;
893 if ( xAdditionalPropSet.is() )
895 if ( !xRow->appendPropertySetValue(
896 xAdditionalPropSet,
897 rProp ) )
899 // Append empty entry.
900 xRow->appendVoid( rProp );
903 else
905 // Append empty entry.
906 xRow->appendVoid( rProp );
911 else
913 // Append all Core Properties.
914 xRow->appendString (
915 beans::Property( "ContentType",
917 cppu::UnoType<OUString>::get(),
918 beans::PropertyAttribute::BOUND
919 | beans::PropertyAttribute::READONLY ),
920 rData.getContentType() );
921 xRow->appendString (
922 beans::Property( "Title",
924 cppu::UnoType<OUString>::get(),
925 // @@@ Might actually be read-only!
926 beans::PropertyAttribute::BOUND ),
927 rData.getTitle() );
928 xRow->appendBoolean(
929 beans::Property( "IsDocument",
931 cppu::UnoType<bool>::get(),
932 beans::PropertyAttribute::BOUND
933 | beans::PropertyAttribute::READONLY ),
934 rData.getIsDocument() );
935 xRow->appendBoolean(
936 beans::Property( "IsFolder",
938 cppu::UnoType<bool>::get(),
939 beans::PropertyAttribute::BOUND
940 | beans::PropertyAttribute::READONLY ),
941 rData.getIsFolder() );
943 if ( rData.getIsDocument() )
944 xRow->appendString(
945 beans::Property( "TargetURL",
947 cppu::UnoType<OUString>::get(),
948 // @@@ Might actually be read-only!
949 beans::PropertyAttribute::BOUND ),
950 rData.getTargetURL() );
951 xRow->appendObject(
952 beans::Property(
953 "CreatableContentsInfo",
955 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
956 beans::PropertyAttribute::BOUND
957 | beans::PropertyAttribute::READONLY ),
958 uno::makeAny( rData.getCreatableContentsInfo() ) );
960 // Append all Additional Core Properties.
962 uno::Reference< beans::XPropertySet > xSet =
963 pProvider->getAdditionalPropertySet( rContentId, false );
964 xRow->appendPropertySet( xSet );
967 return xRow;
971 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
972 const uno::Sequence< beans::Property >& rProperties )
974 osl::Guard< osl::Mutex > aGuard( m_aMutex );
975 return getPropertyValues( m_xContext,
976 rProperties,
977 m_aProps,
978 m_pProvider,
979 m_xIdentifier->getContentIdentifier() );
983 uno::Sequence< uno::Any > HierarchyContent::setPropertyValues(
984 const uno::Sequence< beans::PropertyValue >& rValues,
985 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
987 osl::ResettableGuard< osl::Mutex > aGuard( m_aMutex );
989 uno::Sequence< uno::Any > aRet( rValues.getLength() );
990 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
991 sal_Int32 nChanged = 0;
993 beans::PropertyChangeEvent aEvent;
994 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
995 aEvent.Further = false;
996 // aEvent.PropertyName =
997 aEvent.PropertyHandle = -1;
998 // aEvent.OldValue =
999 // aEvent.NewValue =
1001 const beans::PropertyValue* pValues = rValues.getConstArray();
1002 sal_Int32 nCount = rValues.getLength();
1004 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1005 bool bTriedToGetAdditionalPropSet = false;
1007 bool bExchange = false;
1008 OUString aOldTitle;
1009 OUString aOldName;
1010 sal_Int32 nTitlePos = -1;
1012 for ( sal_Int32 n = 0; n < nCount; ++n )
1014 const beans::PropertyValue& rValue = pValues[ n ];
1016 if ( rValue.Name == "ContentType" )
1018 // Read-only property!
1019 aRet[ n ] <<= lang::IllegalAccessException(
1020 "Property is read-only!",
1021 static_cast< cppu::OWeakObject * >( this ) );
1023 else if ( rValue.Name == "IsDocument" )
1025 // Read-only property!
1026 aRet[ n ] <<= lang::IllegalAccessException(
1027 "Property is read-only!",
1028 static_cast< cppu::OWeakObject * >( this ) );
1030 else if ( rValue.Name == "IsFolder" )
1032 // Read-only property!
1033 aRet[ n ] <<= lang::IllegalAccessException(
1034 "Property is read-only!",
1035 static_cast< cppu::OWeakObject * >( this ) );
1037 else if ( rValue.Name == "CreatableContentsInfo" )
1039 // Read-only property!
1040 aRet[ n ] <<= lang::IllegalAccessException(
1041 "Property is read-only!",
1042 static_cast< cppu::OWeakObject * >( this ) );
1044 else if ( rValue.Name == "Title" )
1046 if ( isReadOnly() )
1048 aRet[ n ] <<= lang::IllegalAccessException(
1049 "Property is read-only!",
1050 static_cast< cppu::OWeakObject * >( this ) );
1052 else
1054 OUString aNewValue;
1055 if ( rValue.Value >>= aNewValue )
1057 // No empty titles!
1058 if ( !aNewValue.isEmpty() )
1060 if ( aNewValue != m_aProps.getTitle() )
1062 // modified title -> modified URL -> exchange !
1063 if ( m_eState == PERSISTENT )
1064 bExchange = true;
1066 aOldTitle = m_aProps.getTitle();
1067 aOldName = m_aProps.getName();
1069 m_aProps.setTitle( aNewValue );
1070 m_aProps.setName(
1071 ::ucb_impl::urihelper::encodeSegment(
1072 aNewValue ) );
1074 // property change event will be set later...
1076 // remember position within sequence of values
1077 // (for error handling).
1078 nTitlePos = n;
1081 else
1083 aRet[ n ] <<= lang::IllegalArgumentException(
1084 "Empty title not allowed!",
1085 static_cast< cppu::OWeakObject * >( this ),
1086 -1 );
1089 else
1091 aRet[ n ] <<= beans::IllegalTypeException(
1092 "Property value has wrong type!",
1093 static_cast< cppu::OWeakObject * >( this ) );
1097 else if ( rValue.Name == "TargetURL" )
1099 if ( isReadOnly() )
1101 aRet[ n ] <<= lang::IllegalAccessException(
1102 "Property is read-only!",
1103 static_cast< cppu::OWeakObject * >( this ) );
1105 else
1107 // TargetURL is only supported by links.
1109 if ( m_eKind == LINK )
1111 OUString aNewValue;
1112 if ( rValue.Value >>= aNewValue )
1114 // No empty target URL's!
1115 if ( !aNewValue.isEmpty() )
1117 if ( aNewValue != m_aProps.getTargetURL() )
1119 aEvent.PropertyName = rValue.Name;
1120 aEvent.OldValue <<= m_aProps.getTargetURL();
1121 aEvent.NewValue <<= aNewValue;
1123 aChanges.getArray()[ nChanged ] = aEvent;
1125 m_aProps.setTargetURL( aNewValue );
1126 nChanged++;
1129 else
1131 aRet[ n ] <<= lang::IllegalArgumentException(
1132 "Empty target URL not allowed!",
1133 static_cast< cppu::OWeakObject * >( this ),
1134 -1 );
1137 else
1139 aRet[ n ] <<= beans::IllegalTypeException(
1140 "Property value has wrong type!",
1141 static_cast< cppu::OWeakObject * >( this ) );
1144 else
1146 aRet[ n ] <<= beans::UnknownPropertyException(
1147 "TargetURL only supported by links!",
1148 static_cast< cppu::OWeakObject * >( this ) );
1152 else
1154 // Not a Core Property! Maybe it's an Additional Core Property?!
1156 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1158 xAdditionalPropSet = getAdditionalPropertySet( false );
1159 bTriedToGetAdditionalPropSet = true;
1162 if ( xAdditionalPropSet.is() )
1166 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1167 rValue.Name );
1168 if ( aOldValue != rValue.Value )
1170 xAdditionalPropSet->setPropertyValue(
1171 rValue.Name, rValue.Value );
1173 aEvent.PropertyName = rValue.Name;
1174 aEvent.OldValue = aOldValue;
1175 aEvent.NewValue = rValue.Value;
1177 aChanges.getArray()[ nChanged ] = aEvent;
1178 nChanged++;
1181 catch ( beans::UnknownPropertyException const & e )
1183 aRet[ n ] <<= e;
1185 catch ( lang::WrappedTargetException const & e )
1187 aRet[ n ] <<= e;
1189 catch ( beans::PropertyVetoException const & e )
1191 aRet[ n ] <<= e;
1193 catch ( lang::IllegalArgumentException const & e )
1195 aRet[ n ] <<= e;
1198 else
1200 aRet[ n ] <<= uno::Exception(
1201 "No property set for storing the value!",
1202 static_cast< cppu::OWeakObject * >( this ) );
1207 if ( bExchange )
1209 uno::Reference< ucb::XContentIdentifier > xOldId
1210 = m_xIdentifier;
1211 uno::Reference< ucb::XContentIdentifier > xNewId
1212 = makeNewIdentifier( m_aProps.getTitle() );
1214 aGuard.clear();
1215 if ( exchangeIdentity( xNewId ) )
1217 // Adapt persistent data.
1218 renameData( xOldId, xNewId );
1220 // Adapt Additional Core Properties.
1221 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1222 xNewId->getContentIdentifier() );
1224 else
1226 // Roll-back.
1227 m_aProps.setTitle( aOldTitle );
1228 m_aProps.setName ( aOldName );
1230 aOldTitle.clear();
1231 aOldName.clear();
1233 // Set error .
1234 aRet[ nTitlePos ] <<= uno::Exception(
1235 "Exchange failed!",
1236 static_cast< cppu::OWeakObject * >( this ) );
1238 aGuard.reset();
1241 if ( !aOldTitle.isEmpty() )
1243 aEvent.PropertyName = "Title";
1244 aEvent.OldValue <<= aOldTitle;
1245 aEvent.NewValue <<= m_aProps.getTitle();
1247 aChanges.getArray()[ nChanged ] = aEvent;
1248 nChanged++;
1251 if ( nChanged > 0 )
1253 // Save changes, if content was already made persistent.
1254 if ( !bExchange && ( m_eState == PERSISTENT ) )
1256 if ( !storeData() )
1258 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1260 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1261 }));
1262 ucbhelper::cancelCommandExecution(
1263 ucb::IOErrorCode_CANT_WRITE,
1264 aArgs,
1265 xEnv,
1266 "Cannot store persistent data!",
1267 this );
1268 // Unreachable
1272 aChanges.realloc( nChanged );
1274 aGuard.clear();
1275 notifyPropertiesChange( aChanges );
1278 return aRet;
1282 void HierarchyContent::insert( sal_Int32 nNameClashResolve,
1283 const uno::Reference<
1284 ucb::XCommandEnvironment > & xEnv )
1286 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1288 // Am I the root folder?
1289 if ( m_eKind == ROOT )
1291 ucbhelper::cancelCommandExecution(
1292 uno::makeAny( ucb::UnsupportedCommandException(
1293 "Not supported by root folder!",
1294 static_cast< cppu::OWeakObject * >( this ) ) ),
1295 xEnv );
1296 // Unreachable
1299 // Check, if all required properties were set.
1300 if ( m_aProps.getTitle().isEmpty() )
1302 uno::Sequence<OUString> aProps { "Title" };
1303 ucbhelper::cancelCommandExecution(
1304 uno::makeAny( ucb::MissingPropertiesException(
1305 OUString(),
1306 static_cast< cppu::OWeakObject * >( this ),
1307 aProps ) ),
1308 xEnv );
1309 // Unreachable
1312 // Assemble new content identifier...
1314 uno::Reference< ucb::XContentIdentifier > xId
1315 = makeNewIdentifier( m_aProps.getTitle() );
1317 // Handle possible name clash...
1319 switch ( nNameClashResolve )
1321 // fail.
1322 case ucb::NameClash::ERROR:
1323 if ( hasData( xId ) )
1325 ucbhelper::cancelCommandExecution(
1326 uno::makeAny(
1327 ucb::NameClashException(
1328 OUString(),
1329 static_cast< cppu::OWeakObject * >( this ),
1330 task::InteractionClassification_ERROR,
1331 m_aProps.getTitle() ) ),
1332 xEnv );
1333 // Unreachable
1335 break;
1337 // replace existing object.
1338 case ucb::NameClash::OVERWRITE:
1339 break;
1341 // "invent" a new valid title.
1342 case ucb::NameClash::RENAME:
1343 if ( hasData( xId ) )
1345 sal_Int32 nTry = 0;
1349 OUString aNewId = xId->getContentIdentifier() + "_";
1350 aNewId += OUString::number( ++nTry );
1351 xId = new ::ucbhelper::ContentIdentifier( aNewId );
1353 while ( hasData( xId ) && ( nTry < 1000 ) );
1355 if ( nTry == 1000 )
1357 ucbhelper::cancelCommandExecution(
1358 uno::makeAny(
1359 ucb::UnsupportedNameClashException(
1360 "Unable to resolve name clash!",
1361 static_cast< cppu::OWeakObject * >( this ),
1362 nNameClashResolve ) ),
1363 xEnv );
1364 // Unreachable
1366 else
1368 OUString aNewTitle( m_aProps.getTitle() );
1369 aNewTitle += "_" +
1370 OUString::number( nTry );
1371 m_aProps.setTitle( aNewTitle );
1374 break;
1376 case ucb::NameClash::KEEP: // deprecated
1377 case ucb::NameClash::ASK:
1378 default:
1379 if ( hasData( xId ) )
1381 ucbhelper::cancelCommandExecution(
1382 uno::makeAny(
1383 ucb::UnsupportedNameClashException(
1384 OUString(),
1385 static_cast< cppu::OWeakObject * >( this ),
1386 nNameClashResolve ) ),
1387 xEnv );
1388 // Unreachable
1390 break;
1393 // Identifier changed?
1394 bool bNewId = ( xId->getContentIdentifier()
1395 != m_xIdentifier->getContentIdentifier() );
1396 m_xIdentifier = xId;
1398 if ( !storeData() )
1400 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1402 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1403 }));
1404 ucbhelper::cancelCommandExecution(
1405 ucb::IOErrorCode_CANT_WRITE,
1406 aArgs,
1407 xEnv,
1408 "Cannot store persistent data!",
1409 this );
1410 // Unreachable
1413 m_eState = PERSISTENT;
1415 if ( bNewId )
1417 aGuard.clear();
1418 inserted();
1423 void HierarchyContent::destroy( bool bDeletePhysical,
1424 const uno::Reference<
1425 ucb::XCommandEnvironment > & xEnv )
1427 // @@@ take care about bDeletePhysical -> trashcan support
1429 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1431 uno::Reference< ucb::XContent > xThis = this;
1433 // Persistent?
1434 if ( m_eState != PERSISTENT )
1436 ucbhelper::cancelCommandExecution(
1437 uno::makeAny( ucb::UnsupportedCommandException(
1438 "Not persistent!",
1439 static_cast< cppu::OWeakObject * >( this ) ) ),
1440 xEnv );
1441 // Unreachable
1444 // Am I the root folder?
1445 if ( m_eKind == ROOT )
1447 ucbhelper::cancelCommandExecution(
1448 uno::makeAny( ucb::UnsupportedCommandException(
1449 "Not supported by root folder!",
1450 static_cast< cppu::OWeakObject * >( this ) ) ),
1451 xEnv );
1452 // Unreachable
1455 m_eState = DEAD;
1457 aGuard.clear();
1458 deleted();
1460 if ( m_eKind == FOLDER )
1462 // Process instantiated children...
1464 HierarchyContentRefVector aChildren;
1465 queryChildren( aChildren );
1467 for ( auto & child : aChildren)
1469 child->destroy( bDeletePhysical, xEnv );
1475 void HierarchyContent::transfer(
1476 const ucb::TransferInfo& rInfo,
1477 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1479 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1481 // Persistent?
1482 if ( m_eState != PERSISTENT )
1484 ucbhelper::cancelCommandExecution(
1485 uno::makeAny( ucb::UnsupportedCommandException(
1486 "Not persistent!",
1487 static_cast< cppu::OWeakObject * >( this ) ) ),
1488 xEnv );
1489 // Unreachable
1492 // Is source a hierarchy content?
1493 if ( !rInfo.SourceURL.startsWith( HIERARCHY_URL_SCHEME ":/" ) )
1495 ucbhelper::cancelCommandExecution(
1496 uno::makeAny( ucb::InteractiveBadTransferURLException(
1497 OUString(),
1498 static_cast< cppu::OWeakObject * >( this ) ) ),
1499 xEnv );
1500 // Unreachable
1503 // Is source not a parent of me / not me?
1504 OUString aId = m_xIdentifier->getContentIdentifier();
1505 sal_Int32 nPos = aId.lastIndexOf( '/' );
1506 if ( nPos != ( aId.getLength() - 1 ) )
1508 // No trailing slash found. Append.
1509 aId += "/";
1512 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1514 if ( aId.startsWith( rInfo.SourceURL ) )
1516 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1518 {"Uri", uno::Any(rInfo.SourceURL)}
1519 }));
1520 ucbhelper::cancelCommandExecution(
1521 ucb::IOErrorCode_RECURSIVE,
1522 aArgs,
1523 xEnv,
1524 "Target is equal to or is a child of source!",
1525 this );
1526 // Unreachable
1531 // 0) Obtain content object for source.
1534 uno::Reference< ucb::XContentIdentifier > xId
1535 = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
1537 // Note: The static cast is okay here, because its sure that
1538 // m_xProvider is always the HierarchyContentProvider.
1539 rtl::Reference< HierarchyContent > xSource;
1543 xSource = static_cast< HierarchyContent * >(
1544 m_xProvider->queryContent( xId ).get() );
1546 catch ( ucb::IllegalIdentifierException const & )
1548 // queryContent
1551 if ( !xSource.is() )
1553 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1555 {"Uri", uno::Any(xId->getContentIdentifier())}
1556 }));
1557 ucbhelper::cancelCommandExecution(
1558 ucb::IOErrorCode_CANT_READ,
1559 aArgs,
1560 xEnv,
1561 "Cannot instantiate source object!",
1562 this );
1563 // Unreachable
1567 // 1) Create new child content.
1570 OUString aType = xSource->isFolder()
1571 ? OUString( HIERARCHY_FOLDER_CONTENT_TYPE )
1572 : OUString( HIERARCHY_LINK_CONTENT_TYPE );
1573 ucb::ContentInfo aContentInfo;
1574 aContentInfo.Type = aType;
1575 aContentInfo.Attributes = 0;
1577 // Note: The static cast is okay here, because its sure that
1578 // createNewContent always creates a HierarchyContent.
1579 rtl::Reference< HierarchyContent > xTarget
1580 = static_cast< HierarchyContent * >(
1581 createNewContent( aContentInfo ).get() );
1582 if ( !xTarget.is() )
1584 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1586 {"Folder", uno::Any(aId)}
1587 }));
1588 ucbhelper::cancelCommandExecution(
1589 ucb::IOErrorCode_CANT_CREATE,
1590 aArgs,
1591 xEnv,
1592 "XContentCreator::createNewContent failed!",
1593 this );
1594 // Unreachable
1598 // 2) Copy data from source content to child content.
1601 uno::Sequence< beans::Property > aSourceProps
1602 = xSource->getPropertySetInfo( xEnv )->getProperties();
1603 sal_Int32 nCount = aSourceProps.getLength();
1605 if ( nCount )
1607 bool bHadTitle = rInfo.NewTitle.isEmpty();
1609 // Get all source values.
1610 uno::Reference< sdbc::XRow > xRow
1611 = xSource->getPropertyValues( aSourceProps );
1613 uno::Sequence< beans::PropertyValue > aValues( nCount );
1614 beans::PropertyValue* pValues = aValues.getArray();
1616 const beans::Property* pProps = aSourceProps.getConstArray();
1617 for ( sal_Int32 n = 0; n < nCount; ++n )
1619 const beans::Property& rProp = pProps[ n ];
1620 beans::PropertyValue& rValue = pValues[ n ];
1622 rValue.Name = rProp.Name;
1623 rValue.Handle = rProp.Handle;
1625 if ( !bHadTitle && rProp.Name == "Title" )
1627 // Set new title instead of original.
1628 bHadTitle = true;
1629 rValue.Value <<= rInfo.NewTitle;
1631 else
1632 rValue.Value = xRow->getObject(
1633 n + 1,
1634 uno::Reference< container::XNameAccess >() );
1636 rValue.State = beans::PropertyState_DIRECT_VALUE;
1638 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1640 // Add Additional Core Property.
1643 xTarget->addProperty( rProp.Name,
1644 rProp.Attributes,
1645 rValue.Value );
1647 catch ( beans::PropertyExistException const & )
1650 catch ( beans::IllegalTypeException const & )
1653 catch ( lang::IllegalArgumentException const & )
1659 // Set target values.
1660 xTarget->setPropertyValues( aValues, xEnv );
1664 // 3) Commit (insert) child.
1667 xTarget->insert( rInfo.NameClash, xEnv );
1670 // 4) Transfer (copy) children of source.
1673 if ( xSource->isFolder() )
1675 HierarchyEntry aFolder(
1676 m_xContext, m_pProvider, xId->getContentIdentifier() );
1677 HierarchyEntry::iterator it;
1679 while ( aFolder.next( it ) )
1681 const HierarchyEntryData& rResult = *it;
1683 OUString aChildId = xId->getContentIdentifier();
1684 if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() )
1685 aChildId += "/";
1687 aChildId += rResult.getName();
1689 ucb::TransferInfo aInfo;
1690 aInfo.MoveData = false;
1691 aInfo.NewTitle.clear();
1692 aInfo.SourceURL = aChildId;
1693 aInfo.NameClash = rInfo.NameClash;
1695 // Transfer child to target.
1696 xTarget->transfer( aInfo, xEnv );
1701 // 5) Destroy source ( when moving only ) .
1704 if ( !rInfo.MoveData )
1705 return;
1707 xSource->destroy( true, xEnv );
1709 // Remove all persistent data of source and its children.
1710 if ( !xSource->removeData() )
1712 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1714 {"Uri", uno::Any(xSource->m_xIdentifier->getContentIdentifier())}
1715 }));
1716 ucbhelper::cancelCommandExecution(
1717 ucb::IOErrorCode_CANT_WRITE,
1718 aArgs,
1719 xEnv,
1720 "Cannot remove persistent data of source object!",
1721 this );
1722 // Unreachable
1725 // Remove own and all children's Additional Core Properties.
1726 xSource->removeAdditionalPropertySet();
1730 // HierarchyContentProperties Implementation.
1733 uno::Sequence< ucb::ContentInfo >
1734 HierarchyContentProperties::getCreatableContentsInfo() const
1736 if ( getIsFolder() )
1738 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
1740 // Folder.
1741 aSeq.getArray()[ 0 ].Type = HIERARCHY_FOLDER_CONTENT_TYPE;
1742 aSeq.getArray()[ 0 ].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
1744 uno::Sequence< beans::Property > aFolderProps( 1 );
1745 aFolderProps.getArray()[ 0 ] = beans::Property(
1746 "Title",
1748 cppu::UnoType<OUString>::get(),
1749 beans::PropertyAttribute::BOUND );
1750 aSeq.getArray()[ 0 ].Properties = aFolderProps;
1752 // Link.
1753 aSeq.getArray()[ 1 ].Type = HIERARCHY_LINK_CONTENT_TYPE;
1754 aSeq.getArray()[ 1 ].Attributes = ucb::ContentInfoAttribute::KIND_LINK;
1756 uno::Sequence< beans::Property > aLinkProps( 2 );
1757 aLinkProps.getArray()[ 0 ] = beans::Property(
1758 "Title",
1760 cppu::UnoType<OUString>::get(),
1761 beans::PropertyAttribute::BOUND );
1762 aLinkProps.getArray()[ 1 ] = beans::Property(
1763 "TargetURL",
1765 cppu::UnoType<OUString>::get(),
1766 beans::PropertyAttribute::BOUND );
1767 aSeq.getArray()[ 1 ].Properties = aLinkProps;
1769 return aSeq;
1771 else
1773 return uno::Sequence< ucb::ContentInfo >( 0 );
1777 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */