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