1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: composedprops.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_comphelper.hxx"
33 #include <comphelper/composedprops.hxx>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <cppuhelper/implbase1.hxx>
38 //.........................................................................
41 //.........................................................................
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::beans
;
45 using namespace ::com::sun::star::lang
;
47 //=====================================================================
48 //= OComposedPropertySetInfo
49 //=====================================================================
50 class OComposedPropertySetInfo
: public ::cppu::WeakImplHelper1
< XPropertySetInfo
>
53 Sequence
< Property
> m_aProperties
;
56 OComposedPropertySetInfo(const Sequence
< Property
>& _rProperties
);
58 virtual Sequence
< Property
> SAL_CALL
getProperties( ) throw(RuntimeException
);
59 virtual Property SAL_CALL
getPropertyByName( const ::rtl::OUString
& _rName
) throw(UnknownPropertyException
, RuntimeException
);
60 virtual sal_Bool SAL_CALL
hasPropertyByName( const ::rtl::OUString
& _rName
) throw(RuntimeException
);
63 //=====================================================================
64 //= OComposedPropertySet
65 //=====================================================================
66 //---------------------------------------------------------------------
67 OComposedPropertySet::OComposedPropertySet(
68 const Sequence
< Reference
< XPropertySet
> > & _rElements
,
69 const IPropertySetComposerCallback
* _pPropertyMetaData
)
73 sal_Int32 nSingleSets
= _rElements
.getLength();
76 m_aSingleSets
.resize(nSingleSets
);
77 const Reference
< XPropertySet
>* pSingleSets
= _rElements
.getConstArray();
78 ::std::copy(pSingleSets
, pSingleSets
+ nSingleSets
, m_aSingleSets
.begin());
82 compose(_pPropertyMetaData
);
85 //---------------------------------------------------------------------
86 OComposedPropertySet::~OComposedPropertySet()
92 //---------------------------------------------------------------------
93 void OComposedPropertySet::compose(const IPropertySetComposerCallback
* _pMetaData
)
95 sal_Int32 nSingleSets
= m_aSingleSets
.size();
99 // get the properties of the first set
100 Reference
< XPropertySet
> xMasterSet
= m_aSingleSets
[0];
101 Sequence
< Property
> aMasterProps
;
103 aMasterProps
= xMasterSet
->getPropertySetInfo()->getProperties();
104 sal_Int32 nMasterPropsCount
= aMasterProps
.getLength();
105 const Property
* pMasterProps
= aMasterProps
.getConstArray();
107 // check which of the master properties should be included
108 Sequence
<sal_Bool
> aInclusionFlags(nMasterPropsCount
);
109 sal_Bool
* pInclusionFlags
= aInclusionFlags
.getArray();
111 // the states of all these properties
112 Sequence
< PropertyState
> aPropertyStates(nMasterPropsCount
);
114 for (sal_Int32 i
=0; i
<nMasterPropsCount
; ++i
)
115 pInclusionFlags
[i
] = sal_True
;
117 Reference
< XPropertySet
> xSecondarySet
;
118 sal_Int32 nSecondaryPropertyCount
;
119 Sequence
< Property
> aSecondaryProperties
;
120 const Property
* pPrimaryProperty
= aMasterProps
.getConstArray();
121 for (sal_Int32 nPrimary
=0; nPrimary
<nMasterPropsCount
; ++nPrimary
, ++pPrimaryProperty
)
123 if (_pMetaData
&& !_pMetaData
->isComposeable(pPrimaryProperty
->Name
))
124 // do not include this property
125 pInclusionFlags
[nPrimary
] = sal_False
;
128 // search the property in all secondary sets
129 for (sal_Int32 i
=1; i
<nSingleSets
; ++i
)
131 xSecondarySet
= m_aSingleSets
[i
];
132 aSecondaryProperties
= xSecondarySet
->getPropertySetInfo()->getProperties();
133 nSecondaryPropertyCount
= aSecondaryProperties
.getLength();
134 const Property
* pSecondaryProperties
= aSecondaryProperties
.getConstArray();
136 // search the current primary property in the secondary property sequence
138 while (k
<nSecondaryPropertyCount
&& (pSecondaryProperties
[k
].Name
!= pPrimaryProperty
->Name
))
141 if (k
>= nSecondaryPropertyCount
)
142 // not found -> do not include
143 pInclusionFlags
[nPrimary
] = sal_False
;
148 // count what's left ....
149 sal_Int32 nOverallProperties
= 0;
150 for (sal_Int32 nCounter
=0; nCounter
<nMasterPropsCount
; ++nCounter
)
152 if (pInclusionFlags
[nCounter
])
153 ++nOverallProperties
;
156 // and finally construct our sequence
157 m_aProperties
= Sequence
< Property
>(nOverallProperties
);
158 Property
* pProperties
= m_aProperties
.getArray();
159 const Property
* pMasterProperties
= pMasterProps
;
160 sal_Int32 nOwnProperties
= 0;
161 for (sal_Int32 nCopy
= 0; nCopy
< nMasterPropsCount
; ++nCopy
, ++pMasterProperties
)
163 if (pInclusionFlags
[nCopy
])
164 pProperties
[nOwnProperties
++] = *pMasterProperties
;
169 //------------------------------------------------------------------------------
170 Reference
< XPropertySetInfo
> SAL_CALL
OComposedPropertySet::getPropertySetInfo( ) throw(RuntimeException
)
172 ::osl::MutexGuard
aGuard(m_aMutex
);
175 m_pInfo
= new OComposedPropertySetInfo(m_aProperties
);
181 //------------------------------------------------------------------------------
182 PropertyState SAL_CALL
OComposedPropertySet::getPropertyState( const ::rtl::OUString
& _rPropertyName
) throw(UnknownPropertyException
, RuntimeException
)
184 // assume DIRECT for the moment
185 PropertyState eState
= PropertyState_DIRECT_VALUE
;
187 sal_Int32 nSingleSets
= m_aSingleSets
.size();
190 // check the master state
191 Reference
< XPropertySet
> xMasterSet(m_aSingleSets
[0]);
195 Reference
< XPropertyState
> xMasterState(xMasterSet
,UNO_QUERY
);
196 aPrimaryValue
= xMasterSet
->getPropertyValue(_rPropertyName
);
198 if (xMasterState
.is())
199 eState
= xMasterState
->getPropertyState(_rPropertyName
);
202 // loop through the secondary sets
203 PropertyState eSecondaryState
;
204 for (sal_Int32 i
=1; i
<nSingleSets
; ++i
)
206 Reference
< XPropertySet
> xSecondary(m_aSingleSets
[i
]);
207 Reference
< XPropertyState
> xSecondaryState(xSecondary
, UNO_QUERY
);
209 // the secondary state
210 eSecondaryState
= PropertyState_DIRECT_VALUE
;
211 if(xSecondaryState
.is())
212 eSecondaryState
= xSecondaryState
->getPropertyState(_rPropertyName
);
214 // the secondary value
215 Any
aSecondaryValue(xSecondary
->getPropertyValue(_rPropertyName
));
217 if ( (PropertyState_AMBIGUOUS_VALUE
== eSecondaryState
) // secondary is ambiguous
218 || !::comphelper::compare(aPrimaryValue
, aSecondaryValue
) // unequal values
221 eState
= PropertyState_AMBIGUOUS_VALUE
;
228 throw UnknownPropertyException( _rPropertyName
, *this );
234 //---------------------------------------------------------------------
235 Sequence
< PropertyState
> SAL_CALL
OComposedPropertySet::getPropertyStates( const Sequence
< ::rtl::OUString
>& _rPropertyName
) throw(UnknownPropertyException
, RuntimeException
)
237 sal_Int32 nCount
= _rPropertyName
.getLength();
238 Sequence
< PropertyState
> aReturn(nCount
);
239 const ::rtl::OUString
* pNames
= _rPropertyName
.getConstArray();
240 PropertyState
* pStates
= aReturn
.getArray();
241 for (sal_Int32 i
=0; i
<nCount
; ++i
, ++pNames
, ++pStates
)
242 *pStates
= getPropertyState(*pNames
);
246 //---------------------------------------------------------------------
247 void SAL_CALL
OComposedPropertySet::setPropertyToDefault( const ::rtl::OUString
& _rPropertyName
) throw(UnknownPropertyException
, RuntimeException
)
249 sal_Int32 nSingleSets
= m_aSingleSets
.size();
250 for (sal_Int32 i
=0; i
<nSingleSets
; ++i
)
252 Reference
< XPropertyState
> xState(m_aSingleSets
[i
], UNO_QUERY
);
254 xState
->setPropertyToDefault(_rPropertyName
);
258 //---------------------------------------------------------------------
259 Any SAL_CALL
OComposedPropertySet::getPropertyDefault( const ::rtl::OUString
& ) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
264 //------------------------------------------------------------------------------
265 void SAL_CALL
OComposedPropertySet::setPropertyValue( const ::rtl::OUString
& _rPropertyName
, const Any
& _rValue
) throw(UnknownPropertyException
, PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
267 sal_Int32 nSingleSets
= m_aSingleSets
.size();
268 for (sal_Int32 i
=0; i
<nSingleSets
; ++i
)
270 if (m_aSingleSets
[i
].is())
271 m_aSingleSets
[i
]->setPropertyValue(_rPropertyName
, _rValue
);
275 //------------------------------------------------------------------------------
276 Any SAL_CALL
OComposedPropertySet::getPropertyValue( const ::rtl::OUString
& _rPropertyName
) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
278 sal_Int32 nSingleSets
= m_aSingleSets
.size();
280 if ((nSingleSets
>0) && (m_aSingleSets
[0].is()))
281 return m_aSingleSets
[0]->getPropertyValue(_rPropertyName
);
285 //------------------------------------------------------------------------------
286 void SAL_CALL
OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString
&, const Reference
< XPropertyChangeListener
>& ) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
289 // hold the single property sets weak
290 // be a property change listener on all single property sets (for all composed properties)
291 // upon property change
292 // determine the new state/value of the composed property
293 // broadcast the new composed property value
296 //------------------------------------------------------------------------------
297 void SAL_CALL
OComposedPropertySet::removePropertyChangeListener( const ::rtl::OUString
&, const Reference
< XPropertyChangeListener
>& ) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
302 //------------------------------------------------------------------------------
303 void SAL_CALL
OComposedPropertySet::addVetoableChangeListener( const ::rtl::OUString
&, const Reference
< XVetoableChangeListener
>& ) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
305 OSL_ENSURE(sal_False
, "OComposedPropertySet::addVetoableChangeListener: no implemented (yet)!");
308 //------------------------------------------------------------------------------
309 void SAL_CALL
OComposedPropertySet::removeVetoableChangeListener( const ::rtl::OUString
&, const Reference
< XVetoableChangeListener
>& ) throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
311 OSL_ENSURE(sal_False
, "OComposedPropertySet::removeVetoableChangeListener: no implemented (yet)!");
314 //------------------------------------------------------------------------------
315 OComposedPropertySetInfo::OComposedPropertySetInfo(const Sequence
< Property
>& rSeq
)
320 //------------------------------------------------------------------------------
321 Sequence
< Property
> SAL_CALL
OComposedPropertySetInfo::getProperties() throw(RuntimeException
)
323 return m_aProperties
;
326 //------------------------------------------------------------------------------
327 Property SAL_CALL
OComposedPropertySetInfo::getPropertyByName( const ::rtl::OUString
& _rName
) throw(UnknownPropertyException
, RuntimeException
)
329 sal_Int32 nLength
= m_aProperties
.getLength();
330 const Property
* pProps
= m_aProperties
.getConstArray();
331 // TODO TODO TODO: this O(n) search really sucks ...
332 for (sal_Int32 i
=0; i
<nLength
; ++i
, ++pProps
)
334 if (pProps
->Name
== _rName
)
338 throw UnknownPropertyException( _rName
, *this );
341 //------------------------------------------------------------------------------
342 sal_Bool SAL_CALL
OComposedPropertySetInfo::hasPropertyByName( const ::rtl::OUString
& _rName
) throw(RuntimeException
)
344 sal_Int32 nLength
= m_aProperties
.getLength();
345 const Property
* pProps
= m_aProperties
.getConstArray();
346 // TODO TODO TODO: this O(n) search really sucks ...
347 for( sal_Int32 i
=0; i
<nLength
; ++i
,++pProps
)
349 if(pProps
->Name
== _rName
)
356 //.........................................................................
357 } // namespace comphelper
358 //.........................................................................