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