1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_forms.hxx" 30 31 #include "model.hxx" 32 33 #include "model_helper.hxx" 34 #include "unohelper.hxx" 35 #include "binding.hxx" 36 #include "submission.hxx" 37 #include "mip.hxx" 38 #include "evaluationcontext.hxx" 39 #include "xmlhelper.hxx" 40 #include "datatyperepository.hxx" 41 #include "NameContainer.hxx" 42 43 #include <rtl/ustring.hxx> 44 #include <rtl/ustrbuf.hxx> 45 #include <tools/debug.hxx> 46 47 #include <comphelper/propertysetinfo.hxx> 48 #include <cppuhelper/typeprovider.hxx> 49 50 #include <algorithm> 51 52 // UNO classes 53 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 54 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> 55 #include <com/sun/star/lang/IllegalArgumentException.hpp> 56 #include <com/sun/star/xml/dom/XDocument.hpp> 57 #include <com/sun/star/xml/dom/XCharacterData.hpp> 58 #include <com/sun/star/xml/dom/NodeType.hpp> 59 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp> 60 #include <com/sun/star/uno/Sequence.hxx> 61 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 62 #include <com/sun/star/beans/PropertyValue.hpp> 63 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 64 #include <com/sun/star/io/XInputStream.hpp> 65 66 67 using com::sun::star::lang::XMultiServiceFactory; 68 using com::sun::star::lang::XUnoTunnel; 69 using com::sun::star::beans::XPropertySet; 70 using com::sun::star::beans::PropertyValue; 71 using rtl::OUString; 72 using rtl::OUStringBuffer; 73 using com::sun::star::beans::PropertyVetoException; 74 using com::sun::star::beans::UnknownPropertyException; 75 using com::sun::star::util::VetoException; 76 using com::sun::star::lang::WrappedTargetException; 77 using com::sun::star::lang::IllegalArgumentException; 78 using com::sun::star::ucb::XSimpleFileAccess; 79 using com::sun::star::io::XInputStream; 80 81 using namespace com::sun::star::uno; 82 using namespace com::sun::star::xml::dom; 83 using namespace xforms; 84 85 86 #if OSL_DEBUG_LEVEL > 1 87 #define DBG_INVARIANT_TYPE(TYPE) class DBG_##TYPE { const TYPE* mpT; void check() { mpT->dbg_assertInvariant(); } public: DBG_##TYPE(const TYPE* pT) : mpT(pT) { check(); } ~DBG_##TYPE() { check(); } } _DBG_##TYPE(this); 88 89 #define DBG_INVARIANT() DBG_INVARIANT_TYPE(Model) 90 #else 91 #define DBG_INVARIANT_TYPE(TYPE) 92 #define DBG_INVARIANT() 93 #endif 94 95 96 97 // 98 // The Model 99 // 100 101 void Model::ensureAtLeastOneInstance() 102 { 103 if( ! mpInstances->hasItems() ) 104 { 105 // create a default instance 106 newInstance( OUString(), OUString(), true ); 107 } 108 } 109 110 111 112 /** Model default constructor; create empty model */ 113 Model::Model() : 114 msID(), 115 mpBindings( NULL ), 116 mpSubmissions( NULL ), 117 mpInstances( new InstanceCollection ), 118 mxNamespaces( new NameContainer<OUString>() ), 119 mxBindings( mpBindings ), 120 mxSubmissions( mpSubmissions ), 121 mxInstances( mpInstances ), 122 mbInitialized( false ), 123 mbExternalData( true ) 124 { 125 initializePropertySet(); 126 127 // initialize bindings collections 128 // (not in initializer list to avoid use of incomplete 'this') 129 mpBindings = new BindingCollection( this ); 130 mxBindings = mpBindings; 131 132 mpSubmissions = new SubmissionCollection( this ); 133 mxSubmissions = mpSubmissions; 134 135 // invariant only holds after construction 136 DBG_INVARIANT(); 137 } 138 139 Model::~Model() throw() 140 { 141 // give up bindings & submissions; the mxBindings/mxSubmissions 142 // references will then delete them 143 mpBindings = NULL; 144 mpSubmissions = NULL; 145 } 146 147 Model* lcl_getModel( const Reference<XUnoTunnel>& xTunnel ) 148 { 149 Model* pModel = NULL; 150 if( xTunnel.is() ) 151 pModel = reinterpret_cast<Model*>( 152 xTunnel->getSomething( Model::getUnoTunnelID() ) ); 153 return pModel; 154 } 155 156 Model* Model::getModel( const Reference<XModel>& xModel ) 157 { 158 return lcl_getModel( Reference<XUnoTunnel>( xModel, UNO_QUERY ) ); 159 } 160 161 EvaluationContext Model::getEvaluationContext() 162 { 163 // the default context is the top-level element node. A default 164 // node (instanceData' is inserted when there is no default node 165 Reference<XDocument> xInstance = getDefaultInstance(); 166 Reference<XNode> xElement( xInstance->getDocumentElement(), UNO_QUERY ); 167 168 // no element found? Then insert default element 'instanceData' 169 if( ! xElement.is() ) 170 { 171 xElement = Reference<XNode>( 172 xInstance->createElement( OUSTRING("instanceData") ), 173 UNO_QUERY_THROW ); 174 Reference<XNode>( xInstance, UNO_QUERY_THROW)->appendChild( xElement ); 175 } 176 177 OSL_ENSURE( xElement.is() && 178 xElement->getNodeType() == NodeType_ELEMENT_NODE, 179 "no element in evaluation context" ); 180 181 return EvaluationContext( xElement, this, mxNamespaces, 0, 1 ); 182 } 183 184 185 Model::IntSequence_t Model::getUnoTunnelID() 186 { 187 static cppu::OImplementationId aImplementationId; 188 return aImplementationId.getImplementationId(); 189 } 190 191 Model::XDocument_t Model::getForeignSchema() const 192 { 193 return mxForeignSchema; 194 } 195 196 void Model::setForeignSchema( const XDocument_t& rDocument ) 197 { 198 mxForeignSchema = rDocument; 199 } 200 201 rtl::OUString Model::getSchemaRef() const 202 { 203 return msSchemaRef; 204 } 205 206 void Model::setSchemaRef( const rtl::OUString& rSchemaRef ) 207 { 208 msSchemaRef = rSchemaRef; 209 } 210 211 Model::XNameContainer_t Model::getNamespaces() const 212 { 213 return mxNamespaces; 214 } 215 216 void Model::setNamespaces( const XNameContainer_t& rNamespaces ) 217 { 218 if( rNamespaces.is() ) 219 mxNamespaces = rNamespaces; 220 } 221 222 bool Model::getExternalData() const 223 { 224 return mbExternalData; 225 } 226 227 void Model::setExternalData( bool _bData ) 228 { 229 mbExternalData = _bData; 230 } 231 232 #if OSL_DEBUG_LEVEL > 1 233 void Model::dbg_assertInvariant() const 234 { 235 OSL_ENSURE( mpInstances != NULL, "no instances found" ); 236 OSL_ENSURE( mxInstances.is(), "No instance container!" ); 237 // OSL_ENSURE( mxInstances->hasElements(), "no instance!" ); 238 239 OSL_ENSURE( mpBindings != NULL, "no bindings element" ); 240 OSL_ENSURE( mxBindings.is(), "No Bindings container" ); 241 242 OSL_ENSURE( mpSubmissions != NULL, "no submissions element" ); 243 OSL_ENSURE( mxSubmissions.is(), "No Submission container" ); 244 245 246 247 /* 248 // check bindings, and things that have to do with our binding 249 std::vector<MIP*> aAllMIPs; // check MIP map 250 sal_Int32 nCount = mpBindings->countItems(); 251 for( sal_Int32 i = 0; i < nCount; i++ ) 252 { 253 Binding* pBind = Binding::getBinding( 254 mpBindings->Collection<XPropertySet_t>::getItem( i ) ); 255 256 // examine and check binding 257 OSL_ENSURE( pBind != NULL, "invalid binding found" ); 258 259 OSL_ENSURE( Model::getModel( pBind->getModel() ) == this, 260 "our binding doesn't know us."); 261 // check this binding's MIP against MIP map 262 MIP* pMIP = const_cast<MIP*>( pBind->_getMIP() ); 263 sal_Int32 nFound = 0; 264 if( pMIP != NULL ) 265 { 266 aAllMIPs.push_back( pMIP ); 267 for( MIPs_t::const_iterator aIter = maMIPs.begin(); 268 aIter != maMIPs.end(); 269 aIter++ ) 270 { 271 if( pMIP == aIter->second ) 272 nFound++; 273 } 274 } 275 OSL_ENSURE( ( pMIP == NULL ) == ( nFound == 0 ), "MIP-map wrong" ); 276 } 277 278 // check MIP map for left-over MIPs 279 for( MIPs_t::const_iterator aIter = maMIPs.begin(); 280 aIter != maMIPs.end(); 281 aIter++ ) 282 { 283 MIP* pMIP = aIter->second; 284 std::vector<MIP*>::iterator aFound = 285 std::find( aAllMIPs.begin(), aAllMIPs.end(), pMIP ); 286 if( aFound != aAllMIPs.end() ) 287 aAllMIPs.erase( aFound ); 288 } 289 OSL_ENSURE( aAllMIPs.empty(), "lonely MIPs found!" ); 290 */ 291 } 292 #endif 293 294 295 // 296 // MIP managment 297 // 298 299 void Model::addMIP( void* pTag, const XNode_t& xNode, const MIP& rMIP ) 300 { 301 OSL_ENSURE( pTag != NULL, "empty tag?" ); 302 OSL_ENSURE( xNode.is(), "no node" ); 303 304 MIPs_t::value_type aValue( xNode, ::std::pair<void*,MIP>( pTag, rMIP ) ); 305 maMIPs.insert( aValue ); 306 } 307 308 void Model::removeMIPs( void* pTag ) 309 { 310 OSL_ENSURE( pTag != NULL, "empty tag?" ); 311 312 for( MIPs_t::iterator aIter = maMIPs.begin(); 313 aIter != maMIPs.end(); ) 314 { 315 if( aIter->second.first == pTag ) 316 { 317 MIPs_t::iterator next( aIter ); ++next; 318 maMIPs.erase( aIter ); 319 aIter = next; 320 } 321 else 322 ++aIter; 323 } 324 } 325 326 MIP Model::queryMIP( const XNode_t& xNode ) const 327 { 328 // OSL_ENSURE( xNode.is(), "no node" ); 329 330 // travel up inheritance chain and inherit MIPs 331 MIP aRet; 332 for( XNode_t xCurrent = xNode; 333 xCurrent.is(); 334 xCurrent = xCurrent->getParentNode() ) 335 { 336 // iterate over all MIPs for this node, and join MIPs 337 MIP aMIP; 338 MIPs_t::const_iterator aEnd = maMIPs.upper_bound( xCurrent ); 339 MIPs_t::const_iterator aIter = maMIPs.lower_bound( xCurrent ); 340 for( ; aIter != aEnd; aIter++ ) 341 aMIP.join( aIter->second.second ); 342 343 // inherit from current node (or set if we are at the start node) 344 if( xCurrent == xNode ) 345 aRet = aMIP; 346 else 347 aRet.inherit( aMIP ); 348 } 349 350 return aRet; 351 } 352 353 354 355 void Model::rebind() 356 { 357 OSL_ENSURE( mpBindings != NULL, "bindings?" ); 358 359 // iterate over all bindings and call update 360 sal_Int32 nCount = mpBindings->countItems(); 361 for( sal_Int32 i = 0; i < nCount; i++ ) 362 { 363 Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); 364 OSL_ENSURE( pBind != NULL, "binding?" ); 365 pBind->update(); 366 } 367 } 368 369 370 371 void Model::deferNotifications( bool bDefer ) 372 { 373 // iterate over all bindings and defer notifications 374 sal_Int32 nCount = mpBindings->countItems(); 375 for( sal_Int32 i = 0; i < nCount; i++ ) 376 { 377 Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); 378 OSL_ENSURE( pBind != NULL, "binding?" ); 379 pBind->deferNotifications( bDefer ); 380 } 381 } 382 383 384 bool Model::setSimpleContent( const XNode_t& xConstNode, 385 const rtl::OUString& sValue ) 386 { 387 OSL_ENSURE( xConstNode.is(), "need node to set data" ); 388 389 bool bRet = false; 390 if( xConstNode.is() ) 391 { 392 // non-const node reference so we can assign children (if necessary) 393 XNode_t xNode( xConstNode ); 394 395 switch( xNode->getNodeType() ) 396 { 397 case NodeType_ELEMENT_NODE: 398 { 399 // find first text node child 400 Reference<XNode> xChild; 401 for( xChild = xNode->getFirstChild(); 402 xChild.is() && xChild->getNodeType() != NodeType_TEXT_NODE; 403 xChild = xChild->getNextSibling() ) 404 ; // empty loop; only find first text node child 405 406 // create text node, if none is found 407 if( ! xChild.is() ) 408 { 409 xChild = Reference<XNode>( 410 xNode->getOwnerDocument()->createTextNode( OUString() ), 411 UNO_QUERY_THROW ); 412 xNode->appendChild( xChild ); 413 } 414 xNode = xChild; 415 416 OSL_ENSURE( xNode.is() && 417 xNode->getNodeType() == NodeType_TEXT_NODE, 418 "text node creation failed?" ); 419 } 420 // no break; continue as with text node: 421 422 case NodeType_TEXT_NODE: 423 case NodeType_ATTRIBUTE_NODE: 424 { 425 // set the node value (defer notifications) 426 if( xNode->getNodeValue() != sValue ) 427 { 428 deferNotifications( true ); 429 xNode->setNodeValue( sValue ); 430 deferNotifications( false ); 431 } 432 bRet = true; 433 } 434 break; 435 436 default: 437 { 438 OSL_ENSURE( false, "bound to unknown node type?" ); 439 } 440 break; 441 442 } 443 } 444 return bRet; 445 } 446 447 void Model::loadInstance( sal_Int32 nInstance ) 448 { 449 Sequence<PropertyValue> aSequence = mpInstances->getItem( nInstance ); 450 451 // find URL from instance 452 OUString sURL; 453 bool bOnce = false; 454 getInstanceData( aSequence, NULL, NULL, &sURL, &bOnce ); 455 456 // if we have a URL, load the document and set it into the instance 457 if( sURL.getLength() > 0 ) 458 { 459 try 460 { 461 Reference<XInputStream> xInput = 462 Reference<XSimpleFileAccess>( 463 createInstance( 464 OUSTRING("com.sun.star.ucb.SimpleFileAccess") ), 465 UNO_QUERY_THROW )->openFileRead( sURL ); 466 if( xInput.is() ) 467 { 468 Reference<XDocument> xInstance = 469 getDocumentBuilder()->parse( xInput ); 470 if( xInstance.is() ) 471 { 472 OUString sEmpty; 473 setInstanceData( aSequence, NULL, &xInstance, 474 bOnce ? &sEmpty : &sURL, NULL); 475 mpInstances->setItem( nInstance, aSequence ); 476 } 477 } 478 } 479 catch( const Exception& ) 480 { 481 // couldn't load the instance -> ignore! 482 } 483 } 484 } 485 486 void Model::loadInstances() 487 { 488 // iterate over instance array to get PropertyValue-Sequence 489 const sal_Int32 nInstances = mpInstances->countItems(); 490 for( sal_Int32 nInstance = 0; nInstance < nInstances; nInstance++ ) 491 { 492 loadInstance( nInstance ); 493 } 494 } 495 496 bool Model::isInitialized() const 497 { 498 return mbInitialized; 499 } 500 501 bool Model::isValid() const 502 { 503 bool bValid = true; 504 sal_Int32 nCount = mpBindings->countItems(); 505 for( sal_Int32 i = 0; bValid && i < nCount; i++ ) 506 { 507 Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); 508 OSL_ENSURE( pBind != NULL, "binding?" ); 509 bValid = pBind->isValid(); 510 } 511 return bValid; 512 } 513 514 515 516 // 517 // implement xforms::XModel 518 // 519 520 rtl::OUString Model::getID() 521 throw( RuntimeException ) 522 { 523 DBG_INVARIANT(); 524 return msID; 525 } 526 527 void Model::setID( const rtl::OUString& sID ) 528 throw( RuntimeException ) 529 { 530 DBG_INVARIANT(); 531 msID = sID; 532 } 533 534 void Model::initialize() 535 throw( RuntimeException ) 536 { 537 DBG_ASSERT( ! mbInitialized, "model already initialized" ); 538 539 // load instances 540 loadInstances(); 541 542 // let's pretend we're initialized and rebind all bindings 543 mbInitialized = true; 544 rebind(); 545 } 546 547 void Model::rebuild() 548 throw( RuntimeException ) 549 { 550 if( ! mbInitialized ) 551 initialize(); 552 else 553 rebind(); 554 } 555 556 void Model::recalculate() 557 throw( RuntimeException ) 558 { 559 rebind(); 560 } 561 562 void Model::revalidate() 563 throw( RuntimeException ) 564 { 565 // do nothing. We don't validate anyways! 566 } 567 568 void Model::refresh() 569 throw( RuntimeException ) 570 { 571 rebind(); 572 } 573 574 575 void SAL_CALL Model::submitWithInteraction( 576 const rtl::OUString& sID, 577 const XInteractionHandler_t& _rxHandler ) 578 throw( VetoException, 579 WrappedTargetException, 580 RuntimeException ) 581 { 582 DBG_INVARIANT(); 583 584 if( mpSubmissions->hasItem( sID ) ) 585 { 586 Submission* pSubmission = 587 Submission::getSubmission( mpSubmissions->getItem( sID ) ); 588 OSL_ENSURE( pSubmission != NULL, "no submission?" ); 589 OSL_ENSURE( pSubmission->getModel() == Reference<XModel>( this ), 590 "wrong model" ); 591 592 // submit. All exceptions are allowed to leave. 593 pSubmission->submitWithInteraction( _rxHandler ); 594 } 595 } 596 597 void Model::submit( const rtl::OUString& sID ) 598 throw( VetoException, WrappedTargetException, RuntimeException ) 599 { 600 submitWithInteraction( sID, NULL ); 601 } 602 603 Model::XDataTypeRepository_t SAL_CALL Model::getDataTypeRepository( ) 604 throw( RuntimeException ) 605 { 606 if ( !mxDataTypes.is() ) 607 mxDataTypes = new ODataTypeRepository; 608 609 return mxDataTypes; 610 } 611 612 // 613 // instance management 614 // 615 616 Model::XSet_t Model::getInstances() 617 throw( RuntimeException ) 618 { 619 return mxInstances; 620 } 621 622 Model::XDocument_t Model::getInstanceDocument( const rtl::OUString& rName ) 623 throw( RuntimeException ) 624 { 625 ensureAtLeastOneInstance(); 626 Reference<XDocument> aInstance; 627 sal_Int32 nInstance = lcl_findInstance( mpInstances, rName ); 628 if( nInstance != -1 ) 629 getInstanceData( mpInstances->getItem( nInstance ), 630 NULL, &aInstance, NULL, NULL ); 631 return aInstance; 632 } 633 634 Model::XDocument_t SAL_CALL Model::getDefaultInstance() 635 throw( RuntimeException ) 636 { 637 ensureAtLeastOneInstance(); 638 DBG_ASSERT( mpInstances->countItems() > 0, "no instance?" ); 639 Reference<XDocument> aInstance; 640 getInstanceData( mpInstances->getItem( 0 ), NULL, &aInstance, NULL, NULL ); 641 return aInstance; 642 } 643 644 645 646 // 647 // bindings management 648 // 649 650 Model::XPropertySet_t SAL_CALL Model::createBinding() 651 throw( RuntimeException ) 652 { 653 DBG_INVARIANT(); 654 return new Binding(); 655 } 656 657 Model::XPropertySet_t Model::cloneBinding( const XPropertySet_t& xBinding ) 658 throw( RuntimeException ) 659 { 660 DBG_INVARIANT(); 661 XPropertySet_t xNewBinding = createBinding(); 662 copy( xBinding, xNewBinding ); 663 return xNewBinding; 664 } 665 666 Model::XPropertySet_t Model::getBinding( const rtl::OUString& sId ) 667 throw( RuntimeException ) 668 { 669 DBG_INVARIANT(); 670 return mpBindings->hasItem( sId ) ? mpBindings->getItem( sId ) : NULL; 671 } 672 673 Model::XSet_t Model::getBindings() 674 throw( RuntimeException ) 675 { 676 DBG_INVARIANT(); 677 return mxBindings; 678 } 679 680 681 682 // 683 // submission management 684 // 685 686 Model::XSubmission_t Model::createSubmission() 687 throw( RuntimeException ) 688 { 689 DBG_INVARIANT(); 690 return new Submission(); 691 } 692 693 Model::XSubmission_t Model::cloneSubmission(const XPropertySet_t& xSubmission) 694 throw( RuntimeException ) 695 { 696 DBG_INVARIANT(); 697 XSubmission_t xNewSubmission = createSubmission(); 698 XPropertySet_t xAsPropertySet( xNewSubmission.get() ); 699 copy( xSubmission.get(), xAsPropertySet ); 700 return xNewSubmission; 701 } 702 703 Model::XSubmission_t Model::getSubmission( const rtl::OUString& sId ) 704 throw( RuntimeException ) 705 { 706 DBG_INVARIANT(); 707 XSubmission_t xSubmission; 708 if ( mpSubmissions->hasItem( sId ) ) 709 xSubmission = xSubmission.query( mpSubmissions->getItem( sId ) ); 710 return xSubmission; 711 } 712 713 Model::XSet_t Model::getSubmissions() 714 throw( RuntimeException ) 715 { 716 DBG_INVARIANT(); 717 return mxSubmissions; 718 } 719 720 721 722 // 723 // implementation of XFormsUIHelper1 interface 724 // can be found in file model_ui.cxx 725 // 726 727 728 729 // 730 // implement XPropertySet & friends 731 // 732 733 #define HANDLE_ID 0 734 #define HANDLE_Instance 1 735 #define HANDLE_InstanceURL 2 736 #define HANDLE_ForeignSchema 3 737 #define HANDLE_SchemaRef 4 738 #define HANDLE_Namespaces 5 739 #define HANDLE_ExternalData 6 740 741 #define REGISTER_PROPERTY( property, type ) \ 742 registerProperty( PROPERTY( property, type ), \ 743 new DirectPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) ); 744 745 #define REGISTER_PROPERTY_API( property, type ) \ 746 registerProperty( PROPERTY( property, type ), \ 747 new APIPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) ); 748 749 #define REGISTER_BOOL_PROPERTY( property ) \ 750 registerProperty( PROPERTY( property, sal_Bool ), \ 751 new BooleanPropertyAccessor< Model, bool >( this, &Model::set##property, &Model::get##property ) ); 752 753 void Model::initializePropertySet() 754 { 755 REGISTER_PROPERTY_API ( ID, OUString ); 756 REGISTER_PROPERTY ( ForeignSchema, XDocument_t ); 757 REGISTER_PROPERTY ( SchemaRef, OUString ); 758 REGISTER_PROPERTY ( Namespaces, XNameContainer_t ); 759 REGISTER_BOOL_PROPERTY( ExternalData ); 760 } 761 762 void Model::update() 763 throw( RuntimeException ) 764 { 765 rebuild(); 766 } 767 768 769 sal_Int64 Model::getSomething( const IntSequence_t& xId ) 770 throw( RuntimeException ) 771 { 772 return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL ); 773 } 774 775 Sequence<sal_Int8> Model::getImplementationId() 776 throw( RuntimeException ) 777 { 778 return getUnoTunnelID(); 779 } 780 781 782 // 783 // 'shift' operators for getting data into and out of Anys 784 // 785 786 void operator <<= ( com::sun::star::uno::Any& rAny, 787 xforms::Model* pModel) 788 { 789 Reference<XPropertySet> xPropSet( static_cast<XPropertySet*>( pModel ) ); 790 rAny <<= xPropSet; 791 } 792 793 bool operator >>= ( xforms::Model* pModel, 794 com::sun::star::uno::Any& rAny ) 795 { 796 bool bRet = false; 797 798 // acquire model pointer through XUnoTunnel 799 Reference<XUnoTunnel> xTunnel( rAny, UNO_QUERY ); 800 if( xTunnel.is() ) 801 { 802 pModel = reinterpret_cast<xforms::Model*>( 803 xTunnel->getSomething( xforms::Model::getUnoTunnelID() ) ); 804 bRet = true; 805 } 806 807 return bRet; 808 } 809