Line data Source code
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 : #include <tools/debug.hxx>
21 : #include <tools/fsys.hxx>
22 : #include <tools/string.hxx>
23 : #include <i18npool/languagetag.hxx>
24 : #include <tools/stream.hxx>
25 : #include <osl/mutex.hxx>
26 : #include <ucbhelper/content.hxx>
27 :
28 : #include <cppuhelper/factory.hxx> // helper for factories
29 : #include <com/sun/star/linguistic2/XConversionDictionary.hpp>
30 : #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
31 : #include <com/sun/star/linguistic2/ConversionPropertyType.hpp>
32 : #include <com/sun/star/util/XFlushable.hpp>
33 : #include <com/sun/star/lang/Locale.hpp>
34 : #include <com/sun/star/lang/EventObject.hpp>
35 : #include <com/sun/star/uno/Reference.h>
36 : #include <com/sun/star/registry/XRegistryKey.hpp>
37 : #include <com/sun/star/util/XFlushListener.hpp>
38 : #include <com/sun/star/io/XActiveDataSource.hpp>
39 : #include <com/sun/star/document/XFilter.hpp>
40 : #include <com/sun/star/beans/PropertyValue.hpp>
41 : #include <xmloff/nmspmap.hxx>
42 : #include <xmloff/xmlnmspe.hxx>
43 : #include <unotools/streamwrap.hxx>
44 :
45 : #include "convdic.hxx"
46 : #include "convdicxml.hxx"
47 : #include "linguistic/misc.hxx"
48 : #include "defs.hxx"
49 :
50 : using namespace std;
51 : using namespace utl;
52 : using namespace osl;
53 : using namespace com::sun::star;
54 : using namespace com::sun::star::lang;
55 : using namespace com::sun::star::uno;
56 : using namespace com::sun::star::linguistic2;
57 : using namespace linguistic;
58 :
59 : using ::rtl::OUString;
60 :
61 : #define XML_NAMESPACE_TCD_STRING "http://openoffice.org/2003/text-conversion-dictionary"
62 : #define CONV_TYPE_HANGUL_HANJA "Hangul / Hanja"
63 : #define CONV_TYPE_SCHINESE_TCHINESE "Chinese simplified / Chinese traditional"
64 :
65 :
66 0 : static const OUString ConversionTypeToText( sal_Int16 nConversionType )
67 : {
68 0 : OUString aRes;
69 0 : if (nConversionType == ConversionDictionaryType::HANGUL_HANJA)
70 0 : aRes = A2OU( CONV_TYPE_HANGUL_HANJA );
71 0 : else if (nConversionType == ConversionDictionaryType::SCHINESE_TCHINESE)
72 0 : aRes = A2OU( CONV_TYPE_SCHINESE_TCHINESE );
73 0 : return aRes;
74 : }
75 :
76 0 : static sal_Int16 GetConversionTypeFromText( const String &rText )
77 : {
78 0 : sal_Int16 nRes = -1;
79 0 : if (rText.EqualsAscii( CONV_TYPE_HANGUL_HANJA ))
80 0 : nRes = ConversionDictionaryType::HANGUL_HANJA;
81 0 : else if (rText.EqualsAscii( CONV_TYPE_SCHINESE_TCHINESE ))
82 0 : nRes = ConversionDictionaryType::SCHINESE_TCHINESE;
83 0 : return nRes;
84 : }
85 :
86 :
87 0 : class ConvDicXMLImportContext :
88 : public SvXMLImportContext
89 : {
90 : public:
91 0 : ConvDicXMLImportContext(
92 : ConvDicXMLImport &rImport,
93 : sal_uInt16 nPrfx, const OUString& rLName ) :
94 0 : SvXMLImportContext( rImport, nPrfx, rLName )
95 : {
96 0 : }
97 :
98 : const ConvDicXMLImport & GetConvDicImport() const
99 : {
100 : return (const ConvDicXMLImport &) GetImport();
101 : }
102 :
103 0 : ConvDicXMLImport & GetConvDicImport()
104 : {
105 0 : return (ConvDicXMLImport &) GetImport();
106 : }
107 :
108 : // SvXMLImportContext
109 : virtual void Characters( const OUString &rChars );
110 : virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList);
111 : };
112 :
113 :
114 0 : class ConvDicXMLDictionaryContext_Impl :
115 : public ConvDicXMLImportContext
116 : {
117 : sal_Int16 nLanguage;
118 : sal_Int16 nConversionType;
119 :
120 : public:
121 0 : ConvDicXMLDictionaryContext_Impl( ConvDicXMLImport &rImport,
122 : sal_uInt16 nPrefix, const OUString& rLName) :
123 0 : ConvDicXMLImportContext( rImport, nPrefix, rLName )
124 : {
125 0 : nLanguage = LANGUAGE_NONE;
126 0 : nConversionType = -1;
127 0 : }
128 :
129 : // SvXMLImportContext
130 : virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
131 : virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList );
132 :
133 : sal_Int16 GetLanguage() const { return nLanguage; }
134 : sal_Int16 GetConversionType() const { return nConversionType; }
135 : };
136 :
137 :
138 0 : class ConvDicXMLEntryTextContext_Impl :
139 : public ConvDicXMLImportContext
140 : {
141 : OUString aLeftText;
142 : sal_Int16 nPropertyType; // used for Chinese simplified/traditional conversion
143 :
144 : public:
145 0 : ConvDicXMLEntryTextContext_Impl(
146 : ConvDicXMLImport &rImport,
147 : sal_uInt16 nPrefix, const OUString& rLName ) :
148 : ConvDicXMLImportContext( rImport, nPrefix, rLName ),
149 0 : nPropertyType( ConversionPropertyType::NOT_DEFINED )
150 : {
151 0 : }
152 :
153 : // SvXMLImportContext
154 : virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
155 : virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList );
156 :
157 0 : const OUString & GetLeftText() const { return aLeftText; }
158 : sal_Int16 GetPropertyType() const { return nPropertyType; }
159 : void SetPropertyType( sal_Int16 nVal ) { nPropertyType = nVal; }
160 : };
161 :
162 :
163 0 : class ConvDicXMLRightTextContext_Impl :
164 : public ConvDicXMLImportContext
165 : {
166 : OUString aRightText;
167 : ConvDicXMLEntryTextContext_Impl &rEntryContext;
168 :
169 : public:
170 0 : ConvDicXMLRightTextContext_Impl(
171 : ConvDicXMLImport &rImport,
172 : sal_uInt16 nPrefix, const OUString& rLName,
173 : ConvDicXMLEntryTextContext_Impl &rParentContext ) :
174 : ConvDicXMLImportContext( rImport, nPrefix, rLName ),
175 0 : rEntryContext( rParentContext )
176 : {
177 0 : }
178 :
179 : // SvXMLImportContext
180 : virtual void EndElement();
181 : virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList );
182 : virtual void Characters( const OUString &rChars );
183 :
184 0 : const OUString & GetRightText() const { return aRightText; }
185 0 : const OUString & GetLeftText() const { return rEntryContext.GetLeftText(); }
186 0 : ConvDic * GetDic() { return GetConvDicImport().GetDic(); }
187 : };
188 :
189 :
190 0 : void ConvDicXMLImportContext::Characters(const OUString & /*rChars*/)
191 : {
192 : /*
193 : Whitespace occurring within the content of token elements is "trimmed"
194 : from the ends (i.e. all whitespace at the beginning and end of the
195 : content is removed), and "collapsed" internally (i.e. each sequence of
196 : 1 or more whitespace characters is replaced with one blank character).
197 : */
198 : //collapsing not done yet!
199 :
200 0 : }
201 :
202 0 : SvXMLImportContext * ConvDicXMLImportContext::CreateChildContext(
203 : sal_uInt16 nPrefix, const OUString& rLocalName,
204 : const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
205 : {
206 0 : SvXMLImportContext *pContext = 0;
207 0 : if ( nPrefix == XML_NAMESPACE_TCD && rLocalName == "text-conversion-dictionary" )
208 0 : pContext = new ConvDicXMLDictionaryContext_Impl( GetConvDicImport(), nPrefix, rLocalName );
209 : else
210 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
211 0 : return pContext;
212 : }
213 :
214 :
215 0 : void ConvDicXMLDictionaryContext_Impl::StartElement(
216 : const uno::Reference< xml::sax::XAttributeList > &rxAttrList )
217 : {
218 0 : sal_Int16 nAttrCount = rxAttrList.is() ? rxAttrList->getLength() : 0;
219 0 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
220 : {
221 0 : OUString aAttrName = rxAttrList->getNameByIndex(i);
222 0 : OUString aLocalName;
223 0 : sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
224 0 : GetKeyByAttrName( aAttrName, &aLocalName );
225 0 : OUString aValue = rxAttrList->getValueByIndex(i);
226 :
227 0 : if ( nPrefix == XML_NAMESPACE_TCD && aLocalName == "lang" )
228 0 : nLanguage = LanguageTag( aValue ).getLanguageType();
229 0 : else if ( nPrefix == XML_NAMESPACE_TCD && aLocalName == "conversion-type" )
230 0 : nConversionType = GetConversionTypeFromText( aValue );
231 0 : }
232 0 : GetConvDicImport().SetLanguage( nLanguage );
233 0 : GetConvDicImport().SetConversionType( nConversionType );
234 :
235 0 : }
236 :
237 0 : SvXMLImportContext * ConvDicXMLDictionaryContext_Impl::CreateChildContext(
238 : sal_uInt16 nPrefix, const OUString& rLocalName,
239 : const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
240 : {
241 0 : SvXMLImportContext *pContext = 0;
242 0 : if ( nPrefix == XML_NAMESPACE_TCD && rLocalName == "entry" )
243 0 : pContext = new ConvDicXMLEntryTextContext_Impl( GetConvDicImport(), nPrefix, rLocalName );
244 : else
245 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
246 0 : return pContext;
247 : }
248 :
249 :
250 0 : SvXMLImportContext * ConvDicXMLEntryTextContext_Impl::CreateChildContext(
251 : sal_uInt16 nPrefix, const OUString& rLocalName,
252 : const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
253 : {
254 0 : SvXMLImportContext *pContext = 0;
255 0 : if ( nPrefix == XML_NAMESPACE_TCD && rLocalName == "right-text" )
256 0 : pContext = new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), nPrefix, rLocalName, *this );
257 : else
258 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
259 0 : return pContext;
260 : }
261 :
262 0 : void ConvDicXMLEntryTextContext_Impl::StartElement(
263 : const uno::Reference< xml::sax::XAttributeList >& rxAttrList )
264 : {
265 0 : sal_Int16 nAttrCount = rxAttrList.is() ? rxAttrList->getLength() : 0;
266 0 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
267 : {
268 0 : OUString aAttrName = rxAttrList->getNameByIndex(i);
269 0 : OUString aLocalName;
270 0 : sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
271 0 : GetKeyByAttrName( aAttrName, &aLocalName );
272 0 : OUString aValue = rxAttrList->getValueByIndex(i);
273 :
274 0 : if ( nPrefix == XML_NAMESPACE_TCD && aLocalName == "left-text" )
275 0 : aLeftText = aValue;
276 0 : if ( nPrefix == XML_NAMESPACE_TCD && aLocalName == "property-type" )
277 0 : nPropertyType = (sal_Int16) aValue.toInt32();
278 0 : }
279 0 : }
280 :
281 :
282 0 : SvXMLImportContext * ConvDicXMLRightTextContext_Impl::CreateChildContext(
283 : sal_uInt16 nPrefix, const OUString& rLocalName,
284 : const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
285 : {
286 : // leaf: return default (empty) context
287 0 : SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
288 0 : return pContext;
289 : }
290 :
291 0 : void ConvDicXMLRightTextContext_Impl::Characters( const OUString &rChars )
292 : {
293 0 : aRightText += rChars;
294 0 : }
295 :
296 0 : void ConvDicXMLRightTextContext_Impl::EndElement()
297 : {
298 0 : ConvDic *pDic = GetDic();
299 0 : if (pDic)
300 0 : pDic->AddEntry( GetLeftText(), GetRightText() );
301 0 : }
302 :
303 :
304 :
305 0 : sal_Bool ConvDicXMLExport::Export()
306 : {
307 0 : sal_Bool bRet = sal_False;
308 :
309 0 : uno::Reference< document::XExporter > xExporter( this );
310 0 : uno::Reference< document::XFilter > xFilter( xExporter, UNO_QUERY );
311 0 : uno::Sequence< beans::PropertyValue > aProps(0);
312 0 : xFilter->filter( aProps ); // calls exportDoc implicitly
313 :
314 0 : return bRet = bSuccess;
315 : }
316 :
317 :
318 0 : sal_uInt32 ConvDicXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum /*eClass*/ )
319 : {
320 0 : _GetNamespaceMap().Add( A2OU( "tcd" ),
321 0 : A2OU( XML_NAMESPACE_TCD_STRING ), XML_NAMESPACE_TCD );
322 :
323 0 : GetDocHandler()->startDocument();
324 :
325 : // Add xmlns line and some other arguments
326 0 : AddAttribute( _GetNamespaceMap().GetAttrNameByKey( XML_NAMESPACE_TCD ),
327 0 : _GetNamespaceMap().GetNameByKey( XML_NAMESPACE_TCD ) );
328 0 : AddAttributeASCII( XML_NAMESPACE_TCD, "package", "org.openoffice.Office" );
329 :
330 0 : OUString aIsoLang( LanguageTag( rDic.nLanguage ).getBcp47() );
331 0 : AddAttribute( XML_NAMESPACE_TCD, "lang", aIsoLang );
332 0 : OUString aConvType( ConversionTypeToText( rDic.nConversionType ) );
333 0 : AddAttribute( XML_NAMESPACE_TCD, "conversion-type", aConvType );
334 :
335 : //!! block necessary in order to have SvXMLElementExport d-tor called
336 : //!! before the call to endDocument
337 : {
338 0 : SvXMLElementExport aRoot( *this, XML_NAMESPACE_TCD, "text-conversion-dictionary", sal_True, sal_True );
339 0 : _ExportContent();
340 : }
341 :
342 0 : GetDocHandler()->endDocument();
343 :
344 0 : bSuccess = sal_True;
345 0 : return 0;
346 : }
347 :
348 :
349 0 : void ConvDicXMLExport::_ExportContent()
350 : {
351 : // aquire sorted list of all keys
352 0 : ConvMapKeySet aKeySet;
353 0 : ConvMap::iterator aIt;
354 0 : for (aIt = rDic.aFromLeft.begin(); aIt != rDic.aFromLeft.end(); ++aIt)
355 0 : aKeySet.insert( (*aIt).first );
356 :
357 0 : ConvMapKeySet::iterator aKeyIt;
358 0 : for (aKeyIt = aKeySet.begin(); aKeyIt != aKeySet.end(); ++aKeyIt)
359 : {
360 0 : OUString aLeftText( *aKeyIt );
361 0 : AddAttribute( XML_NAMESPACE_TCD, "left-text", aLeftText );
362 0 : if (rDic.pConvPropType.get()) // property-type list available?
363 : {
364 0 : sal_Int16 nPropertyType = -1;
365 0 : PropTypeMap::iterator aIt2 = rDic.pConvPropType->find( aLeftText );
366 0 : if (aIt2 != rDic.pConvPropType->end())
367 0 : nPropertyType = (*aIt2).second;
368 : DBG_ASSERT( nPropertyType, "property-type not found" );
369 0 : if (nPropertyType == -1)
370 0 : nPropertyType = ConversionPropertyType::NOT_DEFINED;
371 0 : AddAttribute( XML_NAMESPACE_TCD, "property-type", OUString::valueOf( (sal_Int32) nPropertyType ) );
372 : }
373 : SvXMLElementExport aEntryMain( *this, XML_NAMESPACE_TCD,
374 0 : "entry" , sal_True, sal_True );
375 :
376 : pair< ConvMap::iterator, ConvMap::iterator > aRange =
377 0 : rDic.aFromLeft.equal_range( *aKeyIt );
378 0 : for (aIt = aRange.first; aIt != aRange.second; ++aIt)
379 : {
380 : DBG_ASSERT( *aKeyIt == (*aIt).first, "key <-> entry mismatch" );
381 0 : OUString aRightText( (*aIt).second );
382 : SvXMLElementExport aEntryRightText( *this, XML_NAMESPACE_TCD,
383 0 : "right-text" , sal_True, sal_False );
384 0 : Characters( aRightText );
385 0 : }
386 0 : }
387 0 : }
388 :
389 0 : ::rtl::OUString SAL_CALL ConvDicXMLExport::getImplementationName()
390 : throw( uno::RuntimeException )
391 : {
392 0 : return A2OU( "com.sun.star.lingu2.ConvDicXMLExport" );
393 : }
394 :
395 :
396 0 : void SAL_CALL ConvDicXMLImport::startDocument(void)
397 : throw( xml::sax::SAXException, uno::RuntimeException )
398 : {
399 : // register namespace at first possible opportunity
400 0 : GetNamespaceMap().Add( A2OU( "tcd" ),
401 0 : A2OU( XML_NAMESPACE_TCD_STRING ), XML_NAMESPACE_TCD );
402 0 : SvXMLImport::startDocument();
403 0 : }
404 :
405 0 : void SAL_CALL ConvDicXMLImport::endDocument(void)
406 : throw( xml::sax::SAXException, uno::RuntimeException )
407 : {
408 0 : SvXMLImport::endDocument();
409 0 : }
410 :
411 0 : SvXMLImportContext * ConvDicXMLImport::CreateContext(
412 : sal_uInt16 nPrefix,
413 : const rtl::OUString &rLocalName,
414 : const uno::Reference < xml::sax::XAttributeList > & /*rxAttrList*/ )
415 : {
416 0 : SvXMLImportContext *pContext = 0;
417 0 : if ( nPrefix == XML_NAMESPACE_TCD && rLocalName == "text-conversion-dictionary" )
418 0 : pContext = new ConvDicXMLDictionaryContext_Impl( *this, nPrefix, rLocalName );
419 : else
420 0 : pContext = new SvXMLImportContext( *this, nPrefix, rLocalName );
421 0 : return pContext;
422 : }
423 :
424 :
425 0 : OUString SAL_CALL ConvDicXMLImport::getImplementationName()
426 : throw( uno::RuntimeException )
427 : {
428 0 : return A2OU( "com.sun.star.lingu2.ConvDicXMLImport" );
429 : }
430 :
431 :
432 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|