| /************************************************************** | |
| * | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| * | |
| *************************************************************/ | |
| // MARKER(update_precomp.py): autogen include statement, do not remove | |
| #include "precompiled_forms.hxx" | |
| #include "model.hxx" | |
| #include "model_helper.hxx" | |
| #include "unohelper.hxx" | |
| #include "binding.hxx" | |
| #include "submission.hxx" | |
| #include "mip.hxx" | |
| #include "evaluationcontext.hxx" | |
| #include "xmlhelper.hxx" | |
| #include "datatyperepository.hxx" | |
| #include "NameContainer.hxx" | |
| #include <rtl/ustring.hxx> | |
| #include <rtl/ustrbuf.hxx> | |
| #include <tools/debug.hxx> | |
| #include <comphelper/propertysetinfo.hxx> | |
| #include <cppuhelper/typeprovider.hxx> | |
| #include <algorithm> | |
| // UNO classes | |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> | |
| #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> | |
| #include <com/sun/star/lang/IllegalArgumentException.hpp> | |
| #include <com/sun/star/xml/dom/XDocument.hpp> | |
| #include <com/sun/star/xml/dom/XCharacterData.hpp> | |
| #include <com/sun/star/xml/dom/NodeType.hpp> | |
| #include <com/sun/star/xml/dom/XDocumentBuilder.hpp> | |
| #include <com/sun/star/uno/Sequence.hxx> | |
| #include <com/sun/star/ucb/XSimpleFileAccess.hpp> | |
| #include <com/sun/star/beans/PropertyValue.hpp> | |
| #include <com/sun/star/ucb/XSimpleFileAccess.hpp> | |
| #include <com/sun/star/io/XInputStream.hpp> | |
| using com::sun::star::lang::XMultiServiceFactory; | |
| using com::sun::star::lang::XUnoTunnel; | |
| using com::sun::star::beans::XPropertySet; | |
| using com::sun::star::beans::PropertyValue; | |
| using rtl::OUString; | |
| using rtl::OUStringBuffer; | |
| using com::sun::star::beans::PropertyVetoException; | |
| using com::sun::star::beans::UnknownPropertyException; | |
| using com::sun::star::util::VetoException; | |
| using com::sun::star::lang::WrappedTargetException; | |
| using com::sun::star::lang::IllegalArgumentException; | |
| using com::sun::star::ucb::XSimpleFileAccess; | |
| using com::sun::star::io::XInputStream; | |
| using namespace com::sun::star::uno; | |
| using namespace com::sun::star::xml::dom; | |
| using namespace xforms; | |
| #if OSL_DEBUG_LEVEL > 1 | |
| #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); | |
| #define DBG_INVARIANT() DBG_INVARIANT_TYPE(Model) | |
| #else | |
| #define DBG_INVARIANT_TYPE(TYPE) | |
| #define DBG_INVARIANT() | |
| #endif | |
| // | |
| // The Model | |
| // | |
| void Model::ensureAtLeastOneInstance() | |
| { | |
| if( ! mpInstances->hasItems() ) | |
| { | |
| // create a default instance | |
| newInstance( OUString(), OUString(), true ); | |
| } | |
| } | |
| /** Model default constructor; create empty model */ | |
| Model::Model() : | |
| msID(), | |
| mpBindings( NULL ), | |
| mpSubmissions( NULL ), | |
| mpInstances( new InstanceCollection ), | |
| mxNamespaces( new NameContainer<OUString>() ), | |
| mxBindings( mpBindings ), | |
| mxSubmissions( mpSubmissions ), | |
| mxInstances( mpInstances ), | |
| mbInitialized( false ), | |
| mbExternalData( true ) | |
| { | |
| initializePropertySet(); | |
| // initialize bindings collections | |
| // (not in initializer list to avoid use of incomplete 'this') | |
| mpBindings = new BindingCollection( this ); | |
| mxBindings = mpBindings; | |
| mpSubmissions = new SubmissionCollection( this ); | |
| mxSubmissions = mpSubmissions; | |
| // invariant only holds after construction | |
| DBG_INVARIANT(); | |
| } | |
| Model::~Model() throw() | |
| { | |
| // give up bindings & submissions; the mxBindings/mxSubmissions | |
| // references will then delete them | |
| mpBindings = NULL; | |
| mpSubmissions = NULL; | |
| } | |
| Model* lcl_getModel( const Reference<XUnoTunnel>& xTunnel ) | |
| { | |
| Model* pModel = NULL; | |
| if( xTunnel.is() ) | |
| pModel = reinterpret_cast<Model*>( | |
| xTunnel->getSomething( Model::getUnoTunnelID() ) ); | |
| return pModel; | |
| } | |
| Model* Model::getModel( const Reference<XModel>& xModel ) | |
| { | |
| return lcl_getModel( Reference<XUnoTunnel>( xModel, UNO_QUERY ) ); | |
| } | |
| EvaluationContext Model::getEvaluationContext() | |
| { | |
| // the default context is the top-level element node. A default | |
| // node (instanceData' is inserted when there is no default node | |
| Reference<XDocument> xInstance = getDefaultInstance(); | |
| Reference<XNode> xElement( xInstance->getDocumentElement(), UNO_QUERY ); | |
| // no element found? Then insert default element 'instanceData' | |
| if( ! xElement.is() ) | |
| { | |
| xElement = Reference<XNode>( | |
| xInstance->createElement( OUSTRING("instanceData") ), | |
| UNO_QUERY_THROW ); | |
| Reference<XNode>( xInstance, UNO_QUERY_THROW)->appendChild( xElement ); | |
| } | |
| OSL_ENSURE( xElement.is() && | |
| xElement->getNodeType() == NodeType_ELEMENT_NODE, | |
| "no element in evaluation context" ); | |
| return EvaluationContext( xElement, this, mxNamespaces, 0, 1 ); | |
| } | |
| Model::IntSequence_t Model::getUnoTunnelID() | |
| { | |
| static cppu::OImplementationId aImplementationId; | |
| return aImplementationId.getImplementationId(); | |
| } | |
| Model::XDocument_t Model::getForeignSchema() const | |
| { | |
| return mxForeignSchema; | |
| } | |
| void Model::setForeignSchema( const XDocument_t& rDocument ) | |
| { | |
| mxForeignSchema = rDocument; | |
| } | |
| rtl::OUString Model::getSchemaRef() const | |
| { | |
| return msSchemaRef; | |
| } | |
| void Model::setSchemaRef( const rtl::OUString& rSchemaRef ) | |
| { | |
| msSchemaRef = rSchemaRef; | |
| } | |
| Model::XNameContainer_t Model::getNamespaces() const | |
| { | |
| return mxNamespaces; | |
| } | |
| void Model::setNamespaces( const XNameContainer_t& rNamespaces ) | |
| { | |
| if( rNamespaces.is() ) | |
| mxNamespaces = rNamespaces; | |
| } | |
| bool Model::getExternalData() const | |
| { | |
| return mbExternalData; | |
| } | |
| void Model::setExternalData( bool _bData ) | |
| { | |
| mbExternalData = _bData; | |
| } | |
| #if OSL_DEBUG_LEVEL > 1 | |
| void Model::dbg_assertInvariant() const | |
| { | |
| OSL_ENSURE( mpInstances != NULL, "no instances found" ); | |
| OSL_ENSURE( mxInstances.is(), "No instance container!" ); | |
| // OSL_ENSURE( mxInstances->hasElements(), "no instance!" ); | |
| OSL_ENSURE( mpBindings != NULL, "no bindings element" ); | |
| OSL_ENSURE( mxBindings.is(), "No Bindings container" ); | |
| OSL_ENSURE( mpSubmissions != NULL, "no submissions element" ); | |
| OSL_ENSURE( mxSubmissions.is(), "No Submission container" ); | |
| /* | |
| // check bindings, and things that have to do with our binding | |
| std::vector<MIP*> aAllMIPs; // check MIP map | |
| sal_Int32 nCount = mpBindings->countItems(); | |
| for( sal_Int32 i = 0; i < nCount; i++ ) | |
| { | |
| Binding* pBind = Binding::getBinding( | |
| mpBindings->Collection<XPropertySet_t>::getItem( i ) ); | |
| // examine and check binding | |
| OSL_ENSURE( pBind != NULL, "invalid binding found" ); | |
| OSL_ENSURE( Model::getModel( pBind->getModel() ) == this, | |
| "our binding doesn't know us."); | |
| // check this binding's MIP against MIP map | |
| MIP* pMIP = const_cast<MIP*>( pBind->_getMIP() ); | |
| sal_Int32 nFound = 0; | |
| if( pMIP != NULL ) | |
| { | |
| aAllMIPs.push_back( pMIP ); | |
| for( MIPs_t::const_iterator aIter = maMIPs.begin(); | |
| aIter != maMIPs.end(); | |
| aIter++ ) | |
| { | |
| if( pMIP == aIter->second ) | |
| nFound++; | |
| } | |
| } | |
| OSL_ENSURE( ( pMIP == NULL ) == ( nFound == 0 ), "MIP-map wrong" ); | |
| } | |
| // check MIP map for left-over MIPs | |
| for( MIPs_t::const_iterator aIter = maMIPs.begin(); | |
| aIter != maMIPs.end(); | |
| aIter++ ) | |
| { | |
| MIP* pMIP = aIter->second; | |
| std::vector<MIP*>::iterator aFound = | |
| std::find( aAllMIPs.begin(), aAllMIPs.end(), pMIP ); | |
| if( aFound != aAllMIPs.end() ) | |
| aAllMIPs.erase( aFound ); | |
| } | |
| OSL_ENSURE( aAllMIPs.empty(), "lonely MIPs found!" ); | |
| */ | |
| } | |
| #endif | |
| // | |
| // MIP managment | |
| // | |
| void Model::addMIP( void* pTag, const XNode_t& xNode, const MIP& rMIP ) | |
| { | |
| OSL_ENSURE( pTag != NULL, "empty tag?" ); | |
| OSL_ENSURE( xNode.is(), "no node" ); | |
| MIPs_t::value_type aValue( xNode, ::std::pair<void*,MIP>( pTag, rMIP ) ); | |
| maMIPs.insert( aValue ); | |
| } | |
| void Model::removeMIPs( void* pTag ) | |
| { | |
| OSL_ENSURE( pTag != NULL, "empty tag?" ); | |
| for( MIPs_t::iterator aIter = maMIPs.begin(); | |
| aIter != maMIPs.end(); ) | |
| { | |
| if( aIter->second.first == pTag ) | |
| { | |
| MIPs_t::iterator next( aIter ); ++next; | |
| maMIPs.erase( aIter ); | |
| aIter = next; | |
| } | |
| else | |
| ++aIter; | |
| } | |
| } | |
| MIP Model::queryMIP( const XNode_t& xNode ) const | |
| { | |
| // OSL_ENSURE( xNode.is(), "no node" ); | |
| // travel up inheritance chain and inherit MIPs | |
| MIP aRet; | |
| for( XNode_t xCurrent = xNode; | |
| xCurrent.is(); | |
| xCurrent = xCurrent->getParentNode() ) | |
| { | |
| // iterate over all MIPs for this node, and join MIPs | |
| MIP aMIP; | |
| MIPs_t::const_iterator aEnd = maMIPs.upper_bound( xCurrent ); | |
| MIPs_t::const_iterator aIter = maMIPs.lower_bound( xCurrent ); | |
| for( ; aIter != aEnd; aIter++ ) | |
| aMIP.join( aIter->second.second ); | |
| // inherit from current node (or set if we are at the start node) | |
| if( xCurrent == xNode ) | |
| aRet = aMIP; | |
| else | |
| aRet.inherit( aMIP ); | |
| } | |
| return aRet; | |
| } | |
| void Model::rebind() | |
| { | |
| OSL_ENSURE( mpBindings != NULL, "bindings?" ); | |
| // iterate over all bindings and call update | |
| sal_Int32 nCount = mpBindings->countItems(); | |
| for( sal_Int32 i = 0; i < nCount; i++ ) | |
| { | |
| Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); | |
| OSL_ENSURE( pBind != NULL, "binding?" ); | |
| pBind->update(); | |
| } | |
| } | |
| void Model::deferNotifications( bool bDefer ) | |
| { | |
| // iterate over all bindings and defer notifications | |
| sal_Int32 nCount = mpBindings->countItems(); | |
| for( sal_Int32 i = 0; i < nCount; i++ ) | |
| { | |
| Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); | |
| OSL_ENSURE( pBind != NULL, "binding?" ); | |
| pBind->deferNotifications( bDefer ); | |
| } | |
| } | |
| bool Model::setSimpleContent( const XNode_t& xConstNode, | |
| const rtl::OUString& sValue ) | |
| { | |
| OSL_ENSURE( xConstNode.is(), "need node to set data" ); | |
| bool bRet = false; | |
| if( xConstNode.is() ) | |
| { | |
| // non-const node reference so we can assign children (if necessary) | |
| XNode_t xNode( xConstNode ); | |
| switch( xNode->getNodeType() ) | |
| { | |
| case NodeType_ELEMENT_NODE: | |
| { | |
| // find first text node child | |
| Reference<XNode> xChild; | |
| for( xChild = xNode->getFirstChild(); | |
| xChild.is() && xChild->getNodeType() != NodeType_TEXT_NODE; | |
| xChild = xChild->getNextSibling() ) | |
| ; // empty loop; only find first text node child | |
| // create text node, if none is found | |
| if( ! xChild.is() ) | |
| { | |
| xChild = Reference<XNode>( | |
| xNode->getOwnerDocument()->createTextNode( OUString() ), | |
| UNO_QUERY_THROW ); | |
| xNode->appendChild( xChild ); | |
| } | |
| xNode = xChild; | |
| OSL_ENSURE( xNode.is() && | |
| xNode->getNodeType() == NodeType_TEXT_NODE, | |
| "text node creation failed?" ); | |
| } | |
| // no break; continue as with text node: | |
| case NodeType_TEXT_NODE: | |
| case NodeType_ATTRIBUTE_NODE: | |
| { | |
| // set the node value (defer notifications) | |
| if( xNode->getNodeValue() != sValue ) | |
| { | |
| deferNotifications( true ); | |
| xNode->setNodeValue( sValue ); | |
| deferNotifications( false ); | |
| } | |
| bRet = true; | |
| } | |
| break; | |
| default: | |
| { | |
| OSL_ENSURE( false, "bound to unknown node type?" ); | |
| } | |
| break; | |
| } | |
| } | |
| return bRet; | |
| } | |
| void Model::loadInstance( sal_Int32 nInstance ) | |
| { | |
| Sequence<PropertyValue> aSequence = mpInstances->getItem( nInstance ); | |
| // find URL from instance | |
| OUString sURL; | |
| bool bOnce = false; | |
| getInstanceData( aSequence, NULL, NULL, &sURL, &bOnce ); | |
| // if we have a URL, load the document and set it into the instance | |
| if( sURL.getLength() > 0 ) | |
| { | |
| try | |
| { | |
| Reference<XInputStream> xInput = | |
| Reference<XSimpleFileAccess>( | |
| createInstance( | |
| OUSTRING("com.sun.star.ucb.SimpleFileAccess") ), | |
| UNO_QUERY_THROW )->openFileRead( sURL ); | |
| if( xInput.is() ) | |
| { | |
| Reference<XDocument> xInstance = | |
| getDocumentBuilder()->parse( xInput ); | |
| if( xInstance.is() ) | |
| { | |
| OUString sEmpty; | |
| setInstanceData( aSequence, NULL, &xInstance, | |
| bOnce ? &sEmpty : &sURL, NULL); | |
| mpInstances->setItem( nInstance, aSequence ); | |
| } | |
| } | |
| } | |
| catch( const Exception& ) | |
| { | |
| // couldn't load the instance -> ignore! | |
| } | |
| } | |
| } | |
| void Model::loadInstances() | |
| { | |
| // iterate over instance array to get PropertyValue-Sequence | |
| const sal_Int32 nInstances = mpInstances->countItems(); | |
| for( sal_Int32 nInstance = 0; nInstance < nInstances; nInstance++ ) | |
| { | |
| loadInstance( nInstance ); | |
| } | |
| } | |
| bool Model::isInitialized() const | |
| { | |
| return mbInitialized; | |
| } | |
| bool Model::isValid() const | |
| { | |
| bool bValid = true; | |
| sal_Int32 nCount = mpBindings->countItems(); | |
| for( sal_Int32 i = 0; bValid && i < nCount; i++ ) | |
| { | |
| Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) ); | |
| OSL_ENSURE( pBind != NULL, "binding?" ); | |
| bValid = pBind->isValid(); | |
| } | |
| return bValid; | |
| } | |
| // | |
| // implement xforms::XModel | |
| // | |
| rtl::OUString Model::getID() | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| return msID; | |
| } | |
| void Model::setID( const rtl::OUString& sID ) | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| msID = sID; | |
| } | |
| void Model::initialize() | |
| throw( RuntimeException ) | |
| { | |
| DBG_ASSERT( ! mbInitialized, "model already initialized" ); | |
| // load instances | |
| loadInstances(); | |
| // let's pretend we're initialized and rebind all bindings | |
| mbInitialized = true; | |
| rebind(); | |
| } | |
| void Model::rebuild() | |
| throw( RuntimeException ) | |
| { | |
| if( ! mbInitialized ) | |
| initialize(); | |
| else | |
| rebind(); | |
| } | |
| void Model::recalculate() | |
| throw( RuntimeException ) | |
| { | |
| rebind(); | |
| } | |
| void Model::revalidate() | |
| throw( RuntimeException ) | |
| { | |
| // do nothing. We don't validate anyways! | |
| } | |
| void Model::refresh() | |
| throw( RuntimeException ) | |
| { | |
| rebind(); | |
| } | |
| void SAL_CALL Model::submitWithInteraction( | |
| const rtl::OUString& sID, | |
| const XInteractionHandler_t& _rxHandler ) | |
| throw( VetoException, | |
| WrappedTargetException, | |
| RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| if( mpSubmissions->hasItem( sID ) ) | |
| { | |
| Submission* pSubmission = | |
| Submission::getSubmission( mpSubmissions->getItem( sID ) ); | |
| OSL_ENSURE( pSubmission != NULL, "no submission?" ); | |
| OSL_ENSURE( pSubmission->getModel() == Reference<XModel>( this ), | |
| "wrong model" ); | |
| // submit. All exceptions are allowed to leave. | |
| pSubmission->submitWithInteraction( _rxHandler ); | |
| } | |
| } | |
| void Model::submit( const rtl::OUString& sID ) | |
| throw( VetoException, WrappedTargetException, RuntimeException ) | |
| { | |
| submitWithInteraction( sID, NULL ); | |
| } | |
| Model::XDataTypeRepository_t SAL_CALL Model::getDataTypeRepository( ) | |
| throw( RuntimeException ) | |
| { | |
| if ( !mxDataTypes.is() ) | |
| mxDataTypes = new ODataTypeRepository; | |
| return mxDataTypes; | |
| } | |
| // | |
| // instance management | |
| // | |
| Model::XSet_t Model::getInstances() | |
| throw( RuntimeException ) | |
| { | |
| return mxInstances; | |
| } | |
| Model::XDocument_t Model::getInstanceDocument( const rtl::OUString& rName ) | |
| throw( RuntimeException ) | |
| { | |
| ensureAtLeastOneInstance(); | |
| Reference<XDocument> aInstance; | |
| sal_Int32 nInstance = lcl_findInstance( mpInstances, rName ); | |
| if( nInstance != -1 ) | |
| getInstanceData( mpInstances->getItem( nInstance ), | |
| NULL, &aInstance, NULL, NULL ); | |
| return aInstance; | |
| } | |
| Model::XDocument_t SAL_CALL Model::getDefaultInstance() | |
| throw( RuntimeException ) | |
| { | |
| ensureAtLeastOneInstance(); | |
| DBG_ASSERT( mpInstances->countItems() > 0, "no instance?" ); | |
| Reference<XDocument> aInstance; | |
| getInstanceData( mpInstances->getItem( 0 ), NULL, &aInstance, NULL, NULL ); | |
| return aInstance; | |
| } | |
| // | |
| // bindings management | |
| // | |
| Model::XPropertySet_t SAL_CALL Model::createBinding() | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| return new Binding(); | |
| } | |
| Model::XPropertySet_t Model::cloneBinding( const XPropertySet_t& xBinding ) | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| XPropertySet_t xNewBinding = createBinding(); | |
| copy( xBinding, xNewBinding ); | |
| return xNewBinding; | |
| } | |
| Model::XPropertySet_t Model::getBinding( const rtl::OUString& sId ) | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| return mpBindings->hasItem( sId ) ? mpBindings->getItem( sId ) : NULL; | |
| } | |
| Model::XSet_t Model::getBindings() | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| return mxBindings; | |
| } | |
| // | |
| // submission management | |
| // | |
| Model::XSubmission_t Model::createSubmission() | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| return new Submission(); | |
| } | |
| Model::XSubmission_t Model::cloneSubmission(const XPropertySet_t& xSubmission) | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| XSubmission_t xNewSubmission = createSubmission(); | |
| XPropertySet_t xAsPropertySet( xNewSubmission.get() ); | |
| copy( xSubmission.get(), xAsPropertySet ); | |
| return xNewSubmission; | |
| } | |
| Model::XSubmission_t Model::getSubmission( const rtl::OUString& sId ) | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| XSubmission_t xSubmission; | |
| if ( mpSubmissions->hasItem( sId ) ) | |
| xSubmission = xSubmission.query( mpSubmissions->getItem( sId ) ); | |
| return xSubmission; | |
| } | |
| Model::XSet_t Model::getSubmissions() | |
| throw( RuntimeException ) | |
| { | |
| DBG_INVARIANT(); | |
| return mxSubmissions; | |
| } | |
| // | |
| // implementation of XFormsUIHelper1 interface | |
| // can be found in file model_ui.cxx | |
| // | |
| // | |
| // implement XPropertySet & friends | |
| // | |
| #define HANDLE_ID 0 | |
| #define HANDLE_Instance 1 | |
| #define HANDLE_InstanceURL 2 | |
| #define HANDLE_ForeignSchema 3 | |
| #define HANDLE_SchemaRef 4 | |
| #define HANDLE_Namespaces 5 | |
| #define HANDLE_ExternalData 6 | |
| #define REGISTER_PROPERTY( property, type ) \ | |
| registerProperty( PROPERTY( property, type ), \ | |
| new DirectPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) ); | |
| #define REGISTER_PROPERTY_API( property, type ) \ | |
| registerProperty( PROPERTY( property, type ), \ | |
| new APIPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) ); | |
| #define REGISTER_BOOL_PROPERTY( property ) \ | |
| registerProperty( PROPERTY( property, sal_Bool ), \ | |
| new BooleanPropertyAccessor< Model, bool >( this, &Model::set##property, &Model::get##property ) ); | |
| void Model::initializePropertySet() | |
| { | |
| REGISTER_PROPERTY_API ( ID, OUString ); | |
| REGISTER_PROPERTY ( ForeignSchema, XDocument_t ); | |
| REGISTER_PROPERTY ( SchemaRef, OUString ); | |
| REGISTER_PROPERTY ( Namespaces, XNameContainer_t ); | |
| REGISTER_BOOL_PROPERTY( ExternalData ); | |
| } | |
| void Model::update() | |
| throw( RuntimeException ) | |
| { | |
| rebuild(); | |
| } | |
| sal_Int64 Model::getSomething( const IntSequence_t& xId ) | |
| throw( RuntimeException ) | |
| { | |
| return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL ); | |
| } | |
| Sequence<sal_Int8> Model::getImplementationId() | |
| throw( RuntimeException ) | |
| { | |
| return getUnoTunnelID(); | |
| } | |
| // | |
| // 'shift' operators for getting data into and out of Anys | |
| // | |
| void operator <<= ( com::sun::star::uno::Any& rAny, | |
| xforms::Model* pModel) | |
| { | |
| Reference<XPropertySet> xPropSet( static_cast<XPropertySet*>( pModel ) ); | |
| rAny <<= xPropSet; | |
| } | |
| bool operator >>= ( xforms::Model* pModel, | |
| com::sun::star::uno::Any& rAny ) | |
| { | |
| bool bRet = false; | |
| // acquire model pointer through XUnoTunnel | |
| Reference<XUnoTunnel> xTunnel( rAny, UNO_QUERY ); | |
| if( xTunnel.is() ) | |
| { | |
| pModel = reinterpret_cast<xforms::Model*>( | |
| xTunnel->getSomething( xforms::Model::getUnoTunnelID() ) ); | |
| bRet = true; | |
| } | |
| return bRet; | |
| } |