xref: /trunk/main/xmloff/source/text/XMLIndexMarkExport.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include "XMLIndexMarkExport.hxx"
31 #include <tools/debug.hxx>
32 #include <rtl/ustring.hxx>
33 #include <rtl/ustrbuf.hxx>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <xmloff/xmltoken.hxx>
37 #include "xmloff/xmlnmspe.hxx"
38 #include <xmloff/xmlexp.hxx>
39 #include <xmloff/xmluconv.hxx>
40 
41 
42 using namespace ::xmloff::token;
43 
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
46 using ::com::sun::star::beans::XPropertySet;
47 using ::com::sun::star::beans::XPropertySetInfo;
48 using ::com::sun::star::uno::Reference;
49 using ::com::sun::star::uno::Any;
50 
51 
52 
53 XMLIndexMarkExport::XMLIndexMarkExport(
54     SvXMLExport& rExp,
55     XMLTextParagraphExport& rParaExp)
56 :   sLevel(RTL_CONSTASCII_USTRINGPARAM("Level"))
57 ,   sUserIndexName(RTL_CONSTASCII_USTRINGPARAM("UserIndexName"))
58 ,   sPrimaryKey(RTL_CONSTASCII_USTRINGPARAM("PrimaryKey"))
59 ,   sSecondaryKey(RTL_CONSTASCII_USTRINGPARAM("SecondaryKey"))
60 ,   sDocumentIndexMark(RTL_CONSTASCII_USTRINGPARAM("DocumentIndexMark"))
61 ,   sIsStart(RTL_CONSTASCII_USTRINGPARAM("IsStart"))
62 ,   sIsCollapsed(RTL_CONSTASCII_USTRINGPARAM("IsCollapsed"))
63 ,   sAlternativeText(RTL_CONSTASCII_USTRINGPARAM("AlternativeText"))
64 ,   sTextReading(RTL_CONSTASCII_USTRINGPARAM("TextReading"))
65 ,   sPrimaryKeyReading(RTL_CONSTASCII_USTRINGPARAM("PrimaryKeyReading"))
66 ,   sSecondaryKeyReading(RTL_CONSTASCII_USTRINGPARAM("SecondaryKeyReading"))
67 ,   sMainEntry(RTL_CONSTASCII_USTRINGPARAM("IsMainEntry"))
68 ,   rExport(rExp)
69 ,   rParaExport(rParaExp)
70 {
71 }
72 
73 const enum XMLTokenEnum lcl_pTocMarkNames[] =
74     { XML_TOC_MARK, XML_TOC_MARK_START, XML_TOC_MARK_END };
75 const enum XMLTokenEnum lcl_pUserIndexMarkName[] =
76     { XML_USER_INDEX_MARK,
77           XML_USER_INDEX_MARK_START, XML_USER_INDEX_MARK_END };
78 const enum XMLTokenEnum lcl_pAlphaIndexMarkName[] =
79     { XML_ALPHABETICAL_INDEX_MARK,
80           XML_ALPHABETICAL_INDEX_MARK_START,
81           XML_ALPHABETICAL_INDEX_MARK_END };
82 
83 
84 XMLIndexMarkExport::~XMLIndexMarkExport()
85 {
86 }
87 
88 void XMLIndexMarkExport::ExportIndexMark(
89     const Reference<XPropertySet> & rPropSet,
90     sal_Bool bAutoStyles)
91 {
92     /// index marks have no styles!
93     if (!bAutoStyles)
94     {
95         const enum XMLTokenEnum * pElements = NULL;
96         sal_Int8 nElementNo = -1;
97 
98         // get index mark
99         Any aAny;
100         aAny = rPropSet->getPropertyValue(sDocumentIndexMark);
101         Reference<XPropertySet> xIndexMarkPropSet;
102         aAny >>= xIndexMarkPropSet;
103 
104         // common: handling of start, end, collapsed entries and
105         // alternative text
106 
107         // collapsed/alternative text entry?
108         aAny = rPropSet->getPropertyValue(sIsCollapsed);
109         if (*(sal_Bool *)aAny.getValue())
110         {
111             // collapsed entry: needs alternative text
112             nElementNo = 0;
113 
114             aAny = xIndexMarkPropSet->getPropertyValue(sAlternativeText);
115             OUString sTmp;
116             aAny >>= sTmp;
117             DBG_ASSERT(sTmp.getLength() > 0,
118                        "collapsed index mark without alternative text");
119             rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STRING_VALUE, sTmp);
120         }
121         else
122         {
123             // start and end entries: has ID
124             aAny = rPropSet->getPropertyValue(sIsStart);
125             nElementNo = *(sal_Bool *)aAny.getValue() ? 1 : 2;
126 
127             // generate ID
128             OUStringBuffer sBuf;
129             GetID(sBuf, xIndexMarkPropSet);
130             rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_ID,
131                                  sBuf.makeStringAndClear());
132         }
133 
134         // distinguish between TOC, user, alphab. index marks by
135         // asking for specific properties
136         // Export attributes for -mark-start and -mark elements,
137         // but not for -mark-end
138         Reference<XPropertySetInfo> xPropertySetInfo =
139             xIndexMarkPropSet->getPropertySetInfo();
140         if (xPropertySetInfo->hasPropertyByName(sUserIndexName))
141         {
142             // user index mark
143             pElements = lcl_pUserIndexMarkName;
144             if (nElementNo != 2)
145             {
146                 ExportUserIndexMarkAttributes(xIndexMarkPropSet);
147             }
148         }
149         else if (xPropertySetInfo->hasPropertyByName(sPrimaryKey))
150         {
151             // alphabetical index mark
152             pElements = lcl_pAlphaIndexMarkName;
153             if (nElementNo != 2)
154             {
155                 ExportAlphabeticalIndexMarkAttributes(xIndexMarkPropSet);
156             }
157         }
158         else
159         {
160             // table of content:
161             pElements = lcl_pTocMarkNames;
162             if (nElementNo != 2)
163             {
164                 ExportTOCMarkAttributes(xIndexMarkPropSet);
165             }
166         }
167 
168         // export element
169         DBG_ASSERT(pElements != NULL, "illegal element array");
170         DBG_ASSERT(nElementNo >= 0, "illegal name array index");
171         DBG_ASSERT(nElementNo <= 2, "illegal name array index");
172 
173         if ((pElements != NULL) && (nElementNo != -1))
174         {
175             SvXMLElementExport aElem(rExport,
176                                      XML_NAMESPACE_TEXT,
177                                      pElements[nElementNo],
178                                      sal_False, sal_False);
179         }
180     }
181 }
182 
183 void XMLIndexMarkExport::ExportTOCMarkAttributes(
184     const Reference<XPropertySet> & rPropSet)
185 {
186     // outline level
187     sal_Int16 nLevel = 0;
188     Any aAny = rPropSet->getPropertyValue(sLevel);
189     aAny >>= nLevel;
190     OUStringBuffer sBuf;
191     SvXMLUnitConverter::convertNumber(sBuf, (sal_Int32)nLevel + 1);
192     rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
193                              sBuf.makeStringAndClear());
194 }
195 
196 void lcl_ExportPropertyString( SvXMLExport& rExport,
197                                const Reference<XPropertySet> & rPropSet,
198                                const OUString sProperty,
199                                XMLTokenEnum eToken,
200                                Any& rAny )
201 {
202     rAny = rPropSet->getPropertyValue( sProperty );
203 
204     OUString sValue;
205     if( rAny >>= sValue )
206     {
207         if( sValue.getLength() > 0 )
208         {
209             rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, sValue );
210         }
211     }
212 }
213 
214 void lcl_ExportPropertyBool( SvXMLExport& rExport,
215                              const Reference<XPropertySet> & rPropSet,
216                              const OUString sProperty,
217                              XMLTokenEnum eToken,
218                              Any& rAny )
219 {
220     rAny = rPropSet->getPropertyValue( sProperty );
221 
222     sal_Bool bValue = sal_Bool();
223     if( rAny >>= bValue )
224     {
225         if( bValue )
226         {
227             rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, XML_TRUE );
228         }
229     }
230 }
231 
232 void XMLIndexMarkExport::ExportUserIndexMarkAttributes(
233     const Reference<XPropertySet> & rPropSet)
234 {
235     // name of user index
236     // (unless it's the default index; then it has no name)
237     Any aAny;
238     lcl_ExportPropertyString( rExport, rPropSet, sUserIndexName, XML_INDEX_NAME, aAny );
239 
240     // additionally export outline level; just reuse ExportTOCMarkAttributes
241     ExportTOCMarkAttributes( rPropSet );
242 }
243 
244 void XMLIndexMarkExport::ExportAlphabeticalIndexMarkAttributes(
245     const Reference<XPropertySet> & rPropSet)
246 {
247     // primary and secondary keys (if available)
248     Any aAny;
249     lcl_ExportPropertyString( rExport, rPropSet, sTextReading, XML_STRING_VALUE_PHONETIC, aAny );
250     lcl_ExportPropertyString( rExport, rPropSet, sPrimaryKey, XML_KEY1, aAny );
251     lcl_ExportPropertyString( rExport, rPropSet, sPrimaryKeyReading, XML_KEY1_PHONETIC, aAny );
252     lcl_ExportPropertyString( rExport, rPropSet, sSecondaryKey, XML_KEY2, aAny );
253     lcl_ExportPropertyString( rExport, rPropSet, sSecondaryKeyReading, XML_KEY2_PHONETIC, aAny );
254     lcl_ExportPropertyBool( rExport, rPropSet, sMainEntry, XML_MAIN_ENTRY, aAny );
255 }
256 
257 void XMLIndexMarkExport::GetID(
258     OUStringBuffer& sBuf,
259     const Reference<XPropertySet> & rPropSet)
260 {
261     static const sal_Char sPrefix[] = "IMark";
262 
263     // HACK: use address of object to form identifier
264     sal_Int64 nId = sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(rPropSet.get()));
265     sBuf.appendAscii(sPrefix, sizeof(sPrefix)-1);
266     sBuf.append(nId);
267 }
268