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_chart2.hxx"
30 
31 #include "UncachedDataSequence.hxx"
32 #include "macros.hxx"
33 #include "PropertyHelper.hxx"
34 #include "CommonFunctors.hxx"
35 #include "ModifyListenerHelper.hxx"
36 
37 #include <algorithm>
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #include <rtl/math.hxx>
40 
41 using namespace ::com::sun::star;
42 
43 using ::com::sun::star::uno::Sequence;
44 using ::com::sun::star::uno::Reference;
45 using ::com::sun::star::uno::Any;
46 using ::rtl::OUString;
47 using ::osl::MutexGuard;
48 
49 // necessary for MS compiler
50 using ::comphelper::OPropertyContainer;
51 using ::chart::impl::UncachedDataSequence_Base;
52 
53 namespace
54 {
55 static const OUString lcl_aServiceName(
56     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.UncachedDataSequence" ));
57 
58 enum
59 {
60 //     PROP_SOURCE_IDENTIFIER,
61     PROP_NUMBERFORMAT_KEY,
62     PROP_PROPOSED_ROLE,
63     PROP_XML_RANGE
64 };
65 }  // anonymous namespace
66 
67 
68 // ____________________
69 namespace chart
70 {
71 
72 UncachedDataSequence::UncachedDataSequence(
73     const Reference< chart2::XInternalDataProvider > & xIntDataProv,
74     const OUString & rRangeRepresentation )
75         : OPropertyContainer( GetBroadcastHelper()),
76           UncachedDataSequence_Base( GetMutex()),
77           m_nNumberFormatKey(0),
78           m_xDataProvider( xIntDataProv ),
79           m_aSourceRepresentation( rRangeRepresentation ),
80           m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
81 {
82     registerProperties();
83 }
84 
85 UncachedDataSequence::UncachedDataSequence(
86     const Reference< chart2::XInternalDataProvider > & xIntDataProv,
87     const OUString & rRangeRepresentation,
88     const OUString & rRole )
89         : OPropertyContainer( GetBroadcastHelper()),
90           UncachedDataSequence_Base( GetMutex()),
91           m_nNumberFormatKey(0),
92           m_xDataProvider( xIntDataProv ),
93           m_aSourceRepresentation( rRangeRepresentation ),
94           m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
95 {
96     registerProperties();
97     setFastPropertyValue_NoBroadcast( PROP_PROPOSED_ROLE, uno::makeAny( rRole ));
98 }
99 
100 UncachedDataSequence::UncachedDataSequence( const UncachedDataSequence & rSource )
101         : ::comphelper::OMutexAndBroadcastHelper(),
102           OPropertyContainer( GetBroadcastHelper()),
103           ::comphelper::OPropertyArrayUsageHelper< UncachedDataSequence >(),
104           UncachedDataSequence_Base( GetMutex()),
105           m_nNumberFormatKey( rSource.m_nNumberFormatKey ),
106           m_sRole( rSource.m_sRole ),
107           m_xDataProvider( rSource.m_xDataProvider ),
108           m_aSourceRepresentation( rSource.m_aSourceRepresentation ),
109           m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
110 {
111     registerProperties();
112 }
113 
114 UncachedDataSequence::~UncachedDataSequence()
115 {}
116 
117 void UncachedDataSequence::registerProperties()
118 {
119     registerProperty( C2U( "NumberFormatKey" ),
120                       PROP_NUMBERFORMAT_KEY,
121                       0,   // PropertyAttributes
122                       & m_nNumberFormatKey,
123                       ::getCppuType( & m_nNumberFormatKey ) );
124 
125     registerProperty( C2U( "Role" ),
126                       PROP_PROPOSED_ROLE,
127                       0,   // PropertyAttributes
128                       & m_sRole,
129                       ::getCppuType( & m_sRole ) );
130 
131     registerProperty( C2U( "CachedXMLRange" ),
132                       PROP_XML_RANGE,
133                       0,   // PropertyAttributes
134                       & m_aXMLRange,
135                       ::getCppuType( & m_aXMLRange ) );
136 }
137 
138 // ================================================================================
139 
140 Sequence< OUString > UncachedDataSequence::getSupportedServiceNames_Static()
141 {
142     Sequence< OUString > aServices( 4 );
143     aServices[ 0 ] = lcl_aServiceName;
144     aServices[ 1 ] = C2U( "com.sun.star.chart2.data.DataSequence" );
145     aServices[ 2 ] = C2U( "com.sun.star.chart2.data.NumericalDataSequence" );
146     aServices[ 3 ] = C2U( "com.sun.star.chart2.data.TextualDataSequence" );
147     return aServices;
148 }
149 
150 IMPLEMENT_FORWARD_XINTERFACE2( UncachedDataSequence, UncachedDataSequence_Base, OPropertyContainer )
151 IMPLEMENT_FORWARD_XTYPEPROVIDER2( UncachedDataSequence, UncachedDataSequence_Base, OPropertyContainer )
152 
153 // ____ XPropertySet ____
154 Reference< beans::XPropertySetInfo > SAL_CALL UncachedDataSequence::getPropertySetInfo()
155     throw(uno::RuntimeException)
156 {
157     return Reference< beans::XPropertySetInfo >( createPropertySetInfo( getInfoHelper() ) );
158 }
159 
160 // ____ ::comphelper::OPropertySetHelper ____
161 // __________________________________________
162 ::cppu::IPropertyArrayHelper& UncachedDataSequence::getInfoHelper()
163 {
164 	return *getArrayHelper();
165 }
166 
167 // ____ ::comphelper::OPropertyArrayHelper ____
168 // ____________________________________________
169 ::cppu::IPropertyArrayHelper* UncachedDataSequence::createArrayHelper() const
170 {
171 	Sequence< beans::Property > aProps;
172     // describes all properties which have been registered in the ctor
173 	describeProperties( aProps );
174 
175 	return new ::cppu::OPropertyArrayHelper( aProps );
176 }
177 
178 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
179 APPHELPER_XSERVICEINFO_IMPL( UncachedDataSequence, lcl_aServiceName )
180 
181 // ================================================================================
182 
183 // ________ XNumericalDataSequence ________
184 Sequence< double > SAL_CALL UncachedDataSequence::getNumericalData()
185     throw (uno::RuntimeException)
186 {
187     Sequence< double > aResult;
188     // /--
189     MutexGuard aGuard( GetMutex() );
190     if( m_xDataProvider.is())
191     {
192         Sequence< uno::Any > aValues( m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation ));
193         aResult.realloc( aValues.getLength());
194         ::std::transform( aValues.getConstArray(), aValues.getConstArray() + aValues.getLength(),
195                           aResult.getArray(), CommonFunctors::AnyToDouble());
196     }
197     return aResult;
198     // \--
199 }
200 
201 // ________ XTextualDataSequence ________
202 Sequence< OUString > SAL_CALL UncachedDataSequence::getTextualData()
203     throw (uno::RuntimeException)
204 {
205     Sequence< OUString > aResult;
206     // /--
207     MutexGuard aGuard( GetMutex() );
208     if( m_xDataProvider.is())
209     {
210         Sequence< uno::Any > aValues( m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation ));
211         aResult.realloc( aValues.getLength());
212         ::std::transform( aValues.getConstArray(), aValues.getConstArray() + aValues.getLength(),
213                           aResult.getArray(), CommonFunctors::AnyToString());
214     }
215     return aResult;
216     // \--
217 }
218 
219 // ________ XDataSequence  ________
220 Sequence< Any > SAL_CALL UncachedDataSequence::getData()
221     throw (uno::RuntimeException)
222 {
223     // /--
224     MutexGuard aGuard( GetMutex() );
225     if( m_xDataProvider.is())
226         return m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation );
227     return Sequence< Any >();
228     // \--
229 }
230 
231 OUString SAL_CALL UncachedDataSequence::getSourceRangeRepresentation()
232     throw (uno::RuntimeException)
233 {
234     return getName();
235 }
236 
237 
238 Sequence< OUString > SAL_CALL UncachedDataSequence::generateLabel( chart2::data::LabelOrigin )
239     throw (uno::RuntimeException)
240 {
241     // auto-generated label is an empty string
242     static const Sequence< OUString > aOneEmptyString( 1 );
243     return aOneEmptyString;
244 }
245 
246 ::sal_Int32 SAL_CALL UncachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 )
247     throw (lang::IndexOutOfBoundsException,
248            uno::RuntimeException)
249 {
250     return m_nNumberFormatKey;
251 }
252 
253 // ____ XIndexReplace ____
254 void SAL_CALL UncachedDataSequence::replaceByIndex( ::sal_Int32 Index, const uno::Any& Element )
255     throw (lang::IllegalArgumentException,
256            lang::IndexOutOfBoundsException,
257            lang::WrappedTargetException,
258            uno::RuntimeException)
259 {
260     // /--
261     MutexGuard aGuard( GetMutex() );
262     Sequence< Any > aData( getData());
263     if( Index < aData.getLength() &&
264         m_xDataProvider.is() )
265     {
266         aData[Index] = Element;
267         m_xDataProvider->setDataByRangeRepresentation( m_aSourceRepresentation, aData );
268         fireModifyEvent();
269     }
270 }
271 
272 // ____ XIndexAccess (base of XIndexReplace) ____
273 ::sal_Int32 SAL_CALL UncachedDataSequence::getCount()
274     throw (uno::RuntimeException)
275 {
276     OSL_ENSURE( false, "Implement!" );
277     return 0;
278 }
279 
280 uno::Any SAL_CALL UncachedDataSequence::getByIndex( ::sal_Int32 )
281     throw (lang::IndexOutOfBoundsException,
282            lang::WrappedTargetException,
283            uno::RuntimeException)
284 {
285     OSL_ENSURE( false, "Implement!" );
286     return uno::Any();
287 }
288 
289 // ____ XElementAccess (base of XIndexAccess) ____
290 uno::Type SAL_CALL UncachedDataSequence::getElementType()
291     throw (uno::RuntimeException)
292 {
293     return ::getCppuType( reinterpret_cast< uno::Any * >(0));
294 }
295 
296 ::sal_Bool SAL_CALL UncachedDataSequence::hasElements()
297     throw (uno::RuntimeException)
298 {
299     if( ! m_xDataProvider.is())
300         return sal_False;
301     return m_xDataProvider->hasDataByRangeRepresentation( m_aSourceRepresentation );
302 }
303 
304 // ____ XNamed ____
305 ::rtl::OUString SAL_CALL UncachedDataSequence::getName()
306     throw (uno::RuntimeException)
307 {
308     return m_aSourceRepresentation;
309 }
310 
311 void SAL_CALL UncachedDataSequence::setName( const OUString& aName )
312     throw (uno::RuntimeException)
313 {
314     m_aSourceRepresentation = aName;
315     fireModifyEvent();
316 }
317 
318 
319 
320 Reference< util::XCloneable > SAL_CALL UncachedDataSequence::createClone()
321     throw (uno::RuntimeException)
322 {
323     UncachedDataSequence * pNewSeq = new UncachedDataSequence( *this );
324     return Reference< util::XCloneable >( pNewSeq );
325 }
326 
327 
328 // ____ XModifiable ____
329 ::sal_Bool SAL_CALL UncachedDataSequence::isModified()
330     throw (uno::RuntimeException)
331 {
332     return sal_False;
333 }
334 
335 void SAL_CALL UncachedDataSequence::setModified( ::sal_Bool bModified )
336     throw (beans::PropertyVetoException,
337            uno::RuntimeException)
338 {
339     if( bModified )
340         fireModifyEvent();
341 }
342 
343 // ____ XModifyBroadcaster (base of XModifiable) ____
344 void SAL_CALL UncachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener )
345     throw (uno::RuntimeException)
346 {
347     try
348     {
349         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
350         xBroadcaster->addModifyListener( aListener );
351     }
352     catch( const uno::Exception & ex )
353     {
354         ASSERT_EXCEPTION( ex );
355     }
356 }
357 
358 void SAL_CALL UncachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener )
359     throw (uno::RuntimeException)
360 {
361     try
362     {
363         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
364         xBroadcaster->removeModifyListener( aListener );
365     }
366     catch( const uno::Exception & ex )
367     {
368         ASSERT_EXCEPTION( ex );
369     }
370 }
371 
372 void UncachedDataSequence::fireModifyEvent()
373 {
374     // @todo: currently never called, as data changes are not yet reported by
375     // the data provider
376     m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
377 }
378 
379 }  // namespace chart
380