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