xref: /trunk/main/forms/source/xforms/model.cxx (revision 07a3d7f1)
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 
ensureAtLeastOneInstance()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 */
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 
~Model()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 
lcl_getModel(const Reference<XUnoTunnel> & xTunnel)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 
getModel(const Reference<XModel> & xModel)152 Model* Model::getModel( const Reference<XModel>& xModel )
153 {
154     return lcl_getModel( Reference<XUnoTunnel>( xModel, UNO_QUERY ) );
155 }
156 
getEvaluationContext()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 
getUnoTunnelID()181 Model::IntSequence_t Model::getUnoTunnelID()
182 {
183     static cppu::OImplementationId aImplementationId;
184     return aImplementationId.getImplementationId();
185 }
186 
getForeignSchema() const187 Model::XDocument_t Model::getForeignSchema() const
188 {
189     return mxForeignSchema;
190 }
191 
setForeignSchema(const XDocument_t & rDocument)192 void Model::setForeignSchema( const XDocument_t& rDocument )
193 {
194     mxForeignSchema = rDocument;
195 }
196 
getSchemaRef() const197 rtl::OUString Model::getSchemaRef() const
198 {
199     return msSchemaRef;
200 }
201 
setSchemaRef(const rtl::OUString & rSchemaRef)202 void Model::setSchemaRef( const rtl::OUString& rSchemaRef )
203 {
204     msSchemaRef = rSchemaRef;
205 }
206 
getNamespaces() const207 Model::XNameContainer_t Model::getNamespaces() const
208 {
209     return mxNamespaces;
210 }
211 
setNamespaces(const XNameContainer_t & rNamespaces)212 void Model::setNamespaces( const XNameContainer_t& rNamespaces )
213 {
214     if( rNamespaces.is() )
215         mxNamespaces = rNamespaces;
216 }
217 
getExternalData() const218 bool Model::getExternalData() const
219 {
220     return mbExternalData;
221 }
222 
setExternalData(bool _bData)223 void Model::setExternalData( bool _bData )
224 {
225     mbExternalData = _bData;
226 }
227 
228 #if OSL_DEBUG_LEVEL > 1
dbg_assertInvariant() const229 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 management
293 //
294 
addMIP(void * pTag,const XNode_t & xNode,const MIP & rMIP)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 
removeMIPs(void * pTag)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 
queryMIP(const XNode_t & xNode) const322 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 
rebind()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 
deferNotifications(bool bDefer)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 
setSimpleContent(const XNode_t & xConstNode,const rtl::OUString & sValue)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 
loadInstance(sal_Int32 nInstance)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 
loadInstances()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 
isInitialized() const492 bool Model::isInitialized() const
493 {
494     return mbInitialized;
495 }
496 
isValid() const497 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 
getID()516 rtl::OUString Model::getID()
517     throw( RuntimeException )
518 {
519     DBG_INVARIANT();
520     return msID;
521 }
522 
setID(const rtl::OUString & sID)523 void Model::setID( const rtl::OUString& sID )
524     throw( RuntimeException )
525 {
526     DBG_INVARIANT();
527     msID = sID;
528 }
529 
initialize()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 
rebuild()543 void Model::rebuild()
544     throw( RuntimeException )
545 {
546     if( ! mbInitialized )
547         initialize();
548     else
549         rebind();
550 }
551 
recalculate()552 void Model::recalculate()
553     throw( RuntimeException )
554 {
555     rebind();
556 }
557 
revalidate()558 void Model::revalidate()
559     throw( RuntimeException )
560 {
561     // do nothing. We don't validate anyways!
562 }
563 
refresh()564 void Model::refresh()
565     throw( RuntimeException )
566 {
567     rebind();
568 }
569 
570 
submitWithInteraction(const rtl::OUString & sID,const XInteractionHandler_t & _rxHandler)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 
submit(const rtl::OUString & sID)593 void Model::submit( const rtl::OUString& sID )
594     throw( VetoException, WrappedTargetException, RuntimeException )
595 {
596     submitWithInteraction( sID, NULL );
597 }
598 
getDataTypeRepository()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 
getInstances()612 Model::XSet_t Model::getInstances()
613     throw( RuntimeException )
614 {
615     return mxInstances;
616 }
617 
getInstanceDocument(const rtl::OUString & rName)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 
getDefaultInstance()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 
createBinding()646 Model::XPropertySet_t SAL_CALL Model::createBinding()
647     throw( RuntimeException )
648 {
649     DBG_INVARIANT();
650     return new Binding();
651 }
652 
cloneBinding(const XPropertySet_t & xBinding)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 
getBinding(const rtl::OUString & sId)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 
getBindings()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 
createSubmission()682 Model::XSubmission_t Model::createSubmission()
683     throw( RuntimeException )
684 {
685     DBG_INVARIANT();
686     return new Submission();
687 }
688 
cloneSubmission(const XPropertySet_t & xSubmission)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 
getSubmission(const rtl::OUString & sId)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 
getSubmissions()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 
initializePropertySet()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 
update()758 void Model::update()
759     throw( RuntimeException )
760 {
761     rebuild();
762 }
763 
764 
getSomething(const IntSequence_t & xId)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 
getImplementationId()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 
operator <<=(com::sun::star::uno::Any & rAny,xforms::Model * pModel)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 
operator >>=(xforms::Model * pModel,com::sun::star::uno::Any & rAny)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