merged tag ooo/OOO330_m14
[LibreOffice.git] / comphelper / source / property / composedprops.cxx
blob4b44a8fb474e62cbae03f4a7224580d77ff44af4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include <comphelper/composedprops.hxx>
31 #include <com/sun/star/container/XChild.hpp>
32 #include <com/sun/star/beans/XPropertySetInfo.hpp>
33 #include <cppuhelper/implbase1.hxx>
35 //.........................................................................
36 namespace comphelper
38 //.........................................................................
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::beans;
42 using namespace ::com::sun::star::lang;
44 //=====================================================================
45 //= OComposedPropertySetInfo
46 //=====================================================================
47 class OComposedPropertySetInfo : public ::cppu::WeakImplHelper1< XPropertySetInfo >
49 private:
50 Sequence< Property> m_aProperties;
52 public:
53 OComposedPropertySetInfo(const Sequence< Property>& _rProperties);
55 virtual Sequence< Property > SAL_CALL getProperties( ) throw(RuntimeException);
56 virtual Property SAL_CALL getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException);
57 virtual sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException);
60 //=====================================================================
61 //= OComposedPropertySet
62 //=====================================================================
63 //---------------------------------------------------------------------
64 OComposedPropertySet::OComposedPropertySet(
65 const Sequence< Reference< XPropertySet> > & _rElements,
66 const IPropertySetComposerCallback* _pPropertyMetaData)
67 :m_pInfo(NULL)
69 // copy the sequence
70 sal_Int32 nSingleSets = _rElements.getLength();
71 if (nSingleSets)
73 m_aSingleSets.resize(nSingleSets);
74 const Reference< XPropertySet >* pSingleSets = _rElements.getConstArray();
75 ::std::copy(pSingleSets, pSingleSets + nSingleSets, m_aSingleSets.begin());
78 // impl ctor
79 compose(_pPropertyMetaData);
82 //---------------------------------------------------------------------
83 OComposedPropertySet::~OComposedPropertySet()
85 if (m_pInfo)
86 m_pInfo->release();
89 //---------------------------------------------------------------------
90 void OComposedPropertySet::compose(const IPropertySetComposerCallback* _pMetaData)
92 sal_Int32 nSingleSets = m_aSingleSets.size();
94 if (nSingleSets>0)
96 // get the properties of the first set
97 Reference< XPropertySet > xMasterSet = m_aSingleSets[0];
98 Sequence< Property> aMasterProps;
99 if (xMasterSet.is())
100 aMasterProps = xMasterSet->getPropertySetInfo()->getProperties();
101 sal_Int32 nMasterPropsCount = aMasterProps.getLength();
102 const Property* pMasterProps = aMasterProps.getConstArray();
104 // check which of the master properties should be included
105 Sequence<sal_Bool> aInclusionFlags(nMasterPropsCount);
106 sal_Bool* pInclusionFlags = aInclusionFlags.getArray();
108 // the states of all these properties
109 Sequence< PropertyState > aPropertyStates(nMasterPropsCount);
111 for (sal_Int32 i=0; i<nMasterPropsCount; ++i)
112 pInclusionFlags[i] = sal_True;
114 Reference< XPropertySet > xSecondarySet;
115 sal_Int32 nSecondaryPropertyCount;
116 Sequence< Property > aSecondaryProperties;
117 const Property* pPrimaryProperty = aMasterProps.getConstArray();
118 for (sal_Int32 nPrimary=0; nPrimary<nMasterPropsCount; ++nPrimary, ++pPrimaryProperty)
120 if (_pMetaData && !_pMetaData->isComposeable(pPrimaryProperty->Name))
121 // do not include this property
122 pInclusionFlags[nPrimary] = sal_False;
123 else
125 // search the property in all secondary sets
126 for (sal_Int32 i=1; i<nSingleSets; ++i)
128 xSecondarySet = m_aSingleSets[i];
129 aSecondaryProperties = xSecondarySet->getPropertySetInfo()->getProperties();
130 nSecondaryPropertyCount = aSecondaryProperties.getLength();
131 const Property* pSecondaryProperties = aSecondaryProperties.getConstArray();
133 // search the current primary property in the secondary property sequence
134 sal_Int32 k=0;
135 while (k<nSecondaryPropertyCount && (pSecondaryProperties[k].Name != pPrimaryProperty->Name))
136 ++k;
138 if (k >= nSecondaryPropertyCount)
139 // not found -> do not include
140 pInclusionFlags[nPrimary] = sal_False;
145 // count what's left ....
146 sal_Int32 nOverallProperties = 0;
147 for (sal_Int32 nCounter=0; nCounter<nMasterPropsCount; ++nCounter)
149 if (pInclusionFlags[nCounter])
150 ++nOverallProperties;
153 // and finally construct our sequence
154 m_aProperties = Sequence< Property >(nOverallProperties);
155 Property* pProperties = m_aProperties.getArray();
156 const Property* pMasterProperties = pMasterProps;
157 sal_Int32 nOwnProperties = 0;
158 for (sal_Int32 nCopy = 0; nCopy < nMasterPropsCount; ++nCopy, ++pMasterProperties)
160 if (pInclusionFlags[nCopy])
161 pProperties[nOwnProperties++] = *pMasterProperties;
166 //------------------------------------------------------------------------------
167 Reference< XPropertySetInfo > SAL_CALL OComposedPropertySet::getPropertySetInfo( ) throw(RuntimeException)
169 ::osl::MutexGuard aGuard(m_aMutex);
170 if (!m_pInfo)
172 m_pInfo = new OComposedPropertySetInfo(m_aProperties);
173 m_pInfo->acquire();
175 return m_pInfo;
178 //------------------------------------------------------------------------------
179 PropertyState SAL_CALL OComposedPropertySet::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
181 // assume DIRECT for the moment
182 PropertyState eState = PropertyState_DIRECT_VALUE;
184 sal_Int32 nSingleSets = m_aSingleSets.size();
185 if (nSingleSets>0)
187 // check the master state
188 Reference< XPropertySet > xMasterSet(m_aSingleSets[0]);
189 Any aPrimaryValue;
190 if (xMasterSet.is())
192 Reference< XPropertyState > xMasterState(xMasterSet,UNO_QUERY);
193 aPrimaryValue = xMasterSet->getPropertyValue(_rPropertyName);
195 if (xMasterState.is())
196 eState = xMasterState->getPropertyState(_rPropertyName);
199 // loop through the secondary sets
200 PropertyState eSecondaryState;
201 for (sal_Int32 i=1; i<nSingleSets; ++i)
203 Reference< XPropertySet > xSecondary(m_aSingleSets[i]);
204 Reference< XPropertyState > xSecondaryState(xSecondary, UNO_QUERY);
206 // the secondary state
207 eSecondaryState = PropertyState_DIRECT_VALUE;
208 if(xSecondaryState.is())
209 eSecondaryState = xSecondaryState->getPropertyState(_rPropertyName);
211 // the secondary value
212 Any aSecondaryValue(xSecondary->getPropertyValue(_rPropertyName));
214 if ( (PropertyState_AMBIGUOUS_VALUE == eSecondaryState) // secondary is ambiguous
215 || !::comphelper::compare(aPrimaryValue, aSecondaryValue) // unequal values
218 eState = PropertyState_AMBIGUOUS_VALUE;
219 break;
223 else
225 throw UnknownPropertyException( _rPropertyName, *this );
228 return eState;
231 //---------------------------------------------------------------------
232 Sequence< PropertyState > SAL_CALL OComposedPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
234 sal_Int32 nCount = _rPropertyName.getLength();
235 Sequence< PropertyState > aReturn(nCount);
236 const ::rtl::OUString* pNames = _rPropertyName.getConstArray();
237 PropertyState* pStates = aReturn.getArray();
238 for (sal_Int32 i=0; i<nCount; ++i, ++pNames, ++pStates)
239 *pStates = getPropertyState(*pNames);
240 return aReturn;
243 //---------------------------------------------------------------------
244 void SAL_CALL OComposedPropertySet::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
246 sal_Int32 nSingleSets = m_aSingleSets.size();
247 for (sal_Int32 i=0; i<nSingleSets; ++i)
249 Reference< XPropertyState > xState(m_aSingleSets[i], UNO_QUERY);
250 if(xState.is())
251 xState->setPropertyToDefault(_rPropertyName);
255 //---------------------------------------------------------------------
256 Any SAL_CALL OComposedPropertySet::getPropertyDefault( const ::rtl::OUString& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
258 return Any();
261 //------------------------------------------------------------------------------
262 void SAL_CALL OComposedPropertySet::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
264 sal_Int32 nSingleSets = m_aSingleSets.size();
265 for (sal_Int32 i=0; i<nSingleSets; ++i)
267 if (m_aSingleSets[i].is())
268 m_aSingleSets[i]->setPropertyValue(_rPropertyName, _rValue);
272 //------------------------------------------------------------------------------
273 Any SAL_CALL OComposedPropertySet::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
275 sal_Int32 nSingleSets = m_aSingleSets.size();
277 if ((nSingleSets>0) && (m_aSingleSets[0].is()))
278 return m_aSingleSets[0]->getPropertyValue(_rPropertyName);
279 return Any();
282 //------------------------------------------------------------------------------
283 void SAL_CALL OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
285 // TODO:
286 // hold the single property sets weak
287 // be a property change listener on all single property sets (for all composed properties)
288 // upon property change
289 // determine the new state/value of the composed property
290 // broadcast the new composed property value
293 //------------------------------------------------------------------------------
294 void SAL_CALL OComposedPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
296 // TODO
299 //------------------------------------------------------------------------------
300 void SAL_CALL OComposedPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
302 OSL_ENSURE(sal_False, "OComposedPropertySet::addVetoableChangeListener: no implemented (yet)!");
305 //------------------------------------------------------------------------------
306 void SAL_CALL OComposedPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
308 OSL_ENSURE(sal_False, "OComposedPropertySet::removeVetoableChangeListener: no implemented (yet)!");
311 //------------------------------------------------------------------------------
312 OComposedPropertySetInfo::OComposedPropertySetInfo(const Sequence< Property>& rSeq)
313 :m_aProperties(rSeq)
317 //------------------------------------------------------------------------------
318 Sequence< Property> SAL_CALL OComposedPropertySetInfo::getProperties() throw(RuntimeException)
320 return m_aProperties;
323 //------------------------------------------------------------------------------
324 Property SAL_CALL OComposedPropertySetInfo::getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException)
326 sal_Int32 nLength = m_aProperties.getLength();
327 const Property* pProps = m_aProperties.getConstArray();
328 // TODO TODO TODO: this O(n) search really sucks ...
329 for (sal_Int32 i=0; i<nLength; ++i, ++pProps)
331 if (pProps->Name == _rName)
332 return *pProps;
335 throw UnknownPropertyException( _rName, *this );
338 //------------------------------------------------------------------------------
339 sal_Bool SAL_CALL OComposedPropertySetInfo::hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException)
341 sal_Int32 nLength = m_aProperties.getLength();
342 const Property* pProps = m_aProperties.getConstArray();
343 // TODO TODO TODO: this O(n) search really sucks ...
344 for( sal_Int32 i=0; i<nLength; ++i,++pProps )
346 if(pProps->Name == _rName)
347 return sal_True;
350 return sal_False;
353 //.........................................................................
354 } // namespace comphelper
355 //.........................................................................