1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #include "precompiled_reportdesign.hxx"
24 #include "xmlControlProperty.hxx"
25 #include <xmloff/xmluconv.hxx>
26 #include "xmlfilter.hxx"
27 #include <xmloff/xmltoken.hxx>
28 #include <xmloff/xmlnmspe.hxx>
29 #include <xmloff/nmspmap.hxx>
30 #include "xmlEnums.hxx"
31 #include <tools/debug.hxx>
32 #include <tools/datetime.hxx>
33 #include <unotools/datetime.hxx>
34 #include <com/sun/star/util/DateTime.hpp>
35 
36 #define TYPE_DATE		1
37 #define TYPE_TIME		2
38 #define TYPE_DATETIME	3
39 
40 namespace rptxml
41 {
42 	using namespace ::com::sun::star::uno;
43 	using namespace ::com::sun::star::beans;
44 	using namespace ::com::sun::star::xml::sax;
45 
DBG_NAME(rpt_OXMLControlProperty)46 DBG_NAME( rpt_OXMLControlProperty )
47 
48 OXMLControlProperty::OXMLControlProperty( ORptFilter& rImport
49 				,sal_uInt16 nPrfx
50 				,const ::rtl::OUString& _sLocalName
51 				,const Reference< XAttributeList > & _xAttrList
52 				,const Reference< XPropertySet >& _xControl
53 				,OXMLControlProperty* _pContainer) :
54 	SvXMLImportContext( rImport, nPrfx, _sLocalName )
55 	,m_xControl(_xControl)
56 	,m_pContainer(_pContainer)
57 	,m_bIsList(sal_False)
58 {
59     DBG_CTOR( rpt_OXMLControlProperty,NULL);
60 
61 	m_aPropType = ::getVoidCppuType();
62 
63 	OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
64 	OSL_ENSURE(m_xControl.is(),"Control is NULL!");
65 
66 	const SvXMLNamespaceMap& rMap = rImport.GetNamespaceMap();
67 	const SvXMLTokenMap& rTokenMap = rImport.GetControlPropertyElemTokenMap();
68 
69 	const sal_Int16 nLength = (_xAttrList.is()) ? _xAttrList->getLength() : 0;
70 	for(sal_Int16 i = 0; i < nLength; ++i)
71 	{
72 	 ::rtl::OUString sLocalName;
73 		const rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
74 		const sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName,&sLocalName );
75 		const rtl::OUString sValue = _xAttrList->getValueByIndex( i );
76 
77 		switch( rTokenMap.Get( nPrefix, sLocalName ) )
78 		{
79 			case XML_TOK_LIST_PROPERTY:
80 				m_bIsList = sValue.equalsAscii("true");
81 				break;
82 			case XML_TOK_VALUE_TYPE:
83 				{
84 					// needs to be translated into a ::com::sun::star::uno::Type
85 					DECLARE_STL_USTRINGACCESS_MAP( ::com::sun::star::uno::Type, MapString2Type );
86 					static MapString2Type s_aTypeNameMap;
87 					if (!s_aTypeNameMap.size())
88 					{
89 						s_aTypeNameMap[GetXMLToken( XML_BOOLEAN)]	= ::getBooleanCppuType();
90 						s_aTypeNameMap[GetXMLToken( XML_FLOAT)]		= ::getCppuType( static_cast< double* >(NULL) );
91                         s_aTypeNameMap[GetXMLToken( XML_DOUBLE)]	= ::getCppuType( static_cast< double* >(NULL) );
92 						s_aTypeNameMap[GetXMLToken( XML_STRING)]	= ::getCppuType( static_cast< ::rtl::OUString* >(NULL) );
93 						s_aTypeNameMap[GetXMLToken( XML_INT)]		= ::getCppuType( static_cast< sal_Int32* >(NULL) );
94 						s_aTypeNameMap[GetXMLToken( XML_SHORT)]		= ::getCppuType( static_cast< sal_Int16* >(NULL) );
95 						s_aTypeNameMap[GetXMLToken( XML_DATE)]		= ::getCppuType( static_cast< com::sun::star::util::Date* >(NULL) );
96 						s_aTypeNameMap[GetXMLToken( XML_TIME)]		= ::getCppuType( static_cast< com::sun::star::util::Time* >(NULL) );
97 						s_aTypeNameMap[GetXMLToken( XML_VOID)]		= ::getVoidCppuType();
98 					}
99 
100 					const ConstMapString2TypeIterator aTypePos = s_aTypeNameMap.find(sValue);
101 					OSL_ENSURE(s_aTypeNameMap.end() != aTypePos, "OXMLControlProperty::OXMLControlProperty: invalid type!");
102 					if (s_aTypeNameMap.end() != aTypePos)
103 						m_aPropType = aTypePos->second;
104 				}
105 				break;
106 			case XML_TOK_PROPERTY_NAME:
107 				m_aSetting.Name = sValue;
108 				break;
109             default:
110                 break;
111 		}
112 	}
113 
114 }
115 // -----------------------------------------------------------------------------
116 
~OXMLControlProperty()117 OXMLControlProperty::~OXMLControlProperty()
118 {
119     DBG_DTOR( rpt_OXMLControlProperty,NULL);
120 }
121 // -----------------------------------------------------------------------------
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLocalName,const Reference<XAttributeList> & xAttrList)122 SvXMLImportContext* OXMLControlProperty::CreateChildContext(
123 		sal_uInt16 nPrefix,
124 		const ::rtl::OUString& rLocalName,
125 		const Reference< XAttributeList > & xAttrList )
126 {
127 	SvXMLImportContext *pContext = 0;
128     ORptFilter& rImport = GetOwnImport();
129 	const SvXMLTokenMap&	rTokenMap	= rImport.GetControlPropertyElemTokenMap();
130 
131 	switch( rTokenMap.Get( nPrefix, rLocalName ) )
132 	{
133 		case XML_TOK_LIST_PROPERTY:
134 			rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
135 			pContext = new OXMLControlProperty( rImport, nPrefix, rLocalName,xAttrList,m_xControl);
136 			break;
137 		case XML_TOK_VALUE:
138 			rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
139 			pContext = new OXMLControlProperty( rImport, nPrefix, rLocalName,xAttrList,m_xControl,this );
140 			break;
141         default:
142             break;
143 	}
144 
145 	if( !pContext )
146 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
147 
148 	return pContext;
149 }
150 // -----------------------------------------------------------------------------
EndElement()151 void OXMLControlProperty::EndElement()
152 {
153 	if ( m_aSetting.Name.getLength() && m_xControl.is() )
154 	{
155 		if ( m_bIsList && !m_aSequence.getLength() )
156 			m_aSetting.Value <<= m_aSequence;
157 		try
158 		{
159 			m_xControl->setPropertyValue(m_aSetting.Name,m_aSetting.Value);
160 		}
161 		catch(const Exception&)
162 		{
163 			OSL_ENSURE(0,"Unknown property found!");
164 		}
165 	}
166 }
167 // -----------------------------------------------------------------------------
Characters(const::rtl::OUString & rChars)168 void OXMLControlProperty::Characters( const ::rtl::OUString& rChars )
169 {
170 	if ( m_pContainer )
171 		m_pContainer->addValue(rChars);
172 }
173 // -----------------------------------------------------------------------------
addValue(const::rtl::OUString & _sValue)174 void OXMLControlProperty::addValue(const ::rtl::OUString& _sValue)
175 {
176 	Any aValue;
177 	if( TypeClass_VOID != m_aPropType.getTypeClass() )
178 		aValue = convertString(m_aPropType, _sValue);
179 
180 	if ( !m_bIsList )
181 		m_aSetting.Value = aValue;
182 	else
183 	{
184 		sal_Int32 nPos = m_aSequence.getLength();
185 		m_aSequence.realloc(nPos+1);
186 		m_aSequence[nPos] = aValue;
187 	}
188 }
189 // -----------------------------------------------------------------------------
GetOwnImport()190 ORptFilter& OXMLControlProperty::GetOwnImport()
191 {
192 	return static_cast<ORptFilter&>(GetImport());
193 }
194 // -----------------------------------------------------------------------------
convertString(const::com::sun::star::uno::Type & _rExpectedType,const::rtl::OUString & _rReadCharacters)195 Any OXMLControlProperty::convertString(const ::com::sun::star::uno::Type& _rExpectedType, const ::rtl::OUString& _rReadCharacters)
196 {
197 	ORptFilter& rImporter = GetOwnImport();
198 	Any aReturn;
199 	switch (_rExpectedType.getTypeClass())
200 	{
201 		case TypeClass_BOOLEAN:		// sal_Bool
202 		{
203 			sal_Bool bValue;
204         #if OSL_DEBUG_LEVEL > 0
205 			sal_Bool bSuccess =
206 		#endif
207 			rImporter.GetMM100UnitConverter().convertBool(bValue, _rReadCharacters);
208 			OSL_ENSURE(bSuccess,
209 					::rtl::OString("OXMLControlProperty::convertString: could not convert \"")
210 				+=	::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
211 				+=	::rtl::OString("\" into a boolean!"));
212 			aReturn <<= bValue;
213 		}
214 		break;
215 		case TypeClass_SHORT:		// sal_Int16
216 		case TypeClass_LONG:		// sal_Int32
217 			{	// it's a real int32/16 property
218 				sal_Int32 nValue(0);
219         #if OSL_DEBUG_LEVEL > 0
220 				sal_Bool bSuccess =
221 		#endif
222 				rImporter.GetMM100UnitConverter().convertNumber(nValue, _rReadCharacters);
223 				OSL_ENSURE(bSuccess,
224 						::rtl::OString("OXMLControlProperty::convertString: could not convert \"")
225 					+=	::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
226 					+=	::rtl::OString("\" into an integer!"));
227 				if (TypeClass_SHORT == _rExpectedType.getTypeClass())
228 					aReturn <<= (sal_Int16)nValue;
229 				else
230 					aReturn <<= (sal_Int32)nValue;
231 				break;
232 			}
233 		case TypeClass_HYPER:
234 		{
235 			OSL_ENSURE(sal_False, "OXMLControlProperty::convertString: 64-bit integers not implemented yet!");
236 		}
237 		break;
238 		case TypeClass_DOUBLE:
239 		{
240 			double nValue = 0.0;
241         #if OSL_DEBUG_LEVEL > 0
242 			sal_Bool bSuccess =
243 		#endif
244 			rImporter.GetMM100UnitConverter().convertDouble(nValue, _rReadCharacters);
245 			OSL_ENSURE(bSuccess,
246 					::rtl::OString("OXMLControlProperty::convertString: could not convert \"")
247 				+=	::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
248 				+=	::rtl::OString("\" into a double!"));
249 			aReturn <<= (double)nValue;
250 		}
251 		break;
252 		case TypeClass_STRING:
253 			aReturn <<= _rReadCharacters;
254 			break;
255 		case TypeClass_STRUCT:
256 			{
257 				// recognized structs:
258 				static ::com::sun::star::uno::Type s_aDateType		= ::getCppuType(static_cast< ::com::sun::star::util::Date* >(NULL));
259 				static ::com::sun::star::uno::Type s_aTimeType		= ::getCppuType(static_cast< ::com::sun::star::util::Time* >(NULL));
260 				static ::com::sun::star::uno::Type s_aDateTimeType	= ::getCppuType(static_cast< ::com::sun::star::util::DateTime* >(NULL));
261 				sal_Int32 nType = 0;
262 				if	( _rExpectedType.equals(s_aDateType) )
263                     nType = TYPE_DATE;
264                 else if ( _rExpectedType.equals(s_aTimeType) )
265                     nType = TYPE_TIME;
266                 else if ( _rExpectedType.equals(s_aDateTimeType) )
267                     nType = TYPE_DATETIME;
268 				if ( !nType )
269 				{
270 					// first extract the double
271 					double nValue = 0;
272                 #if OSL_DEBUG_LEVEL > 0
273 					sal_Bool bSuccess =
274 				#endif
275 					rImporter.GetMM100UnitConverter().convertDouble(nValue, _rReadCharacters);
276 					OSL_ENSURE(bSuccess,
277 							::rtl::OString("OPropertyImport::convertString: could not convert \"")
278 						+=	::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
279 						+=	::rtl::OString("\" into a double!"));
280 
281 					// then convert it into the target type
282 					switch (nType)
283 					{
284 						case TYPE_DATE:
285 						{
286 							OSL_ENSURE(((sal_uInt32)nValue) - nValue == 0,
287 								"OPropertyImport::convertString: a Date value with a fractional part?");
288 							aReturn <<= implGetDate(nValue);
289 						}
290 						break;
291 						case TYPE_TIME:
292 						{
293 							OSL_ENSURE(((sal_uInt32)nValue) == 0,
294 								"OPropertyImport::convertString: a Time value with more than a fractional part?");
295 							aReturn <<= implGetTime(nValue);
296 						}
297 						break;
298 						case TYPE_DATETIME:
299 						{
300 							::com::sun::star::util::Time aTime = implGetTime(nValue);
301 							::com::sun::star::util::Date aDate = implGetDate(nValue);
302 
303 							::com::sun::star::util::DateTime aDateTime;
304 							aDateTime.HundredthSeconds = aTime.HundredthSeconds;
305 							aDateTime.Seconds = aTime.Seconds;
306 							aDateTime.Minutes = aTime.Minutes;
307 							aDateTime.Hours = aTime.Hours;
308 							aDateTime.Day = aDate.Day;
309 							aDateTime.Month = aDate.Month;
310 							aDateTime.Year = aDate.Year;
311 							aReturn <<= aDateTime;
312 						}
313 						break;
314                         default:
315                             break;
316 					}
317 				}
318 				else
319 					OSL_ENSURE(sal_False, "OPropertyImport::convertString: unsupported property type!");
320 			}
321 			break;
322 		default:
323 			OSL_ENSURE(sal_False, "OXMLControlProperty::convertString: invalid type class!");
324 	}
325 
326 	return aReturn;
327 }
328 //---------------------------------------------------------------------
implGetTime(double _nValue)329 ::com::sun::star::util::Time OXMLControlProperty::implGetTime(double _nValue)
330 {
331 	::com::sun::star::util::Time aTime;
332 	sal_uInt32 nIntValue = sal_Int32(_nValue * 8640000);
333 	nIntValue *= 8640000;
334 	aTime.HundredthSeconds = (sal_uInt16)( nIntValue % 100 );
335 	nIntValue /= 100;
336 	aTime.Seconds = (sal_uInt16)( nIntValue % 60 );
337 	nIntValue /= 60;
338 	aTime.Minutes = (sal_uInt16)( nIntValue % 60 );
339 	nIntValue /= 60;
340 	OSL_ENSURE(nIntValue < 24, "OPropertyImport::implGetTime: more than a day?");
341 	aTime.Hours = static_cast< sal_uInt16 >( nIntValue );
342 
343 	return aTime;
344 }
345 
346 //---------------------------------------------------------------------
implGetDate(double _nValue)347 ::com::sun::star::util::Date OXMLControlProperty::implGetDate(double _nValue)
348 {
349 	Date aToolsDate((sal_uInt32)_nValue);
350 	::com::sun::star::util::Date aDate;
351 	::utl::typeConvert(aToolsDate, aDate);
352 	return aDate;
353 }
354 //----------------------------------------------------------------------------
355 } // namespace rptxml
356 // -----------------------------------------------------------------------------
357