LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / xmloff / source / text / txtvfldi.cxx
blob35dcd65b5528c71f0e9fdfffc6046a08db0b2af4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 /** @#file
23 * export of all variable related text fields (and database display field)
25 #include <txtvfldi.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/txtimp.hxx>
28 #include <xmloff/xmlnamespace.hxx>
29 #include <xmloff/namespacemap.hxx>
30 #include <xmloff/i18nmap.hxx>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmluconv.hxx>
33 #include <xmloff/xmlement.hxx>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/text/SetVariableType.hpp>
36 #include <com/sun/star/text/XDependentTextField.hpp>
37 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/XPropertySetInfo.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/xml/sax/XAttributeList.hpp>
42 #include <com/sun/star/style/NumberingType.hpp>
43 #include <com/sun/star/container/XIndexReplace.hpp>
45 #include <sax/tools/converter.hxx>
47 #include <rtl/ustring.hxx>
48 #include <osl/diagnose.h>
49 #include <sal/log.hxx>
51 #include <tools/debug.hxx>
52 #include <tools/diagnose_ex.h>
55 // service names
56 constexpr char16_t sAPI_fieldmaster_prefix[] = u"com.sun.star.text.FieldMaster.";
57 constexpr OUStringLiteral sAPI_get_expression = u"GetExpression";
58 constexpr OUStringLiteral sAPI_set_expression = u"SetExpression";
59 constexpr OUStringLiteral sAPI_user = u"User";
60 constexpr OUStringLiteral sAPI_database = u"com.sun.star.text.TextField.Database";
62 // property names
63 constexpr OUStringLiteral sAPI_content = u"Content";
64 constexpr OUStringLiteral sAPI_sub_type = u"SubType";
65 constexpr OUStringLiteral sAPI_number_format = u"NumberFormat";
66 constexpr OUStringLiteral sAPI_is_visible = u"IsVisible";
67 constexpr OUStringLiteral sAPI_current_presentation = u"CurrentPresentation";
70 using namespace ::com::sun::star;
71 using namespace ::com::sun::star::uno;
72 using namespace ::com::sun::star::beans;
73 using namespace ::com::sun::star::text;
74 using namespace ::com::sun::star::style;
75 using namespace ::xmloff::token;
78 // XMLVarFieldImportContext: superclass for all variable related fields
81 XMLVarFieldImportContext::XMLVarFieldImportContext(
82 SvXMLImport& rImport, XMLTextImportHelper& rHlp,
83 const OUString& pServiceName,
84 bool bFormula, bool bFormulaDefault,
85 bool bDescription, bool bHelp, bool bHint, bool bVisible,
86 bool bIsDisplayFormula,
87 bool bType, bool bStyle, bool bValue,
88 bool bPresentation) :
89 XMLTextFieldImportContext(rImport, rHlp, pServiceName),
90 aValueHelper(rImport, rHlp, bType, bStyle, bValue, false),
91 bDisplayFormula(false),
92 bDisplayNone(false),
93 bFormulaOK(false),
94 bDescriptionOK(false),
95 bHelpOK(false),
96 bHintOK(false),
97 bDisplayOK(false),
98 bSetFormula(bFormula),
99 bSetFormulaDefault(bFormulaDefault),
100 bSetDescription(bDescription),
101 bSetHelp(bHelp),
102 bSetHint(bHint),
103 bSetVisible(bVisible),
104 bSetDisplayFormula(bIsDisplayFormula),
105 bSetPresentation(bPresentation)
109 void XMLVarFieldImportContext::ProcessAttribute(
110 sal_Int32 nAttrToken,
111 std::string_view sAttrValue )
113 switch (nAttrToken)
115 case XML_ELEMENT(TEXT, XML_NAME):
116 sName = OUString::fromUtf8(sAttrValue);
117 bValid = true; // we assume: field with name is valid!
118 break;
119 case XML_ELEMENT(TEXT, XML_DESCRIPTION):
120 sDescription = OUString::fromUtf8(sAttrValue);
121 bDescriptionOK = true;
122 break;
123 case XML_ELEMENT(TEXT, XML_HELP):
124 sHelp = OUString::fromUtf8(sAttrValue);
125 bHelpOK = true;
126 break;
127 case XML_ELEMENT(TEXT, XML_HINT):
128 sHint = OUString::fromUtf8(sAttrValue);
129 bHintOK = true;
130 break;
131 case XML_ELEMENT(TEXT, XML_FORMULA):
133 OUString sTmp;
134 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
135 GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
136 if( XML_NAMESPACE_OOOW == nPrefix )
138 sFormula = sTmp;
139 bFormulaOK = true;
141 else
142 sFormula = OUString::fromUtf8(sAttrValue);
144 break;
145 case XML_ELEMENT(TEXT, XML_DISPLAY):
146 if (IsXMLToken(sAttrValue, XML_FORMULA))
148 bDisplayFormula = true;
149 bDisplayNone = false;
150 bDisplayOK = true;
152 else if (IsXMLToken(sAttrValue, XML_VALUE))
154 bDisplayFormula = false;
155 bDisplayNone = false;
156 bDisplayOK = true;
158 else if (IsXMLToken(sAttrValue, XML_NONE))
160 bDisplayFormula = false;
161 bDisplayNone = true;
162 bDisplayOK = true;
163 } // else: no change
164 DBG_ASSERT(!(bDisplayFormula && bDisplayNone),
165 "illegal display values");
166 break;
167 default:
168 // delegate all others to value helper
169 aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
170 break;
174 void XMLVarFieldImportContext::PrepareField(
175 const Reference<XPropertySet> & xPropertySet)
177 // bSetName: not implemented
179 if (bSetFormula)
181 if (!bFormulaOK && bSetFormulaDefault)
183 sFormula = GetContent();
184 bFormulaOK = true;
187 if (bFormulaOK)
189 xPropertySet->setPropertyValue(sAPI_content, Any(sFormula));
193 if (bSetDescription && bDescriptionOK)
195 xPropertySet->setPropertyValue("Hint", Any(sDescription));
198 if (bSetHelp && bHelpOK)
200 xPropertySet->setPropertyValue("Help", Any(sHelp));
203 if (bSetHint && bHintOK)
205 xPropertySet->setPropertyValue("Tooltip", Any(sHint));
208 if (bSetVisible && bDisplayOK)
210 bool bTmp = !bDisplayNone;
211 xPropertySet->setPropertyValue(sAPI_is_visible, Any(bTmp));
214 // workaround for #no-bug#: display formula by default
215 if (xPropertySet->getPropertySetInfo()->
216 hasPropertyByName("IsShowFormula") &&
217 !bSetDisplayFormula)
219 bDisplayFormula = false;
220 bSetDisplayFormula = true;
224 if (bSetDisplayFormula)
226 bool bTmp = bDisplayFormula && bDisplayOK;
227 xPropertySet->setPropertyValue("IsShowFormula", Any(bTmp));
230 // delegate to value helper
231 aValueHelper.SetDefault(GetContent());
232 aValueHelper.PrepareField(xPropertySet);
234 // finally, set the current presentation
235 if (bSetPresentation)
237 Any aAny;
238 aAny <<= GetContent();
239 xPropertySet->setPropertyValue(sAPI_current_presentation, aAny);
244 // variable set fields
247 XMLSetVarFieldImportContext::XMLSetVarFieldImportContext(
248 SvXMLImport& rImport, XMLTextImportHelper& rHlp,
249 const OUString& pServiceName, VarType eVarType,
250 bool bFormula, bool bFormulaDefault,
251 bool bDescription, bool bHelp, bool bHint, bool bVisible, bool bIsDisplayFormula,
252 bool bType, bool bStyle, bool bValue, bool bPresentation) :
253 XMLVarFieldImportContext(rImport, rHlp, pServiceName,
254 bFormula, bFormulaDefault,
255 bDescription, bHelp, bHint, bVisible, bIsDisplayFormula,
256 bType, bStyle, bValue, bPresentation),
257 eFieldType(eVarType)
261 void XMLSetVarFieldImportContext::endFastElement(sal_Int32 )
263 // should we call PrepareField on the field, or rather on it's master?
264 // currently: call on field (just like superclass)
265 // possible alternatives: call on master
266 // call field or master depending on variable
267 // PrepareMaster() in addition to PrepareField()
269 DBG_ASSERT(!GetServiceName().isEmpty(), "no service name for element!");
271 if (bValid)
273 DBG_ASSERT(!GetName().isEmpty(), "variable name needed!");
275 // find field master
276 Reference<XPropertySet> xMaster;
277 if (FindFieldMaster(xMaster))
279 // create field/Service
280 Reference<XPropertySet> xPropSet;
281 if (CreateField(xPropSet, "com.sun.star.text.TextField." + GetServiceName()))
283 Reference<XDependentTextField> xDepTextField(xPropSet, UNO_QUERY);
284 if (xDepTextField.is())
286 // attach field to field master
287 xDepTextField->attachTextFieldMaster(xMaster);
289 // attach field to document
290 Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
291 if (xTextContent.is())
293 try {
294 // insert, set field properties and exit!
295 GetImportHelper().InsertTextContent(xTextContent);
296 PrepareField(xPropSet);
297 } catch (lang::IllegalArgumentException & /*e*/)
299 // ignore e: #i54023#
301 return;
308 // above: exit on success; so for all error cases we end up here!
309 // write element content
310 GetImportHelper().InsertString(GetContent());
313 bool XMLSetVarFieldImportContext::FindFieldMaster(
314 Reference<XPropertySet> & xMaster)
316 // currently: delegate to XMLVariableDeclImportContext;
317 // should eventually go here
318 return XMLVariableDeclImportContext::FindFieldMaster(xMaster,
319 GetImport(),
320 GetImportHelper(),
321 GetName(),
322 eFieldType);
326 // sequence field
329 XMLSequenceFieldImportContext::XMLSequenceFieldImportContext(
330 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
331 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
332 VarTypeSequence,
333 // formula
334 true, true,
335 false, false, false, false,
336 false,
337 false, false, false, true),
339 sNumFormat(OUString('1')),
340 sNumFormatSync(GetXMLToken(XML_FALSE)),
341 bRefNameOK(false)
345 void XMLSequenceFieldImportContext::ProcessAttribute(
346 sal_Int32 nAttrToken, std::string_view sAttrValue )
348 switch (nAttrToken)
350 case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
351 sNumFormat = OUString::fromUtf8(sAttrValue);
352 break;
353 case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
354 sNumFormatSync = OUString::fromUtf8(sAttrValue);
355 break;
356 case XML_ELEMENT(TEXT, XML_REF_NAME):
357 sRefName = OUString::fromUtf8(sAttrValue);
358 bRefNameOK = true;
359 break;
360 default:
361 // delegate to super class (name, formula)
362 XMLSetVarFieldImportContext::ProcessAttribute(nAttrToken,
363 sAttrValue);
364 break;
365 } // switch
368 void XMLSequenceFieldImportContext::PrepareField(
369 const Reference<XPropertySet> & xPropertySet)
371 // delegate to super class (formula)
372 XMLSetVarFieldImportContext::PrepareField(xPropertySet);
374 // set format
375 sal_Int16 nNumType = NumberingType::ARABIC;
376 GetImport().GetMM100UnitConverter().convertNumFormat( nNumType, sNumFormat, sNumFormatSync );
377 xPropertySet->setPropertyValue(sAPI_number_format, Any(nNumType));
379 // handle reference name
380 if (bRefNameOK)
382 Any aAny = xPropertySet->getPropertyValue("SequenceValue");
383 sal_Int16 nValue = 0;
384 aAny >>= nValue;
385 GetImportHelper().InsertSequenceID(sRefName, GetName(), nValue);
390 // variable set field
393 XMLVariableSetFieldImportContext::XMLVariableSetFieldImportContext(
394 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
395 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
396 VarTypeSimple,
397 // formula, value&type, style,
398 // display none
399 true, true,
400 false, false, false,
401 true, false,
402 true, true, true,
403 true)
407 void XMLVariableSetFieldImportContext::PrepareField(
408 const Reference<XPropertySet> & xPropertySet)
410 // set type
411 Any aAny;
412 aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
413 xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
415 // the remainder is handled by super class
416 XMLSetVarFieldImportContext::PrepareField(xPropertySet);
420 // variable input field
423 XMLVariableInputFieldImportContext::XMLVariableInputFieldImportContext(
424 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
425 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
426 VarTypeSimple,
427 // description, display none/formula,
428 // value&type, style, formula
429 true, true,
430 true, true, true,
431 true, false,
432 true, true, true,
433 true)
437 void XMLVariableInputFieldImportContext::PrepareField(
438 const Reference<XPropertySet> & xPropertySet)
440 // set type (input field)
441 Any aAny;
442 xPropertySet->setPropertyValue("Input", Any(true));
444 // set type
445 aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
446 xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
448 // the remainder is handled by super class
449 XMLSetVarFieldImportContext::PrepareField(xPropertySet);
453 // user field
456 XMLUserFieldImportContext::XMLUserFieldImportContext(
457 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
458 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_user,
459 VarTypeUserField,
460 // display none/formula, style
461 false, false,
462 false, false, false, true,
463 true,
464 false, true, false,
465 false)
470 // user input field
473 // bug: doesn't work (SO API lacking)
474 XMLUserFieldInputImportContext::XMLUserFieldInputImportContext(
475 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
476 XMLVarFieldImportContext(rImport, rHlp, "InputUser",
477 // description, style
478 false, false,
479 true, false, false,
480 false, false,
481 false /*???*/, true, false,
482 false)
486 void XMLUserFieldInputImportContext::PrepareField(
487 const Reference<XPropertySet> & xPropertySet)
489 xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
491 // delegate to super class
492 XMLVarFieldImportContext::PrepareField(xPropertySet);
496 // variable get field
499 XMLVariableGetFieldImportContext::XMLVariableGetFieldImportContext(
500 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
501 XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
502 // style, display formula
503 false, false,
504 false, false, false,
505 false, true,
506 true, true, false,
507 true)
511 void XMLVariableGetFieldImportContext::PrepareField(
512 const Reference<XPropertySet> & xPropertySet)
514 // set name
515 xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
517 // the remainder is handled by super class
518 XMLVarFieldImportContext::PrepareField(xPropertySet);
522 // expression field
525 XMLExpressionFieldImportContext::XMLExpressionFieldImportContext(
526 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
527 XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
528 // formula, type, style, display formula
529 true, true,
530 false, false, false,
531 false, true,
532 true, true, false,
533 true)
535 bValid = true; // always valid
539 void XMLExpressionFieldImportContext::PrepareField(
540 const Reference<XPropertySet> & xPropertySet)
542 xPropertySet->setPropertyValue(sAPI_sub_type, Any(sal_Int16(SetVariableType::FORMULA)));
544 // delegate to super class
545 XMLVarFieldImportContext::PrepareField(xPropertySet);
549 // text input field
552 XMLTextInputFieldImportContext::XMLTextInputFieldImportContext(
553 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
554 XMLVarFieldImportContext(rImport, rHlp, "Input",
555 // description
556 false, false,
557 true, true, true,
558 false, false,
559 false, false, false,
560 false)
562 bValid = true; // always valid
565 void XMLTextInputFieldImportContext::PrepareField(
566 const Reference<XPropertySet> & xPropertySet)
568 XMLVarFieldImportContext::PrepareField(xPropertySet);
570 xPropertySet->setPropertyValue(sAPI_content, Any(GetContent()));
574 // table formula field
577 XMLTableFormulaImportContext::XMLTableFormulaImportContext(
578 SvXMLImport& rImport,
579 XMLTextImportHelper& rHlp) :
580 XMLTextFieldImportContext(rImport, rHlp, "TableFormula"),
581 aValueHelper(rImport, rHlp, false, true, false, true),
582 bIsShowFormula(false)
586 void XMLTableFormulaImportContext::ProcessAttribute(
587 sal_Int32 nAttrToken,
588 std::string_view sAttrValue )
590 switch (nAttrToken)
592 case XML_ELEMENT(TEXT, XML_FORMULA):
593 aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
594 bValid = true; // we need a formula!
595 break;
597 case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
598 aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
599 break;
600 case XML_ELEMENT(TEXT, XML_DISPLAY):
601 if ( sAttrValue == "formula" )
602 bIsShowFormula = true;
603 break;
604 default:
605 // unknown attribute -> ignore
606 XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
607 break;
611 void XMLTableFormulaImportContext::PrepareField(
612 const Reference<XPropertySet> & xPropertySet)
614 // set format and formula
615 aValueHelper.PrepareField( xPropertySet );
617 Any aAny;
619 // set 'show formula' and presentation
620 xPropertySet->setPropertyValue( "IsShowFormula", Any(bIsShowFormula) );
622 aAny <<= GetContent();
623 xPropertySet->setPropertyValue( "CurrentPresentation", aAny );
627 // variable declarations
629 // Should be adapted to XMLVarField-/XMLSetVarFieldImportContext scheme!
632 // declaration container import (<variable/user-field/sequence-decls>)
635 XMLVariableDeclsImportContext::XMLVariableDeclsImportContext(
636 SvXMLImport& rImport, XMLTextImportHelper& rHlp, enum VarType eVarType) :
637 SvXMLImportContext(rImport),
638 eVarDeclsContextType(eVarType),
639 rImportHelper(rHlp)
643 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLVariableDeclsImportContext::createFastChildContext(
644 sal_Int32 nElement,
645 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
647 SvXMLImportContextRef xImportContext;
649 if( IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT) )
651 enum XMLTokenEnum eElementName;
652 switch (eVarDeclsContextType)
654 case VarTypeSequence:
655 eElementName = XML_SEQUENCE_DECL;
656 break;
657 case VarTypeSimple:
658 eElementName = XML_VARIABLE_DECL;
659 break;
660 case VarTypeUserField:
661 eElementName = XML_USER_FIELD_DECL;
662 break;
663 default:
664 OSL_FAIL("unknown field type!");
665 eElementName = XML_SEQUENCE_DECL;
666 break;
669 if( nElement == XML_ELEMENT(TEXT, eElementName) )
671 return new XMLVariableDeclImportContext(
672 GetImport(), rImportHelper, nElement, xAttrList,
673 eVarDeclsContextType);
677 // if no context was created, use default context
678 return nullptr;
682 // declaration import (<variable/user-field/sequence-decl> elements)
685 XMLVariableDeclImportContext::XMLVariableDeclImportContext(
686 SvXMLImport& rImport, XMLTextImportHelper& rHlp,
687 sal_Int32 nElement,
688 const Reference<xml::sax::XFastAttributeList> & xAttrList,
689 enum VarType eVarType) :
690 SvXMLImportContext(rImport)
692 // bug?? which properties for userfield/userfieldmaster
693 XMLValueImportHelper aValueHelper(rImport, rHlp, true, false, true, false);
694 sal_Unicode cSeparationChar('.');
696 sal_Int8 nNumLevel(-1);
697 OUString sName;
699 if (nElement != XML_ELEMENT(TEXT, XML_SEQUENCE_DECL) &&
700 nElement != XML_ELEMENT(TEXT, XML_VARIABLE_DECL) &&
701 nElement != XML_ELEMENT(TEXT, XML_USER_FIELD_DECL) )
702 return;
704 // TODO: check validity (need name!)
706 // parse attributes
707 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
709 switch (aIter.getToken())
711 case XML_ELEMENT(TEXT, XML_NAME):
712 sName = aIter.toString();
713 break;
714 case XML_ELEMENT(TEXT, XML_DISPLAY_OUTLINE_LEVEL):
716 sal_Int32 nLevel;
717 bool const bRet = ::sax::Converter::convertNumber(
718 nLevel, aIter.toView(), 0,
719 GetImport().GetTextImport()->GetChapterNumbering()->
720 getCount());
721 if (bRet)
723 nNumLevel = static_cast< sal_Int8 >( nLevel-1 ); // API numbers -1..9
725 break;
727 case XML_ELEMENT(TEXT, XML_SEPARATION_CHARACTER):
728 cSeparationChar =
729 static_cast<char>(aIter.toString().toChar());
730 break;
732 default:
733 // delegate to value helper
734 aValueHelper.ProcessAttribute(aIter.getToken(), aIter.toView());
735 break;
739 Reference<XPropertySet> xFieldMaster;
740 if (!FindFieldMaster(xFieldMaster, GetImport(), rHlp,
741 sName, eVarType))
742 return;
744 // now we have a field master: process attributes!
745 Any aAny;
747 switch (eVarType)
749 case VarTypeSequence:
750 xFieldMaster->setPropertyValue("ChapterNumberingLevel", Any(nNumLevel));
752 if (nNumLevel >= 0)
754 OUString sStr(&cSeparationChar, 1);
755 xFieldMaster->setPropertyValue(
756 "NumberingSeparator", Any(sStr));
758 break;
759 case VarTypeSimple:
761 // set string or non-string SubType (#93192#)
762 // The SubType was already set in the FindFieldMaster
763 // method, but it needs to be adjusted if it's a string.
764 aAny <<= aValueHelper.IsStringValue()
765 ? SetVariableType::STRING : SetVariableType::VAR;
766 xFieldMaster->setPropertyValue(sAPI_sub_type, aAny);
768 break;
769 case VarTypeUserField:
771 bool bTmp = !aValueHelper.IsStringValue();
772 xFieldMaster->setPropertyValue("IsExpression", Any(bTmp));
773 aValueHelper.PrepareField(xFieldMaster);
774 break;
776 default:
777 OSL_FAIL("unknown varfield type");
778 } // switch
782 bool XMLVariableDeclImportContext::FindFieldMaster(
783 Reference<XPropertySet> & xMaster, SvXMLImport& rImport,
784 XMLTextImportHelper& rImportHelper,
785 const OUString& sVarName, enum VarType eVarType)
787 static sal_Int32 nCollisionCount = 0;
789 // rename field
790 // currently: no family in use! Use 0.
791 OUString sName = rImportHelper.GetRenameMap().Get(
792 sal::static_int_cast< sal_uInt16 >(eVarType), sVarName);
794 // get text fields supplier and field masters
795 Reference<XTextFieldsSupplier> xTextFieldsSupp(rImport.GetModel(),
796 UNO_QUERY);
797 Reference<container::XNameAccess> xFieldMasterNameAccess =
798 xTextFieldsSupp->getTextFieldMasters();
800 OUString sVarServiceName =
801 OUString::Concat(sAPI_fieldmaster_prefix) +
802 sAPI_set_expression +
803 "." +
804 sName;
806 OUString sUserServiceName =
807 OUString::Concat(sAPI_fieldmaster_prefix) +
808 sAPI_user +
809 "." +
810 sName;
812 if (xFieldMasterNameAccess->hasByName(sVarServiceName)) {
813 // variable field master already in document
815 Any aAny = xFieldMasterNameAccess->getByName(sVarServiceName);
816 aAny >>= xMaster;
818 aAny = xMaster->getPropertyValue(sAPI_sub_type);
819 sal_Int16 nType = 0;
820 aAny >>= nType;
822 enum VarType eFMVarType =
823 (SetVariableType::SEQUENCE == nType) ?
824 VarTypeSequence : VarTypeSimple;
826 if (eFMVarType != eVarType)
828 ++nCollisionCount;
829 OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount));
831 // FIXME! can't find if name is taken already!!!!
833 rImportHelper.GetRenameMap().Add(
834 sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
836 // call FindFieldMaster recursively to create new master
837 return FindFieldMaster(xMaster, rImport, rImportHelper,
838 sNew, eVarType);
840 } else if (xFieldMasterNameAccess->hasByName(sUserServiceName)) {
841 // user field: get field master
842 Any aAny = xFieldMasterNameAccess->getByName(sUserServiceName);
843 aAny >>= xMaster;
845 if (VarTypeUserField != eVarType) {
846 ++nCollisionCount;
847 // find new name that is not taken
848 OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount));
850 // FIXME! can't find if name is taken already!!!!
852 rImportHelper.GetRenameMap().Add(
853 sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
855 // call FindFieldMaster recursively to create new master
856 return FindFieldMaster(xMaster, rImport, rImportHelper,
857 sNew, eVarType);
859 } else {
860 // field name not used: create field master
862 // import -> model is MultiServiceFactory -> createInstance
863 Reference<lang::XMultiServiceFactory>
864 xFactory(rImport.GetModel(),UNO_QUERY);
865 if( xFactory.is() ) {
867 OUString sService = sAPI_fieldmaster_prefix
868 + ((eVarType==VarTypeUserField) ?
869 OUString(sAPI_user) : OUString(sAPI_set_expression));
870 Reference<XInterface> xIfc =
871 xFactory->createInstance( sService );
872 if (xIfc.is()) {
873 Reference<XPropertySet> xTmp( xIfc, UNO_QUERY );
874 xMaster = xTmp;
876 // set name
877 xMaster->setPropertyValue("Name", Any(sName));
879 if (eVarType != VarTypeUserField) {
880 // set subtype for setexp field
881 Any aAny;
882 aAny <<= ((eVarType == VarTypeSimple) ?
883 SetVariableType::VAR :
884 SetVariableType::SEQUENCE);
885 xMaster->setPropertyValue(sAPI_sub_type, aAny);
886 } // else : user field: no subtype
888 } else {
889 return false;
891 } else {
892 return false;
896 DBG_ASSERT(xMaster.is(), "no field master found!?!");
897 return true;
901 // Database Display field import
904 XMLDatabaseDisplayImportContext::XMLDatabaseDisplayImportContext(
905 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
906 XMLDatabaseFieldImportContext(rImport, rHlp, sAPI_database, false),
907 aValueHelper(rImport, rHlp, false, true, false, false),
908 bColumnOK(false),
909 bDisplay( true ),
910 bDisplayOK( false )
914 void XMLDatabaseDisplayImportContext::ProcessAttribute(
915 sal_Int32 nAttrToken, std::string_view sAttrValue )
917 switch (nAttrToken)
919 case XML_ELEMENT(TEXT, XML_COLUMN_NAME):
920 sColumnName = OUString::fromUtf8(sAttrValue);
921 bColumnOK = true;
922 break;
923 case XML_ELEMENT(TEXT, XML_DISPLAY):
925 bool bNone = IsXMLToken( sAttrValue, XML_NONE );
926 bool bValue = IsXMLToken( sAttrValue, XML_VALUE );
927 bDisplay = bValue;
928 bDisplayOK = bNone || bValue;
930 break;
931 case XML_ELEMENT(TEXT, XML_DATABASE_NAME):
932 case XML_ELEMENT(TEXT, XML_TABLE_NAME):
933 case XML_ELEMENT(TEXT, XML_TABLE_TYPE):
934 // handled by super class
935 XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken,
936 sAttrValue);
937 break;
938 default:
939 // remainder handled by value helper
940 aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
941 break;
944 bValid = m_bTableOK && m_bDatabaseOK && bColumnOK;
947 void XMLDatabaseDisplayImportContext::endFastElement(sal_Int32 )
949 // we have an EndElement of our own, because database fields need
950 // to be attached to a field master before they can be inserted into
951 // the document. Database stuff (database, table, column) all goes
952 // to the field master, value & style go to the field.
954 if (bValid)
957 // so here goes: we start with the master
958 Reference<XPropertySet> xMaster;
960 // create and prepare field master first
961 if (CreateField(xMaster,
962 "com.sun.star.text.FieldMaster.Database"))
964 Any aAny;
965 xMaster->setPropertyValue("DataColumnName", Any(sColumnName));
967 // fieldmaster takes database, table and column name
968 XMLDatabaseFieldImportContext::PrepareField(xMaster);
970 // create field
971 Reference<XPropertySet> xField;
972 if (CreateField(xField,
973 sAPI_database))
975 // attach field master
976 Reference<XDependentTextField> xDepField(xField, UNO_QUERY);
977 if (xDepField.is())
979 // attach field to field master
980 xDepField->attachTextFieldMaster(xMaster);
982 // attach field to document
983 Reference<XTextContent> xTextContent(xField, UNO_QUERY);
984 if (xTextContent.is())
986 // insert, set field properties and exit!
989 GetImportHelper().InsertTextContent(xTextContent);
991 // prepare field: format from database?
992 bool bTmp = !aValueHelper.IsFormatOK();
993 xField->setPropertyValue("DataBaseFormat", Any(bTmp));
995 // value, value-type and format done by value helper
996 aValueHelper.PrepareField(xField);
998 // visibility
999 if( bDisplayOK )
1001 xField->setPropertyValue(sAPI_is_visible, Any(bDisplay));
1004 // set presentation
1005 aAny <<= GetContent();
1006 xField->setPropertyValue(sAPI_current_presentation, aAny);
1008 // success!
1009 return;
1011 catch (const lang::IllegalArgumentException&)
1013 TOOLS_WARN_EXCEPTION("xmloff.text", "Failed to insert text content");
1021 // above: exit on success; so for all error cases we end up here!
1022 // write element content
1023 GetImportHelper().InsertString(GetContent());
1027 // value import helper
1029 namespace {
1031 enum ValueType
1033 XML_VALUE_TYPE_STRING,
1034 XML_VALUE_TYPE_FLOAT,
1035 XML_VALUE_TYPE_CURRENCY,
1036 XML_VALUE_TYPE_PERCENTAGE,
1037 XML_VALUE_TYPE_DATE,
1038 XML_VALUE_TYPE_TIME,
1039 XML_VALUE_TYPE_BOOLEAN
1044 SvXMLEnumMapEntry<ValueType> const aValueTypeMap[] =
1046 { XML_FLOAT, XML_VALUE_TYPE_FLOAT },
1047 { XML_CURRENCY, XML_VALUE_TYPE_CURRENCY },
1048 { XML_PERCENTAGE, XML_VALUE_TYPE_PERCENTAGE },
1049 { XML_DATE, XML_VALUE_TYPE_DATE },
1050 { XML_TIME, XML_VALUE_TYPE_TIME },
1051 { XML_BOOLEAN, XML_VALUE_TYPE_BOOLEAN },
1052 { XML_STRING, XML_VALUE_TYPE_STRING },
1053 { XML_TOKEN_INVALID, ValueType(0) }
1056 XMLValueImportHelper::XMLValueImportHelper(
1057 SvXMLImport& rImprt,
1058 XMLTextImportHelper& rHlp,
1059 bool bType, bool bStyle, bool bValue, bool bFormula) :
1061 rImport(rImprt),
1062 rHelper(rHlp),
1064 fValue(0.0),
1065 nFormatKey(0),
1066 bIsDefaultLanguage(true),
1068 bStringType(false),
1069 bFormatOK(false),
1070 bStringValueOK(false),
1071 bFormulaOK(false),
1073 bSetType(bType),
1074 bSetValue(bValue),
1075 bSetStyle(bStyle),
1076 bSetFormula(bFormula)
1080 void XMLValueImportHelper::ProcessAttribute(
1081 sal_Int32 nAttrToken, std::string_view sAttrValue )
1083 switch (nAttrToken)
1085 case XML_ELEMENT(TEXT, XML_VALUE_TYPE): // #i32362#: src680m48++ saves text:value-type
1086 case XML_ELEMENT(OFFICE, XML_VALUE_TYPE):
1088 // convert enum
1089 ValueType eValueType = XML_VALUE_TYPE_STRING;
1090 bool bRet = SvXMLUnitConverter::convertEnum(
1091 eValueType, sAttrValue, aValueTypeMap);
1093 if (bRet) {
1094 switch (eValueType)
1096 case XML_VALUE_TYPE_STRING:
1097 bStringType = true;
1098 break;
1099 case XML_VALUE_TYPE_FLOAT:
1100 case XML_VALUE_TYPE_CURRENCY:
1101 case XML_VALUE_TYPE_PERCENTAGE:
1102 case XML_VALUE_TYPE_DATE:
1103 case XML_VALUE_TYPE_TIME:
1104 case XML_VALUE_TYPE_BOOLEAN:
1105 bStringType = false;
1106 break;
1108 default:
1109 OSL_FAIL("unknown value type");
1112 break;
1115 case XML_ELEMENT(TEXT, XML_VALUE):
1116 case XML_ELEMENT(OFFICE, XML_VALUE):
1118 double fTmp;
1119 bool const bRet = ::sax::Converter::convertDouble(fTmp,sAttrValue);
1120 if (bRet) {
1121 fValue = fTmp;
1123 break;
1126 case XML_ELEMENT(TEXT, XML_TIME_VALUE):
1127 case XML_ELEMENT(OFFICE, XML_TIME_VALUE):
1129 double fTmp;
1130 bool const bRet =
1131 ::sax::Converter::convertDuration(fTmp, sAttrValue);
1132 if (bRet) {
1133 fValue = fTmp;
1135 break;
1138 case XML_ELEMENT(TEXT, XML_DATE_VALUE):
1139 case XML_ELEMENT(OFFICE, XML_DATE_VALUE):
1141 double fTmp;
1142 bool bRet = rImport.GetMM100UnitConverter().
1143 convertDateTime(fTmp,sAttrValue);
1144 if (bRet) {
1145 fValue = fTmp;
1147 break;
1150 case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE):
1152 bool bTmp(false);
1153 bool bRet = ::sax::Converter::convertBool(bTmp, sAttrValue);
1154 if (bRet) {
1155 fValue = (bTmp ? 1.0 : 0.0);
1157 else
1159 double fTmp;
1160 bRet = ::sax::Converter::convertDouble(fTmp, sAttrValue);
1161 if (bRet) {
1162 fValue = fTmp;
1165 break;
1168 case XML_ELEMENT(TEXT, XML_STRING_VALUE):
1169 case XML_ELEMENT(OFFICE, XML_STRING_VALUE):
1170 sValue = OUString::fromUtf8(sAttrValue);
1171 bStringValueOK = true;
1172 break;
1174 case XML_ELEMENT(TEXT, XML_FORMULA):
1176 OUString sTmp;
1177 sal_uInt16 nPrefix = rImport.GetNamespaceMap().
1178 GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
1179 if( XML_NAMESPACE_OOOW == nPrefix )
1181 sFormula = sTmp;
1182 bFormulaOK = true;
1184 else
1185 sFormula = OUString::fromUtf8(sAttrValue);
1187 break;
1189 case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
1191 sal_Int32 nKey = rHelper.GetDataStyleKey(
1192 OUString::fromUtf8(sAttrValue), &bIsDefaultLanguage);
1193 if (-1 != nKey)
1195 nFormatKey = nKey;
1196 bFormatOK = true;
1198 break;
1200 default:
1201 XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
1202 } // switch
1205 void XMLValueImportHelper::PrepareField(
1206 const Reference<XPropertySet> & xPropertySet)
1208 Any aAny;
1210 if (bSetType)
1212 // ??? how to set type?
1215 if (bSetFormula)
1217 aAny <<= !bFormulaOK ? sDefault : sFormula;
1218 xPropertySet->setPropertyValue(sAPI_content, aAny);
1221 // format/style
1222 if (bSetStyle && bFormatOK)
1224 xPropertySet->setPropertyValue(sAPI_number_format, Any(nFormatKey));
1226 if( xPropertySet->getPropertySetInfo()->
1227 hasPropertyByName( "IsFixedLanguage" ) )
1229 bool bIsFixedLanguage = ! bIsDefaultLanguage;
1230 xPropertySet->setPropertyValue( "IsFixedLanguage", Any(bIsFixedLanguage) );
1234 // value: string or float
1235 if (bSetValue)
1237 if (bStringType)
1239 aAny <<= !bStringValueOK ? sDefault : sValue;
1240 xPropertySet->setPropertyValue(sAPI_content, aAny);
1242 else
1244 xPropertySet->setPropertyValue("Value", Any(fValue));
1249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */