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