1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmloff.hxx" 30 31 #include "xmloff/xformsexport.hxx" 32 33 #include "XFormsModelExport.hxx" 34 #include "xformsapi.hxx" 35 36 #include <xmloff/xmlexp.hxx> 37 #include <xmloff/xmltoken.hxx> 38 #include "xmloff/xmlnmspe.hxx" 39 #include <xmloff/nmspmap.hxx> 40 #include "DomExport.hxx" 41 #include <xmloff/xmluconv.hxx> 42 #include <comphelper/componentcontext.hxx> 43 #include <comphelper/processfactory.hxx> 44 45 #include "tools/debug.hxx" 46 #include <tools/diagnose_ex.h> 47 #include <com/sun/star/container/XIndexAccess.hpp> 48 #include <com/sun/star/container/XNameAccess.hpp> 49 #include <com/sun/star/xml/dom/XDocument.hpp> 50 #include <com/sun/star/form/binding/XValueBinding.hpp> 51 #include <com/sun/star/form/binding/XBindableValue.hpp> 52 #include <com/sun/star/form/binding/XListEntrySink.hpp> 53 #include <com/sun/star/form/binding/XListEntrySource.hpp> 54 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp> 55 #include <com/sun/star/xforms/XModel.hpp> 56 #include <com/sun/star/xforms/XDataTypeRepository.hpp> 57 #include <com/sun/star/xforms/XFormsSupplier.hpp> 58 #include <com/sun/star/beans/PropertyValue.hpp> 59 #include <com/sun/star/container/XEnumerationAccess.hpp> 60 #include <com/sun/star/container/XEnumeration.hpp> 61 #include <com/sun/star/container/XNameContainer.hpp> 62 #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp> 63 #include <com/sun/star/xsd/DataTypeClass.hpp> 64 #include <com/sun/star/xsd/XDataType.hpp> 65 #include <com/sun/star/util/Date.hpp> 66 #include <com/sun/star/util/Time.hpp> 67 #include <com/sun/star/util/DateTime.hpp> 68 69 using namespace com::sun::star; 70 using namespace com::sun::star::uno; 71 using namespace xmloff::token; 72 73 using rtl::OUString; 74 using rtl::OUStringBuffer; 75 using com::sun::star::beans::XPropertySet; 76 using com::sun::star::beans::XPropertySetInfo; 77 using com::sun::star::container::XIndexAccess; 78 using com::sun::star::container::XNameAccess; 79 using com::sun::star::container::XNameContainer; 80 using com::sun::star::container::XEnumerationAccess; 81 using com::sun::star::container::XEnumeration; 82 using com::sun::star::xml::dom::XDocument; 83 using com::sun::star::form::binding::XValueBinding; 84 using com::sun::star::form::binding::XBindableValue; 85 using com::sun::star::form::binding::XListEntrySink; 86 using com::sun::star::form::submission::XSubmissionSupplier; 87 using com::sun::star::beans::PropertyValue; 88 using com::sun::star::xsd::XDataType; 89 using com::sun::star::xforms::XDataTypeRepository; 90 using com::sun::star::xforms::XFormsSupplier; 91 using com::sun::star::util::Date; 92 using com::sun::star::util::DateTime; 93 94 void exportXForms( SvXMLExport& rExport ) 95 { 96 Reference<XFormsSupplier> xSupplier( rExport.GetModel(), UNO_QUERY ); 97 if( xSupplier.is() ) 98 { 99 Reference<XNameContainer> xForms = xSupplier->getXForms(); 100 if( xForms.is() ) 101 { 102 Sequence<OUString> aNames = xForms->getElementNames(); 103 const OUString* pNames = aNames.getConstArray(); 104 sal_Int32 nNames = aNames.getLength(); 105 106 for( sal_Int32 n = 0; n < nNames; n++ ) 107 { 108 Reference<XPropertySet> xModel( xForms->getByName( pNames[n] ), 109 UNO_QUERY ); 110 exportXFormsModel( rExport, xModel ); 111 } 112 } 113 } 114 } 115 116 117 void exportXFormsInstance( SvXMLExport&, const Sequence<PropertyValue>& ); 118 void exportXFormsBinding( SvXMLExport&, const Reference<XPropertySet>& ); 119 void exportXFormsSubmission( SvXMLExport&, const Reference<XPropertySet>& ); 120 void exportXFormsSchemas( SvXMLExport&, const Reference<com::sun::star::xforms::XModel>& ); 121 122 123 typedef OUString (*convert_t)( const Any& ); 124 typedef struct 125 { 126 const sal_Char* pPropertyName; 127 sal_uInt16 nPropertyNameLength; 128 sal_uInt16 nNamespace; 129 sal_uInt16 nToken; 130 convert_t aConverter; 131 } ExportTable; 132 void lcl_export( const Reference<XPropertySet>& rPropertySet, 133 SvXMLExport& rExport, 134 const ExportTable* pTable ); 135 136 #define TABLE_ENTRY(NAME,NAMESPACE,TOKEN,CONVERTER) { NAME,sizeof(NAME)-1,XML_NAMESPACE_##NAMESPACE,xmloff::token::XML_##TOKEN, CONVERTER } 137 #define TABLE_END { NULL, 0, 0, 0, NULL } 138 139 140 // any conversion functions 141 OUString lcl_string( const Any& ); 142 OUString lcl_bool( const Any& ); 143 OUString lcl_whitespace( const Any& ); 144 template<typename T, void (*FUNC)( OUStringBuffer&, T )> OUString lcl_convert( const Any& ); 145 template<typename T, void (*FUNC)( OUStringBuffer&, const T& )> OUString lcl_convertRef( const Any& ); 146 147 void lcl_formatDate( OUStringBuffer& aBuffer, const Date& aDate ); 148 void lcl_formatTime( OUStringBuffer& aBuffer, const com::sun::star::util::Time& aTime ); 149 void lcl_formatDateTime( OUStringBuffer& aBuffer, const DateTime& aDateTime ); 150 151 convert_t lcl_int32 = &lcl_convert<sal_Int32,&SvXMLUnitConverter::convertNumber>; 152 convert_t lcl_double = &lcl_convert<double,&SvXMLUnitConverter::convertDouble>; 153 convert_t lcl_dateTime = &lcl_convertRef<DateTime,&lcl_formatDateTime>; 154 convert_t lcl_date = &lcl_convertRef<Date,&lcl_formatDate>; 155 convert_t lcl_time = &lcl_convertRef<com::sun::star::util::Time,&lcl_formatTime>; 156 157 // other functions 158 OUString lcl_getXSDType( SvXMLExport& rExport, 159 const Reference<XPropertySet>& xType ); 160 161 162 // 163 // the model 164 // 165 166 static const ExportTable aXFormsModelTable[] = 167 { 168 TABLE_ENTRY( "ID", NONE, ID, lcl_string ), 169 TABLE_ENTRY( "SchemaRef", NONE, SCHEMA, lcl_string ), 170 TABLE_END 171 }; 172 173 void exportXFormsModel( SvXMLExport& rExport, 174 const Reference<XPropertySet>& xModelPropSet ) 175 { 176 // no model -> don't do anything! 177 Reference<com::sun::star::xforms::XModel> xModel( xModelPropSet, UNO_QUERY ); 178 if( ! xModel.is() || ! xModelPropSet.is() ) 179 return; 180 181 lcl_export( xModelPropSet, rExport, aXFormsModelTable ); 182 SvXMLElementExport aModelElement( rExport, XML_NAMESPACE_XFORMS, XML_MODEL, 183 sal_True, sal_True ); 184 185 // instances 186 Reference<XIndexAccess> xInstances( xModel->getInstances(), 187 UNO_QUERY_THROW); 188 sal_Int32 nCount = xInstances->getCount(); 189 sal_Int32 i = 0; 190 for( i = 0; i < nCount; i++ ) 191 { 192 Sequence<PropertyValue> aInstance; 193 xInstances->getByIndex( i ) >>= aInstance; 194 exportXFormsInstance( rExport, aInstance ); 195 } 196 197 198 // bindings 199 Reference<XIndexAccess> xBindings( xModel->getBindings(), UNO_QUERY_THROW); 200 nCount = xBindings->getCount(); 201 for( i = 0; i < nCount; i++ ) 202 { 203 Reference<XPropertySet> aBinding( xBindings->getByIndex( i ), 204 UNO_QUERY_THROW ); 205 exportXFormsBinding( rExport, aBinding ); 206 } 207 208 // submissions 209 Reference<XIndexAccess> xSubmissions( xModel->getSubmissions(), 210 UNO_QUERY_THROW ); 211 nCount = xSubmissions->getCount(); 212 for( i = 0; i < nCount; i++ ) 213 { 214 Reference<XPropertySet> xSubmission( xSubmissions->getByIndex( i ), 215 UNO_QUERY_THROW ); 216 exportXFormsSubmission( rExport, xSubmission ); 217 } 218 219 // schemas 220 exportXFormsSchemas( rExport, xModel ); 221 } 222 223 // 224 // the instance 225 // 226 227 static const ExportTable aXFormsInstanceTable[] = 228 { 229 TABLE_ENTRY( "InstanceURL", NONE, SRC, lcl_string ), 230 TABLE_END 231 }; 232 233 void exportXFormsInstance( SvXMLExport& rExport, 234 const Sequence<PropertyValue>& xInstance ) 235 { 236 OUString sId; 237 OUString sURL; 238 Reference<XDocument> xDoc; 239 240 const PropertyValue* pInstance = xInstance.getConstArray(); 241 sal_Int32 nCount = xInstance.getLength(); 242 for( sal_Int32 i = 0; i < nCount; i++ ) 243 { 244 OUString sName = pInstance[i].Name; 245 const Any& rAny = pInstance[i].Value; 246 if( sName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ID") ) ) 247 rAny >>= sId; 248 else if( sName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("URL") ) ) 249 rAny >>= sURL; 250 else if( sName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Instance") )) 251 rAny >>= xDoc; 252 } 253 254 if( sId.getLength() > 0 ) 255 rExport.AddAttribute( XML_NAMESPACE_NONE, XML_ID, sId ); 256 257 if( sURL.getLength() > 0 ) 258 rExport.AddAttribute( XML_NAMESPACE_NONE, XML_SRC, sURL ); 259 260 SvXMLElementExport aElem( rExport, XML_NAMESPACE_XFORMS, XML_INSTANCE, 261 sal_True, sal_True ); 262 rExport.IgnorableWhitespace(); 263 if( xDoc.is() ) 264 { 265 exportDom( rExport, xDoc ); 266 } 267 } 268 269 270 // 271 // the binding 272 // 273 274 static const ExportTable aXFormsBindingTable[] = 275 { 276 TABLE_ENTRY( "BindingID", NONE, ID, lcl_string ), 277 TABLE_ENTRY( "BindingExpression", NONE, NODESET, lcl_string ), 278 TABLE_ENTRY( "ReadonlyExpression", NONE, READONLY, lcl_string ), 279 TABLE_ENTRY( "RelevantExpression", NONE, RELEVANT, lcl_string ), 280 TABLE_ENTRY( "RequiredExpression", NONE, REQUIRED, lcl_string ), 281 TABLE_ENTRY( "ConstraintExpression", NONE, CONSTRAINT, lcl_string ), 282 TABLE_ENTRY( "CalculateExpression", NONE, CALCULATE, lcl_string ), 283 // type handled separatly, for type name <-> XSD type conversion 284 // TABLE_ENTRY( "Type", NONE, TYPE, lcl_string ), 285 TABLE_END 286 }; 287 288 void exportXFormsBinding( SvXMLExport& rExport, 289 const Reference<XPropertySet>& xBinding ) 290 { 291 // name check; generate binding ID if necessary 292 { 293 OUString sName; 294 xBinding->getPropertyValue( OUSTRING("BindingID") ) >>= sName; 295 if( sName.getLength() == 0 ) 296 { 297 // if we don't have a name yet, generate one on the fly 298 OUStringBuffer aBuffer; 299 aBuffer.append( OUSTRING("bind_" ) ); 300 sal_Int64 nId = reinterpret_cast<sal_uInt64>( xBinding.get() ); 301 aBuffer.append( nId , 16 ); 302 sName = aBuffer.makeStringAndClear(); 303 xBinding->setPropertyValue( OUSTRING("BindingID"), makeAny(sName)); 304 } 305 } 306 307 lcl_export( xBinding, rExport, aXFormsBindingTable ); 308 309 // handle type attribute 310 { 311 OUString sTypeName; 312 xBinding->getPropertyValue( OUSTRING("Type") ) >>= sTypeName; 313 314 try 315 { 316 // now get type, and determine whether its a standard type. If 317 // so, export the XSD name 318 Reference<com::sun::star::xforms::XModel> xModel( 319 xBinding->getPropertyValue( OUSTRING("Model") ), 320 UNO_QUERY ); 321 Reference<XDataTypeRepository> xRepository( 322 xModel.is() ? xModel->getDataTypeRepository() : Reference<XDataTypeRepository>() ); 323 if( xRepository.is() ) 324 { 325 Reference<XPropertySet> xDataType( 326 xRepository->getDataType( sTypeName ), 327 UNO_QUERY ); 328 329 // if it's a basic data type, write out the XSD name 330 // for the XSD type class 331 bool bIsBasic = false; 332 xDataType->getPropertyValue( OUSTRING("IsBasic") ) >>= bIsBasic; 333 if( bIsBasic ) 334 sTypeName = lcl_getXSDType( rExport, xDataType ); 335 } 336 } 337 catch( Exception& ) 338 { 339 ; // ignore; just use typename 340 } 341 342 // now that we have the proper type name, write out the attribute 343 if( sTypeName.getLength() > 0 ) 344 { 345 rExport.AddAttribute( XML_NAMESPACE_NONE, XML_TYPE, 346 sTypeName ); 347 } 348 } 349 350 // we need to ensure all the namespaces in the binding will work correctly. 351 // to do so, we will write out all missing namespace declaractions. 352 const SvXMLNamespaceMap& rMap = rExport.GetNamespaceMap(); 353 Reference<XNameAccess> xNamespaces( 354 xBinding->getPropertyValue( OUSTRING("ModelNamespaces") ), UNO_QUERY); 355 if( xNamespaces.is() ) 356 { 357 // iterate over Prefixes for this binding 358 Sequence<OUString> aPrefixes = xNamespaces->getElementNames(); 359 const OUString* pPrefixes = aPrefixes.getConstArray(); 360 sal_Int32 nPrefixes = aPrefixes.getLength(); 361 for( sal_Int32 i = 0; i < nPrefixes; i++ ) 362 { 363 const OUString& rPrefix = pPrefixes[i]; 364 OUString sURI; 365 xNamespaces->getByName( rPrefix ) >>= sURI; 366 367 // check whether prefix/URI pair is in map; else write declaration 368 // (we don't need to change the map, since this element has no 369 // other content) 370 sal_uInt16 nKey = rMap.GetKeyByPrefix( rPrefix ); 371 if( nKey == XML_NAMESPACE_UNKNOWN || 372 rMap.GetNameByKey( nKey ) != sURI ) 373 { 374 rExport.AddAttribute( OUSTRING("xmlns:") + rPrefix, sURI ); 375 } 376 } 377 } 378 379 SvXMLElementExport aElement( rExport, XML_NAMESPACE_XFORMS, XML_BIND, 380 sal_True, sal_True ); 381 } 382 383 384 // 385 // the submission 386 // 387 388 static const ExportTable aXFormsSubmissionTable[] = 389 { 390 TABLE_ENTRY( "ID", NONE, ID, lcl_string ), 391 TABLE_ENTRY( "Bind", NONE, BIND, lcl_string ), 392 TABLE_ENTRY( "Ref", NONE, REF, lcl_string ), 393 TABLE_ENTRY( "Action", NONE, ACTION, lcl_string ), 394 TABLE_ENTRY( "Method", NONE, METHOD, lcl_string ), 395 TABLE_ENTRY( "Version", NONE, VERSION, lcl_string ), 396 TABLE_ENTRY( "Indent", NONE, INDENT, lcl_bool ), 397 TABLE_ENTRY( "MediaType", NONE, MEDIATYPE, lcl_string ), 398 TABLE_ENTRY( "Encoding", NONE, ENCODING, lcl_string ), 399 TABLE_ENTRY( "OmitXmlDeclaration", NONE, OMIT_XML_DECLARATION, lcl_bool ), 400 TABLE_ENTRY( "Standalone", NONE, STANDALONE, lcl_bool ), 401 TABLE_ENTRY( "CDataSectionElement", NONE, CDATA_SECTION_ELEMENTS, lcl_string ), 402 TABLE_ENTRY( "Replace", NONE, REPLACE, lcl_string ), 403 TABLE_ENTRY( "Separator", NONE, SEPARATOR, lcl_string ), 404 TABLE_ENTRY( "IncludeNamespacePrefixes", NONE, INCLUDENAMESPACEPREFIXES, lcl_string ), 405 TABLE_END 406 }; 407 408 void exportXFormsSubmission( SvXMLExport& rExport, 409 const Reference<XPropertySet>& xSubmission ) 410 { 411 lcl_export( xSubmission, rExport, aXFormsSubmissionTable ); 412 SvXMLElementExport aElement( rExport, XML_NAMESPACE_XFORMS, XML_SUBMISSION, 413 sal_True, sal_True ); 414 } 415 416 417 418 // 419 // export data types as XSD schema 420 // 421 422 static const ExportTable aDataTypeFacetTable[] = 423 { 424 TABLE_ENTRY( "Length", XSD, LENGTH, lcl_int32 ), 425 TABLE_ENTRY( "MinLength", XSD, MINLENGTH, lcl_int32 ), 426 TABLE_ENTRY( "MaxLength", XSD, MAXLENGTH, lcl_int32 ), 427 TABLE_ENTRY( "MinInclusiveInt", XSD, MININCLUSIVE, lcl_int32 ), 428 TABLE_ENTRY( "MinExclusiveInt", XSD, MINEXCLUSIVE, lcl_int32 ), 429 TABLE_ENTRY( "MaxInclusiveInt", XSD, MAXINCLUSIVE, lcl_int32 ), 430 TABLE_ENTRY( "MaxExclusiveInt", XSD, MAXEXCLUSIVE, lcl_int32 ), 431 TABLE_ENTRY( "MinInclusiveDouble", XSD, MININCLUSIVE, lcl_double ), 432 TABLE_ENTRY( "MinExclusiveDouble", XSD, MINEXCLUSIVE, lcl_double ), 433 TABLE_ENTRY( "MaxInclusiveDouble", XSD, MAXINCLUSIVE, lcl_double ), 434 TABLE_ENTRY( "MaxExclusiveDouble", XSD, MAXEXCLUSIVE, lcl_double ), 435 TABLE_ENTRY( "MinInclusiveDate", XSD, MININCLUSIVE, lcl_date ), 436 TABLE_ENTRY( "MinExclusiveDate", XSD, MINEXCLUSIVE, lcl_date ), 437 TABLE_ENTRY( "MaxInclusiveDate", XSD, MAXINCLUSIVE, lcl_date ), 438 TABLE_ENTRY( "MaxExclusiveDate", XSD, MAXEXCLUSIVE, lcl_date ), 439 TABLE_ENTRY( "MinInclusiveTime", XSD, MININCLUSIVE, lcl_time ), 440 TABLE_ENTRY( "MinExclusiveTime", XSD, MINEXCLUSIVE, lcl_time ), 441 TABLE_ENTRY( "MaxInclusiveTime", XSD, MAXINCLUSIVE, lcl_time ), 442 TABLE_ENTRY( "MaxExclusiveTime", XSD, MAXEXCLUSIVE, lcl_time ), 443 TABLE_ENTRY( "MinInclusiveDateTime", XSD, MININCLUSIVE, lcl_dateTime ), 444 TABLE_ENTRY( "MinExclusiveDateTime", XSD, MINEXCLUSIVE, lcl_dateTime ), 445 TABLE_ENTRY( "MaxInclusiveDateTime", XSD, MAXINCLUSIVE, lcl_dateTime ), 446 TABLE_ENTRY( "MaxExclusiveDateTime", XSD, MAXEXCLUSIVE, lcl_dateTime ), 447 TABLE_ENTRY( "Pattern", XSD, PATTERN, lcl_string ), 448 // ??? XML_ENUMERATION, 449 TABLE_ENTRY( "WhiteSpace", XSD, WHITESPACE, lcl_whitespace ), 450 TABLE_ENTRY( "TotalDigits", XSD, TOTALDIGITS, lcl_int32 ), 451 TABLE_ENTRY( "FractionDigits", XSD, FRACTIONDIGITS, lcl_int32 ), 452 TABLE_END 453 }; 454 455 // export facets through table; use the same table as lcl_export does 456 void lcl_exportDataTypeFacets( SvXMLExport& rExport, 457 const Reference<XPropertySet>& rPropertySet, 458 const ExportTable* pTable ) 459 { 460 Reference<XPropertySetInfo> xInfo = rPropertySet->getPropertySetInfo(); 461 for( const ExportTable* pCurrent = pTable; 462 pCurrent->pPropertyName != NULL; 463 pCurrent++ ) 464 { 465 OUString sName( OUString::createFromAscii( pCurrent->pPropertyName ) ); 466 if( xInfo->hasPropertyByName( sName ) ) 467 { 468 OUString sValue = (*pCurrent->aConverter)( 469 rPropertySet->getPropertyValue( sName ) ); 470 471 if( sValue.getLength() > 0 ) 472 { 473 rExport.AddAttribute( XML_NAMESPACE_NONE, XML_VALUE, sValue ); 474 SvXMLElementExport aFacet( 475 rExport, 476 pCurrent->nNamespace, 477 static_cast<XMLTokenEnum>( pCurrent->nToken ), 478 sal_True, sal_True ); 479 } 480 } 481 } 482 } 483 484 OUString lcl_getXSDType( SvXMLExport& rExport, 485 const Reference<XPropertySet>& xType ) 486 { 487 // we use string as default... 488 XMLTokenEnum eToken = XML_STRING; 489 490 sal_uInt16 nDataTypeClass = 0; 491 xType->getPropertyValue( OUSTRING("TypeClass") ) >>= nDataTypeClass; 492 switch( nDataTypeClass ) 493 { 494 case com::sun::star::xsd::DataTypeClass::STRING: 495 eToken = XML_STRING; 496 break; 497 case com::sun::star::xsd::DataTypeClass::anyURI: 498 eToken = XML_ANYURI; 499 break; 500 case com::sun::star::xsd::DataTypeClass::DECIMAL: 501 eToken = XML_DECIMAL; 502 break; 503 case com::sun::star::xsd::DataTypeClass::DOUBLE: 504 eToken = XML_DOUBLE; 505 break; 506 case com::sun::star::xsd::DataTypeClass::FLOAT: 507 eToken = XML_FLOAT; 508 break; 509 case com::sun::star::xsd::DataTypeClass::BOOLEAN: 510 eToken = XML_BOOLEAN; 511 break; 512 case com::sun::star::xsd::DataTypeClass::DATETIME: 513 eToken = XML_DATETIME_XSD; 514 break; 515 case com::sun::star::xsd::DataTypeClass::TIME: 516 eToken = XML_TIME; 517 break; 518 case com::sun::star::xsd::DataTypeClass::DATE: 519 eToken = XML_DATE; 520 break; 521 case com::sun::star::xsd::DataTypeClass::gYear: 522 eToken = XML_YEAR; 523 break; 524 case com::sun::star::xsd::DataTypeClass::gDay: 525 eToken = XML_DAY; 526 break; 527 case com::sun::star::xsd::DataTypeClass::gMonth: 528 eToken = XML_MONTH; 529 break; 530 case com::sun::star::xsd::DataTypeClass::DURATION: 531 case com::sun::star::xsd::DataTypeClass::gYearMonth: 532 case com::sun::star::xsd::DataTypeClass::gMonthDay: 533 case com::sun::star::xsd::DataTypeClass::hexBinary: 534 case com::sun::star::xsd::DataTypeClass::base64Binary: 535 case com::sun::star::xsd::DataTypeClass::QName: 536 case com::sun::star::xsd::DataTypeClass::NOTATION: 537 default: 538 DBG_ERROR( "unknown data type" ); 539 } 540 541 return rExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_XSD, 542 GetXMLToken( eToken ) ); 543 } 544 545 void lcl_exportDataType( SvXMLExport& rExport, 546 const Reference<XPropertySet>& xType ) 547 { 548 // we do not need to export basic types; exit if we have one 549 bool bIsBasic = false; 550 xType->getPropertyValue( OUSTRING("IsBasic") ) >>= bIsBasic; 551 if( bIsBasic ) 552 return; 553 554 // no basic type -> export 555 556 // <xsd:simpleType name="..."> 557 OUString sName; 558 xType->getPropertyValue( OUSTRING("Name") ) >>= sName; 559 rExport.AddAttribute( XML_NAMESPACE_NONE, XML_NAME, sName ); 560 SvXMLElementExport aSimpleType( rExport, 561 XML_NAMESPACE_XSD, XML_SIMPLETYPE, 562 sal_True, sal_True ); 563 564 // <xsd:restriction base="xsd:..."> 565 rExport.AddAttribute( XML_NAMESPACE_NONE, XML_BASE, 566 lcl_getXSDType( rExport, xType ) ); 567 SvXMLElementExport aRestriction( rExport, 568 XML_NAMESPACE_XSD, 569 XML_RESTRICTION, 570 sal_True, sal_True ); 571 572 // export facets 573 lcl_exportDataTypeFacets( rExport, 574 Reference<XPropertySet>( xType, UNO_QUERY ), 575 aDataTypeFacetTable ); 576 } 577 578 void exportXFormsSchemas( SvXMLExport& rExport, 579 const Reference<com::sun::star::xforms::XModel>& xModel ) 580 { 581 // TODO: for now, we'll fake this... 582 { 583 SvXMLElementExport aSchemaElem( rExport, XML_NAMESPACE_XSD, XML_SCHEMA, 584 sal_True, sal_True ); 585 586 // now get data type repositry, and export 587 Reference<XEnumerationAccess> xTypes( xModel->getDataTypeRepository(), 588 UNO_QUERY ); 589 if( xTypes.is() ) 590 { 591 Reference<XEnumeration> xEnum = xTypes->createEnumeration(); 592 DBG_ASSERT( xEnum.is(), "no enum?" ); 593 while( xEnum->hasMoreElements() ) 594 { 595 Reference<XPropertySet> xType( xEnum->nextElement(), UNO_QUERY ); 596 lcl_exportDataType( rExport, xType ); 597 } 598 } 599 } 600 601 // export other, 'foreign' schemas 602 Reference<XPropertySet> xPropSet( xModel, UNO_QUERY ); 603 if( xPropSet.is() ) 604 { 605 Reference<XDocument> xDocument( 606 xPropSet->getPropertyValue( OUSTRING("ForeignSchema") ), 607 UNO_QUERY ); 608 609 if( xDocument.is() ) 610 exportDom( rExport, xDocument ); 611 } 612 } 613 614 615 616 // 617 // helper functions 618 // 619 620 void lcl_export( const Reference<XPropertySet>& rPropertySet, 621 SvXMLExport& rExport, 622 const ExportTable* pTable ) 623 { 624 for( const ExportTable* pCurrent = pTable; 625 pCurrent->pPropertyName != NULL; 626 pCurrent++ ) 627 { 628 Any aAny = rPropertySet->getPropertyValue( 629 OUString::createFromAscii( pCurrent->pPropertyName ) ); 630 OUString sValue = (*pCurrent->aConverter)( aAny ); 631 632 if( sValue.getLength() > 0 ) 633 rExport.AddAttribute( 634 pCurrent->nNamespace, 635 static_cast<XMLTokenEnum>( pCurrent->nToken ), 636 sValue ); 637 } 638 } 639 640 641 642 // 643 // any conversion functions 644 // 645 646 template<typename T, void (*FUNC)( OUStringBuffer&, T )> 647 OUString lcl_convert( const Any& rAny ) 648 { 649 OUStringBuffer aBuffer; 650 T aData = T(); 651 if( rAny >>= aData ) 652 { 653 FUNC( aBuffer, aData ); 654 } 655 return aBuffer.makeStringAndClear(); 656 } 657 658 template<typename T, void (*FUNC)( OUStringBuffer&, const T& )> 659 OUString lcl_convertRef( const Any& rAny ) 660 { 661 OUStringBuffer aBuffer; 662 T aData; 663 if( rAny >>= aData ) 664 { 665 FUNC( aBuffer, aData ); 666 } 667 return aBuffer.makeStringAndClear(); 668 } 669 670 OUString lcl_string( const Any& rAny ) 671 { 672 OUString aResult; 673 rAny >>= aResult; 674 return aResult; 675 } 676 677 OUString lcl_bool( const Any& rAny ) 678 { 679 bool bResult = bool(); 680 if( rAny >>= bResult ) 681 return GetXMLToken( bResult ? XML_TRUE : XML_FALSE ); 682 DBG_ERROR( "expected boolean value" ); 683 return OUString(); 684 } 685 686 void lcl_formatDate( OUStringBuffer& aBuffer, const Date& rDate ) 687 { 688 aBuffer.append( static_cast<sal_Int32>( rDate.Year ) ); 689 aBuffer.append( sal_Unicode('-') ); 690 aBuffer.append( static_cast<sal_Int32>( rDate.Month ) ); 691 aBuffer.append( sal_Unicode('-') ); 692 aBuffer.append( static_cast<sal_Int32>( rDate.Day ) ); 693 } 694 695 void lcl_formatTime( OUStringBuffer& aBuffer, const com::sun::star::util::Time& rTime ) 696 { 697 DateTime aDateTime; 698 aDateTime.Hours = rTime.Hours; 699 aDateTime.Minutes = rTime.Minutes; 700 aDateTime.Seconds = rTime.Seconds; 701 aDateTime.HundredthSeconds = rTime.HundredthSeconds; 702 SvXMLUnitConverter::convertTime( aBuffer, aDateTime ); 703 } 704 705 void lcl_formatDateTime( OUStringBuffer& aBuffer, const DateTime& aDateTime ) 706 { 707 SvXMLUnitConverter::convertDateTime( aBuffer, aDateTime ); 708 } 709 710 OUString lcl_whitespace( const Any& rAny ) 711 { 712 OUString sResult; 713 sal_uInt16 n = sal_uInt16(); 714 if( rAny >>= n ) 715 { 716 switch( n ) 717 { 718 case com::sun::star::xsd::WhiteSpaceTreatment::Preserve: 719 sResult = GetXMLToken( XML_PRESERVE ); 720 break; 721 case com::sun::star::xsd::WhiteSpaceTreatment::Replace: 722 sResult = GetXMLToken( XML_REPLACE ); 723 break; 724 case com::sun::star::xsd::WhiteSpaceTreatment::Collapse: 725 sResult = GetXMLToken( XML_COLLAPSE ); 726 break; 727 } 728 } 729 return sResult; 730 } 731 732 733 /// return name of Binding 734 OUString lcl_getXFormsBindName( const Reference<XPropertySet>& xBinding ) 735 { 736 OUString sProp( OUSTRING( "BindingID" ) ); 737 738 OUString sReturn; 739 if( xBinding.is() && 740 xBinding->getPropertySetInfo()->hasPropertyByName( sProp ) ) 741 { 742 xBinding->getPropertyValue( sProp ) >>= sReturn; 743 } 744 return sReturn; 745 } 746 747 // return name of binding 748 OUString getXFormsBindName( const Reference<XPropertySet>& xControl ) 749 { 750 Reference<XBindableValue> xBindable( xControl, UNO_QUERY ); 751 return xBindable.is() 752 ? lcl_getXFormsBindName( 753 Reference<XPropertySet>( xBindable->getValueBinding(), UNO_QUERY )) 754 : OUString(); 755 } 756 757 // return name of list binding 758 OUString getXFormsListBindName( const Reference<XPropertySet>& xControl ) 759 { 760 Reference<XListEntrySink> xListEntrySink( xControl, UNO_QUERY ); 761 return xListEntrySink.is() 762 ? lcl_getXFormsBindName( 763 Reference<XPropertySet>( xListEntrySink->getListEntrySource(), 764 UNO_QUERY ) ) 765 : OUString(); 766 } 767 768 OUString getXFormsSubmissionName( const Reference<XPropertySet>& xBinding ) 769 { 770 OUString sReturn; 771 772 Reference<XSubmissionSupplier> xSubmissionSupplier( xBinding, UNO_QUERY ); 773 if( xSubmissionSupplier.is() ) 774 { 775 Reference<XPropertySet> xPropertySet( 776 xSubmissionSupplier->getSubmission(), UNO_QUERY ); 777 OUString sProp( OUSTRING("ID") ); 778 if( xPropertySet.is() && 779 xPropertySet->getPropertySetInfo()->hasPropertyByName( sProp ) ) 780 { 781 xPropertySet->getPropertyValue( sProp ) >>= sReturn; 782 } 783 } 784 785 return sReturn; 786 } 787 788 void getXFormsSettings( const Reference< XNameAccess >& _rXForms, Sequence< PropertyValue >& _out_rSettings ) 789 { 790 _out_rSettings = Sequence< PropertyValue >(); 791 792 OSL_PRECOND( _rXForms.is(), "getXFormsSettings: invalid XForms container!" ); 793 if ( !_rXForms.is() ) 794 return; 795 796 try 797 { 798 // we want to export some special properties of our XForms models as config-item-map-named, 799 // which implies we need a PropertyValue whose value is an XNameAccess, whose keys 800 // are the names of the XForm models, and which in turn provides named sequences of 801 // PropertyValues - which denote the actual property values of the given named model. 802 803 Sequence< ::rtl::OUString > aModelNames( _rXForms->getElementNames() ); 804 805 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); 806 Reference< XNameContainer > xModelSettings( 807 aContext.createComponent( "com.sun.star.document.NamedPropertyValues" ), 808 UNO_QUERY_THROW ); 809 810 for ( const ::rtl::OUString* pModelName = aModelNames.getConstArray(); 811 pModelName != aModelNames.getConstArray() + aModelNames.getLength(); 812 ++pModelName 813 ) 814 { 815 Reference< XPropertySet > xModelProps( _rXForms->getByName( *pModelName ), UNO_QUERY_THROW ); 816 817 Sequence< PropertyValue > aModelSettings( 1 ); 818 aModelSettings[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ); 819 aModelSettings[0].Value = xModelProps->getPropertyValue( aModelSettings[0].Name ); 820 821 xModelSettings->insertByName( *pModelName, makeAny( aModelSettings ) ); 822 } 823 824 if ( xModelSettings->hasElements() ) 825 { 826 _out_rSettings.realloc( 1 ); 827 _out_rSettings[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XFormModels" ) ); 828 _out_rSettings[0].Value <<= xModelSettings; 829 } 830 } 831 catch( const Exception& ) 832 { 833 DBG_UNHANDLED_EXCEPTION(); 834 } 835 } 836