LCOV - code coverage report
Current view: top level - libreoffice/forms/source/xforms - model_ui.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 457 0.0 %
Date: 2012-12-17 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "model.hxx"
      22             : #include "model_helper.hxx"
      23             : #include "mip.hxx"
      24             : #include "evaluationcontext.hxx"
      25             : #include "unohelper.hxx"
      26             : #include "submission/serialization_app_xml.hxx"
      27             : #include "resourcehelper.hxx"
      28             : #include "xmlhelper.hxx"
      29             : #include "convert.hxx"
      30             : 
      31             : #include <rtl/ustring.hxx>
      32             : #include <rtl/ustrbuf.hxx>
      33             : #include <tools/debug.hxx>
      34             : 
      35             : // UNO classes
      36             : #include <com/sun/star/xml/dom/XNode.hpp>
      37             : #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
      38             : #include <com/sun/star/xml/dom/XDocumentFragment.hpp>
      39             : #include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
      40             : #include <com/sun/star/xml/xpath/XXPathObject.hpp>
      41             : #include <com/sun/star/xml/xpath/XPathObjectType.hpp>
      42             : #include <com/sun/star/beans/PropertyValue.hpp>
      43             : #include <com/sun/star/io/XInputStream.hpp>
      44             : #include <com/sun/star/io/XActiveDataSink.hpp>
      45             : #include <com/sun/star/io/XTextInputStream.hpp>
      46             : #include <com/sun/star/container/XEnumeration.hpp>
      47             : #include <com/sun/star/container/XNameContainer.hpp>
      48             : #include <com/sun/star/frame/XModel.hpp>
      49             : #include <com/sun/star/xforms/XFormsSupplier.hpp>
      50             : #include <com/sun/star/xforms/XDataTypeRepository.hpp>
      51             : #include <com/sun/star/xsd/XDataType.hpp>
      52             : #include <com/sun/star/xsd/DataTypeClass.hpp>
      53             : 
      54             : 
      55             : using rtl::OUString;
      56             : using rtl::OUStringBuffer;
      57             : using com::sun::star::beans::PropertyValue;
      58             : using com::sun::star::io::XInputStream;
      59             : using com::sun::star::io::XActiveDataSink;
      60             : using com::sun::star::io::XTextInputStream;
      61             : using com::sun::star::container::XEnumeration;
      62             : using com::sun::star::container::XNameContainer;
      63             : using com::sun::star::xforms::XFormsSupplier;
      64             : 
      65             : using namespace xforms;
      66             : using namespace com::sun::star::uno;
      67             : using namespace com::sun::star::xml::dom;
      68             : using namespace com::sun::star::xml::xpath;
      69             : 
      70             : 
      71             : 
      72             : //
      73             : // implement XFormsUIHelper1
      74             : //
      75             : 
      76           0 : OUString Model::getDefaultServiceNameForNode( const XNode_t& xNode )
      77             :     throw( RuntimeException )
      78             : {
      79             :     // determine service for control. string/text field is default.
      80           0 :     OUString sService = OUSTRING("com.sun.star.form.component.TextField");
      81             : 
      82             :     // query repository for suitable type
      83             :     OSL_ENSURE( mxDataTypes.is(), "no type repository?" );
      84           0 :     OUString sTypeName = queryMIP( xNode ).getTypeName();
      85           0 :     if( mxDataTypes->hasByName( sTypeName ) )
      86             :     {
      87             :         OSL_ENSURE( mxDataTypes->getDataType( sTypeName ).is(),
      88             :                     "has or has not?" );
      89             : 
      90           0 :         switch( mxDataTypes->getDataType( sTypeName )->getTypeClass() )
      91             :         {
      92             :         case com::sun::star::xsd::DataTypeClass::BOOLEAN:
      93           0 :             sService = OUSTRING("com.sun.star.form.component.CheckBox");
      94           0 :             break;
      95             :         case com::sun::star::xsd::DataTypeClass::DOUBLE:
      96             :         case com::sun::star::xsd::DataTypeClass::DECIMAL:
      97             :         case com::sun::star::xsd::DataTypeClass::FLOAT:
      98           0 :             sService = OUSTRING("com.sun.star.form.component.NumericField");
      99           0 :             break;
     100             : 
     101             :         case com::sun::star::xsd::DataTypeClass::STRING:
     102             :         case com::sun::star::xsd::DataTypeClass::DURATION:
     103             :         case com::sun::star::xsd::DataTypeClass::DATETIME:
     104             :         case com::sun::star::xsd::DataTypeClass::TIME:
     105             :         case com::sun::star::xsd::DataTypeClass::DATE:
     106             :         case com::sun::star::xsd::DataTypeClass::gYearMonth:
     107             :         case com::sun::star::xsd::DataTypeClass::gYear:
     108             :         case com::sun::star::xsd::DataTypeClass::gMonthDay:
     109             :         case com::sun::star::xsd::DataTypeClass::gDay:
     110             :         case com::sun::star::xsd::DataTypeClass::gMonth:
     111             :         case com::sun::star::xsd::DataTypeClass::hexBinary:
     112             :         case com::sun::star::xsd::DataTypeClass::base64Binary:
     113             :         case com::sun::star::xsd::DataTypeClass::anyURI:
     114             :         case com::sun::star::xsd::DataTypeClass::QName:
     115             :         case com::sun::star::xsd::DataTypeClass::NOTATION:
     116             :         default:
     117             :             // keep default
     118           0 :             break;
     119             :         }
     120             :     }
     121             : 
     122           0 :     return sService;
     123             : }
     124             : 
     125             : 
     126           0 : static void lcl_OutPosition( OUStringBuffer& rBuffer,
     127             :                       const Reference<XNode>& xNode )
     128             : {
     129             :     OSL_ENSURE( xNode->getParentNode().is(), "need parent" );
     130             : 
     131             :     // count # of occurrences of this node
     132           0 :     sal_Int32 nFound = 0;
     133           0 :     sal_Int32 nPosition = -1;
     134           0 :     if( xNode->getParentNode().is() )
     135             :     {
     136           0 :         for( Reference<XNode> xIter = xNode->getParentNode()->getFirstChild();
     137           0 :              xIter != NULL;
     138           0 :              xIter = xIter->getNextSibling() )
     139             :         {
     140           0 :             if( xIter->getNodeType() == xNode->getNodeType() &&
     141           0 :                 xIter->getNodeName() == xNode->getNodeName() &&
     142           0 :                 xIter->getNamespaceURI() == xNode->getNamespaceURI() )
     143             :             {
     144           0 :                 nFound++;
     145           0 :                 if( xIter == xNode )
     146           0 :                     nPosition = nFound;
     147             :             }
     148           0 :         }
     149             :     }
     150             :     OSL_ENSURE( nFound > 0  &&  nPosition > 0, "node not found???" );
     151             : 
     152             :     // output position (if necessary)
     153           0 :     if( nFound > 1 )
     154             :     {
     155           0 :         rBuffer.insert( 0, sal_Unicode(']') );
     156           0 :         rBuffer.insert( 0, nPosition );
     157           0 :         rBuffer.insert( 0, sal_Unicode('[') );
     158             :     }
     159           0 : }
     160             : 
     161           0 : static void lcl_OutName( OUStringBuffer& rBuffer,
     162             :                   const Reference<XNode>& xNode )
     163             : {
     164           0 :     rBuffer.insert( 0, xNode->getNodeName() );
     165           0 :     OUString sPrefix = xNode->getPrefix();
     166           0 :     if( !sPrefix.isEmpty() )
     167             :     {
     168           0 :         rBuffer.insert( 0, sal_Unicode(':') );
     169           0 :         rBuffer.insert( 0, sPrefix );
     170           0 :     }
     171           0 : }
     172             : 
     173           0 : static void lcl_OutInstance( OUStringBuffer& rBuffer,
     174             :                       const Reference<XNode>& xNode,
     175             :                       Model* pModel )
     176             : {
     177           0 :     Reference<XDocument> xDoc = xNode->getOwnerDocument();
     178             : 
     179           0 :     if( xDoc != pModel->getDefaultInstance() )
     180             :     {
     181           0 :         rBuffer.insert( 0, OUSTRING("')") );
     182             : 
     183             :         // iterate over instances, and find the right one
     184           0 :         OUString sInstanceName;
     185             :         Reference<XEnumeration> xEnum =
     186           0 :             pModel->getInstances()->createEnumeration();
     187           0 :         while( sInstanceName.isEmpty() && xEnum->hasMoreElements() )
     188             :         {
     189           0 :             Sequence<PropertyValue> aValues;
     190           0 :             xEnum->nextElement() >>= aValues;
     191             : 
     192             :             // get ID and instance
     193           0 :             OUString sId;
     194           0 :             Reference<XDocument> xInstance;
     195           0 :             getInstanceData( aValues, &sId, &xInstance, NULL, NULL );
     196             : 
     197             :             // now check whether this was our instance:
     198           0 :             if( xInstance == xDoc )
     199           0 :                 sInstanceName = sId;
     200           0 :         }
     201             : 
     202           0 :         rBuffer.insert( 0, sInstanceName );
     203           0 :         rBuffer.insert( 0, OUSTRING("instance('") );
     204           0 :     }
     205           0 : }
     206             : 
     207           0 : OUString Model::getDefaultBindingExpressionForNode(
     208             :     const XNode_t& xNode,
     209             :     const EvaluationContext& rContext)
     210             : {
     211             :     OSL_ENSURE( xNode.is(), "need node" );
     212             : 
     213             :     // iterate upwards and put sections into the expression buffer.
     214             :     // Stop iteration either at context node (relative expression) or
     215             :     // at document root, whichever occurs first.
     216           0 :     OUStringBuffer aBuffer;
     217           0 :     for( Reference<XNode> xCurrent = xNode;
     218           0 :          xCurrent.is()  &&  xCurrent != rContext.mxContextNode;
     219           0 :          xCurrent = xCurrent->getParentNode() )
     220             :     {
     221             :         // insert a '/' for every step except the first
     222           0 :         if( aBuffer.getLength() > 0 )
     223           0 :             aBuffer.insert( 0, sal_Unicode('/') );
     224             : 
     225           0 :         switch( xCurrent->getNodeType() )
     226             :         {
     227             :         case NodeType_ELEMENT_NODE:
     228           0 :             lcl_OutPosition( aBuffer, xCurrent );
     229           0 :             lcl_OutName( aBuffer, xCurrent );
     230           0 :             break;
     231             : 
     232             :         case NodeType_TEXT_NODE:
     233           0 :             lcl_OutPosition( aBuffer, xCurrent );
     234           0 :             aBuffer.insert( 0, OUSTRING("text()") );
     235           0 :             break;
     236             : 
     237             :         case NodeType_ATTRIBUTE_NODE:
     238           0 :             lcl_OutName( aBuffer, xCurrent );
     239           0 :             aBuffer.insert( 0, sal_Unicode('@') );
     240           0 :             break;
     241             : 
     242             :         case NodeType_DOCUMENT_NODE:
     243             :             // check for which instance we have
     244           0 :             lcl_OutInstance( aBuffer, xCurrent, this );
     245           0 :             break;
     246             : 
     247             :         default:
     248             :             // unknown type? fail!
     249             :             OSL_FAIL( "unknown node type!" );
     250           0 :             xCurrent.set( NULL );
     251           0 :             aBuffer.makeStringAndClear();
     252             :             // we'll remove the slash below
     253           0 :             aBuffer.insert( 0, sal_Unicode('/') );
     254           0 :             break;
     255             :         }
     256           0 :     }
     257             : 
     258           0 :     return aBuffer.makeStringAndClear();
     259             : }
     260             : 
     261             : 
     262             : 
     263           0 : OUString Model::getDefaultBindingExpressionForNode( const XNode_t& xNode )
     264             :     throw( RuntimeException )
     265             : {
     266           0 :     return getDefaultBindingExpressionForNode( xNode, getEvaluationContext() );
     267             : }
     268             : 
     269           0 : static bool lcl_isWhitespace( const OUString& rString )
     270             : {
     271           0 :     sal_Int32 nLength = rString.getLength();
     272           0 :     const sal_Unicode* pStr = rString.getStr();
     273             : 
     274           0 :     bool bWhitespace = true;
     275           0 :     for( sal_Int32 i = 0; bWhitespace && ( i < nLength ); i++ )
     276             :     {
     277           0 :         sal_Unicode c = pStr[i];
     278             :         bWhitespace = ( c == sal_Unicode(0x09) ||
     279             :                         c == sal_Unicode(0x0A) ||
     280             :                         c == sal_Unicode(0x0D) ||
     281           0 :                         c == sal_Unicode(0x20) );
     282             :     }
     283           0 :     return bWhitespace;
     284             : }
     285             : 
     286           0 : OUString Model::getNodeDisplayName( const XNode_t& xNode,
     287             :                                     sal_Bool bDetail )
     288             :     throw( RuntimeException )
     289             : {
     290           0 :     OUStringBuffer aBuffer;
     291             : 
     292           0 :     switch( xNode->getNodeType() )
     293             :     {
     294             :     case NodeType_ELEMENT_NODE:
     295           0 :         lcl_OutName( aBuffer, xNode );
     296           0 :         break;
     297             : 
     298             :     case NodeType_TEXT_NODE:
     299             :         {
     300           0 :             OUString sContent = xNode->getNodeValue();
     301           0 :             if( bDetail || ! lcl_isWhitespace( sContent ) )
     302             :             {
     303           0 :                 aBuffer.append( sal_Unicode('"') );
     304           0 :                 aBuffer.append( Convert::collapseWhitespace( sContent ) );
     305           0 :                 aBuffer.append( sal_Unicode('"') );
     306           0 :             }
     307             :         }
     308           0 :         break;
     309             : 
     310             :     case NodeType_ATTRIBUTE_NODE:
     311           0 :         lcl_OutName( aBuffer, xNode );
     312           0 :         aBuffer.insert( 0, sal_Unicode('@') );
     313           0 :         break;
     314             : 
     315             :     case NodeType_DOCUMENT_NODE:
     316           0 :         if( xNode == getDefaultInstance() )
     317           0 :             aBuffer.append( sal_Unicode('/') );
     318             :         else
     319           0 :             lcl_OutInstance( aBuffer, xNode, this );
     320           0 :         break;
     321             : 
     322             :     default:
     323             :         // unknown type? fail!
     324             :         OSL_FAIL( "unknown node type!" );
     325           0 :         break;
     326             :     }
     327             : 
     328           0 :     return aBuffer.makeStringAndClear();
     329             : }
     330             : 
     331           0 : OUString Model::getNodeName( const XNode_t& xNode )
     332             :     throw( RuntimeException )
     333             : {
     334           0 :     OUStringBuffer aBuffer;
     335             : 
     336           0 :     switch( xNode->getNodeType() )
     337             :     {
     338             :     case NodeType_ELEMENT_NODE:
     339             :     case NodeType_ATTRIBUTE_NODE:
     340           0 :         lcl_OutName( aBuffer, xNode );
     341           0 :         break;
     342             : 
     343             :     case NodeType_TEXT_NODE:
     344             :     case NodeType_DOCUMENT_NODE:
     345             :     default:
     346             :         // unknown type? fail!
     347             :         OSL_FAIL( "no name for this node type!" );
     348           0 :         break;
     349             :     }
     350             : 
     351           0 :     return aBuffer.makeStringAndClear();
     352             : }
     353             : 
     354           0 : OUString Model::getBindingName( const XPropertySet_t& xBinding,
     355             :                                 sal_Bool /*bDetail*/ )
     356             :     throw( RuntimeException )
     357             : {
     358           0 :     OUString sID;
     359           0 :     xBinding->getPropertyValue( OUSTRING("BindingID" ) ) >>= sID;
     360           0 :     OUString sExpression;
     361           0 :     xBinding->getPropertyValue( OUSTRING("BindingExpression" ) ) >>= sExpression;
     362             : 
     363           0 :     OUStringBuffer aBuffer;
     364           0 :     if( !sID.isEmpty() )
     365             :     {
     366           0 :         aBuffer.append( sID );
     367           0 :         aBuffer.append( OUSTRING(" (" ));
     368           0 :         aBuffer.append( sExpression );
     369           0 :         aBuffer.append( OUSTRING(")" ));
     370             :     }
     371             :     else
     372           0 :         aBuffer.append( sExpression );
     373             : 
     374           0 :     return aBuffer.makeStringAndClear();
     375             : }
     376             : 
     377           0 : OUString Model::getSubmissionName( const XPropertySet_t& xSubmission,
     378             :                                    sal_Bool /*bDetail*/ )
     379             :     throw( RuntimeException )
     380             : {
     381           0 :     OUString sID;
     382           0 :     xSubmission->getPropertyValue( OUSTRING("ID") ) >>= sID;
     383           0 :     return sID;
     384             : }
     385             : 
     386           0 : Model::XPropertySet_t Model::cloneBindingAsGhost( const XPropertySet_t &xBinding )
     387             :     throw( RuntimeException )
     388             : {
     389             :     // Create a new binding instance first...
     390           0 :     Binding *pBinding = new Binding();
     391             : 
     392             :     // ...and bump up the "defered notification counter"
     393             :     // to prevent this binding from contributing to the
     394             :     // MIPs table...
     395           0 :     pBinding->deferNotifications(true);
     396             : 
     397             :     // Copy the propertyset and return result...
     398           0 :     XPropertySet_t xNewBinding(pBinding);
     399           0 :     copy( xBinding, xNewBinding );
     400           0 :     return xNewBinding;
     401             : }
     402             : 
     403           0 : void Model::removeBindingIfUseless( const XPropertySet_t& xBinding )
     404             :     throw( RuntimeException )
     405             : {
     406           0 :     Binding* pBinding = Binding::getBinding( xBinding );
     407           0 :     if( pBinding != NULL )
     408             :     {
     409           0 :         if( ! pBinding->isUseful() )
     410           0 :             mpBindings->removeItem( pBinding );
     411             :     }
     412           0 : }
     413             : 
     414           0 : Model::XDocument_t Model::newInstance( const rtl::OUString& sName,
     415             :                          const rtl::OUString& sURL,
     416             :                          sal_Bool bURLOnce )
     417             :     throw( RuntimeException )
     418             : {
     419             :     // create a default instance with <instanceData> element
     420           0 :     XDocument_t xInstance = getDocumentBuilder()->newDocument();
     421             :     DBG_ASSERT( xInstance.is(), "failed to create DOM instance" );
     422             : 
     423           0 :     Reference<XNode>( xInstance, UNO_QUERY_THROW )->appendChild(
     424           0 :         Reference<XNode>( xInstance->createElement( OUSTRING("instanceData") ),
     425           0 :                           UNO_QUERY_THROW ) );
     426             : 
     427           0 :     Sequence<PropertyValue> aSequence;
     428           0 :     bool bOnce = bURLOnce; // bool, so we can take address in setInstanceData
     429           0 :     setInstanceData( aSequence, &sName, &xInstance, &sURL, &bOnce );
     430           0 :     sal_Int32 nInstance = mpInstances->addItem( aSequence );
     431           0 :     loadInstance( nInstance );
     432             : 
     433           0 :     return xInstance;
     434             : }
     435             : 
     436           0 : static sal_Int32 lcl_findProp( const PropertyValue* pValues,
     437             :                         sal_Int32 nLength,
     438             :                         const rtl::OUString& rName )
     439             : {
     440           0 :     bool bFound = false;
     441           0 :     sal_Int32 n = 0;
     442           0 :     for( ; !bFound && n < nLength; n++ )
     443             :     {
     444           0 :         bFound = ( pValues[n].Name == rName );
     445             :     }
     446           0 :     return bFound ? ( n - 1) : -1;
     447             : }
     448             : 
     449           0 : sal_Int32 xforms::lcl_findInstance( const InstanceCollection* pInstances,
     450             :                                     const rtl::OUString& rName )
     451             : {
     452           0 :     sal_Int32 nLength = pInstances->countItems();
     453           0 :     sal_Int32 n = 0;
     454           0 :     bool bFound = false;
     455           0 :     for( ; !bFound  &&  n < nLength; n++ )
     456             :     {
     457           0 :         OUString sName;
     458           0 :         getInstanceData( pInstances->getItem( n ), &sName, NULL, NULL, NULL );
     459           0 :         bFound = ( sName == rName );
     460           0 :     }
     461           0 :     return bFound ? ( n - 1 ) : -1;
     462             : }
     463             : 
     464           0 : void Model::renameInstance( const rtl::OUString& sFrom,
     465             :                             const rtl::OUString& sTo,
     466             :                             const rtl::OUString& sURL,
     467             :                             sal_Bool bURLOnce )
     468             :     throw( RuntimeException )
     469             : {
     470           0 :     sal_Int32 nPos = lcl_findInstance( mpInstances, sFrom );
     471           0 :     if( nPos != -1 )
     472             :     {
     473           0 :         Sequence<PropertyValue> aSeq = mpInstances->getItem( nPos );
     474           0 :         PropertyValue* pSeq = aSeq.getArray();
     475           0 :         sal_Int32 nLength = aSeq.getLength();
     476             : 
     477           0 :         sal_Int32 nProp = lcl_findProp( pSeq, nLength, OUSTRING("ID") );
     478           0 :         if( nProp == -1 )
     479             :         {
     480             :             // add name property
     481           0 :             aSeq.realloc( nLength + 1 );
     482           0 :             pSeq = aSeq.getArray();
     483           0 :             pSeq[ nLength ].Name = OUSTRING("ID");
     484           0 :             nProp = nLength;
     485             :         }
     486             : 
     487             :         // change name
     488           0 :         pSeq[ nProp ].Value <<= sTo;
     489             : 
     490             :         // change url
     491           0 :         nProp = lcl_findProp( pSeq, nLength, OUSTRING("URL") );
     492           0 :         if(nProp != -1)
     493           0 :             pSeq[ nProp ].Value <<= sURL;
     494             : 
     495             :         // change urlonce
     496           0 :         nProp = lcl_findProp( pSeq, nLength, OUSTRING("URLOnce") );
     497           0 :         if(nProp != -1)
     498           0 :             pSeq[ nProp ].Value <<= bURLOnce;
     499             : 
     500             :         // set instance
     501           0 :         mpInstances->setItem( nPos, aSeq );
     502             :     }
     503           0 : }
     504             : 
     505           0 : void Model::removeInstance( const rtl::OUString& sName )
     506             :     throw( RuntimeException )
     507             : {
     508           0 :     sal_Int32 nPos = lcl_findInstance( mpInstances, sName );
     509           0 :     if( nPos != -1 )
     510           0 :         mpInstances->removeItem( mpInstances->getItem( nPos ) );
     511           0 : }
     512             : 
     513           0 : static Reference<XNameContainer> lcl_getModels(
     514             :     const Reference<com::sun::star::frame::XModel>& xComponent )
     515             : {
     516           0 :     Reference<XNameContainer> xRet;
     517           0 :     Reference<XFormsSupplier> xSupplier( xComponent, UNO_QUERY );
     518           0 :     if( xSupplier.is() )
     519             :     {
     520           0 :         xRet = xSupplier->getXForms();
     521             :     }
     522           0 :     return xRet;
     523             : }
     524             : 
     525           0 : Model::XModel_t Model::newModel( const Reference<com::sun::star::frame::XModel>& xCmp,
     526             :                                  const OUString& sName )
     527             :     throw( RuntimeException )
     528             : {
     529           0 :     Model::XModel_t xModel;
     530           0 :     Reference<XNameContainer> xModels = lcl_getModels( xCmp );
     531           0 :     if( xModels.is()
     532           0 :         && ! xModels->hasByName( sName ) )
     533             :     {
     534           0 :         Model* pModel = new Model();
     535           0 :         xModel.set( pModel );
     536             : 
     537           0 :         pModel->setID( sName );
     538           0 :         pModel->newInstance( OUString(), OUString(), sal_False );
     539           0 :         pModel->initialize();
     540           0 :         xModels->insertByName( sName, makeAny( xModel ) );
     541             :     }
     542             : 
     543           0 :     return xModel;
     544             : }
     545             : 
     546           0 : void Model::renameModel( const Reference<com::sun::star::frame::XModel>& xCmp,
     547             :                          const OUString& sFrom,
     548             :                          const OUString& sTo )
     549             :     throw( RuntimeException )
     550             : {
     551           0 :     Reference<XNameContainer> xModels = lcl_getModels( xCmp );
     552           0 :     if( xModels.is()
     553           0 :         && xModels->hasByName( sFrom )
     554           0 :         && ! xModels->hasByName( sTo ) )
     555             :     {
     556           0 :         Reference<XModel> xModel( xModels->getByName( sFrom ), UNO_QUERY );
     557           0 :         xModel->setID( sTo );
     558           0 :         xModels->insertByName( sTo, makeAny( xModel ) );
     559           0 :         xModels->removeByName( sFrom );
     560           0 :     }
     561           0 : }
     562             : 
     563           0 : void Model::removeModel( const Reference<com::sun::star::frame::XModel>& xCmp,
     564             :                          const OUString& sName )
     565             :     throw( RuntimeException )
     566             : {
     567           0 :     Reference<XNameContainer> xModels = lcl_getModels( xCmp );
     568           0 :     if( xModels.is()
     569           0 :         && xModels->hasByName( sName ) )
     570             :     {
     571           0 :         xModels->removeByName( sName );
     572           0 :     }
     573           0 : }
     574             : 
     575           0 : Model::XNode_t Model::createElement( const XNode_t& xParent,
     576             :                                      const OUString& sName )
     577             :     throw( RuntimeException )
     578             : {
     579           0 :     Reference<XNode> xNode;
     580           0 :     if( xParent.is()
     581           0 :         && isValidXMLName( sName ) )
     582             :     {
     583             :         // TODO: implement proper namespace handling
     584           0 :         xNode.set( xParent->getOwnerDocument()->createElement( sName ),
     585           0 :                    UNO_QUERY );
     586             :     }
     587           0 :     return xNode;
     588             : }
     589             : 
     590           0 : Model::XNode_t Model::createAttribute( const XNode_t& xParent,
     591             :                                        const OUString& sName )
     592             :     throw( RuntimeException )
     593             : {
     594           0 :     Reference<XNode> xNode;
     595           0 :     Reference<XElement> xElement( xParent, UNO_QUERY );
     596           0 :     if( xParent.is()
     597           0 :         && xElement.is()
     598           0 :         && isValidXMLName( sName ) )
     599             :     {
     600             :         // handle case where attribute already exists
     601           0 :         sal_Int32 nCount = 0;
     602           0 :         OUString sUniqueName = sName;
     603           0 :         while( xElement->hasAttribute( sUniqueName ) )
     604             :         {
     605           0 :             nCount++;
     606           0 :             sUniqueName = sName + OUString::valueOf( nCount );
     607             :         }
     608             : 
     609             :         // TODO: implement proper namespace handling
     610           0 :         xNode.set( xParent->getOwnerDocument()->createAttribute( sUniqueName ),
     611           0 :                    UNO_QUERY );
     612             :     }
     613           0 :     return xNode;
     614             : }
     615             : 
     616           0 : Model::XNode_t Model::renameNode( const XNode_t& xNode,
     617             :                                   const rtl::OUString& sName )
     618             :     throw( RuntimeException )
     619             : {
     620             :     // early out if we don't have to change the name
     621           0 :     if( xNode->getNodeName() == sName )
     622           0 :         return xNode;
     623             : 
     624             :     // refuse to change name if its an attribute, and the name is already used
     625           0 :     if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE
     626           0 :         && xNode->getParentNode().is()
     627           0 :         && Reference<XElement>(xNode->getParentNode(), UNO_QUERY_THROW)->hasAttribute( sName ) )
     628           0 :         return xNode;
     629             : 
     630             :     // note old binding expression so we can adjust bindings below
     631             :     OUString sOldDefaultBindingExpression =
     632           0 :         getDefaultBindingExpressionForNode( xNode );
     633             : 
     634           0 :     Reference<XDocument> xDoc = xNode->getOwnerDocument();
     635           0 :     Reference<XNode> xNew;
     636           0 :     if( xNode->getNodeType() == NodeType_ELEMENT_NODE )
     637             :     {
     638           0 :         Reference<XElement> xElem = xDoc->createElement( sName );
     639           0 :         xNew.set( xElem, UNO_QUERY );
     640             : 
     641             :         // iterate over all attributes and append them to the new element
     642           0 :         Reference<XElement> xOldElem( xNode, UNO_QUERY );
     643             :         OSL_ENSURE( xNode.is(), "no element?" );
     644             : 
     645           0 :         Reference<XNamedNodeMap> xMap = xNode->getAttributes();
     646           0 :         sal_Int32 nLength = xMap.is() ? xMap->getLength() : 0;
     647           0 :         for( sal_Int32 n = 0; n < nLength; n++ )
     648             :         {
     649           0 :             Reference<XAttr> xAttr( xMap->item(n), UNO_QUERY );
     650           0 :             xElem->setAttributeNode( xOldElem->removeAttributeNode( xAttr ) );
     651           0 :         }
     652             : 
     653             :         // iterate over all children and append them to the new element
     654           0 :         for( Reference<XNode> xCurrent = xNode->getFirstChild();
     655           0 :              xCurrent.is();
     656           0 :              xCurrent = xNode->getFirstChild() )
     657             :         {
     658           0 :             xNew->appendChild( xNode->removeChild( xCurrent ) );
     659           0 :         }
     660             : 
     661           0 :         xNode->getParentNode()->replaceChild( xNew, xNode );
     662             :     }
     663           0 :     else if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE )
     664             :     {
     665             :         // create new attribute
     666           0 :         Reference<XAttr> xAttr = xDoc->createAttribute( sName );
     667           0 :         xAttr->setValue( xNode->getNodeValue() );
     668             : 
     669             :         // replace node
     670           0 :         Reference<XNode> xParent = xNode->getParentNode();
     671           0 :         xParent->removeChild( xNode );
     672           0 :         xNew = xParent->appendChild( Reference<XNode>( xAttr, UNO_QUERY ) );
     673             :     }
     674             :     else
     675             :     {
     676             :         OSL_FAIL( "can't rename this node type" );
     677             :     }
     678             : 
     679             :     // adjust bindings (if necessary):
     680           0 :     if( xNew.is() )
     681             :     {
     682             :         // iterate over bindings and replace default expressions
     683             :         OUString sNewDefaultBindingExpression =
     684           0 :             getDefaultBindingExpressionForNode( xNew );
     685           0 :         for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ )
     686             :         {
     687             :             Binding* pBinding = Binding::getBinding(
     688           0 :                 mpBindings->Collection<XPropertySet_t>::getItem( n ) );
     689             : 
     690           0 :             if( pBinding->getBindingExpression()
     691           0 :                     == sOldDefaultBindingExpression )
     692           0 :                 pBinding->setBindingExpression( sNewDefaultBindingExpression );
     693           0 :         }
     694             :     }
     695             : 
     696             :     // return node; return old node if renaming failed
     697           0 :     return xNew.is() ? xNew : xNode;
     698             : }
     699             : 
     700           0 : Model::XPropertySet_t Model::getBindingForNode( const XNode_t& xNode,
     701             :                                                 sal_Bool bCreate )
     702             :     throw( RuntimeException )
     703             : {
     704             :     OSL_ENSURE( xNode.is(), "no node?" );
     705             : 
     706             :     // We will iterate over all bindings and determine the
     707             :     // appropriateness of the respective binding for this node. The
     708             :     // best one will be used. If we don't find any and bCreate is set,
     709             :     // then we will create a suitable binding.
     710           0 :     Binding* pBestBinding = NULL;
     711           0 :     sal_Int32 nBestScore = 0;
     712             : 
     713           0 :     for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ )
     714             :     {
     715             :         Binding* pBinding = Binding::getBinding(
     716           0 :             mpBindings->Collection<XPropertySet_t>::getItem( n ) );
     717             : 
     718             :         OSL_ENSURE( pBinding != NULL, "no binding?" );
     719           0 :         Reference<XNodeList> xNodeList = pBinding->getXNodeList();
     720             : 
     721           0 :         sal_Int32 nNodes = xNodeList.is() ? xNodeList->getLength() : 0;
     722           0 :         if( nNodes > 0  &&  xNodeList->item( 0 ) == xNode )
     723             :         {
     724             :             // allright, we found a suitable node. Let's determine how
     725             :             // well it fits. Score:
     726             :             // - bind to exactly this node is better than whole nodeset
     727             :             // - simple binding expressions is better than complex ones
     728           0 :             sal_Int32 nScore = 0;
     729           0 :             if( nNodes == 1 )
     730           0 :                 nScore ++;
     731           0 :             if( pBinding->isSimpleBindingExpression() )
     732           0 :                 nScore ++;
     733             : 
     734             :             // if we found a better binding, remember it
     735           0 :             if( nScore > nBestScore )
     736             :             {
     737           0 :                 pBestBinding = pBinding;
     738           0 :                 nBestScore = nScore;
     739             :             }
     740             :         }
     741           0 :     }
     742             : 
     743             :     // create binding, if none was found and bCreate is set
     744             :     OSL_ENSURE( ( nBestScore == 0 ) == ( pBestBinding == NULL ),
     745             :                 "score != binding?" );
     746           0 :     if( bCreate  &&  pBestBinding == NULL )
     747             :     {
     748           0 :         pBestBinding = new Binding();
     749             :         pBestBinding->setBindingExpression(
     750           0 :             getDefaultBindingExpressionForNode( xNode ) );
     751           0 :         mpBindings->addItem( pBestBinding );
     752             :     }
     753             : 
     754           0 :     return pBestBinding;
     755             : }
     756             : 
     757           0 : void Model::removeBindingForNode( const XNode_t& )
     758             :     throw( RuntimeException )
     759             : {
     760             :     // determine whether suitable binding is still used
     761           0 : }
     762             : 
     763           0 : static OUString lcl_serializeForDisplay( const Reference< XAttr >& _rxAttrNode )
     764             : {
     765           0 :     ::rtl::OUString sResult;
     766             :     OSL_ENSURE( _rxAttrNode.is(), "lcl_serializeForDisplay( attr ): invalid argument!" );
     767           0 :     if ( _rxAttrNode.is() )
     768             :     {
     769           0 :         ::rtl::OUStringBuffer aBuffer;
     770           0 :         aBuffer.append( _rxAttrNode->getName() );
     771           0 :         aBuffer.appendAscii( "=" );
     772           0 :         ::rtl::OUString sValue = _rxAttrNode->getValue();
     773           0 :         sal_Unicode nQuote = '"';
     774           0 :         if ( sValue.indexOf( nQuote ) >= 0 )
     775           0 :             nQuote = '\'';
     776           0 :         aBuffer.append( nQuote );
     777           0 :         aBuffer.append( sValue );
     778           0 :         aBuffer.append( nQuote );
     779           0 :         aBuffer.append( (sal_Unicode)' ' );
     780           0 :         sResult = aBuffer.makeStringAndClear();
     781             :     }
     782           0 :     return sResult;
     783             : }
     784             : 
     785           0 : static OUString lcl_serializeForDisplay( const Reference<XNodeList>& xNodes )
     786             : {
     787           0 :     ::rtl::OUString sResult;
     788             : 
     789             :     // create document fragment
     790           0 :     Reference<XDocument> xDocument( getDocumentBuilder()->newDocument() );
     791             :     Reference<XDocumentFragment> xFragment(
     792           0 :         xDocument->createDocumentFragment() );
     793           0 :     Reference<XNode> xNode( xFragment, UNO_QUERY );
     794             :     OSL_ENSURE( xFragment.is(), "xFragment" );
     795             :     OSL_ENSURE( xNode.is(), "xNode" );
     796             : 
     797           0 :     sal_Int32 nAttributeNodes = 0;
     798             : 
     799             :     // attach nodelist to fragment
     800           0 :     sal_Int32 nLength = xNodes->getLength();
     801           0 :     for( sal_Int32 i = 0; i < nLength; i++ )
     802             :     {
     803           0 :         Reference<XNode> xCurrent = xNodes->item( i );
     804             : 
     805           0 :         switch ( xCurrent->getNodeType() )
     806             :         {
     807             :         case NodeType_DOCUMENT_NODE:
     808             :             // special-case documents: use top-level element instead
     809           0 :             xCurrent = xCurrent->getFirstChild();
     810           0 :             break;
     811             :         case NodeType_ATTRIBUTE_NODE:
     812             :         {
     813           0 :             Reference< XAttr > xAttr( xCurrent, UNO_QUERY );
     814           0 :             if ( xAttr.is() )
     815             :             {
     816           0 :                 sResult += lcl_serializeForDisplay( xAttr );
     817           0 :                 ++nAttributeNodes;
     818           0 :             }
     819             :         }
     820           0 :         continue;
     821             : 
     822             :         default:
     823           0 :             break;
     824             :         }
     825             : 
     826             :         // append node
     827           0 :         xNode->appendChild( xDocument->importNode( xCurrent, sal_True ) );
     828           0 :     }
     829             :     OSL_ENSURE( ( nAttributeNodes == 0 ) || ( nAttributeNodes == nLength ),
     830             :         "lcl_serializeForDisplay: mixed attribute and non-attribute nodes?" );
     831           0 :     if ( nAttributeNodes )
     832             :         // had only attribute nodes
     833             :         return sResult;
     834             : 
     835             :     // serialize fragment
     836           0 :     CSerializationAppXML aSerialization;
     837           0 :     aSerialization.setSource( xFragment );
     838           0 :     aSerialization.serialize();
     839             : 
     840             :     // copy stream into buffer
     841             :     Reference<XTextInputStream> xTextInputStream(
     842             :         createInstance( OUSTRING("com.sun.star.io.TextInputStream") ),
     843           0 :         UNO_QUERY );
     844             :     Reference<XActiveDataSink>( xTextInputStream, UNO_QUERY_THROW )
     845           0 :         ->setInputStream( aSerialization.getInputStream() );
     846             : 
     847             :     /* WORK AROUND for problem in serialization: currently, multiple
     848             :       XML delarations (<?xml...?>) are being written out and we don't
     849             :       want them. When this is fixed, the code below is nice and
     850             :       simple. The current code filters out the declarations.
     851             :     OUString sResult = xTextInputStream->readString( Sequence<sal_Unicode>(),
     852             :                                                      sal_True );
     853             :     */
     854             : 
     855             :     // well, the serialization prepends XML header(s) that we need to
     856             :     // remove first.
     857           0 :     OUStringBuffer aBuffer;
     858           0 :     while( ! xTextInputStream->isEOF() )
     859             :     {
     860           0 :         OUString sLine = xTextInputStream->readLine();
     861           0 :         if( !sLine.isEmpty()
     862           0 :             && sLine.compareToAscii( "<?xml", 5 ) != 0 )
     863             :         {
     864           0 :             aBuffer.append( sLine );
     865           0 :             aBuffer.append( sal_Unicode('\n') );
     866             :         }
     867           0 :     }
     868           0 :     sResult = aBuffer.makeStringAndClear();
     869             : 
     870           0 :     return sResult;
     871             : }
     872             : 
     873           0 : static OUString lcl_serializeForDisplay( const Reference<XXPathObject>& xResult )
     874             : {
     875             :     // error handling first
     876           0 :     if( ! xResult.is() )
     877           0 :         return getResource( RID_STR_XFORMS_CANT_EVALUATE );
     878             : 
     879             : 
     880             :     // TODO: localize
     881           0 :     OUStringBuffer aBuffer;
     882             : 
     883           0 :     switch( xResult->getObjectType() )
     884             :     {
     885             :     case XPathObjectType_XPATH_BOOLEAN:
     886           0 :         aBuffer.append( xResult->getBoolean()
     887             :                         ? OUSTRING("true")
     888           0 :                         : OUSTRING("false") );
     889           0 :         break;
     890             : 
     891             :     case XPathObjectType_XPATH_STRING:
     892           0 :         aBuffer.append( sal_Unicode('"') );
     893           0 :         aBuffer.append( xResult->getString() );
     894           0 :         aBuffer.append( sal_Unicode('"') );
     895           0 :         break;
     896             : 
     897             :     case XPathObjectType_XPATH_NODESET:
     898           0 :         aBuffer.append( lcl_serializeForDisplay( xResult->getNodeList() ) );
     899           0 :         break;
     900             : 
     901             :     case XPathObjectType_XPATH_NUMBER:
     902           0 :         aBuffer.append( xResult->getDouble() );
     903           0 :         break;
     904             : 
     905             :     case XPathObjectType_XPATH_UNDEFINED:
     906             :     case XPathObjectType_XPATH_POINT:
     907             :     case XPathObjectType_XPATH_RANGE:
     908             :     case XPathObjectType_XPATH_LOCATIONSET:
     909             :     case XPathObjectType_XPATH_USERS:
     910             :     case XPathObjectType_XPATH_XSLT_TREE:
     911             :     default:
     912             :         // TODO: localized error message?
     913           0 :         break;
     914             :     }
     915             : 
     916           0 :     return aBuffer.makeStringAndClear();
     917             : }
     918             : 
     919           0 : OUString Model::getResultForExpression(
     920             :     const XPropertySet_t& xBinding,
     921             :     sal_Bool bIsBindingExpression,
     922             :     const OUString& sExpression )
     923             :     throw( RuntimeException )
     924             : {
     925           0 :     Binding* pBinding = Binding::getBinding( xBinding );
     926           0 :     if( pBinding == NULL )
     927           0 :         throw RuntimeException();
     928             : 
     929             :     // prepare & evaluate expression
     930           0 :     OUStringBuffer aBuffer;
     931           0 :     ComputedExpression aExpression;
     932           0 :     aExpression.setExpression( sExpression );
     933           0 :     if( bIsBindingExpression )
     934             :     {
     935             :         // binding: use binding context and evaluation
     936           0 :         aExpression.evaluate( pBinding->getEvaluationContext() );
     937           0 :         aBuffer.append( lcl_serializeForDisplay( aExpression.getXPath() ) );
     938             :     }
     939             :     else
     940             :     {
     941             :         // MIP (not binding): iterate over bindings contexts
     942             :         std::vector<EvaluationContext> aContext =
     943           0 :             pBinding->getMIPEvaluationContexts();
     944           0 :         for( std::vector<EvaluationContext>::iterator aIter = aContext.begin();
     945           0 :              aIter != aContext.end();
     946             :              ++aIter )
     947             :         {
     948           0 :             aExpression.evaluate( *aIter );
     949           0 :             aBuffer.append( lcl_serializeForDisplay(aExpression.getXPath()) );
     950           0 :             aBuffer.append( sal_Unicode('\n') );
     951           0 :         }
     952             :     }
     953           0 :     return aBuffer.makeStringAndClear();
     954             : }
     955             : 
     956           0 : sal_Bool Model::isValidXMLName( const OUString& sName )
     957             :     throw( RuntimeException )
     958             : {
     959           0 :     return isValidQName( sName, NULL );
     960             : }
     961             : 
     962           0 : sal_Bool Model::isValidPrefixName( const OUString& sName )
     963             :     throw( RuntimeException )
     964             : {
     965           0 :     return ::isValidPrefixName( sName, NULL );
     966             : }
     967             : 
     968           0 : void Model::setNodeValue(
     969             :     const XNode_t& xNode,
     970             :     const rtl::OUString& sValue )
     971             :     throw( RuntimeException )
     972             : {
     973           0 :     setSimpleContent( xNode, sValue );
     974           0 : }
     975             : 
     976             : 
     977             : //
     978             : // helper functions from model_helper.hxx
     979             : //
     980             : 
     981           0 : void xforms::getInstanceData(
     982             :     const Sequence<PropertyValue>& aValues,
     983             :     OUString* pID,
     984             :     Reference<XDocument>* pInstance,
     985             :     OUString* pURL,
     986             :     bool* pURLOnce )
     987             : {
     988           0 :     sal_Int32 nValues = aValues.getLength();
     989           0 :     const PropertyValue* pValues = aValues.getConstArray();
     990           0 :     for( sal_Int32 n = 0; n < nValues; n++ )
     991             :     {
     992           0 :         const PropertyValue& rValue = pValues[n];
     993             : #define PROP(NAME) \
     994             :         if( p##NAME != NULL && \
     995             :             rValue.Name == #NAME ) \
     996             :             rValue.Value >>= (*p##NAME)
     997           0 :         PROP(ID);
     998           0 :         PROP(Instance);
     999           0 :         PROP(URL);
    1000           0 :         PROP(URLOnce);
    1001             : #undef PROP
    1002             :     }
    1003           0 : }
    1004             : 
    1005           0 : void xforms::setInstanceData(
    1006             :     Sequence<PropertyValue>& aSequence,
    1007             :     const OUString* _pID,
    1008             :     const Reference<XDocument>* _pInstance,
    1009             :     const OUString* _pURL,
    1010             :     const bool* _pURLOnce )
    1011             : {
    1012             :     // get old instance data
    1013           0 :     OUString sID;
    1014           0 :     Reference<XDocument> xInstance;
    1015           0 :     OUString sURL;
    1016           0 :     bool bURLOnce = false;
    1017           0 :     getInstanceData( aSequence, &sID, &xInstance, &sURL, &bURLOnce );
    1018           0 :     const OUString* pID = !sID.isEmpty() ? &sID : NULL;
    1019           0 :     const Reference<XDocument>* pInstance = xInstance.is() ? &xInstance : NULL;
    1020           0 :     const OUString* pURL = !sURL.isEmpty() ? &sURL : NULL;
    1021           0 :     const bool* pURLOnce = ( bURLOnce && pURL != NULL ) ? &bURLOnce : NULL;
    1022             : 
    1023             :     // determine new instance data
    1024             : #define PROP(NAME) if( _p##NAME != NULL ) p##NAME = _p##NAME
    1025           0 :     PROP(ID);
    1026           0 :     PROP(Instance);
    1027           0 :     PROP(URL);
    1028           0 :     PROP(URLOnce);
    1029             : #undef PROP
    1030             : 
    1031             :     // count # of values we want to set
    1032           0 :     sal_Int32 nCount = 0;
    1033             : #define PROP(NAME) if( p##NAME != NULL ) nCount++
    1034           0 :     PROP(ID);
    1035           0 :     PROP(Instance);
    1036           0 :     PROP(URL);
    1037           0 :     PROP(URLOnce);
    1038             : #undef PROP
    1039             : 
    1040             :     // realloc sequence and enter values;
    1041           0 :     aSequence.realloc( nCount );
    1042           0 :     PropertyValue* pSequence = aSequence.getArray();
    1043           0 :     sal_Int32 nIndex = 0;
    1044             : #define PROP(NAME) \
    1045             :     if( p##NAME != NULL ) \
    1046             :     { \
    1047             :         pSequence[ nIndex ].Name = OUSTRING(#NAME); \
    1048             :         pSequence[ nIndex ].Value <<= *p##NAME; \
    1049             :         nIndex++; \
    1050             :     }
    1051           0 :     PROP(ID);
    1052           0 :     PROP(Instance);
    1053           0 :     PROP(URL);
    1054           0 :     PROP(URLOnce);
    1055             : #undef PROP
    1056           0 : }
    1057             : 
    1058             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10