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_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> 34 35 //......................................................................... 36 namespace comphelper 37 { 38 //......................................................................... 39 40 using namespace ::com::sun::star::uno; 41 using namespace ::com::sun::star::beans; 42 using namespace ::com::sun::star::lang; 43 44 //===================================================================== 45 //= OComposedPropertySetInfo 46 //===================================================================== 47 class OComposedPropertySetInfo : public ::cppu::WeakImplHelper1< XPropertySetInfo > 48 { 49 private: 50 Sequence< Property> m_aProperties; 51 52 public: 53 OComposedPropertySetInfo(const Sequence< Property>& _rProperties); 54 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); 58 }; 59 60 //===================================================================== 61 //= OComposedPropertySet 62 //===================================================================== 63 //--------------------------------------------------------------------- 64 OComposedPropertySet::OComposedPropertySet( 65 const Sequence< Reference< XPropertySet> > & _rElements, 66 const IPropertySetComposerCallback* _pPropertyMetaData) 67 :m_pInfo(NULL) 68 { 69 // copy the sequence 70 sal_Int32 nSingleSets = _rElements.getLength(); 71 if (nSingleSets) 72 { 73 m_aSingleSets.resize(nSingleSets); 74 const Reference< XPropertySet >* pSingleSets = _rElements.getConstArray(); 75 ::std::copy(pSingleSets, pSingleSets + nSingleSets, m_aSingleSets.begin()); 76 } 77 78 // impl ctor 79 compose(_pPropertyMetaData); 80 } 81 82 //--------------------------------------------------------------------- 83 OComposedPropertySet::~OComposedPropertySet() 84 { 85 if (m_pInfo) 86 m_pInfo->release(); 87 } 88 89 //--------------------------------------------------------------------- 90 void OComposedPropertySet::compose(const IPropertySetComposerCallback* _pMetaData) 91 { 92 sal_Int32 nSingleSets = m_aSingleSets.size(); 93 94 if (nSingleSets>0) 95 { 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(); 103 104 // check which of the master properties should be included 105 Sequence<sal_Bool> aInclusionFlags(nMasterPropsCount); 106 sal_Bool* pInclusionFlags = aInclusionFlags.getArray(); 107 108 // the states of all these properties 109 Sequence< PropertyState > aPropertyStates(nMasterPropsCount); 110 111 for (sal_Int32 i=0; i<nMasterPropsCount; ++i) 112 pInclusionFlags[i] = sal_True; 113 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) 119 { 120 if (_pMetaData && !_pMetaData->isComposeable(pPrimaryProperty->Name)) 121 // do not include this property 122 pInclusionFlags[nPrimary] = sal_False; 123 else 124 { 125 // search the property in all secondary sets 126 for (sal_Int32 i=1; i<nSingleSets; ++i) 127 { 128 xSecondarySet = m_aSingleSets[i]; 129 aSecondaryProperties = xSecondarySet->getPropertySetInfo()->getProperties(); 130 nSecondaryPropertyCount = aSecondaryProperties.getLength(); 131 const Property* pSecondaryProperties = aSecondaryProperties.getConstArray(); 132 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; 137 138 if (k >= nSecondaryPropertyCount) 139 // not found -> do not include 140 pInclusionFlags[nPrimary] = sal_False; 141 } 142 } 143 } 144 145 // count what's left .... 146 sal_Int32 nOverallProperties = 0; 147 for (sal_Int32 nCounter=0; nCounter<nMasterPropsCount; ++nCounter) 148 { 149 if (pInclusionFlags[nCounter]) 150 ++nOverallProperties; 151 } 152 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) 159 { 160 if (pInclusionFlags[nCopy]) 161 pProperties[nOwnProperties++] = *pMasterProperties; 162 } 163 } 164 } 165 166 //------------------------------------------------------------------------------ 167 Reference< XPropertySetInfo > SAL_CALL OComposedPropertySet::getPropertySetInfo( ) throw(RuntimeException) 168 { 169 ::osl::MutexGuard aGuard(m_aMutex); 170 if (!m_pInfo) 171 { 172 m_pInfo = new OComposedPropertySetInfo(m_aProperties); 173 m_pInfo->acquire(); 174 } 175 return m_pInfo; 176 } 177 178 //------------------------------------------------------------------------------ 179 PropertyState SAL_CALL OComposedPropertySet::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException) 180 { 181 // assume DIRECT for the moment 182 PropertyState eState = PropertyState_DIRECT_VALUE; 183 184 sal_Int32 nSingleSets = m_aSingleSets.size(); 185 if (nSingleSets>0) 186 { 187 // check the master state 188 Reference< XPropertySet > xMasterSet(m_aSingleSets[0]); 189 Any aPrimaryValue; 190 if (xMasterSet.is()) 191 { 192 Reference< XPropertyState > xMasterState(xMasterSet,UNO_QUERY); 193 aPrimaryValue = xMasterSet->getPropertyValue(_rPropertyName); 194 195 if (xMasterState.is()) 196 eState = xMasterState->getPropertyState(_rPropertyName); 197 } 198 199 // loop through the secondary sets 200 PropertyState eSecondaryState; 201 for (sal_Int32 i=1; i<nSingleSets; ++i) 202 { 203 Reference< XPropertySet > xSecondary(m_aSingleSets[i]); 204 Reference< XPropertyState > xSecondaryState(xSecondary, UNO_QUERY); 205 206 // the secondary state 207 eSecondaryState = PropertyState_DIRECT_VALUE; 208 if(xSecondaryState.is()) 209 eSecondaryState = xSecondaryState->getPropertyState(_rPropertyName); 210 211 // the secondary value 212 Any aSecondaryValue(xSecondary->getPropertyValue(_rPropertyName)); 213 214 if ( (PropertyState_AMBIGUOUS_VALUE == eSecondaryState) // secondary is ambiguous 215 || !::comphelper::compare(aPrimaryValue, aSecondaryValue) // unequal values 216 ) 217 { 218 eState = PropertyState_AMBIGUOUS_VALUE; 219 break; 220 } 221 } 222 } 223 else 224 { 225 throw UnknownPropertyException( _rPropertyName, *this ); 226 } 227 228 return eState; 229 } 230 231 //--------------------------------------------------------------------- 232 Sequence< PropertyState > SAL_CALL OComposedPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyName ) throw(UnknownPropertyException, RuntimeException) 233 { 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; 241 } 242 243 //--------------------------------------------------------------------- 244 void SAL_CALL OComposedPropertySet::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException) 245 { 246 sal_Int32 nSingleSets = m_aSingleSets.size(); 247 for (sal_Int32 i=0; i<nSingleSets; ++i) 248 { 249 Reference< XPropertyState > xState(m_aSingleSets[i], UNO_QUERY); 250 if(xState.is()) 251 xState->setPropertyToDefault(_rPropertyName); 252 } 253 } 254 255 //--------------------------------------------------------------------- 256 Any SAL_CALL OComposedPropertySet::getPropertyDefault( const ::rtl::OUString& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 257 { 258 return Any(); 259 } 260 261 //------------------------------------------------------------------------------ 262 void SAL_CALL OComposedPropertySet::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) 263 { 264 sal_Int32 nSingleSets = m_aSingleSets.size(); 265 for (sal_Int32 i=0; i<nSingleSets; ++i) 266 { 267 if (m_aSingleSets[i].is()) 268 m_aSingleSets[i]->setPropertyValue(_rPropertyName, _rValue); 269 } 270 } 271 272 //------------------------------------------------------------------------------ 273 Any SAL_CALL OComposedPropertySet::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 274 { 275 sal_Int32 nSingleSets = m_aSingleSets.size(); 276 277 if ((nSingleSets>0) && (m_aSingleSets[0].is())) 278 return m_aSingleSets[0]->getPropertyValue(_rPropertyName); 279 return Any(); 280 } 281 282 //------------------------------------------------------------------------------ 283 void SAL_CALL OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 284 { 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 291 } 292 293 //------------------------------------------------------------------------------ 294 void SAL_CALL OComposedPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 295 { 296 // TODO 297 } 298 299 //------------------------------------------------------------------------------ 300 void SAL_CALL OComposedPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 301 { 302 OSL_ENSURE(sal_False, "OComposedPropertySet::addVetoableChangeListener: no implemented (yet)!"); 303 } 304 305 //------------------------------------------------------------------------------ 306 void SAL_CALL OComposedPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 307 { 308 OSL_ENSURE(sal_False, "OComposedPropertySet::removeVetoableChangeListener: no implemented (yet)!"); 309 } 310 311 //------------------------------------------------------------------------------ 312 OComposedPropertySetInfo::OComposedPropertySetInfo(const Sequence< Property>& rSeq) 313 :m_aProperties(rSeq) 314 { 315 } 316 317 //------------------------------------------------------------------------------ 318 Sequence< Property> SAL_CALL OComposedPropertySetInfo::getProperties() throw(RuntimeException) 319 { 320 return m_aProperties; 321 } 322 323 //------------------------------------------------------------------------------ 324 Property SAL_CALL OComposedPropertySetInfo::getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException) 325 { 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) 330 { 331 if (pProps->Name == _rName) 332 return *pProps; 333 } 334 335 throw UnknownPropertyException( _rName, *this ); 336 } 337 338 //------------------------------------------------------------------------------ 339 sal_Bool SAL_CALL OComposedPropertySetInfo::hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException) 340 { 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 ) 345 { 346 if(pProps->Name == _rName) 347 return sal_True; 348 } 349 350 return sal_False; 351 } 352 353 //......................................................................... 354 } // namespace comphelper 355 //......................................................................... 356 357 358