/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/** @#file
*
* export of all variable related text fields (and database display field)
*/
#include <txtvfldi.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/txtimp.hxx>
#include <xmloff/xmlnumi.hxx>
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/nmspmap.hxx>
#include <xmloff/i18nmap.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmlement.hxx>
#include <com/sun/star/text/SetVariableType.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/text/XDependentTextField.hpp>
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#include <sax/tools/converter.hxx>
#include <rtl/ustring.hxx>
#include <osl/diagnose.h>
#include <tools/debug.hxx>
// service names
static const sal_Char sAPI_fieldmaster_prefix[] = "com.sun.star.text.FieldMaster.";
static const sal_Char sAPI_get_expression[] = "GetExpression";
static const sal_Char sAPI_set_expression[] = "SetExpression";
static const sal_Char sAPI_user[] = "User";
static const sal_Char sAPI_database[] = "com.sun.star.text.TextField.Database";
// property names
static const sal_Char sAPI_content[] = "Content";
static const sal_Char sAPI_sub_type[] = "SubType";
static const sal_Char sAPI_number_format[] = "NumberFormat";
static const sal_Char sAPI_is_visible[] = "IsVisible";
static const sal_Char sAPI_current_presentation[] = "CurrentPresentation";
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::style;
using namespace ::xmloff::token;
// XMLVarFieldImportContext: superclass for all variable related fields
XMLVarFieldImportContext::XMLVarFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
const sal_Char* pServiceName, sal_uInt16 nPrfx,
const OUString& rLocalName,
bool bFormula, bool bFormulaDefault,
bool bDescription, bool bHelp, bool bHint, bool bVisible,
bool bIsDisplayFormula,
bool bType, bool bStyle, bool bValue,
bool bPresentation) :
XMLTextFieldImportContext(rImport, rHlp, pServiceName, nPrfx, rLocalName),
aValueHelper(rImport, rHlp, bType, bStyle, bValue, false),
bDisplayFormula(false),
bDisplayNone(false),
bFormulaOK(false),
bDescriptionOK(false),
bHelpOK(false),
bHintOK(false),
bDisplayOK(false),
bSetFormula(bFormula),
bSetFormulaDefault(bFormulaDefault),
bSetDescription(bDescription),
bSetHelp(bHelp),
bSetHint(bHint),
bSetVisible(bVisible),
bSetDisplayFormula(bIsDisplayFormula),
bSetPresentation(bPresentation)
{
}
void XMLVarFieldImportContext::ProcessAttribute(
sal_uInt16 nAttrToken,
const OUString& sAttrValue )
{
switch (nAttrToken)
{
case XML_TOK_TEXTFIELD_NAME:
sName = sAttrValue;
bValid = true; // we assume: field with name is valid!
break;
case XML_TOK_TEXTFIELD_DESCRIPTION:
sDescription = sAttrValue;
bDescriptionOK = true;
break;
case XML_TOK_TEXTFIELD_HELP:
sHelp = sAttrValue;
bHelpOK = true;
break;
case XML_TOK_TEXTFIELD_HINT:
sHint = sAttrValue;
bHintOK = true;
break;
case XML_TOK_TEXTFIELD_FORMULA:
{
OUString sTmp;
sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
GetKeyByAttrName_( sAttrValue, &sTmp );
if( XML_NAMESPACE_OOOW == nPrefix )
{
sFormula = sTmp;
bFormulaOK = true;
}
else
sFormula = sAttrValue;
}
break;
case XML_TOK_TEXTFIELD_DISPLAY:
if (IsXMLToken(sAttrValue, XML_FORMULA))
{
bDisplayFormula = true;
bDisplayNone = false;
bDisplayOK = true;
}
else if (IsXMLToken(sAttrValue, XML_VALUE))
{
bDisplayFormula = false;
bDisplayNone = false;
bDisplayOK = true;
}
else if (IsXMLToken(sAttrValue, XML_NONE))
{
bDisplayFormula = false;
bDisplayNone = true;
bDisplayOK = true;
} // else: no change
DBG_ASSERT(!(bDisplayFormula && bDisplayNone),
"illegal display values");
break;
default:
// delegate all others to value helper
aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
break;
}
}
void XMLVarFieldImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
// bSetName: not implemented
if (bSetFormula)
{
if (!bFormulaOK && bSetFormulaDefault)
{
sFormula = GetContent();
bFormulaOK = true;
}
if (bFormulaOK)
{
xPropertySet->setPropertyValue(sAPI_content, Any(sFormula));
}
}
if (bSetDescription && bDescriptionOK)
{
xPropertySet->setPropertyValue("Hint", Any(sDescription));
}
if (bSetHelp && bHelpOK)
{
xPropertySet->setPropertyValue("Help", Any(sHelp));
}
if (bSetHint && bHintOK)
{
xPropertySet->setPropertyValue("Tooltip", Any(sHint));
}
if (bSetVisible && bDisplayOK)
{
bool bTmp = ! (bDisplayNone && bDisplayOK);
xPropertySet->setPropertyValue(sAPI_is_visible, Any(bTmp));
}
// workaround for #no-bug#: display formula by default
if (xPropertySet->getPropertySetInfo()->
hasPropertyByName("IsShowFormula") &&
!bSetDisplayFormula)
{
bDisplayFormula = false;
bSetDisplayFormula = true;
}
if (bSetDisplayFormula)
{
bool bTmp = bDisplayFormula && bDisplayOK;
xPropertySet->setPropertyValue("IsShowFormula", Any(bTmp));
}
// delegate to value helper
aValueHelper.SetDefault(GetContent());
aValueHelper.PrepareField(xPropertySet);
// finally, set the curren presentation
if (bSetPresentation)
{
Any aAny;
aAny <<= GetContent();
xPropertySet->setPropertyValue(sAPI_current_presentation, aAny);
}
}
// variable set fields
XMLSetVarFieldImportContext::XMLSetVarFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
const sal_Char* pServiceName, sal_uInt16 nPrfx,
const OUString& rLocalName, VarType eVarType,
bool bFormula, bool bFormulaDefault,
bool bDescription, bool bHelp, bool bHint, bool bVisible, bool bIsDisplayFormula,
bool bType, bool bStyle, bool bValue, bool bPresentation) :
XMLVarFieldImportContext(rImport, rHlp, pServiceName,
nPrfx, rLocalName,
bFormula, bFormulaDefault,
bDescription, bHelp, bHint, bVisible, bIsDisplayFormula,
bType, bStyle, bValue, bPresentation),
eFieldType(eVarType)
{
}
void XMLSetVarFieldImportContext::EndElement()
{
// should we call PrepareField on the field, or rather on it's master?
// currently: call on field (just like superclass)
// possible alternatives: call on master
// call field or master depending on variable
// PrepareMaster() in addition to PrepareField()
DBG_ASSERT(!GetServiceName().isEmpty(), "no service name for element!");
if (bValid)
{
DBG_ASSERT(!GetName().isEmpty(), "variable name needed!");
// find field master
Reference<XPropertySet> xMaster;
if (FindFieldMaster(xMaster))
{
// create field/Service
Reference<XPropertySet> xPropSet;
if (CreateField(xPropSet, "com.sun.star.text.TextField." + GetServiceName()))
{
Reference<XDependentTextField> xDepTextField(xPropSet, UNO_QUERY);
if (xDepTextField.is())
{
// attach field to field master
xDepTextField->attachTextFieldMaster(xMaster);
// attach field to document
Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
if (xTextContent.is())
{
try {
// insert, set field properties and exit!
GetImportHelper().InsertTextContent(xTextContent);
PrepareField(xPropSet);
} catch (lang::IllegalArgumentException & /*e*/)
{
// ignore e: #i54023#
};
return;
}
}
}
}
}
// above: exit on success; so for all error cases we end up here!
// write element content
GetImportHelper().InsertString(GetContent());
}
bool XMLSetVarFieldImportContext::FindFieldMaster(
Reference<XPropertySet> & xMaster)
{
// currently: delegate to XMLVariableDeclImportContext;
// should eventually go here
return XMLVariableDeclImportContext::FindFieldMaster(xMaster,
GetImport(),
GetImportHelper(),
GetName(),
eFieldType);
}
// sequence field
XMLSequenceFieldImportContext::XMLSequenceFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx, const OUString& rLocalName) :
XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
nPrfx, rLocalName, VarTypeSequence,
// formula
true, true,
false, false, false, false,
false,
false, false, false, true),
sNumFormat(OUString('1')),
sNumFormatSync(GetXMLToken(XML_FALSE)),
bRefNameOK(false)
{
}
void XMLSequenceFieldImportContext::ProcessAttribute(
sal_uInt16 nAttrToken, const OUString& sAttrValue )
{
switch (nAttrToken)
{
case XML_TOK_TEXTFIELD_NUM_FORMAT:
sNumFormat = sAttrValue;
break;
case XML_TOK_TEXTFIELD_NUM_LETTER_SYNC:
sNumFormatSync = sAttrValue;
break;
case XML_TOK_TEXTFIELD_REF_NAME:
sRefName = sAttrValue;
bRefNameOK = true;
break;
default:
// delegate to super class (name, formula)
XMLSetVarFieldImportContext::ProcessAttribute(nAttrToken,
sAttrValue);
break;
} // switch
}
void XMLSequenceFieldImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
// delegate to super class (formula)
XMLSetVarFieldImportContext::PrepareField(xPropertySet);
// set format
sal_Int16 nNumType = NumberingType::ARABIC;
GetImport().GetMM100UnitConverter().convertNumFormat( nNumType, sNumFormat, sNumFormatSync );
xPropertySet->setPropertyValue(sAPI_number_format, Any(nNumType));
// handle reference name
if (bRefNameOK)
{
Any aAny;
aAny = xPropertySet->getPropertyValue("SequenceValue");
sal_Int16 nValue = 0;
aAny >>= nValue;
GetImportHelper().InsertSequenceID(sRefName, GetName(), nValue);
}
}
// variable set field
XMLVariableSetFieldImportContext::XMLVariableSetFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx, const OUString& rLocalName) :
XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
nPrfx, rLocalName, VarTypeSimple,
// formula, value&type, style,
// display none
true, true,
false, false, false,
true, false,
true, true, true,
true)
{
}
void XMLVariableSetFieldImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
// set type
Any aAny;
aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
// the remainder is handled by super class
XMLSetVarFieldImportContext::PrepareField(xPropertySet);
}
// variable input field
XMLVariableInputFieldImportContext::XMLVariableInputFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp, sal_uInt16 nPrfx,
const OUString& rLocalName) :
XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
nPrfx, rLocalName, VarTypeSimple,
// description, display none/formula,
// value&type, style, formula
true, true,
true, true, true,
true, false,
true, true, true,
true)
{
}
void XMLVariableInputFieldImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
// set type (input field)
Any aAny;
xPropertySet->setPropertyValue("Input", Any(true));
// set type
aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
// the remainder is handled by super class
XMLSetVarFieldImportContext::PrepareField(xPropertySet);
}
// user field
XMLUserFieldImportContext::XMLUserFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx, const OUString& rLocalName) :
XMLSetVarFieldImportContext(rImport, rHlp, sAPI_user, nPrfx,
rLocalName, VarTypeUserField,
// display none/formula, style
false, false,
false, false, false, true,
true,
false, true, false,
false)
{
}
// user input field
// bug: doesn't work (SO API lacking)
XMLUserFieldInputImportContext::XMLUserFieldInputImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp, sal_uInt16 nPrfx,
const OUString& rLocalName) :
XMLVarFieldImportContext(rImport, rHlp, "InputUser",
nPrfx, rLocalName,
// description, style
false, false,
true, false, false,
false, false,
false /*???*/, true, false,
false)
{
}
void XMLUserFieldInputImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
// delegate to super class
XMLVarFieldImportContext::PrepareField(xPropertySet);
}
// variable get field
XMLVariableGetFieldImportContext::XMLVariableGetFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx, const OUString& rLocalName) :
XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
nPrfx, rLocalName,
// style, display formula
false, false,
false, false, false,
false, true,
true, true, false,
true)
{
}
void XMLVariableGetFieldImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
// set name
xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
// the remainder is handled by super class
XMLVarFieldImportContext::PrepareField(xPropertySet);
}
// expression field
XMLExpressionFieldImportContext::XMLExpressionFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx, const OUString& rLocalName) :
XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
nPrfx, rLocalName,
// formula, type, style, display formula
true, true,
false, false, false,
false, true,
true, true, false,
true)
{
bValid = true; // always valid
}
void XMLExpressionFieldImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
xPropertySet->setPropertyValue(sAPI_sub_type, Any(sal_Int16(SetVariableType::FORMULA)));
// delegate to super class
XMLVarFieldImportContext::PrepareField(xPropertySet);
}
// text input field
XMLTextInputFieldImportContext::XMLTextInputFieldImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx, const OUString& sLocalName) :
XMLVarFieldImportContext(rImport, rHlp, "Input",
nPrfx, sLocalName,
// description
false, false,
true, true, true,
false, false,
false, false, false,
false)
{
bValid = true; // always valid
}
void XMLTextInputFieldImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
XMLVarFieldImportContext::PrepareField(xPropertySet);
xPropertySet->setPropertyValue(sAPI_content, Any(GetContent()));
}
// table formula field
XMLTableFormulaImportContext::XMLTableFormulaImportContext(
SvXMLImport& rImport,
XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx,
const OUString& rLocalName) :
XMLTextFieldImportContext(rImport, rHlp, "TableFormula",
nPrfx, rLocalName),
aValueHelper(rImport, rHlp, false, true, false, true),
bIsShowFormula(false)
{
}
void XMLTableFormulaImportContext::ProcessAttribute(
sal_uInt16 nAttrToken,
const OUString& sAttrValue )
{
switch (nAttrToken)
{
case XML_TOK_TEXTFIELD_FORMULA:
aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
bValid = true; // we need a formula!
break;
case XML_TOK_TEXTFIELD_DATA_STYLE_NAME:
aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
break;
case XML_TOK_TEXTFIELD_DISPLAY:
if ( sAttrValue == "formula" )
bIsShowFormula = true;
break;
default:
// unknown attribute -> ignore
break;
}
}
void XMLTableFormulaImportContext::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
// set format and formula
aValueHelper.PrepareField( xPropertySet );
Any aAny;
// set 'show formula' and presentation
xPropertySet->setPropertyValue( "IsShowFormula", Any(bIsShowFormula) );
aAny <<= GetContent();
xPropertySet->setPropertyValue( "CurrentPresentation", aAny );
}
// variable declarations
// Should be adapted to XMLVarField-/XMLSetVarFieldImportContext scheme!
// declaration container import (<variable/user-field/sequence-decls>)
XMLVariableDeclsImportContext::XMLVariableDeclsImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp, sal_uInt16 nPrfx,
const OUString& rLocalName, enum VarType eVarType) :
SvXMLImportContext(rImport, nPrfx, rLocalName),
eVarDeclsContextType(eVarType),
rImportHelper(rHlp)
{
}
SvXMLImportContextRef XMLVariableDeclsImportContext::CreateChildContext(
sal_uInt16 nPrefix, const OUString& rLocalName,
const Reference<xml::sax::XAttributeList> & xAttrList )
{
enum XMLTokenEnum eElementName;
SvXMLImportContextRef xImportContext;
if( XML_NAMESPACE_TEXT == nPrefix )
{
switch (eVarDeclsContextType)
{
case VarTypeSequence:
eElementName = XML_SEQUENCE_DECL;
break;
case VarTypeSimple:
eElementName = XML_VARIABLE_DECL;
break;
case VarTypeUserField:
eElementName = XML_USER_FIELD_DECL;
break;
default:
OSL_FAIL("unknown field type!");
eElementName = XML_SEQUENCE_DECL;
break;
}
if( IsXMLToken( rLocalName, eElementName ) )
{
xImportContext = new XMLVariableDeclImportContext(
GetImport(), rImportHelper, nPrefix, rLocalName, xAttrList,
eVarDeclsContextType);
}
}
// if no context was created, use default context
if (!xImportContext) {
xImportContext = SvXMLImportContext::CreateChildContext(nPrefix,
rLocalName,
xAttrList);
}
return xImportContext;
}
// declaration import (<variable/user-field/sequence-decl> elements)
XMLVariableDeclImportContext::XMLVariableDeclImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp,
sal_uInt16 nPrfx, const OUString& rLocalName,
const Reference<xml::sax::XAttributeList> & xAttrList,
enum VarType eVarType) :
SvXMLImportContext(rImport, nPrfx, rLocalName),
// bug?? which properties for userfield/userfieldmaster
aValueHelper(rImport, rHlp, true, false, true, false),
cSeparationChar('.')
{
sal_Int8 nNumLevel(-1);
OUString sName;
if ( (XML_NAMESPACE_TEXT == nPrfx) &&
( ( IsXMLToken( rLocalName, XML_SEQUENCE_DECL )) ||
( IsXMLToken( rLocalName, XML_VARIABLE_DECL)) ||
( IsXMLToken( rLocalName, XML_USER_FIELD_DECL)) )) {
// TODO: check validity (need name!)
// parse attributes
sal_Int16 nLength = xAttrList->getLength();
for(sal_Int16 i=0; i<nLength; i++) {
OUString sLocalName;
sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
GetKeyByAttrName( xAttrList->getNameByIndex(i), &sLocalName );
sal_uInt16 nToken = rHlp.
GetTextFieldAttrTokenMap().Get(nPrefix, sLocalName);
switch (nToken)
{
case XML_TOK_TEXTFIELD_NAME:
sName = xAttrList->getValueByIndex(i);
break;
case XML_TOK_TEXTFIELD_NUMBERING_LEVEL:
{
sal_Int32 nLevel;
bool const bRet = ::sax::Converter::convertNumber(
nLevel, xAttrList->getValueByIndex(i), 0,
GetImport().GetTextImport()->GetChapterNumbering()->
getCount());
if (bRet)
{
nNumLevel = static_cast< sal_Int8 >( nLevel-1 ); // API numbers -1..9
}
break;
}
case XML_TOK_TEXTFIELD_NUMBERING_SEPARATOR:
cSeparationChar =
static_cast<sal_Char>(xAttrList->getValueByIndex(i).toChar());
break;
default:
// delegate to value helper
aValueHelper.ProcessAttribute(nToken,
xAttrList->getValueByIndex(i));
break;
}
}
Reference<XPropertySet> xFieldMaster;
if (FindFieldMaster(xFieldMaster, GetImport(), rHlp,
sName, eVarType))
{
// now we have a field master: process attributes!
Any aAny;
switch (eVarType)
{
case VarTypeSequence:
xFieldMaster->setPropertyValue("ChapterNumberingLevel", Any(nNumLevel));
if (nNumLevel >= 0)
{
OUString sStr(&cSeparationChar, 1);
xFieldMaster->setPropertyValue(
"NumberingSeparator", Any(sStr));
}
break;
case VarTypeSimple:
{
// set string or non-string SubType (#93192#)
// The SubType was already set in the FindFieldMaster
// method, but it needs to be adjusted if it's a string.
aAny <<= aValueHelper.IsStringValue()
? SetVariableType::STRING : SetVariableType::VAR;
xFieldMaster->setPropertyValue(sAPI_sub_type, aAny);
}
break;
case VarTypeUserField:
{
bool bTmp = !aValueHelper.IsStringValue();
xFieldMaster->setPropertyValue("IsExpression", Any(bTmp));
aValueHelper.PrepareField(xFieldMaster);
break;
}
default:
OSL_FAIL("unknown varfield type");
} // switch
} // else: no field master found/constructed
} // else: no sequence-decl
}
bool XMLVariableDeclImportContext::FindFieldMaster(
Reference<XPropertySet> & xMaster, SvXMLImport& rImport,
XMLTextImportHelper& rImportHelper,
const OUString& sVarName, enum VarType eVarType)
{
static sal_Int32 nCollisionCount = 0;
// rename field
// currently: no family in use! Use 0.
OUString sName = rImportHelper.GetRenameMap().Get(
sal::static_int_cast< sal_uInt16 >(eVarType), sVarName);
// get text fields supplier and field masters
Reference<XTextFieldsSupplier> xTextFieldsSupp(rImport.GetModel(),
UNO_QUERY);
Reference<container::XNameAccess> xFieldMasterNameAccess(
xTextFieldsSupp->getTextFieldMasters(), UNO_QUERY);
OUStringBuffer sBuffer;
sBuffer.append(sAPI_fieldmaster_prefix);
sBuffer.append(sAPI_set_expression);
sBuffer.append(".");
sBuffer.append(sName);
OUString sVarServiceName = sBuffer.makeStringAndClear();
sBuffer.append(sAPI_fieldmaster_prefix);
sBuffer.append(sAPI_user);
sBuffer.append(".");
sBuffer.append(sName);
OUString sUserServiceName = sBuffer.makeStringAndClear();
if (xFieldMasterNameAccess->hasByName(sVarServiceName)) {
// variable field master already in document
Any aAny = xFieldMasterNameAccess->getByName(sVarServiceName);
aAny >>= xMaster;
aAny = xMaster->getPropertyValue(sAPI_sub_type);
sal_Int16 nType = 0;
aAny >>= nType;
enum VarType eFMVarType =
(SetVariableType::SEQUENCE == nType) ?
VarTypeSequence : VarTypeSimple;
if (eFMVarType != eVarType)
{
OUString sNew;
// FIXME! can't find if name is taken already!!!!
nCollisionCount++;
OUStringBuffer aBuf;
aBuf.append(sName);
aBuf.append("_renamed_");
aBuf.append(nCollisionCount);
sNew = aBuf.makeStringAndClear();
rImportHelper.GetRenameMap().Add(
sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
// call FindFieldMaster recursively to create new master
return FindFieldMaster(xMaster, rImport, rImportHelper,
sNew, eVarType);
}
} else if (xFieldMasterNameAccess->hasByName(sUserServiceName)) {
// user field: get field master
Any aAny = xFieldMasterNameAccess->getByName(sUserServiceName);
aAny >>= xMaster;
if (VarTypeUserField != eVarType) {
// find new name that is not taken
OUString sNew;
// FIXME! can't find if name is taken already!!!!
nCollisionCount++;
OUStringBuffer aBuf;
aBuf.append(sName);
aBuf.append("_renamed_");
aBuf.append(nCollisionCount);
sNew = aBuf.makeStringAndClear();
rImportHelper.GetRenameMap().Add(
sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
// call FindFieldMaster recursively to create new master
return FindFieldMaster(xMaster, rImport, rImportHelper,
sNew, eVarType);
}
} else {
// field name not used: create field master
// import -> model is MultiServiceFactory -> createInstance
Reference<lang::XMultiServiceFactory>
xFactory(rImport.GetModel(),UNO_QUERY);
if( xFactory.is() ) {
OUStringBuffer sService;
sService.append(sAPI_fieldmaster_prefix);
sService.appendAscii((eVarType==VarTypeUserField) ?
sAPI_user : sAPI_set_expression);
Reference<XInterface> xIfc =
xFactory->createInstance( sService.makeStringAndClear() );
if (xIfc.is()) {
Reference<XPropertySet> xTmp( xIfc, UNO_QUERY );
xMaster = xTmp;
// set name
xMaster->setPropertyValue("Name", Any(sName));
if (eVarType != VarTypeUserField) {
// set subtype for setexp field
Any aAny;
aAny <<= ((eVarType == VarTypeSimple) ?
SetVariableType::VAR :
SetVariableType::SEQUENCE);
xMaster->setPropertyValue(sAPI_sub_type, aAny);
} // else : user field: no subtype
} else {
return false;
}
} else {
return false;
}
}
DBG_ASSERT(xMaster.is(), "no field master found!?!");
return true;
}
// Database Display field import
XMLDatabaseDisplayImportContext::XMLDatabaseDisplayImportContext(
SvXMLImport& rImport, XMLTextImportHelper& rHlp, sal_uInt16 nPrfx,
const OUString& rLocalName) :
XMLDatabaseFieldImportContext(rImport, rHlp, sAPI_database,
nPrfx, rLocalName, false),
aValueHelper(rImport, rHlp, false, true, false, false),
bColumnOK(false),
bDisplay( true ),
bDisplayOK( false )
{
}
void XMLDatabaseDisplayImportContext::ProcessAttribute(
sal_uInt16 nAttrToken, const OUString& sAttrValue )
{
switch (nAttrToken)
{
case XML_TOK_TEXTFIELD_COLUMN_NAME:
sColumnName = sAttrValue;
bColumnOK = true;
break;
case XML_TOK_TEXTFIELD_DISPLAY:
{
bool bNone = IsXMLToken( sAttrValue, XML_NONE );
bool bValue = IsXMLToken( sAttrValue, XML_VALUE );
bDisplay = bValue;
bDisplayOK = bNone || bValue;
}
break;
case XML_TOK_TEXTFIELD_DATABASE_NAME:
case XML_TOK_TEXTFIELD_TABLE_NAME:
case XML_TOK_TEXTFIELD_TABLE_TYPE:
// handled by super class
XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken,
sAttrValue);
break;
default:
// remainder handled by value helper
aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
break;
}
bValid = bTableOK && bDatabaseOK && bColumnOK;
}
void XMLDatabaseDisplayImportContext::EndElement()
{
// we have an EndElement of our own, because database fields need
// to be attached to a field master before they can be inserted into
// the document. Database stuff (database, table, column) all goes
// to the field master, value & style go to the field.
if (bValid)
{
// so here goes: we start with the master
Reference<XPropertySet> xMaster;
// create and prepare field master first
if (CreateField(xMaster,
"com.sun.star.text.FieldMaster.Database"))
{
Any aAny;
xMaster->setPropertyValue("DataColumnName", Any(sColumnName));
// fieldmaster takes database, table and column name
XMLDatabaseFieldImportContext::PrepareField(xMaster);
// create field
Reference<XPropertySet> xField;
if (CreateField(xField,
sAPI_database))
{
// attach field master
Reference<XDependentTextField> xDepField(xField, UNO_QUERY);
if (xDepField.is())
{
// attach field to field master
xDepField->attachTextFieldMaster(xMaster);
// attach field to document
Reference<XTextContent> xTextContent(xField, UNO_QUERY);
if (xTextContent.is())
{
// insert, set field properties and exit!
GetImportHelper().InsertTextContent(xTextContent);
// prepare field: format from database?
bool bTmp = !aValueHelper.IsFormatOK();
xField->setPropertyValue("DataBaseFormat", Any(bTmp));
// value, value-type and format done by value helper
aValueHelper.PrepareField(xField);
// visibility
if( bDisplayOK )
{
xField->setPropertyValue(sAPI_is_visible, Any(bDisplay));
}
// set presentation
aAny <<= GetContent();
xField->setPropertyValue(sAPI_current_presentation, aAny);
// success!
return;
}
}
}
}
}
// above: exit on success; so for all error cases we end up here!
// write element content
GetImportHelper().InsertString(GetContent());
}
// value import helper
enum ValueType
{
XML_VALUE_TYPE_STRING,
XML_VALUE_TYPE_FLOAT,
XML_VALUE_TYPE_CURRENCY,
XML_VALUE_TYPE_PERCENTAGE,
XML_VALUE_TYPE_DATE,
XML_VALUE_TYPE_TIME,
XML_VALUE_TYPE_BOOLEAN
};
static SvXMLEnumMapEntry<ValueType> const aValueTypeMap[] =
{
{ XML_FLOAT, XML_VALUE_TYPE_FLOAT },
{ XML_CURRENCY, XML_VALUE_TYPE_CURRENCY },
{ XML_PERCENTAGE, XML_VALUE_TYPE_PERCENTAGE },
{ XML_DATE, XML_VALUE_TYPE_DATE },
{ XML_TIME, XML_VALUE_TYPE_TIME },
{ XML_BOOLEAN, XML_VALUE_TYPE_BOOLEAN },
{ XML_STRING, XML_VALUE_TYPE_STRING },
{ XML_TOKEN_INVALID, ValueType(0) }
};
XMLValueImportHelper::XMLValueImportHelper(
SvXMLImport& rImprt,
XMLTextImportHelper& rHlp,
bool bType, bool bStyle, bool bValue, bool bFormula) :
rImport(rImprt),
rHelper(rHlp),
fValue(0.0),
nFormatKey(0),
bIsDefaultLanguage(true),
bStringType(false),
bFormatOK(false),
bStringValueOK(false),
bFormulaOK(false),
bSetType(bType),
bSetValue(bValue),
bSetStyle(bStyle),
bSetFormula(bFormula)
{
}
void XMLValueImportHelper::ProcessAttribute(
sal_uInt16 nAttrToken, const OUString& sAttrValue )
{
switch (nAttrToken)
{
case XML_TOK_TEXTFIELD_VALUE_TYPE:
{
// convert enum
ValueType eValueType = XML_VALUE_TYPE_STRING;
bool bRet = SvXMLUnitConverter::convertEnum(
eValueType, sAttrValue, aValueTypeMap);
if (bRet) {
switch (eValueType)
{
case XML_VALUE_TYPE_STRING:
bStringType = true;
break;
case XML_VALUE_TYPE_FLOAT:
case XML_VALUE_TYPE_CURRENCY:
case XML_VALUE_TYPE_PERCENTAGE:
case XML_VALUE_TYPE_DATE:
case XML_VALUE_TYPE_TIME:
case XML_VALUE_TYPE_BOOLEAN:
bStringType = false;
break;
default:
OSL_FAIL("unknown value type");
}
}
break;
}
case XML_TOK_TEXTFIELD_VALUE:
{
double fTmp;
bool const bRet = ::sax::Converter::convertDouble(fTmp,sAttrValue);
if (bRet) {
fValue = fTmp;
}
break;
}
case XML_TOK_TEXTFIELD_TIME_VALUE:
{
double fTmp;
bool const bRet =
::sax::Converter::convertDuration(fTmp, sAttrValue);
if (bRet) {
fValue = fTmp;
}
break;
}
case XML_TOK_TEXTFIELD_DATE_VALUE:
{
double fTmp;
bool bRet = rImport.GetMM100UnitConverter().
convertDateTime(fTmp,sAttrValue);
if (bRet) {
fValue = fTmp;
}
break;
}
case XML_TOK_TEXTFIELD_BOOL_VALUE:
{
bool bTmp(false);
bool bRet = ::sax::Converter::convertBool(bTmp, sAttrValue);
if (bRet) {
fValue = (bTmp ? 1.0 : 0.0);
}
else
{
double fTmp;
bRet = ::sax::Converter::convertDouble(fTmp, sAttrValue);
if (bRet) {
fValue = fTmp;
}
}
break;
}
case XML_TOK_TEXTFIELD_STRING_VALUE:
sValue = sAttrValue;
bStringValueOK = true;
break;
case XML_TOK_TEXTFIELD_FORMULA:
{
OUString sTmp;
sal_uInt16 nPrefix = rImport.GetNamespaceMap().
GetKeyByAttrName_( sAttrValue, &sTmp );
if( XML_NAMESPACE_OOOW == nPrefix )
{
sFormula = sTmp;
bFormulaOK = true;
}
else
sFormula = sAttrValue;
}
break;
case XML_TOK_TEXTFIELD_DATA_STYLE_NAME:
{
sal_Int32 nKey = rHelper.GetDataStyleKey(
sAttrValue, &bIsDefaultLanguage);
if (-1 != nKey)
{
nFormatKey = nKey;
bFormatOK = true;
}
break;
}
} // switch
}
void XMLValueImportHelper::PrepareField(
const Reference<XPropertySet> & xPropertySet)
{
Any aAny;
if (bSetType)
{
// ??? how to set type?
}
if (bSetFormula)
{
aAny <<= !bFormulaOK ? sDefault : sFormula;
xPropertySet->setPropertyValue(sAPI_content, aAny);
}
// format/style
if (bSetStyle && bFormatOK)
{
xPropertySet->setPropertyValue(sAPI_number_format, Any(nFormatKey));
if( xPropertySet->getPropertySetInfo()->
hasPropertyByName( "IsFixedLanguage" ) )
{
bool bIsFixedLanguage = ! bIsDefaultLanguage;
xPropertySet->setPropertyValue( "IsFixedLanguage", Any(bIsFixedLanguage) );
}
}
// value: string or float
if (bSetValue)
{
if (bStringType)
{
aAny <<= !bStringValueOK ? sDefault : sValue;
xPropertySet->setPropertyValue(sAPI_content, aAny);
}
else
{
xPropertySet->setPropertyValue("Value", Any(fValue));
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V560 A part of conditional expression is always true: bDisplayOK.
↑ V519 The 'aAny' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 848, 850.