LCOV - code coverage report
Current view: top level - forms/source/xforms - model_ui.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 0 444 0.0 %
Date: 2015-06-13 12:38:46 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             : #include <comphelper/processfactory.hxx>
      35             : 
      36             : // UNO classes
      37             : #include <com/sun/star/xml/dom/XNode.hpp>
      38             : #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
      39             : #include <com/sun/star/xml/dom/XDocumentFragment.hpp>
      40             : #include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
      41             : #include <com/sun/star/xml/xpath/XXPathObject.hpp>
      42             : #include <com/sun/star/xml/xpath/XPathObjectType.hpp>
      43             : #include <com/sun/star/beans/PropertyValue.hpp>
      44             : #include <com/sun/star/io/XInputStream.hpp>
      45             : #include <com/sun/star/io/XActiveDataSink.hpp>
      46             : #include <com/sun/star/io/TextInputStream.hpp>
      47             : #include <com/sun/star/container/XEnumeration.hpp>
      48             : #include <com/sun/star/container/XNameContainer.hpp>
      49             : #include <com/sun/star/frame/XModel.hpp>
      50             : #include <com/sun/star/xforms/XFormsSupplier.hpp>
      51             : #include <com/sun/star/xforms/XDataTypeRepository.hpp>
      52             : #include <com/sun/star/xsd/XDataType.hpp>
      53             : #include <com/sun/star/xsd/DataTypeClass.hpp>
      54             : 
      55             : 
      56             : using com::sun::star::beans::PropertyValue;
      57             : using com::sun::star::io::XInputStream;
      58             : using com::sun::star::io::XActiveDataSink;
      59             : using com::sun::star::io::TextInputStream;
      60             : using com::sun::star::io::XTextInputStream2;
      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, std::exception )
      78             : {
      79             :     // determine service for control. string/text field is default.
      80           0 :     OUString sService = "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 = "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 = "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             :              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, ']' );
     156           0 :         rBuffer.insert( 0, nPosition );
     157           0 :         rBuffer.insert( 0, '[' );
     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, ':' );
     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, "')" );
     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, "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.isEmpty() )
     223           0 :             aBuffer.insert( 0, '/' );
     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, "text()" );
     235           0 :             break;
     236             : 
     237             :         case NodeType_ATTRIBUTE_NODE:
     238           0 :             lcl_OutName( aBuffer, xCurrent );
     239           0 :             aBuffer.insert( 0, '@' );
     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, '/' );
     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, std::exception )
     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           0 :         bWhitespace = ( c == sal_Unicode(0x09) ||
     279           0 :                         c == sal_Unicode(0x0A) ||
     280           0 :                         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, std::exception )
     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 = aBuffer + "\"" + Convert::collapseWhitespace( sContent ) + "\"";
     304           0 :             }
     305             :         }
     306           0 :         break;
     307             : 
     308             :     case NodeType_ATTRIBUTE_NODE:
     309           0 :         lcl_OutName( aBuffer, xNode );
     310           0 :         aBuffer.insert( 0, '@' );
     311           0 :         break;
     312             : 
     313             :     case NodeType_DOCUMENT_NODE:
     314           0 :         if( xNode == getDefaultInstance() )
     315           0 :             aBuffer.append( '/' );
     316             :         else
     317           0 :             lcl_OutInstance( aBuffer, xNode, this );
     318           0 :         break;
     319             : 
     320             :     default:
     321             :         // unknown type? fail!
     322             :         OSL_FAIL( "unknown node type!" );
     323           0 :         break;
     324             :     }
     325             : 
     326           0 :     return aBuffer.makeStringAndClear();
     327             : }
     328             : 
     329           0 : OUString Model::getNodeName( const XNode_t& xNode )
     330             :     throw( RuntimeException, std::exception )
     331             : {
     332           0 :     OUStringBuffer aBuffer;
     333             : 
     334           0 :     switch( xNode->getNodeType() )
     335             :     {
     336             :     case NodeType_ELEMENT_NODE:
     337             :     case NodeType_ATTRIBUTE_NODE:
     338           0 :         lcl_OutName( aBuffer, xNode );
     339           0 :         break;
     340             : 
     341             :     case NodeType_TEXT_NODE:
     342             :     case NodeType_DOCUMENT_NODE:
     343             :     default:
     344             :         // unknown type? fail!
     345             :         OSL_FAIL( "no name for this node type!" );
     346           0 :         break;
     347             :     }
     348             : 
     349           0 :     return aBuffer.makeStringAndClear();
     350             : }
     351             : 
     352           0 : OUString Model::getBindingName( const XPropertySet_t& xBinding,
     353             :                                 sal_Bool /*bDetail*/ )
     354             :     throw( RuntimeException, std::exception )
     355             : {
     356           0 :     OUString sID;
     357           0 :     xBinding->getPropertyValue( "BindingID" ) >>= sID;
     358           0 :     OUString sExpression;
     359           0 :     xBinding->getPropertyValue( "BindingExpression" ) >>= sExpression;
     360             : 
     361           0 :     OUString sRet;
     362           0 :     if( !sID.isEmpty() )
     363             :     {
     364           0 :         sRet = sID + " (" + sExpression + ") ";
     365             :     }
     366             :     else
     367           0 :         sRet = sExpression;
     368             : 
     369           0 :     return sRet;
     370             : }
     371             : 
     372           0 : OUString Model::getSubmissionName( const XPropertySet_t& xSubmission,
     373             :                                    sal_Bool /*bDetail*/ )
     374             :     throw( RuntimeException, std::exception )
     375             : {
     376           0 :     OUString sID;
     377           0 :     xSubmission->getPropertyValue( "ID" ) >>= sID;
     378           0 :     return sID;
     379             : }
     380             : 
     381           0 : Model::XPropertySet_t Model::cloneBindingAsGhost( const XPropertySet_t &xBinding )
     382             :     throw( RuntimeException, std::exception )
     383             : {
     384             :     // Create a new binding instance first...
     385           0 :     Binding *pBinding = new Binding();
     386             : 
     387             :     // ...and bump up the "defered notification counter"
     388             :     // to prevent this binding from contributing to the
     389             :     // MIPs table...
     390           0 :     pBinding->deferNotifications(true);
     391             : 
     392             :     // Copy the propertyset and return result...
     393           0 :     XPropertySet_t xNewBinding(pBinding);
     394           0 :     copy( xBinding, xNewBinding );
     395           0 :     return xNewBinding;
     396             : }
     397             : 
     398           0 : void Model::removeBindingIfUseless( const XPropertySet_t& xBinding )
     399             :     throw( RuntimeException, std::exception )
     400             : {
     401           0 :     Binding* pBinding = Binding::getBinding( xBinding );
     402           0 :     if( pBinding != NULL )
     403             :     {
     404           0 :         if( ! pBinding->isUseful() )
     405           0 :             mpBindings->removeItem( pBinding );
     406             :     }
     407           0 : }
     408             : 
     409           0 : Model::XDocument_t Model::newInstance( const OUString& sName,
     410             :                          const OUString& sURL,
     411             :                          sal_Bool bURLOnce )
     412             :     throw( RuntimeException, std::exception )
     413             : {
     414             :     // create a default instance with <instanceData> element
     415           0 :     XDocument_t xInstance = getDocumentBuilder()->newDocument();
     416             :     DBG_ASSERT( xInstance.is(), "failed to create DOM instance" );
     417             : 
     418           0 :     Reference<XNode>( xInstance, UNO_QUERY_THROW )->appendChild(
     419           0 :         Reference<XNode>( xInstance->createElement( "instanceData" ),
     420           0 :                           UNO_QUERY_THROW ) );
     421             : 
     422           0 :     Sequence<PropertyValue> aSequence;
     423           0 :     bool bOnce = bURLOnce; // bool, so we can take address in setInstanceData
     424           0 :     setInstanceData( aSequence, &sName, &xInstance, &sURL, &bOnce );
     425           0 :     sal_Int32 nInstance = mpInstances->addItem( aSequence );
     426           0 :     loadInstance( nInstance );
     427             : 
     428           0 :     return xInstance;
     429             : }
     430             : 
     431           0 : static sal_Int32 lcl_findProp( const PropertyValue* pValues,
     432             :                         sal_Int32 nLength,
     433             :                         const OUString& rName )
     434             : {
     435           0 :     bool bFound = false;
     436           0 :     sal_Int32 n = 0;
     437           0 :     for( ; !bFound && n < nLength; n++ )
     438             :     {
     439           0 :         bFound = ( pValues[n].Name == rName );
     440             :     }
     441           0 :     return bFound ? ( n - 1) : -1;
     442             : }
     443             : 
     444           0 : sal_Int32 xforms::lcl_findInstance( const InstanceCollection* pInstances,
     445             :                                     const OUString& rName )
     446             : {
     447           0 :     sal_Int32 nLength = pInstances->countItems();
     448           0 :     sal_Int32 n = 0;
     449           0 :     bool bFound = false;
     450           0 :     for( ; !bFound  &&  n < nLength; n++ )
     451             :     {
     452           0 :         OUString sName;
     453           0 :         getInstanceData( pInstances->getItem( n ), &sName, NULL, NULL, NULL );
     454           0 :         bFound = ( sName == rName );
     455           0 :     }
     456           0 :     return bFound ? ( n - 1 ) : -1;
     457             : }
     458             : 
     459           0 : void Model::renameInstance( const OUString& sFrom,
     460             :                             const OUString& sTo,
     461             :                             const OUString& sURL,
     462             :                             sal_Bool bURLOnce )
     463             :     throw( RuntimeException, std::exception )
     464             : {
     465           0 :     sal_Int32 nPos = lcl_findInstance( mpInstances, sFrom );
     466           0 :     if( nPos != -1 )
     467             :     {
     468           0 :         Sequence<PropertyValue> aSeq = mpInstances->getItem( nPos );
     469           0 :         PropertyValue* pSeq = aSeq.getArray();
     470           0 :         sal_Int32 nLength = aSeq.getLength();
     471             : 
     472           0 :         sal_Int32 nProp = lcl_findProp( pSeq, nLength, "ID" );
     473           0 :         if( nProp == -1 )
     474             :         {
     475             :             // add name property
     476           0 :             aSeq.realloc( nLength + 1 );
     477           0 :             pSeq = aSeq.getArray();
     478           0 :             pSeq[ nLength ].Name = "ID";
     479           0 :             nProp = nLength;
     480             :         }
     481             : 
     482             :         // change name
     483           0 :         pSeq[ nProp ].Value <<= sTo;
     484             : 
     485             :         // change url
     486           0 :         nProp = lcl_findProp( pSeq, nLength, "URL" );
     487           0 :         if(nProp != -1)
     488           0 :             pSeq[ nProp ].Value <<= sURL;
     489             : 
     490             :         // change urlonce
     491           0 :         nProp = lcl_findProp( pSeq, nLength, "URLOnce" );
     492           0 :         if(nProp != -1)
     493           0 :             pSeq[ nProp ].Value <<= bURLOnce;
     494             : 
     495             :         // set instance
     496           0 :         mpInstances->setItem( nPos, aSeq );
     497             :     }
     498           0 : }
     499             : 
     500           0 : void Model::removeInstance( const OUString& sName )
     501             :     throw( RuntimeException, std::exception )
     502             : {
     503           0 :     sal_Int32 nPos = lcl_findInstance( mpInstances, sName );
     504           0 :     if( nPos != -1 )
     505           0 :         mpInstances->removeItem( mpInstances->getItem( nPos ) );
     506           0 : }
     507             : 
     508           0 : static Reference<XNameContainer> lcl_getModels(
     509             :     const Reference<com::sun::star::frame::XModel>& xComponent )
     510             : {
     511           0 :     Reference<XNameContainer> xRet;
     512           0 :     Reference<XFormsSupplier> xSupplier( xComponent, UNO_QUERY );
     513           0 :     if( xSupplier.is() )
     514             :     {
     515           0 :         xRet = xSupplier->getXForms();
     516             :     }
     517           0 :     return xRet;
     518             : }
     519             : 
     520           0 : Model::XModel_t Model::newModel( const Reference<com::sun::star::frame::XModel>& xCmp,
     521             :                                  const OUString& sName )
     522             :     throw( RuntimeException, std::exception )
     523             : {
     524           0 :     Model::XModel_t xModel;
     525           0 :     Reference<XNameContainer> xModels = lcl_getModels( xCmp );
     526           0 :     if( xModels.is()
     527           0 :         && ! xModels->hasByName( sName ) )
     528             :     {
     529           0 :         Model* pModel = new Model();
     530           0 :         xModel.set( pModel );
     531             : 
     532           0 :         pModel->setID( sName );
     533           0 :         pModel->newInstance( OUString(), OUString(), sal_False );
     534           0 :         pModel->initialize();
     535           0 :         xModels->insertByName( sName, makeAny( xModel ) );
     536             :     }
     537             : 
     538           0 :     return xModel;
     539             : }
     540             : 
     541           0 : void Model::renameModel( const Reference<com::sun::star::frame::XModel>& xCmp,
     542             :                          const OUString& sFrom,
     543             :                          const OUString& sTo )
     544             :     throw( RuntimeException, std::exception )
     545             : {
     546           0 :     Reference<XNameContainer> xModels = lcl_getModels( xCmp );
     547           0 :     if( xModels.is()
     548           0 :         && xModels->hasByName( sFrom )
     549           0 :         && ! xModels->hasByName( sTo ) )
     550             :     {
     551           0 :         Reference<XModel> xModel( xModels->getByName( sFrom ), UNO_QUERY );
     552           0 :         xModel->setID( sTo );
     553           0 :         xModels->insertByName( sTo, makeAny( xModel ) );
     554           0 :         xModels->removeByName( sFrom );
     555           0 :     }
     556           0 : }
     557             : 
     558           0 : void Model::removeModel( const Reference<com::sun::star::frame::XModel>& xCmp,
     559             :                          const OUString& sName )
     560             :     throw( RuntimeException, std::exception )
     561             : {
     562           0 :     Reference<XNameContainer> xModels = lcl_getModels( xCmp );
     563           0 :     if( xModels.is()
     564           0 :         && xModels->hasByName( sName ) )
     565             :     {
     566           0 :         xModels->removeByName( sName );
     567           0 :     }
     568           0 : }
     569             : 
     570           0 : Model::XNode_t Model::createElement( const XNode_t& xParent,
     571             :                                      const OUString& sName )
     572             :     throw( RuntimeException, std::exception )
     573             : {
     574           0 :     Reference<XNode> xNode;
     575           0 :     if( xParent.is()
     576           0 :         && isValidXMLName( sName ) )
     577             :     {
     578             :         // TODO: implement proper namespace handling
     579           0 :         xNode.set( xParent->getOwnerDocument()->createElement( sName ),
     580           0 :                    UNO_QUERY );
     581             :     }
     582           0 :     return xNode;
     583             : }
     584             : 
     585           0 : Model::XNode_t Model::createAttribute( const XNode_t& xParent,
     586             :                                        const OUString& sName )
     587             :     throw( RuntimeException, std::exception )
     588             : {
     589           0 :     Reference<XNode> xNode;
     590           0 :     Reference<XElement> xElement( xParent, UNO_QUERY );
     591           0 :     if( xParent.is()
     592           0 :         && xElement.is()
     593           0 :         && isValidXMLName( sName ) )
     594             :     {
     595             :         // handle case where attribute already exists
     596           0 :         sal_Int32 nCount = 0;
     597           0 :         OUString sUniqueName = sName;
     598           0 :         while( xElement->hasAttribute( sUniqueName ) )
     599             :         {
     600           0 :             nCount++;
     601           0 :             sUniqueName = sName + OUString::number( nCount );
     602             :         }
     603             : 
     604             :         // TODO: implement proper namespace handling
     605           0 :         xNode.set( xParent->getOwnerDocument()->createAttribute( sUniqueName ),
     606           0 :                    UNO_QUERY );
     607             :     }
     608           0 :     return xNode;
     609             : }
     610             : 
     611           0 : Model::XNode_t Model::renameNode( const XNode_t& xNode,
     612             :                                   const OUString& sName )
     613             :     throw( RuntimeException, std::exception )
     614             : {
     615             :     // early out if we don't have to change the name
     616           0 :     if( xNode->getNodeName() == sName )
     617           0 :         return xNode;
     618             : 
     619             :     // refuse to change name if its an attribute, and the name is already used
     620           0 :     if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE
     621           0 :         && xNode->getParentNode().is()
     622           0 :         && Reference<XElement>(xNode->getParentNode(), UNO_QUERY_THROW)->hasAttribute( sName ) )
     623           0 :         return xNode;
     624             : 
     625             :     // note old binding expression so we can adjust bindings below
     626             :     OUString sOldDefaultBindingExpression =
     627           0 :         getDefaultBindingExpressionForNode( xNode );
     628             : 
     629           0 :     Reference<XDocument> xDoc = xNode->getOwnerDocument();
     630           0 :     Reference<XNode> xNew;
     631           0 :     if( xNode->getNodeType() == NodeType_ELEMENT_NODE )
     632             :     {
     633           0 :         Reference<XElement> xElem = xDoc->createElement( sName );
     634           0 :         xNew.set( xElem, UNO_QUERY );
     635             : 
     636             :         // iterate over all attributes and append them to the new element
     637           0 :         Reference<XElement> xOldElem( xNode, UNO_QUERY );
     638             :         OSL_ENSURE( xNode.is(), "no element?" );
     639             : 
     640           0 :         Reference<XNamedNodeMap> xMap = xNode->getAttributes();
     641           0 :         sal_Int32 nLength = xMap.is() ? xMap->getLength() : 0;
     642           0 :         for( sal_Int32 n = 0; n < nLength; n++ )
     643             :         {
     644           0 :             Reference<XAttr> xAttr( xMap->item(n), UNO_QUERY );
     645           0 :             xElem->setAttributeNode( xOldElem->removeAttributeNode( xAttr ) );
     646           0 :         }
     647             : 
     648             :         // iterate over all children and append them to the new element
     649           0 :         for( Reference<XNode> xCurrent = xNode->getFirstChild();
     650             :              xCurrent.is();
     651           0 :              xCurrent = xNode->getFirstChild() )
     652             :         {
     653           0 :             xNew->appendChild( xNode->removeChild( xCurrent ) );
     654           0 :         }
     655             : 
     656           0 :         xNode->getParentNode()->replaceChild( xNew, xNode );
     657             :     }
     658           0 :     else if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE )
     659             :     {
     660             :         // create new attribute
     661           0 :         Reference<XAttr> xAttr = xDoc->createAttribute( sName );
     662           0 :         xAttr->setValue( xNode->getNodeValue() );
     663             : 
     664             :         // replace node
     665           0 :         Reference<XNode> xParent = xNode->getParentNode();
     666           0 :         xParent->removeChild( xNode );
     667           0 :         xNew = xParent->appendChild( xAttr );
     668             :     }
     669             :     else
     670             :     {
     671             :         OSL_FAIL( "can't rename this node type" );
     672             :     }
     673             : 
     674             :     // adjust bindings (if necessary):
     675           0 :     if( xNew.is() )
     676             :     {
     677             :         // iterate over bindings and replace default expressions
     678             :         OUString sNewDefaultBindingExpression =
     679           0 :             getDefaultBindingExpressionForNode( xNew );
     680           0 :         for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ )
     681             :         {
     682             :             Binding* pBinding = Binding::getBinding(
     683           0 :                 mpBindings->Collection<XPropertySet_t>::getItem( n ) );
     684             : 
     685           0 :             if( pBinding->getBindingExpression()
     686           0 :                     == sOldDefaultBindingExpression )
     687           0 :                 pBinding->setBindingExpression( sNewDefaultBindingExpression );
     688           0 :         }
     689             :     }
     690             : 
     691             :     // return node; return old node if renaming failed
     692           0 :     return xNew.is() ? xNew : xNode;
     693             : }
     694             : 
     695           0 : Model::XPropertySet_t Model::getBindingForNode( const XNode_t& xNode,
     696             :                                                 sal_Bool bCreate )
     697             :     throw( RuntimeException, std::exception )
     698             : {
     699             :     OSL_ENSURE( xNode.is(), "no node?" );
     700             : 
     701             :     // We will iterate over all bindings and determine the
     702             :     // appropriateness of the respective binding for this node. The
     703             :     // best one will be used. If we don't find any and bCreate is set,
     704             :     // then we will create a suitable binding.
     705           0 :     Binding* pBestBinding = NULL;
     706           0 :     sal_Int32 nBestScore = 0;
     707             : 
     708           0 :     for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ )
     709             :     {
     710             :         Binding* pBinding = Binding::getBinding(
     711           0 :             mpBindings->Collection<XPropertySet_t>::getItem( n ) );
     712             : 
     713             :         OSL_ENSURE( pBinding != NULL, "no binding?" );
     714           0 :         Reference<XNodeList> xNodeList = pBinding->getXNodeList();
     715             : 
     716           0 :         sal_Int32 nNodes = xNodeList.is() ? xNodeList->getLength() : 0;
     717           0 :         if( nNodes > 0  &&  xNodeList->item( 0 ) == xNode )
     718             :         {
     719             :             // allright, we found a suitable node. Let's determine how
     720             :             // well it fits. Score:
     721             :             // - bind to exactly this node is better than whole nodeset
     722             :             // - simple binding expressions is better than complex ones
     723           0 :             sal_Int32 nScore = 0;
     724           0 :             if( nNodes == 1 )
     725           0 :                 nScore ++;
     726           0 :             if( pBinding->isSimpleBindingExpression() )
     727           0 :                 nScore ++;
     728             : 
     729             :             // if we found a better binding, remember it
     730           0 :             if( nScore > nBestScore )
     731             :             {
     732           0 :                 pBestBinding = pBinding;
     733           0 :                 nBestScore = nScore;
     734             :             }
     735             :         }
     736           0 :     }
     737             : 
     738             :     // create binding, if none was found and bCreate is set
     739             :     OSL_ENSURE( ( nBestScore == 0 ) == ( pBestBinding == NULL ),
     740             :                 "score != binding?" );
     741           0 :     if( bCreate  &&  pBestBinding == NULL )
     742             :     {
     743           0 :         pBestBinding = new Binding();
     744             :         pBestBinding->setBindingExpression(
     745           0 :             getDefaultBindingExpressionForNode( xNode ) );
     746           0 :         mpBindings->addItem( pBestBinding );
     747             :     }
     748             : 
     749           0 :     return pBestBinding;
     750             : }
     751             : 
     752           0 : void Model::removeBindingForNode( const XNode_t& )
     753             :     throw( RuntimeException, std::exception )
     754             : {
     755             :     // determine whether suitable binding is still used
     756           0 : }
     757             : 
     758           0 : static OUString lcl_serializeForDisplay( const Reference< XAttr >& _rxAttrNode )
     759             : {
     760           0 :     OUString sResult;
     761             :     OSL_ENSURE( _rxAttrNode.is(), "lcl_serializeForDisplay( attr ): invalid argument!" );
     762           0 :     if ( _rxAttrNode.is() )
     763             :     {
     764           0 :         OUString sValue = _rxAttrNode->getValue();
     765           0 :         sal_Unicode nQuote = '"';
     766           0 :         if ( sValue.indexOf( nQuote ) >= 0 )
     767           0 :             nQuote = '\'';
     768             : 
     769           0 :         sResult = _rxAttrNode->getName() + "=" + OUString(nQuote) + sValue + OUString(nQuote) + " ";
     770             :     }
     771           0 :     return sResult;
     772             : }
     773             : 
     774           0 : static OUString lcl_serializeForDisplay( const Reference<XNodeList>& xNodes )
     775             : {
     776           0 :     OUString sResult;
     777             : 
     778             :     // create document fragment
     779           0 :     Reference<XDocument> xDocument( getDocumentBuilder()->newDocument() );
     780             :     Reference<XDocumentFragment> xFragment(
     781           0 :         xDocument->createDocumentFragment() );
     782             :     OSL_ENSURE( xFragment.is(), "xFragment" );
     783             : 
     784           0 :     sal_Int32 nAttributeNodes = 0;
     785             : 
     786             :     // attach nodelist to fragment
     787           0 :     sal_Int32 nLength = xNodes->getLength();
     788           0 :     for( sal_Int32 i = 0; i < nLength; i++ )
     789             :     {
     790           0 :         Reference<XNode> xCurrent = xNodes->item( i );
     791             : 
     792           0 :         switch ( xCurrent->getNodeType() )
     793             :         {
     794             :         case NodeType_DOCUMENT_NODE:
     795             :             // special-case documents: use top-level element instead
     796           0 :             xCurrent = xCurrent->getFirstChild();
     797           0 :             break;
     798             :         case NodeType_ATTRIBUTE_NODE:
     799             :         {
     800           0 :             Reference< XAttr > xAttr( xCurrent, UNO_QUERY );
     801           0 :             if ( xAttr.is() )
     802             :             {
     803           0 :                 sResult += lcl_serializeForDisplay( xAttr );
     804           0 :                 ++nAttributeNodes;
     805           0 :             }
     806             :         }
     807           0 :         continue;
     808             : 
     809             :         default:
     810           0 :             break;
     811             :         }
     812             : 
     813             :         // append node
     814           0 :         xFragment->appendChild( xDocument->importNode( xCurrent, sal_True ) );
     815           0 :     }
     816             :     OSL_ENSURE( ( nAttributeNodes == 0 ) || ( nAttributeNodes == nLength ),
     817             :         "lcl_serializeForDisplay: mixed attribute and non-attribute nodes?" );
     818           0 :     if ( nAttributeNodes )
     819             :         // had only attribute nodes
     820           0 :         return sResult;
     821             : 
     822             :     // serialize fragment
     823           0 :     CSerializationAppXML aSerialization;
     824           0 :     aSerialization.setSource( xFragment );
     825           0 :     aSerialization.serialize();
     826             : 
     827             :     // copy stream into buffer
     828           0 :     Reference<XTextInputStream2> xTextInputStream = TextInputStream::create( comphelper::getProcessComponentContext() );
     829           0 :     xTextInputStream->setInputStream( aSerialization.getInputStream() );
     830             : 
     831             :     /* WORK AROUND for problem in serialization: currently, multiple
     832             :       XML delarations (<?xml...?>) are being written out and we don't
     833             :       want them. When this is fixed, the code below is nice and
     834             :       simple. The current code filters out the declarations.
     835             :     OUString sResult = xTextInputStream->readString( Sequence<sal_Unicode>(),
     836             :                                                      sal_True );
     837             :     */
     838             : 
     839             :     // well, the serialization prepends XML header(s) that we need to
     840             :     // remove first.
     841           0 :     OUStringBuffer aBuffer;
     842           0 :     while( ! xTextInputStream->isEOF() )
     843             :     {
     844           0 :         OUString sLine = xTextInputStream->readLine();
     845           0 :         if( !sLine.isEmpty()
     846           0 :             && !sLine.startsWith( "<?xml" ) )
     847             :         {
     848           0 :             aBuffer.append( sLine );
     849           0 :             aBuffer.append( '\n' );
     850             :         }
     851           0 :     }
     852           0 :     sResult = aBuffer.makeStringAndClear();
     853             : 
     854           0 :     return sResult;
     855             : }
     856             : 
     857           0 : static OUString lcl_serializeForDisplay( const Reference<XXPathObject>& xResult )
     858             : {
     859             :     // error handling first
     860           0 :     if( ! xResult.is() )
     861           0 :         return getResource( RID_STR_XFORMS_CANT_EVALUATE );
     862             : 
     863             : 
     864             :     // TODO: localize
     865           0 :     OUStringBuffer aBuffer;
     866             : 
     867           0 :     switch( xResult->getObjectType() )
     868             :     {
     869             :     case XPathObjectType_XPATH_BOOLEAN:
     870           0 :         aBuffer.append( xResult->getBoolean()
     871             :                         ? OUString("true")
     872           0 :                         : OUString("false") );
     873           0 :         break;
     874             : 
     875             :     case XPathObjectType_XPATH_STRING:
     876           0 :         aBuffer = aBuffer + "\"" + xResult->getString() + "\"";
     877           0 :         break;
     878             : 
     879             :     case XPathObjectType_XPATH_NODESET:
     880           0 :         aBuffer.append( lcl_serializeForDisplay( xResult->getNodeList() ) );
     881           0 :         break;
     882             : 
     883             :     case XPathObjectType_XPATH_NUMBER:
     884           0 :         aBuffer.append( xResult->getDouble() );
     885           0 :         break;
     886             : 
     887             :     case XPathObjectType_XPATH_UNDEFINED:
     888             :     case XPathObjectType_XPATH_POINT:
     889             :     case XPathObjectType_XPATH_RANGE:
     890             :     case XPathObjectType_XPATH_LOCATIONSET:
     891             :     case XPathObjectType_XPATH_USERS:
     892             :     case XPathObjectType_XPATH_XSLT_TREE:
     893             :     default:
     894             :         // TODO: localized error message?
     895           0 :         break;
     896             :     }
     897             : 
     898           0 :     return aBuffer.makeStringAndClear();
     899             : }
     900             : 
     901           0 : OUString Model::getResultForExpression(
     902             :     const XPropertySet_t& xBinding,
     903             :     sal_Bool bIsBindingExpression,
     904             :     const OUString& sExpression )
     905             :     throw( RuntimeException, std::exception )
     906             : {
     907           0 :     Binding* pBinding = Binding::getBinding( xBinding );
     908           0 :     if( pBinding == NULL )
     909           0 :         throw RuntimeException();
     910             : 
     911             :     // prepare & evaluate expression
     912           0 :     OUStringBuffer aBuffer;
     913           0 :     ComputedExpression aExpression;
     914           0 :     aExpression.setExpression( sExpression );
     915           0 :     if( bIsBindingExpression )
     916             :     {
     917             :         // binding: use binding context and evaluation
     918           0 :         aExpression.evaluate( pBinding->getEvaluationContext() );
     919           0 :         aBuffer.append( lcl_serializeForDisplay( aExpression.getXPath() ) );
     920             :     }
     921             :     else
     922             :     {
     923             :         // MIP (not binding): iterate over bindings contexts
     924             :         std::vector<EvaluationContext> aContext =
     925           0 :             pBinding->getMIPEvaluationContexts();
     926           0 :         for( std::vector<EvaluationContext>::iterator aIter = aContext.begin();
     927           0 :              aIter != aContext.end();
     928             :              ++aIter )
     929             :         {
     930           0 :             aExpression.evaluate( *aIter );
     931           0 :             aBuffer.append( lcl_serializeForDisplay(aExpression.getXPath()) );
     932           0 :             aBuffer.append( '\n' );
     933           0 :         }
     934             :     }
     935           0 :     return aBuffer.makeStringAndClear();
     936             : }
     937             : 
     938           0 : sal_Bool Model::isValidXMLName( const OUString& sName )
     939             :     throw( RuntimeException, std::exception )
     940             : {
     941           0 :     return isValidQName( sName, NULL );
     942             : }
     943             : 
     944           0 : sal_Bool Model::isValidPrefixName( const OUString& sName )
     945             :     throw( RuntimeException, std::exception )
     946             : {
     947           0 :     return ::isValidPrefixName( sName, NULL );
     948             : }
     949             : 
     950           0 : void Model::setNodeValue(
     951             :     const XNode_t& xNode,
     952             :     const OUString& sValue )
     953             :     throw( RuntimeException, std::exception )
     954             : {
     955           0 :     setSimpleContent( xNode, sValue );
     956           0 : }
     957             : 
     958             : 
     959             : 
     960             : // helper functions from model_helper.hxx
     961             : 
     962             : 
     963           0 : void xforms::getInstanceData(
     964             :     const Sequence<PropertyValue>& aValues,
     965             :     OUString* pID,
     966             :     Reference<XDocument>* pInstance,
     967             :     OUString* pURL,
     968             :     bool* pURLOnce )
     969             : {
     970           0 :     sal_Int32 nValues = aValues.getLength();
     971           0 :     const PropertyValue* pValues = aValues.getConstArray();
     972           0 :     for( sal_Int32 n = 0; n < nValues; n++ )
     973             :     {
     974           0 :         const PropertyValue& rValue = pValues[n];
     975             : #define PROP(NAME) \
     976             :         if( p##NAME != NULL && \
     977             :             rValue.Name == #NAME ) \
     978             :             rValue.Value >>= (*p##NAME)
     979           0 :         PROP(ID);
     980           0 :         PROP(Instance);
     981           0 :         PROP(URL);
     982           0 :         PROP(URLOnce);
     983             : #undef PROP
     984             :     }
     985           0 : }
     986             : 
     987           0 : void xforms::setInstanceData(
     988             :     Sequence<PropertyValue>& aSequence,
     989             :     const OUString* _pID,
     990             :     const Reference<XDocument>* _pInstance,
     991             :     const OUString* _pURL,
     992             :     const bool* _pURLOnce )
     993             : {
     994             :     // get old instance data
     995           0 :     OUString sID;
     996           0 :     Reference<XDocument> xInstance;
     997           0 :     OUString sURL;
     998           0 :     bool bURLOnce = false;
     999           0 :     getInstanceData( aSequence, &sID, &xInstance, &sURL, &bURLOnce );
    1000           0 :     const OUString* pID = !sID.isEmpty() ? &sID : NULL;
    1001           0 :     const Reference<XDocument>* pInstance = xInstance.is() ? &xInstance : NULL;
    1002           0 :     const OUString* pURL = !sURL.isEmpty() ? &sURL : NULL;
    1003           0 :     const bool* pURLOnce = ( bURLOnce && pURL != NULL ) ? &bURLOnce : NULL;
    1004             : 
    1005             :     // determine new instance data
    1006             : #define PROP(NAME) if( _p##NAME != NULL ) p##NAME = _p##NAME
    1007           0 :     PROP(ID);
    1008           0 :     PROP(Instance);
    1009           0 :     PROP(URL);
    1010           0 :     PROP(URLOnce);
    1011             : #undef PROP
    1012             : 
    1013             :     // count # of values we want to set
    1014           0 :     sal_Int32 nCount = 0;
    1015             : #define PROP(NAME) if( p##NAME != NULL ) nCount++
    1016           0 :     PROP(ID);
    1017           0 :     PROP(Instance);
    1018           0 :     PROP(URL);
    1019           0 :     PROP(URLOnce);
    1020             : #undef PROP
    1021             : 
    1022             :     // realloc sequence and enter values;
    1023           0 :     aSequence.realloc( nCount );
    1024           0 :     PropertyValue* pSequence = aSequence.getArray();
    1025           0 :     sal_Int32 nIndex = 0;
    1026             : #define PROP(NAME) \
    1027             :     if( p##NAME != NULL ) \
    1028             :     { \
    1029             :         pSequence[ nIndex ].Name = #NAME; \
    1030             :         pSequence[ nIndex ].Value <<= *p##NAME; \
    1031             :         nIndex++; \
    1032             :     }
    1033           0 :     PROP(ID);
    1034           0 :     PROP(Instance);
    1035           0 :     PROP(URL);
    1036           0 :     PROP(URLOnce);
    1037             : #undef PROP
    1038           0 : }
    1039             : 
    1040             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11