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