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 //.........................................................................
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
>
50 Sequence
< Property
> m_aProperties
;
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
)
70 sal_Int32 nSingleSets
= _rElements
.getLength();
73 m_aSingleSets
.resize(nSingleSets
);
74 const Reference
< XPropertySet
>* pSingleSets
= _rElements
.getConstArray();
75 ::std::copy(pSingleSets
, pSingleSets
+ nSingleSets
, m_aSingleSets
.begin());
79 compose(_pPropertyMetaData
);
82 //---------------------------------------------------------------------
83 OComposedPropertySet::~OComposedPropertySet()
89 //---------------------------------------------------------------------
90 void OComposedPropertySet::compose(const IPropertySetComposerCallback
* _pMetaData
)
92 sal_Int32 nSingleSets
= m_aSingleSets
.size();
96 // get the properties of the first set
97 Reference
< XPropertySet
> xMasterSet
= m_aSingleSets
[0];
98 Sequence
< Property
> aMasterProps
;
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
;
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
135 while (k
<nSecondaryPropertyCount
&& (pSecondaryProperties
[k
].Name
!= pPrimaryProperty
->Name
))
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
);
172 m_pInfo
= new OComposedPropertySetInfo(m_aProperties
);
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();
187 // check the master state
188 Reference
< XPropertySet
> xMasterSet(m_aSingleSets
[0]);
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
;
225 throw UnknownPropertyException( _rPropertyName
, *this );
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
);
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
);
251 xState
->setPropertyToDefault(_rPropertyName
);
255 //---------------------------------------------------------------------
256 Any SAL_CALL
OComposedPropertySet::getPropertyDefault( const ::rtl::OUString
& ) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
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
);
282 //------------------------------------------------------------------------------
283 void SAL_CALL
OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString
&, const Reference
< XPropertyChangeListener
>& ) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
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
)
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
)
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
)
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
)
353 //.........................................................................
354 } // namespace comphelper
355 //.........................................................................