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/nmspmap.hxx>
30 #include <xmloff/xmlnmspe.hxx>
31 #include <unotools/streamwrap.hxx>
33 #include "convdic.hxx"
34 #include "convdicxml.hxx"
35 #include <linguistic/misc.hxx>
39 using namespace com::sun::star
;
40 using namespace com::sun::star::lang
;
41 using namespace com::sun::star::uno
;
42 using namespace com::sun::star::linguistic2
;
43 using namespace linguistic
;
46 #define XML_NAMESPACE_TCD_STRING "http://openoffice.org/2003/text-conversion-dictionary"
47 #define CONV_TYPE_HANGUL_HANJA "Hangul / Hanja"
48 #define CONV_TYPE_SCHINESE_TCHINESE "Chinese simplified / Chinese traditional"
51 static OUString
ConversionTypeToText( sal_Int16 nConversionType
)
54 if (nConversionType
== ConversionDictionaryType::HANGUL_HANJA
)
55 aRes
= CONV_TYPE_HANGUL_HANJA
;
56 else if (nConversionType
== ConversionDictionaryType::SCHINESE_TCHINESE
)
57 aRes
= CONV_TYPE_SCHINESE_TCHINESE
;
61 static sal_Int16
GetConversionTypeFromText( const OUString
&rText
)
64 if (rText
== CONV_TYPE_HANGUL_HANJA
)
65 nRes
= ConversionDictionaryType::HANGUL_HANJA
;
66 else if (rText
== CONV_TYPE_SCHINESE_TCHINESE
)
67 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 void Characters( const OUString
&rChars
) override
;
88 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
89 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
93 class ConvDicXMLDictionaryContext_Impl
:
94 public ConvDicXMLImportContext
96 LanguageType nLanguage
;
97 sal_Int16 nConversionType
;
100 ConvDicXMLDictionaryContext_Impl( ConvDicXMLImport
&rImport
) :
101 ConvDicXMLImportContext( rImport
)
103 nLanguage
= LANGUAGE_NONE
;
104 nConversionType
= -1;
107 // SvXMLImportContext
108 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& Attribs
) override
;
109 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
110 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
114 class ConvDicXMLEntryTextContext_Impl
:
115 public ConvDicXMLImportContext
120 ConvDicXMLEntryTextContext_Impl( ConvDicXMLImport
&rImport
) :
121 ConvDicXMLImportContext( rImport
)
125 // SvXMLImportContext
126 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& Attribs
) override
;
127 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
128 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
130 const OUString
& GetLeftText() const { return aLeftText
; }
134 class ConvDicXMLRightTextContext_Impl
:
135 public ConvDicXMLImportContext
138 ConvDicXMLEntryTextContext_Impl
&rEntryContext
;
141 ConvDicXMLRightTextContext_Impl(
142 ConvDicXMLImport
&rImport
,
143 ConvDicXMLEntryTextContext_Impl
&rParentContext
) :
144 ConvDicXMLImportContext( rImport
),
145 rEntryContext( rParentContext
)
149 // SvXMLImportContext
150 virtual void SAL_CALL
endFastElement( sal_Int32 nElement
) override
;
151 virtual void Characters( const OUString
&rChars
) override
;
153 const OUString
& GetRightText() const { return aRightText
; }
154 const OUString
& GetLeftText() const { return rEntryContext
.GetLeftText(); }
158 void ConvDicXMLImportContext::Characters(const OUString
& /*rChars*/)
161 Whitespace occurring within the content of token elements is "trimmed"
162 from the ends (i.e. all whitespace at the beginning and end of the
163 content is removed), and "collapsed" internally (i.e. each sequence of
164 1 or more whitespace characters is replaced with one blank character).
166 //collapsing not done yet!
170 css::uno::Reference
<XFastContextHandler
> ConvDicXMLImportContext::createFastChildContext(
172 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
174 if ( Element
== ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY
)
175 return new ConvDicXMLDictionaryContext_Impl( GetConvDicImport() );
177 return new SvXMLImportContext( GetImport() );
181 void ConvDicXMLDictionaryContext_Impl::startFastElement( sal_Int32
/*nElement*/,
182 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& rxAttrList
)
184 if ( rxAttrList
.is() )
186 sax_fastparser::FastAttributeList
*pAttribList
=
187 sax_fastparser::FastAttributeList::castToFastAttributeList( rxAttrList
);
189 for (auto &aIter
: *pAttribList
)
191 switch (aIter
.getToken())
193 case XML_NAMESPACE_TCD
| XML_LANG
:
194 nLanguage
= LanguageTag::convertToLanguageType( aIter
.toString() );
196 case XML_NAMESPACE_TCD
| XML_CONVERSION_TYPE
:
197 nConversionType
= GetConversionTypeFromText( aIter
.toString() );
204 GetConvDicImport().SetLanguage( nLanguage
);
205 GetConvDicImport().SetConversionType( nConversionType
);
209 css::uno::Reference
<XFastContextHandler
> ConvDicXMLDictionaryContext_Impl::createFastChildContext(
211 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
213 if ( Element
== ConvDicXMLToken::ENTRY
)
214 return new ConvDicXMLEntryTextContext_Impl( GetConvDicImport() );
216 return new SvXMLImportContext(GetImport());
219 css::uno::Reference
<XFastContextHandler
> ConvDicXMLEntryTextContext_Impl::createFastChildContext(
221 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
223 if ( Element
== ConvDicXMLToken::RIGHT_TEXT
)
224 return new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), *this );
226 return new SvXMLImportContext(GetImport());
229 void ConvDicXMLEntryTextContext_Impl::startFastElement(
230 sal_Int32
/*Element*/,
231 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& rxAttrList
)
233 if ( rxAttrList
.is() )
235 sax_fastparser::FastAttributeList
*pAttribList
=
236 sax_fastparser::FastAttributeList::castToFastAttributeList( rxAttrList
);
238 for (auto &aIter
: *pAttribList
)
240 switch (aIter
.getToken())
242 case XML_NAMESPACE_TCD
| XML_LEFT_TEXT
:
243 aLeftText
= aIter
.toString();
253 void ConvDicXMLRightTextContext_Impl::Characters( const OUString
&rChars
)
255 aRightText
+= rChars
;
258 void ConvDicXMLRightTextContext_Impl::endFastElement( sal_Int32
/*nElement*/ )
260 ConvDic
*pDic
= GetConvDicImport().GetDic();
262 pDic
->AddEntry( GetLeftText(), GetRightText() );
266 bool ConvDicXMLExport::Export()
268 uno::Reference
< document::XExporter
> xExporter( this );
269 uno::Reference
< document::XFilter
> xFilter( xExporter
, UNO_QUERY
);
270 uno::Sequence
< beans::PropertyValue
> aProps(0);
271 xFilter
->filter( aProps
); // calls exportDoc implicitly
277 ErrCode
ConvDicXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum
/*eClass*/ )
279 GetNamespaceMap_().Add( "tcd",
280 XML_NAMESPACE_TCD_STRING
, XML_NAMESPACE_TCD
);
282 GetDocHandler()->startDocument();
284 // Add xmlns line and some other arguments
285 AddAttribute( GetNamespaceMap_().GetAttrNameByKey( XML_NAMESPACE_TCD
),
286 GetNamespaceMap_().GetNameByKey( XML_NAMESPACE_TCD
) );
287 AddAttributeASCII( XML_NAMESPACE_TCD
, "package", "org.openoffice.Office" );
289 OUString
aIsoLang( LanguageTag::convertToBcp47( rDic
.nLanguage
) );
290 AddAttribute( XML_NAMESPACE_TCD
, "lang", aIsoLang
);
291 OUString
aConvType( ConversionTypeToText( rDic
.nConversionType
) );
292 AddAttribute( XML_NAMESPACE_TCD
, "conversion-type", aConvType
);
294 //!! block necessary in order to have SvXMLElementExport d-tor called
295 //!! before the call to endDocument
297 SvXMLElementExport
aRoot( *this, XML_NAMESPACE_TCD
, "text-conversion-dictionary", true, true );
301 GetDocHandler()->endDocument();
308 void ConvDicXMLExport::ExportContent_()
310 // acquire sorted list of all keys
311 ConvMapKeySet aKeySet
;
312 for (auto const& elem
: rDic
.aFromLeft
)
313 aKeySet
.insert( elem
.first
);
315 for (const OUString
& aLeftText
: aKeySet
)
317 AddAttribute( XML_NAMESPACE_TCD
, "left-text", aLeftText
);
318 if (rDic
.pConvPropType
) // property-type list available?
320 sal_Int16 nPropertyType
= -1;
321 PropTypeMap::iterator aIt2
= rDic
.pConvPropType
->find( aLeftText
);
322 if (aIt2
!= rDic
.pConvPropType
->end())
323 nPropertyType
= (*aIt2
).second
;
324 DBG_ASSERT( nPropertyType
, "property-type not found" );
325 if (nPropertyType
== -1)
326 nPropertyType
= ConversionPropertyType::NOT_DEFINED
;
327 AddAttribute( XML_NAMESPACE_TCD
, "property-type", OUString::number( nPropertyType
) );
329 SvXMLElementExport
aEntryMain( *this, XML_NAMESPACE_TCD
,
330 "entry" , true, true );
332 pair
< ConvMap::iterator
, ConvMap::iterator
> aRange
=
333 rDic
.aFromLeft
.equal_range(aLeftText
);
334 for (auto aIt
= aRange
.first
; aIt
!= aRange
.second
; ++aIt
)
336 DBG_ASSERT( aLeftText
== (*aIt
).first
, "key <-> entry mismatch" );
337 OUString
aRightText( (*aIt
).second
);
338 SvXMLElementExport
aEntryRightText( *this, XML_NAMESPACE_TCD
,
339 "right-text" , true, false );
340 Characters( aRightText
);
345 //!! see comment for pDic member
346 ConvDicXMLImport::ConvDicXMLImport( ConvDic
*pConvDic
) :
347 SvXMLImport ( comphelper::getProcessComponentContext(), "com.sun.star.lingu2.ConvDicXMLImport", SvXMLImportFlags::ALL
),
350 nLanguage
= LANGUAGE_NONE
;
351 nConversionType
= -1;
352 GetNamespaceMap().Add( GetXMLToken(XML_NP_TCD
), GetXMLToken(XML_N_TCD
), XML_NAMESPACE_TCD
);
355 SvXMLImportContext
* ConvDicXMLImport::CreateFastContext(
357 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
)
359 if( Element
== ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY
)
360 return new ConvDicXMLDictionaryContext_Impl( *this );
362 return SvXMLImport::CreateFastContext( Element
, xAttrList
);
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */