xref: /trunk/main/forms/source/xforms/model.cxx (revision 137931e43899a1545869cb6af6ea936d8cee4956)
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 management
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 {
527     DBG_INVARIANT();
528     return msID;
529 }
530 
setID(const rtl::OUString & sID)531 void Model::setID( const rtl::OUString& sID )
532 {
533     DBG_INVARIANT();
534     msID = sID;
535 }
536 
initialize()537 void Model::initialize()
538 {
539     DBG_ASSERT( ! mbInitialized, "model already initialized" );
540 
541     // load instances
542     loadInstances();
543 
544     // let's pretend we're initialized and rebind all bindings
545     mbInitialized = true;
546     rebind();
547 }
548 
rebuild()549 void Model::rebuild()
550 {
551     if( ! mbInitialized )
552         initialize();
553     else
554         rebind();
555 }
556 
recalculate()557 void Model::recalculate()
558 {
559     rebind();
560 }
561 
revalidate()562 void Model::revalidate()
563 {
564     // do nothing. We don't validate anyways!
565 }
566 
refresh()567 void Model::refresh()
568 {
569     rebind();
570 }
571 
572 
submitWithInteraction(const rtl::OUString & sID,const XInteractionHandler_t & _rxHandler)573 void SAL_CALL Model::submitWithInteraction(
574     const rtl::OUString& sID,
575     const XInteractionHandler_t& _rxHandler )
576 {
577     DBG_INVARIANT();
578 
579     if( mpSubmissions->hasItem( sID ) )
580     {
581         Submission* pSubmission =
582             Submission::getSubmission( mpSubmissions->getItem( sID ) );
583         OSL_ENSURE( pSubmission != NULL, "no submission?" );
584         OSL_ENSURE( pSubmission->getModel() == Reference<XModel>( this ),
585                     "wrong model" );
586 
587         // submit. All exceptions are allowed to leave.
588         pSubmission->submitWithInteraction( _rxHandler );
589     }
590 }
591 
submit(const rtl::OUString & sID)592 void Model::submit( const rtl::OUString& sID )
593 {
594     submitWithInteraction( sID, NULL );
595 }
596 
getDataTypeRepository()597 Model::XDataTypeRepository_t SAL_CALL Model::getDataTypeRepository(  )
598 {
599     if ( !mxDataTypes.is() )
600         mxDataTypes = new ODataTypeRepository;
601 
602     return mxDataTypes;
603 }
604 
605 //
606 // instance management
607 //
608 
getInstances()609 Model::XSet_t Model::getInstances()
610 {
611     return mxInstances;
612 }
613 
getInstanceDocument(const rtl::OUString & rName)614 Model::XDocument_t Model::getInstanceDocument( const rtl::OUString& rName )
615 {
616     ensureAtLeastOneInstance();
617     Reference<XDocument> aInstance;
618     sal_Int32 nInstance = lcl_findInstance( mpInstances, rName );
619     if( nInstance != -1 )
620         getInstanceData( mpInstances->getItem( nInstance ),
621                          NULL, &aInstance, NULL, NULL );
622     return aInstance;
623 }
624 
getDefaultInstance()625 Model::XDocument_t SAL_CALL Model::getDefaultInstance()
626 {
627     ensureAtLeastOneInstance();
628     DBG_ASSERT( mpInstances->countItems() > 0, "no instance?" );
629     Reference<XDocument> aInstance;
630     getInstanceData( mpInstances->getItem( 0 ), NULL, &aInstance, NULL, NULL );
631     return aInstance;
632 }
633 
634 
635 
636 //
637 // bindings management
638 //
639 
createBinding()640 Model::XPropertySet_t SAL_CALL Model::createBinding()
641 {
642     DBG_INVARIANT();
643     return new Binding();
644 }
645 
cloneBinding(const XPropertySet_t & xBinding)646 Model::XPropertySet_t Model::cloneBinding( const XPropertySet_t& xBinding )
647 {
648     DBG_INVARIANT();
649     XPropertySet_t xNewBinding = createBinding();
650     copy( xBinding, xNewBinding );
651     return xNewBinding;
652 }
653 
getBinding(const rtl::OUString & sId)654 Model::XPropertySet_t Model::getBinding( const rtl::OUString& sId )
655 {
656     DBG_INVARIANT();
657     return mpBindings->hasItem( sId ) ? mpBindings->getItem( sId ) : NULL;
658 }
659 
getBindings()660 Model::XSet_t Model::getBindings()
661 {
662     DBG_INVARIANT();
663     return mxBindings;
664 }
665 
666 
667 
668 //
669 // submission management
670 //
671 
createSubmission()672 Model::XSubmission_t Model::createSubmission()
673 {
674     DBG_INVARIANT();
675     return new Submission();
676 }
677 
cloneSubmission(const XPropertySet_t & xSubmission)678 Model::XSubmission_t Model::cloneSubmission(const XPropertySet_t& xSubmission)
679 {
680     DBG_INVARIANT();
681     XSubmission_t xNewSubmission = createSubmission();
682     XPropertySet_t xAsPropertySet( xNewSubmission.get() );
683     copy( xSubmission.get(), xAsPropertySet );
684     return xNewSubmission;
685 }
686 
getSubmission(const rtl::OUString & sId)687 Model::XSubmission_t Model::getSubmission( const rtl::OUString& sId )
688 {
689     DBG_INVARIANT();
690     XSubmission_t xSubmission;
691     if ( mpSubmissions->hasItem( sId ) )
692         xSubmission = xSubmission.query( mpSubmissions->getItem( sId ) );
693     return xSubmission;
694 }
695 
getSubmissions()696 Model::XSet_t Model::getSubmissions()
697 {
698     DBG_INVARIANT();
699     return mxSubmissions;
700 }
701 
702 
703 
704 //
705 // implementation of XFormsUIHelper1 interface
706 //   can be found in file model_ui.cxx
707 //
708 
709 
710 
711 //
712 // implement XPropertySet & friends
713 //
714 
715 #define HANDLE_ID 0
716 #define HANDLE_Instance 1
717 #define HANDLE_InstanceURL 2
718 #define HANDLE_ForeignSchema 3
719 #define HANDLE_SchemaRef 4
720 #define HANDLE_Namespaces 5
721 #define HANDLE_ExternalData 6
722 
723 #define REGISTER_PROPERTY( property, type )   \
724     registerProperty( PROPERTY( property, type ), \
725     new DirectPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) );
726 
727 #define REGISTER_PROPERTY_API( property, type )   \
728     registerProperty( PROPERTY( property, type ), \
729     new APIPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) );
730 
731 #define REGISTER_BOOL_PROPERTY( property )   \
732     registerProperty( PROPERTY( property, sal_Bool ), \
733     new BooleanPropertyAccessor< Model, bool >( this, &Model::set##property, &Model::get##property ) );
734 
initializePropertySet()735 void Model::initializePropertySet()
736 {
737     REGISTER_PROPERTY_API ( ID,            OUString );
738     REGISTER_PROPERTY     ( ForeignSchema, XDocument_t );
739     REGISTER_PROPERTY     ( SchemaRef,     OUString );
740     REGISTER_PROPERTY     ( Namespaces,    XNameContainer_t );
741     REGISTER_BOOL_PROPERTY( ExternalData );
742 }
743 
update()744 void Model::update()
745 {
746     rebuild();
747 }
748 
749 
getSomething(const IntSequence_t & xId)750 sal_Int64 Model::getSomething( const IntSequence_t& xId )
751 {
752     return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL );
753 }
754 
getImplementationId()755 Sequence<sal_Int8> Model::getImplementationId()
756 {
757     return getUnoTunnelID();
758 }
759 
760 
761 //
762 // 'shift' operators for getting data into and out of Anys
763 //
764 
operator <<=(com::sun::star::uno::Any & rAny,xforms::Model * pModel)765 void operator <<= ( com::sun::star::uno::Any& rAny,
766                     xforms::Model* pModel)
767 {
768     Reference<XPropertySet> xPropSet( static_cast<XPropertySet*>( pModel ) );
769     rAny <<= xPropSet;
770 }
771 
operator >>=(xforms::Model * pModel,com::sun::star::uno::Any & rAny)772 bool operator >>= ( xforms::Model* pModel,
773                     com::sun::star::uno::Any& rAny )
774 {
775     bool bRet = false;
776 
777     // acquire model pointer through XUnoTunnel
778     Reference<XUnoTunnel> xTunnel( rAny, UNO_QUERY );
779     if( xTunnel.is() )
780     {
781         pModel = reinterpret_cast<xforms::Model*>(
782             xTunnel->getSomething( xforms::Model::getUnoTunnelID() ) );
783         bRet = true;
784     }
785 
786     return bRet;
787 }
788