1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <tools/debug.hxx>
21 #include <i18nlangtag/languagetag.hxx>
23 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
24 #include <com/sun/star/linguistic2/ConversionPropertyType.hpp>
25 #include <com/sun/star/lang/Locale.hpp>
26 #include <com/sun/star/uno/Reference.h>
27 #include <com/sun/star/document/XFilter.hpp>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #include <xmloff/namespacemap.hxx>
30 #include <xmloff/xmlnamespace.hxx>
31 #include <unotools/streamwrap.hxx>
33 #include "convdic.hxx"
34 #include "convdicxml.hxx"
35 #include <linguistic/misc.hxx>
38 using namespace com::sun::star
;
39 using namespace com::sun::star::lang
;
40 using namespace com::sun::star::uno
;
41 using namespace com::sun::star::linguistic2
;
42 using namespace linguistic
;
45 constexpr OUStringLiteral XML_NAMESPACE_TCD_STRING
= u
"http://openoffice.org/2003/text-conversion-dictionary";
46 constexpr OUStringLiteral CONV_TYPE_HANGUL_HANJA
= u
"Hangul / Hanja";
47 constexpr OUStringLiteral CONV_TYPE_SCHINESE_TCHINESE
= u
"Chinese simplified / Chinese traditional";
50 static OUString
ConversionTypeToText( sal_Int16 nConversionType
)
53 if (nConversionType
== ConversionDictionaryType::HANGUL_HANJA
)
54 aRes
= CONV_TYPE_HANGUL_HANJA
;
55 else if (nConversionType
== ConversionDictionaryType::SCHINESE_TCHINESE
)
56 aRes
= CONV_TYPE_SCHINESE_TCHINESE
;
60 static sal_Int16
GetConversionTypeFromText( std::u16string_view rText
)
63 if (rText
== CONV_TYPE_HANGUL_HANJA
)
64 nRes
= ConversionDictionaryType::HANGUL_HANJA
;
65 else if (rText
== CONV_TYPE_SCHINESE_TCHINESE
)
66 nRes
= ConversionDictionaryType::SCHINESE_TCHINESE
;
72 class ConvDicXMLImportContext
:
73 public SvXMLImportContext
76 ConvDicXMLImportContext( ConvDicXMLImport
&rImport
) :
77 SvXMLImportContext( rImport
)
81 ConvDicXMLImport
& GetConvDicImport()
83 return static_cast<ConvDicXMLImport
&>(GetImport());
87 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
88 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
92 class ConvDicXMLDictionaryContext_Impl
:
93 public ConvDicXMLImportContext
95 LanguageType nLanguage
;
96 sal_Int16 nConversionType
;
99 ConvDicXMLDictionaryContext_Impl( ConvDicXMLImport
&rImport
) :
100 ConvDicXMLImportContext( rImport
),
101 nLanguage(LANGUAGE_NONE
), nConversionType(-1)
105 // SvXMLImportContext
106 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& Attribs
) override
;
107 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
108 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
112 class ConvDicXMLEntryTextContext_Impl
:
113 public ConvDicXMLImportContext
118 ConvDicXMLEntryTextContext_Impl( ConvDicXMLImport
&rImport
) :
119 ConvDicXMLImportContext( rImport
)
123 // SvXMLImportContext
124 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& Attribs
) override
;
125 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
126 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
128 const OUString
& GetLeftText() const { return aLeftText
; }
132 class ConvDicXMLRightTextContext_Impl
:
133 public ConvDicXMLImportContext
136 ConvDicXMLEntryTextContext_Impl
&rEntryContext
;
139 ConvDicXMLRightTextContext_Impl(
140 ConvDicXMLImport
&rImport
,
141 ConvDicXMLEntryTextContext_Impl
&rParentContext
) :
142 ConvDicXMLImportContext( rImport
),
143 rEntryContext( rParentContext
)
147 // SvXMLImportContext
148 virtual void SAL_CALL
endFastElement( sal_Int32 nElement
) override
;
149 virtual void SAL_CALL
characters( const OUString
&rChars
) override
;
154 //void ConvDicXMLImportContext::characters(const OUString & /*rChars*/)
157 Whitespace occurring within the content of token elements is "trimmed"
158 from the ends (i.e. all whitespace at the beginning and end of the
159 content is removed), and "collapsed" internally (i.e. each sequence of
160 1 or more whitespace characters is replaced with one blank character).
162 //collapsing not done yet!
166 css::uno::Reference
<XFastContextHandler
> ConvDicXMLImportContext::createFastChildContext(
168 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
170 if ( Element
== ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY
)
171 return new ConvDicXMLDictionaryContext_Impl( GetConvDicImport() );
176 void ConvDicXMLDictionaryContext_Impl::startFastElement( sal_Int32
/*nElement*/,
177 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& rxAttrList
)
179 for (auto &aIter
: sax_fastparser::castToFastAttributeList( rxAttrList
))
181 switch (aIter
.getToken())
183 case XML_NAMESPACE_TCD
| XML_LANG
:
184 nLanguage
= LanguageTag::convertToLanguageType( aIter
.toString() );
186 case XML_NAMESPACE_TCD
| XML_CONVERSION_TYPE
:
187 nConversionType
= GetConversionTypeFromText( aIter
.toString() );
193 GetConvDicImport().SetLanguage( nLanguage
);
194 GetConvDicImport().SetConversionType( nConversionType
);
198 css::uno::Reference
<XFastContextHandler
> ConvDicXMLDictionaryContext_Impl::createFastChildContext(
200 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
202 if ( Element
== ConvDicXMLToken::ENTRY
)
203 return new ConvDicXMLEntryTextContext_Impl( GetConvDicImport() );
207 css::uno::Reference
<XFastContextHandler
> ConvDicXMLEntryTextContext_Impl::createFastChildContext(
209 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
211 if ( Element
== ConvDicXMLToken::RIGHT_TEXT
)
212 return new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), *this );
216 void ConvDicXMLEntryTextContext_Impl::startFastElement(
217 sal_Int32
/*Element*/,
218 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& rxAttrList
)
220 for (auto &aIter
: sax_fastparser::castToFastAttributeList( rxAttrList
))
222 switch (aIter
.getToken())
224 case XML_NAMESPACE_TCD
| XML_LEFT_TEXT
:
225 aLeftText
= aIter
.toString();
234 void ConvDicXMLRightTextContext_Impl::characters( const OUString
&rChars
)
236 aRightText
+= rChars
;
239 void ConvDicXMLRightTextContext_Impl::endFastElement( sal_Int32
/*nElement*/ )
241 ConvDic
*pDic
= GetConvDicImport().GetDic();
243 pDic
->AddEntry( rEntryContext
.GetLeftText(), aRightText
);
247 bool ConvDicXMLExport::Export()
249 uno::Reference
< document::XExporter
> xExporter( this );
250 uno::Reference
< document::XFilter
> xFilter( xExporter
, UNO_QUERY
);
251 xFilter
->filter( {} ); // calls exportDoc implicitly
257 ErrCode
ConvDicXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum
/*eClass*/ )
259 GetNamespaceMap_().Add( "tcd",
260 XML_NAMESPACE_TCD_STRING
, XML_NAMESPACE_TCD
);
262 GetDocHandler()->startDocument();
264 // Add xmlns line and some other arguments
265 AddAttribute( GetNamespaceMap_().GetAttrNameByKey( XML_NAMESPACE_TCD
),
266 GetNamespaceMap_().GetNameByKey( XML_NAMESPACE_TCD
) );
267 AddAttribute( XML_NAMESPACE_TCD
, "package", "org.openoffice.Office" );
269 OUString
aIsoLang( LanguageTag::convertToBcp47( rDic
.nLanguage
) );
270 AddAttribute( XML_NAMESPACE_TCD
, "lang", aIsoLang
);
271 OUString
aConvType( ConversionTypeToText( rDic
.nConversionType
) );
272 AddAttribute( XML_NAMESPACE_TCD
, "conversion-type", aConvType
);
274 //!! block necessary in order to have SvXMLElementExport d-tor called
275 //!! before the call to endDocument
277 SvXMLElementExport
aRoot( *this, XML_NAMESPACE_TCD
, "text-conversion-dictionary", true, true );
281 GetDocHandler()->endDocument();
288 void ConvDicXMLExport::ExportContent_()
290 // acquire sorted list of all keys
291 std::set
<OUString
> aKeySet
;
292 for (auto const& elem
: rDic
.aFromLeft
)
293 aKeySet
.insert( elem
.first
);
295 for (const OUString
& aLeftText
: aKeySet
)
297 AddAttribute( XML_NAMESPACE_TCD
, "left-text", aLeftText
);
298 if (rDic
.pConvPropType
) // property-type list available?
300 sal_Int16 nPropertyType
= -1;
301 PropTypeMap::iterator aIt2
= rDic
.pConvPropType
->find( aLeftText
);
302 if (aIt2
!= rDic
.pConvPropType
->end())
303 nPropertyType
= (*aIt2
).second
;
304 DBG_ASSERT( nPropertyType
, "property-type not found" );
305 if (nPropertyType
== -1)
306 nPropertyType
= ConversionPropertyType::NOT_DEFINED
;
307 AddAttribute( XML_NAMESPACE_TCD
, "property-type", OUString::number( nPropertyType
) );
309 SvXMLElementExport
aEntryMain( *this, XML_NAMESPACE_TCD
,
310 "entry" , true, true );
312 std::pair
< ConvMap::iterator
, ConvMap::iterator
> aRange
=
313 rDic
.aFromLeft
.equal_range(aLeftText
);
314 for (auto aIt
= aRange
.first
; aIt
!= aRange
.second
; ++aIt
)
316 DBG_ASSERT( aLeftText
== (*aIt
).first
, "key <-> entry mismatch" );
317 OUString
aRightText( (*aIt
).second
);
318 SvXMLElementExport
aEntryRightText( *this, XML_NAMESPACE_TCD
,
319 "right-text" , true, false );
320 Characters( aRightText
);
325 //!! see comment for pDic member
326 ConvDicXMLImport::ConvDicXMLImport( ConvDic
*pConvDic
) :
327 SvXMLImport ( comphelper::getProcessComponentContext(), "com.sun.star.lingu2.ConvDicXMLImport", SvXMLImportFlags::ALL
),
328 pDic ( pConvDic
), nLanguage(LANGUAGE_NONE
), nConversionType(-1)
330 GetNamespaceMap().Add( GetXMLToken(XML_NP_TCD
), GetXMLToken(XML_N_TCD
), XML_NAMESPACE_TCD
);
333 SvXMLImportContext
* ConvDicXMLImport::CreateFastContext(
335 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
337 if( Element
== ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY
)
338 return new ConvDicXMLDictionaryContext_Impl( *this );
342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */