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