LibreOffice Module xmloff (master)  1
xformsexport.cxx
Go to the documentation of this file.
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 <xmloff/xformsexport.hxx>
22 
23 #include "XFormsModelExport.hxx"
24 
25 #include <xmloff/xmlexp.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlnamespace.hxx>
28 #include <xmloff/namespacemap.hxx>
29 #include <DomExport.hxx>
30 
31 #include <sax/tools/converter.hxx>
32 
35 
36 #include <tools/diagnose_ex.h>
37 #include <sal/log.hxx>
38 #include <com/sun/star/container/XIndexAccess.hpp>
39 #include <com/sun/star/container/XNameAccess.hpp>
40 #include <com/sun/star/document/NamedPropertyValues.hpp>
41 #include <com/sun/star/frame/XModel.hpp>
42 #include <com/sun/star/xml/dom/XDocument.hpp>
43 #include <com/sun/star/form/binding/XBindableValue.hpp>
44 #include <com/sun/star/form/binding/XListEntrySink.hpp>
45 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
46 #include <com/sun/star/xforms/XModel.hpp>
47 #include <com/sun/star/xforms/XDataTypeRepository.hpp>
48 #include <com/sun/star/xforms/XFormsSupplier.hpp>
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <com/sun/star/container/XEnumerationAccess.hpp>
51 #include <com/sun/star/container/XEnumeration.hpp>
52 #include <com/sun/star/container/XNameContainer.hpp>
53 #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
54 #include <com/sun/star/xsd/DataTypeClass.hpp>
55 #include <com/sun/star/util/Date.hpp>
56 #include <com/sun/star/util/Time.hpp>
57 #include <com/sun/star/util/DateTime.hpp>
58 #include <com/sun/star/util/Duration.hpp>
59 
60 using namespace com::sun::star;
61 using namespace com::sun::star::uno;
62 using namespace xmloff::token;
63 
65 using com::sun::star::beans::XPropertySetInfo;
66 using com::sun::star::container::XIndexAccess;
67 using com::sun::star::container::XNameAccess;
68 using com::sun::star::container::XNameContainer;
69 using com::sun::star::container::XEnumerationAccess;
70 using com::sun::star::container::XEnumeration;
71 using com::sun::star::xml::dom::XDocument;
72 using com::sun::star::form::binding::XBindableValue;
73 using com::sun::star::form::binding::XListEntrySink;
74 using com::sun::star::form::submission::XSubmissionSupplier;
75 using com::sun::star::beans::PropertyValue;
76 using com::sun::star::xforms::XDataTypeRepository;
77 using com::sun::star::xforms::XFormsSupplier;
78 using com::sun::star::util::Duration;
79 
80 void exportXForms( SvXMLExport& rExport )
81 {
82  Reference<XFormsSupplier> xSupplier( rExport.GetModel(), UNO_QUERY );
83  if( !xSupplier.is() )
84  return;
85 
86  Reference<XNameContainer> xForms = xSupplier->getXForms();
87  if( xForms.is() )
88  {
89  const Sequence<OUString> aNames = xForms->getElementNames();
90 
91  for( const auto& rName : aNames )
92  {
93  Reference<XPropertySet> xModel( xForms->getByName( rName ),
94  UNO_QUERY );
95  exportXFormsModel( rExport, xModel );
96  }
97  }
98 }
99 
100 
105 
106 
107 typedef OUString (*convert_t)( const Any& );
108 
109 namespace {
110 
111 struct ExportTable
112 {
113  const char* pPropertyName;
114  sal_uInt16 const nNamespace;
115  sal_uInt16 nToken;
116  convert_t const aConverter;
117 };
118 
119 }
120 
121 static void lcl_export( const Reference<XPropertySet>& rPropertySet,
122  SvXMLExport& rExport,
123  const ExportTable* pTable );
124 
125 #define TABLE_ENTRY(NAME,NAMESPACE,TOKEN,CONVERTER) { NAME,XML_NAMESPACE_##NAMESPACE,xmloff::token::XML_##TOKEN, CONVERTER }
126 #define TABLE_END { nullptr, 0, 0, nullptr }
127 
128 // any conversion functions
129 static OUString xforms_string( const Any& );
130 static OUString xforms_bool( const Any& );
131 static OUString xforms_whitespace( const Any& );
132 template<typename T, void (*FUNC)( OUStringBuffer&, T )> static OUString xforms_convert( const Any& );
133 template<typename T, void (*FUNC)( OUStringBuffer&, const T& )> static OUString xforms_convertRef( const Any& );
134 
135 static void xforms_formatDate( OUStringBuffer& aBuffer, const util::Date& aDate );
136 static void xforms_formatTime( OUStringBuffer& aBuffer, const css::util::Time& aTime );
137 static void xforms_formatDateTime( OUStringBuffer& aBuffer, const util::DateTime& aDateTime );
138 
139 static void convertNumber(OUStringBuffer & b, sal_Int32 n) {
140  b.append(n);
141 }
142 
143 convert_t const xforms_int32 = &xforms_convert<sal_Int32,&convertNumber>;
144 convert_t const xforms_double = &xforms_convert<double,&::sax::Converter::convertDouble>;
145 convert_t const xforms_dateTime = &xforms_convertRef<util::DateTime,&xforms_formatDateTime>;
146 convert_t const xforms_date = &xforms_convertRef<util::Date,&xforms_formatDate>;
147 convert_t const xforms_time = &xforms_convertRef<css::util::Time,&xforms_formatTime>;
148 
149 // other functions
150 static OUString lcl_getXSDType( SvXMLExport const & rExport,
151  const Reference<XPropertySet>& xType );
152 
153 
154 // the model
155 
156 
157 const ExportTable aXFormsModelTable[] =
158 {
159  TABLE_ENTRY( "ID", NONE, ID, xforms_string ),
160  TABLE_ENTRY( "SchemaRef", NONE, SCHEMA, xforms_string ),
161  TABLE_END
162 };
163 
165  const Reference<XPropertySet>& xModelPropSet )
166 {
167  // no model -> don't do anything!
168  Reference<css::xforms::XModel> xModel( xModelPropSet, UNO_QUERY );
169  if( ! xModel.is() || ! xModelPropSet.is() )
170  return;
171 
172  lcl_export( xModelPropSet, rExport, aXFormsModelTable );
173  SvXMLElementExport aModelElement( rExport, XML_NAMESPACE_XFORMS, XML_MODEL,
174  true, true );
175 
176  // instances
177  Reference<XIndexAccess> xInstances( xModel->getInstances(),
178  UNO_QUERY_THROW);
179  sal_Int32 nCount = xInstances->getCount();
180  sal_Int32 i = 0;
181  for( i = 0; i < nCount; i++ )
182  {
183  Sequence<PropertyValue> aInstance;
184  xInstances->getByIndex( i ) >>= aInstance;
185  exportXFormsInstance( rExport, aInstance );
186  }
187 
188 
189  // bindings
190  Reference<XIndexAccess> xBindings( xModel->getBindings(), UNO_QUERY_THROW);
191  nCount = xBindings->getCount();
192  for( i = 0; i < nCount; i++ )
193  {
194  Reference<XPropertySet> aBinding( xBindings->getByIndex( i ),
195  UNO_QUERY_THROW );
196  exportXFormsBinding( rExport, aBinding );
197  }
198 
199  // submissions
200  Reference<XIndexAccess> xSubmissions( xModel->getSubmissions(),
201  UNO_QUERY_THROW );
202  nCount = xSubmissions->getCount();
203  for( i = 0; i < nCount; i++ )
204  {
205  Reference<XPropertySet> xSubmission( xSubmissions->getByIndex( i ),
206  UNO_QUERY_THROW );
207  exportXFormsSubmission( rExport, xSubmission );
208  }
209 
210  // schemas
211  exportXFormsSchemas( rExport, xModel );
212 }
213 
214 
215 // the instance
216 
217 
219  const Sequence<PropertyValue>& xInstance )
220 {
221  OUString sId;
222  OUString sURL;
224 
225  for( const auto& rProp : xInstance )
226  {
227  OUString sName = rProp.Name;
228  const Any& rAny = rProp.Value;
229  if ( sName == "ID" )
230  rAny >>= sId;
231  else if ( sName == "URL" )
232  rAny >>= sURL;
233  else if ( sName == "Instance" )
234  rAny >>= xDoc;
235  }
236 
237  if( !sId.isEmpty() )
238  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_ID, sId );
239 
240  if( !sURL.isEmpty() )
241  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_SRC, sURL );
242 
244  true, true );
245  rExport.IgnorableWhitespace();
246  if( xDoc.is() )
247  {
248  exportDom( rExport, xDoc );
249  }
250 }
251 
252 
253 // the binding
254 
255 
256 const ExportTable aXFormsBindingTable[] =
257 {
258  TABLE_ENTRY( "BindingID", NONE, ID, xforms_string ),
259  TABLE_ENTRY( "BindingExpression", NONE, NODESET, xforms_string ),
260  TABLE_ENTRY( "ReadonlyExpression", NONE, READONLY, xforms_string ),
261  TABLE_ENTRY( "RelevantExpression", NONE, RELEVANT, xforms_string ),
262  TABLE_ENTRY( "RequiredExpression", NONE, REQUIRED, xforms_string ),
263  TABLE_ENTRY( "ConstraintExpression", NONE, CONSTRAINT, xforms_string ),
264  TABLE_ENTRY( "CalculateExpression", NONE, CALCULATE, xforms_string ),
265  // type handled separately, for type name <-> XSD type conversion
266  // TABLE_ENTRY( "Type", NONE, TYPE, xforms_string ),
267  TABLE_END
268 };
269 
271  const Reference<XPropertySet>& xBinding )
272 {
273  // name check; generate binding ID if necessary
274  {
275  OUString sName;
276  xBinding->getPropertyValue( "BindingID" ) >>= sName;
277  if( sName.isEmpty() )
278  {
279  // if we don't have a name yet, generate one on the fly
280  sal_Int64 nId = reinterpret_cast<sal_uInt64>( xBinding.get() );
281  sName = "bind_" + OUString::number( nId , 16 );
282  xBinding->setPropertyValue( "BindingID", makeAny(sName));
283  }
284  }
285 
286  lcl_export( xBinding, rExport, aXFormsBindingTable );
287 
288  // handle type attribute
289  {
290  OUString sTypeName;
291  xBinding->getPropertyValue( "Type" ) >>= sTypeName;
292 
293  try
294  {
295  // now get type, and determine whether it's a standard type. If
296  // so, export the XSD name
298  xBinding->getPropertyValue( "Model" ),
299  UNO_QUERY );
300  Reference<XDataTypeRepository> xRepository(
301  xModel.is() ? xModel->getDataTypeRepository() : Reference<XDataTypeRepository>() );
302  if( xRepository.is() )
303  {
304  Reference<XPropertySet> xDataType =
305  xRepository->getDataType( sTypeName );
306 
307  // if it's a basic data type, write out the XSD name
308  // for the XSD type class
309  bool bIsBasic = false;
310  xDataType->getPropertyValue( "IsBasic" ) >>= bIsBasic;
311  if( bIsBasic )
312  sTypeName = lcl_getXSDType( rExport, xDataType );
313  }
314  }
315  catch( Exception& )
316  {
317  ; // ignore; just use typename
318  }
319 
320  // now that we have the proper type name, write out the attribute
321  if( !sTypeName.isEmpty() )
322  {
324  sTypeName );
325  }
326  }
327 
328  // we need to ensure all the namespaces in the binding will work correctly.
329  // to do so, we will write out all missing namespace declaractions.
330  const SvXMLNamespaceMap& rMap = rExport.GetNamespaceMap();
331  Reference<XNameAccess> xNamespaces(
332  xBinding->getPropertyValue( "ModelNamespaces" ), UNO_QUERY);
333  if( xNamespaces.is() )
334  {
335  // iterate over Prefixes for this binding
336  const Sequence<OUString> aPrefixes = xNamespaces->getElementNames();
337  for( const OUString& rPrefix : aPrefixes )
338  {
339  OUString sURI;
340  xNamespaces->getByName( rPrefix ) >>= sURI;
341 
342  // check whether prefix/URI pair is in map; else write declaration
343  // (we don't need to change the map, since this element has no
344  // other content)
345  sal_uInt16 nKey = rMap.GetKeyByPrefix( rPrefix );
346  if( nKey == XML_NAMESPACE_UNKNOWN ||
347  rMap.GetNameByKey( nKey ) != sURI )
348  {
349  // add declaration if it doesn't already exist
350  SvXMLAttributeList& rAttrList = rExport.GetAttrList();
351  OUString sName = "xmlns:" + rPrefix;
352  sal_Int16 nFound = rAttrList.GetIndexByName(sName);
353  // duplicate xmlns:script, http://openoffice.org/2000/script seen
354  assert(nFound == -1 || rAttrList.getValueByIndex(nFound) == sURI);
355  if (nFound != -1)
356  continue;
357  rAttrList.AddAttribute(sName, sURI);
358  }
359  }
360  }
361 
363  true, true );
364 }
365 
366 
367 // the submission
368 
369 
370 const ExportTable aXFormsSubmissionTable[] =
371 {
372  TABLE_ENTRY( "ID", NONE, ID, xforms_string ),
373  TABLE_ENTRY( "Bind", NONE, BIND, xforms_string ),
374  TABLE_ENTRY( "Ref", NONE, REF, xforms_string ),
375  TABLE_ENTRY( "Action", NONE, ACTION, xforms_string ),
376  TABLE_ENTRY( "Method", NONE, METHOD, xforms_string ),
377  TABLE_ENTRY( "Version", NONE, VERSION, xforms_string ),
378  TABLE_ENTRY( "Indent", NONE, INDENT, xforms_bool ),
379  TABLE_ENTRY( "MediaType", NONE, MEDIATYPE, xforms_string ),
380  TABLE_ENTRY( "Encoding", NONE, ENCODING, xforms_string ),
381  TABLE_ENTRY( "OmitXmlDeclaration", NONE, OMIT_XML_DECLARATION, xforms_bool ),
382  TABLE_ENTRY( "Standalone", NONE, STANDALONE, xforms_bool ),
383  TABLE_ENTRY( "CDataSectionElement", NONE, CDATA_SECTION_ELEMENTS, xforms_string ),
384  TABLE_ENTRY( "Replace", NONE, REPLACE, xforms_string ),
385  TABLE_ENTRY( "Separator", NONE, SEPARATOR, xforms_string ),
386  TABLE_ENTRY( "IncludeNamespacePrefixes", NONE, INCLUDENAMESPACEPREFIXES, xforms_string ),
387  TABLE_END
388 };
389 
391  const Reference<XPropertySet>& xSubmission )
392 {
393  lcl_export( xSubmission, rExport, aXFormsSubmissionTable );
395  true, true );
396 }
397 
398 
399 // export data types as XSD schema
400 
401 
402 const ExportTable aDataTypeFacetTable[] =
403 {
404  TABLE_ENTRY( "Length", XSD, LENGTH, xforms_int32 ),
405  TABLE_ENTRY( "MinLength", XSD, MINLENGTH, xforms_int32 ),
406  TABLE_ENTRY( "MaxLength", XSD, MAXLENGTH, xforms_int32 ),
407  TABLE_ENTRY( "MinInclusiveInt", XSD, MININCLUSIVE, xforms_int32 ),
408  TABLE_ENTRY( "MinExclusiveInt", XSD, MINEXCLUSIVE, xforms_int32 ),
409  TABLE_ENTRY( "MaxInclusiveInt", XSD, MAXINCLUSIVE, xforms_int32 ),
410  TABLE_ENTRY( "MaxExclusiveInt", XSD, MAXEXCLUSIVE, xforms_int32 ),
411  TABLE_ENTRY( "MinInclusiveDouble", XSD, MININCLUSIVE, xforms_double ),
412  TABLE_ENTRY( "MinExclusiveDouble", XSD, MINEXCLUSIVE, xforms_double ),
413  TABLE_ENTRY( "MaxInclusiveDouble", XSD, MAXINCLUSIVE, xforms_double ),
414  TABLE_ENTRY( "MaxExclusiveDouble", XSD, MAXEXCLUSIVE, xforms_double ),
415  TABLE_ENTRY( "MinInclusiveDate", XSD, MININCLUSIVE, xforms_date ),
416  TABLE_ENTRY( "MinExclusiveDate", XSD, MINEXCLUSIVE, xforms_date ),
417  TABLE_ENTRY( "MaxInclusiveDate", XSD, MAXINCLUSIVE, xforms_date ),
418  TABLE_ENTRY( "MaxExclusiveDate", XSD, MAXEXCLUSIVE, xforms_date ),
419  TABLE_ENTRY( "MinInclusiveTime", XSD, MININCLUSIVE, xforms_time ),
420  TABLE_ENTRY( "MinExclusiveTime", XSD, MINEXCLUSIVE, xforms_time ),
421  TABLE_ENTRY( "MaxInclusiveTime", XSD, MAXINCLUSIVE, xforms_time ),
422  TABLE_ENTRY( "MaxExclusiveTime", XSD, MAXEXCLUSIVE, xforms_time ),
423  TABLE_ENTRY( "MinInclusiveDateTime", XSD, MININCLUSIVE, xforms_dateTime ),
424  TABLE_ENTRY( "MinExclusiveDateTime", XSD, MINEXCLUSIVE, xforms_dateTime ),
425  TABLE_ENTRY( "MaxInclusiveDateTime", XSD, MAXINCLUSIVE, xforms_dateTime ),
426  TABLE_ENTRY( "MaxExclusiveDateTime", XSD, MAXEXCLUSIVE, xforms_dateTime ),
427  TABLE_ENTRY( "Pattern", XSD, PATTERN, xforms_string ),
428  // ??? XML_ENUMERATION,
429  TABLE_ENTRY( "WhiteSpace", XSD, WHITESPACE, xforms_whitespace ),
430  TABLE_ENTRY( "TotalDigits", XSD, TOTALDIGITS, xforms_int32 ),
431  TABLE_ENTRY( "FractionDigits", XSD, FRACTIONDIGITS, xforms_int32 ),
432  TABLE_END
433 };
434 
435 // export facets through table; use the same table as lcl_export does
436 static void lcl_exportDataTypeFacets( SvXMLExport& rExport,
437  const Reference<XPropertySet>& rPropertySet,
438  const ExportTable* pTable )
439 {
440  Reference<XPropertySetInfo> xInfo = rPropertySet->getPropertySetInfo();
441  for( const ExportTable* pCurrent = pTable;
442  pCurrent->pPropertyName != nullptr;
443  pCurrent++ )
444  {
445  OUString sName( OUString::createFromAscii( pCurrent->pPropertyName ) );
446  if( xInfo->hasPropertyByName( sName ) )
447  {
448  OUString sValue = (*pCurrent->aConverter)(
449  rPropertySet->getPropertyValue( sName ) );
450 
451  if( !sValue.isEmpty() )
452  {
453  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_VALUE, sValue );
454  SvXMLElementExport aFacet(
455  rExport,
456  pCurrent->nNamespace,
457  static_cast<XMLTokenEnum>( pCurrent->nToken ),
458  true, true );
459  }
460  }
461  }
462 }
463 
464 static OUString lcl_getXSDType( SvXMLExport const & rExport,
465  const Reference<XPropertySet>& xType )
466 {
467  // we use string as default...
469 
470  sal_uInt16 nDataTypeClass = 0;
471  xType->getPropertyValue( "TypeClass" ) >>= nDataTypeClass;
472  switch( nDataTypeClass )
473  {
474  case css::xsd::DataTypeClass::STRING:
475  eToken = XML_STRING;
476  break;
477  case css::xsd::DataTypeClass::anyURI:
478  eToken = XML_ANYURI;
479  break;
480  case css::xsd::DataTypeClass::DECIMAL:
481  eToken = XML_DECIMAL;
482  break;
483  case css::xsd::DataTypeClass::DOUBLE:
484  eToken = XML_DOUBLE;
485  break;
486  case css::xsd::DataTypeClass::FLOAT:
487  eToken = XML_FLOAT;
488  break;
489  case css::xsd::DataTypeClass::BOOLEAN:
490  eToken = XML_BOOLEAN;
491  break;
492  case css::xsd::DataTypeClass::DATETIME:
493  eToken = XML_DATETIME_XSD;
494  break;
495  case css::xsd::DataTypeClass::TIME:
496  eToken = XML_TIME;
497  break;
498  case css::xsd::DataTypeClass::DATE:
499  eToken = XML_DATE;
500  break;
501  case css::xsd::DataTypeClass::gYear:
502  eToken = XML_YEAR;
503  break;
504  case css::xsd::DataTypeClass::gDay:
505  eToken = XML_DAY;
506  break;
507  case css::xsd::DataTypeClass::gMonth:
508  eToken = XML_MONTH;
509  break;
510  case css::xsd::DataTypeClass::DURATION:
511  case css::xsd::DataTypeClass::gYearMonth:
512  case css::xsd::DataTypeClass::gMonthDay:
513  case css::xsd::DataTypeClass::hexBinary:
514  case css::xsd::DataTypeClass::base64Binary:
515  case css::xsd::DataTypeClass::QName:
516  case css::xsd::DataTypeClass::NOTATION:
517  default:
518  OSL_FAIL( "unknown data type" );
519  }
520 
522  GetXMLToken( eToken ) );
523 }
524 
525 static void lcl_exportDataType( SvXMLExport& rExport,
526  const Reference<XPropertySet>& xType )
527 {
528  // we do not need to export basic types; exit if we have one
529  bool bIsBasic = false;
530  xType->getPropertyValue( "IsBasic" ) >>= bIsBasic;
531  if( bIsBasic )
532  return;
533 
534  // no basic type -> export
535 
536  // <xsd:simpleType name="...">
537  OUString sName;
538  xType->getPropertyValue( "Name" ) >>= sName;
539  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_NAME, sName );
540  SvXMLElementExport aSimpleType( rExport,
542  true, true );
543 
544  // <xsd:restriction base="xsd:...">
546  lcl_getXSDType( rExport, xType ) );
547  SvXMLElementExport aRestriction( rExport,
550  true, true );
551 
552  // export facets
553  lcl_exportDataTypeFacets( rExport,
554  xType,
555  aDataTypeFacetTable );
556 }
557 
559  const Reference<css::xforms::XModel>& xModel )
560 {
561  // TODO: for now, we'll fake this...
562  {
563  SvXMLElementExport aSchemaElem( rExport, XML_NAMESPACE_XSD, XML_SCHEMA,
564  true, true );
565 
566  // now get data type repository, and export
567  Reference<XEnumerationAccess> xTypes = xModel->getDataTypeRepository();
568  if( xTypes.is() )
569  {
570  Reference<XEnumeration> xEnum = xTypes->createEnumeration();
571  SAL_WARN_IF( !xEnum.is(), "xmloff", "no enum?" );
572  while( xEnum->hasMoreElements() )
573  {
574  Reference<XPropertySet> xType( xEnum->nextElement(), UNO_QUERY );
575  lcl_exportDataType( rExport, xType );
576  }
577  }
578  }
579 
580  // export other, 'foreign' schemas
581  Reference<XPropertySet> xPropSet( xModel, UNO_QUERY );
582  if( xPropSet.is() )
583  {
584  Reference<XDocument> xDocument(
585  xPropSet->getPropertyValue( "ForeignSchema" ),
586  UNO_QUERY );
587 
588  if( xDocument.is() )
589  exportDom( rExport, xDocument );
590  }
591 }
592 
593 
594 // helper functions
595 
596 
597 static void lcl_export( const Reference<XPropertySet>& rPropertySet,
598  SvXMLExport& rExport,
599  const ExportTable* pTable )
600 {
601  for( const ExportTable* pCurrent = pTable;
602  pCurrent->pPropertyName != nullptr;
603  pCurrent++ )
604  {
605  Any aAny = rPropertySet->getPropertyValue(
606  OUString::createFromAscii( pCurrent->pPropertyName ) );
607  OUString sValue = (*pCurrent->aConverter)( aAny );
608 
609  if( !sValue.isEmpty() )
610  rExport.AddAttribute(
611  pCurrent->nNamespace,
612  static_cast<XMLTokenEnum>( pCurrent->nToken ),
613  sValue );
614  }
615 }
616 
617 
618 // any conversion functions
619 
620 
621 template<typename T, void (*FUNC)( OUStringBuffer&, T )>
622 OUString xforms_convert( const Any& rAny )
623 {
624  OUStringBuffer aBuffer;
625  T aData = T();
626  if( rAny >>= aData )
627  {
628  FUNC( aBuffer, aData );
629  }
630  return aBuffer.makeStringAndClear();
631 }
632 
633 template<typename T, void (*FUNC)( OUStringBuffer&, const T& )>
634 OUString xforms_convertRef( const Any& rAny )
635 {
636  OUStringBuffer aBuffer;
637  T aData;
638  if( rAny >>= aData )
639  {
640  FUNC( aBuffer, aData );
641  }
642  return aBuffer.makeStringAndClear();
643 }
644 
645 OUString xforms_string( const Any& rAny )
646 {
647  OUString aResult;
648  rAny >>= aResult;
649  return aResult;
650 }
651 
652 OUString xforms_bool( const Any& rAny )
653 {
654  bool bResult = bool();
655  if( rAny >>= bResult )
656  return GetXMLToken( bResult ? XML_TRUE : XML_FALSE );
657  OSL_FAIL( "expected boolean value" );
658  return OUString();
659 }
660 
661 void xforms_formatDate( OUStringBuffer& aBuffer, const util::Date& rDate )
662 {
663  aBuffer.append( OUString::number( rDate.Year ) +
664  "-" + OUString::number( rDate.Month ) +
665  "-" + OUString::number( rDate.Day ) );
666 }
667 
668 void xforms_formatTime( OUStringBuffer& aBuffer, const css::util::Time& rTime )
669 {
670  Duration aDuration;
671  aDuration.Hours = rTime.Hours;
672  aDuration.Minutes = rTime.Minutes;
673  aDuration.Seconds = rTime.Seconds;
674  aDuration.NanoSeconds = rTime.NanoSeconds;
675  ::sax::Converter::convertDuration( aBuffer, aDuration );
676 }
677 
678 void xforms_formatDateTime( OUStringBuffer& aBuffer, const util::DateTime& aDateTime )
679 {
680  ::sax::Converter::convertDateTime(aBuffer, aDateTime, nullptr);
681 }
682 
683 OUString xforms_whitespace( const Any& rAny )
684 {
685  OUString sResult;
686  sal_uInt16 n = sal_uInt16();
687  if( rAny >>= n )
688  {
689  switch( n )
690  {
691  case css::xsd::WhiteSpaceTreatment::Preserve:
692  sResult = GetXMLToken( XML_PRESERVE );
693  break;
694  case css::xsd::WhiteSpaceTreatment::Replace:
695  sResult = GetXMLToken( XML_REPLACE );
696  break;
697  case css::xsd::WhiteSpaceTreatment::Collapse:
698  sResult = GetXMLToken( XML_COLLAPSE );
699  break;
700  }
701  }
702  return sResult;
703 }
704 
705 
707 static OUString lcl_getXFormsBindName( const Reference<XPropertySet>& xBinding )
708 {
709  OUString sProp( "BindingID" );
710 
711  OUString sReturn;
712  if( xBinding.is() &&
713  xBinding->getPropertySetInfo()->hasPropertyByName( sProp ) )
714  {
715  xBinding->getPropertyValue( sProp ) >>= sReturn;
716  }
717  return sReturn;
718 }
719 
720 // return name of binding
721 OUString getXFormsBindName( const Reference<XPropertySet>& xControl )
722 {
723  Reference<XBindableValue> xBindable( xControl, UNO_QUERY );
724  return xBindable.is()
726  Reference<XPropertySet>( xBindable->getValueBinding(), UNO_QUERY ))
727  : OUString();
728 }
729 
730 // return name of list binding
732 {
733  Reference<XListEntrySink> xListEntrySink( xControl, UNO_QUERY );
734  return xListEntrySink.is()
736  Reference<XPropertySet>( xListEntrySink->getListEntrySource(),
737  UNO_QUERY ) )
738  : OUString();
739 }
740 
742 {
743  OUString sReturn;
744 
745  Reference<XSubmissionSupplier> xSubmissionSupplier( xBinding, UNO_QUERY );
746  if( xSubmissionSupplier.is() )
747  {
748  Reference<XPropertySet> xPropertySet(
749  xSubmissionSupplier->getSubmission(), UNO_QUERY );
750  OUString sProp( "ID" );
751  if( xPropertySet.is() &&
752  xPropertySet->getPropertySetInfo()->hasPropertyByName( sProp ) )
753  {
754  xPropertySet->getPropertyValue( sProp ) >>= sReturn;
755  }
756  }
757 
758  return sReturn;
759 }
760 
762 {
763  _out_rSettings = Sequence< PropertyValue >();
764 
765  OSL_PRECOND( _rXForms.is(), "getXFormsSettings: invalid XForms container!" );
766  if ( !_rXForms.is() )
767  return;
768 
769  try
770  {
771  // we want to export some special properties of our XForms models as config-item-map-named,
772  // which implies we need a PropertyValue whose value is an XNameAccess, whose keys
773  // are the names of the XForm models, and which in turn provides named sequences of
774  // PropertyValues - which denote the actual property values of the given named model.
775 
776  const Sequence< OUString > aModelNames( _rXForms->getElementNames() );
777 
778  Reference< XNameContainer > xModelSettings = document::NamedPropertyValues::create( comphelper::getProcessComponentContext() );
779 
780  for ( auto const & modelName : aModelNames )
781  {
782  Reference< XPropertySet > xModelProps( _rXForms->getByName( modelName ), UNO_QUERY_THROW );
783 
784  static constexpr OUStringLiteral sExternalData = u"ExternalData";
786  sExternalData, xModelProps->getPropertyValue(sExternalData)) };
787 
788  xModelSettings->insertByName( modelName, makeAny( aModelSettings ) );
789  }
790 
791  if ( xModelSettings->hasElements() )
792  {
793  _out_rSettings = { comphelper::makePropertyValue("XFormModels", xModelSettings) };
794  }
795  }
796  catch( const Exception& )
797  {
798  DBG_UNHANDLED_EXCEPTION("xmloff");
799  }
800 }
801 
802 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void getXFormsSettings(const Reference< XNameAccess > &_rXForms, Sequence< PropertyValue > &_out_rSettings)
const ExportTable aDataTypeFacetTable[]
convert_t const xforms_double
sal_uInt16 GetKeyByPrefix(const OUString &rPrefix) const
static void xforms_formatDate(OUStringBuffer &aBuffer, const util::Date &aDate)
constexpr sal_uInt16 XML_NAMESPACE_XFORMS
static void exportXFormsSchemas(SvXMLExport &, const Reference< css::xforms::XModel > &)
#define TABLE_END
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
sal_Int64 n
sal_Int16 nId
OUString getXFormsSubmissionName(const Reference< XPropertySet > &xBinding)
ACTION
#define SEPARATOR
static void lcl_exportDataTypeFacets(SvXMLExport &rExport, const Reference< XPropertySet > &rPropertySet, const ExportTable *pTable)
OUString getXFormsListBindName(const Reference< XPropertySet > &xControl)
NONE
static OUString xforms_whitespace(const Any &)
const sal_uInt16 XML_NAMESPACE_UNKNOWN
SvXMLAttributeList & GetAttrList()
Definition: xmlexp.hxx:379
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlexp.hxx:416
int nCount
void AddAttribute(sal_uInt16 nPrefix, const OUString &rName, const OUString &rValue)
Definition: xmlexp.cxx:910
static void convertNumber(OUStringBuffer &b, sal_Int32 n)
sal_Int16 GetIndexByName(const OUString &rName) const
Definition: attrlist.cxx:177
const char * sName
static OUString xforms_convert(const Any &)
constexpr OUStringLiteral aData
static void lcl_exportDataType(SvXMLExport &rExport, const Reference< XPropertySet > &xType)
#define DBG_UNHANDLED_EXCEPTION(...)
static void lcl_export(const Reference< XPropertySet > &rPropertySet, SvXMLExport &rExport, const ExportTable *pTable)
convert_t const xforms_time
const ExportTable aXFormsBindingTable[]
static OUString lcl_getXFormsBindName(const Reference< XPropertySet > &xBinding)
return name of Binding
void exportXForms(SvXMLExport &rExport)
export an XForms model.
void exportXFormsModel(SvXMLExport &rExport, const Reference< XPropertySet > &xModelPropSet)
int i
constexpr OUStringLiteral PATTERN
class SAL_NO_VTABLE XPropertySet
convert_t const xforms_int32
float u
static void convertDateTime(OUStringBuffer &rBuffer, const css::util::DateTime &rDateTime, sal_Int16 const *pTimeZoneOffset, bool bAddTimeIf0AM=false)
constexpr sal_uInt16 XML_NAMESPACE_XSD
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
convert_t const xforms_date
#define VERSION
const sal_uInt16 XML_NAMESPACE_NONE
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
static OUString lcl_getXSDType(SvXMLExport const &rExport, const Reference< XPropertySet > &xType)
const SvXMLNamespaceMap & GetNamespaceMap() const
Definition: xmlexp.hxx:390
static OUString xforms_string(const Any &)
const OUString & GetNameByKey(sal_uInt16 nKey) const
const ExportTable aXFormsSubmissionTable[]
static OUString xforms_bool(const Any &)
static void exportXFormsInstance(SvXMLExport &, const Sequence< PropertyValue > &)
void IgnorableWhitespace()
Definition: xmlexp.cxx:2186
DefTokenId nToken
OUString getXFormsBindName(const Reference< XPropertySet > &xControl)
std::unique_ptr< char[]> aBuffer
convert_t const xforms_dateTime
static void exportXFormsSubmission(SvXMLExport &, const Reference< XPropertySet > &)
Any makeAny(Color const &value)
#define SAL_WARN_IF(condition, area, stream)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3472
const char * pPropertyName
Handling of tokens in XML:
OReadImagesDocumentHandler::Image_XML_Namespace nNamespace
void exportDom(SvXMLExport &rExport, const Reference< XDocument > &xDocument)
Definition: DomExport.cxx:243
static void xforms_formatDateTime(OUStringBuffer &aBuffer, const util::DateTime &aDateTime)
Reference< XComponentContext > getProcessComponentContext()
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:49
static OUString xforms_convertRef(const Any &)
static void exportXFormsBinding(SvXMLExport &, const Reference< XPropertySet > &)
void AddAttribute(const OUString &sName, const OUString &sValue)
Definition: attrlist.cxx:110
static void xforms_formatTime(OUStringBuffer &aBuffer, const css::util::Time &aTime)
Reference< XModel > xModel
#define TABLE_ENTRY(NAME, NAMESPACE, TOKEN, CONVERTER)
XMLTokenEnum eToken
Definition: xmltoken.cxx:40
const ExportTable aXFormsModelTable[]
OUString(* convert_t)(const Any &)
const bool READONLY
OUString sId
virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) override
Definition: attrlist.cxx:69