1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_comphelper.hxx" 26 #include <comphelper/composedprops.hxx> 27 #include <com/sun/star/container/XChild.hpp> 28 #include <com/sun/star/beans/XPropertySetInfo.hpp> 29 #include <cppuhelper/implbase1.hxx> 30 31 //......................................................................... 32 namespace comphelper 33 { 34 //......................................................................... 35 36 using namespace ::com::sun::star::uno; 37 using namespace ::com::sun::star::beans; 38 using namespace ::com::sun::star::lang; 39 40 //===================================================================== 41 //= OComposedPropertySetInfo 42 //===================================================================== 43 class OComposedPropertySetInfo : public ::cppu::WeakImplHelper1< XPropertySetInfo > 44 { 45 private: 46 Sequence< Property> m_aProperties; 47 48 public: 49 OComposedPropertySetInfo(const Sequence< Property>& _rProperties); 50 51 virtual Sequence< Property > SAL_CALL getProperties( ) throw(RuntimeException); 52 virtual Property SAL_CALL getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException); 53 virtual sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException); 54 }; 55 56 //===================================================================== 57 //= OComposedPropertySet 58 //===================================================================== 59 //--------------------------------------------------------------------- OComposedPropertySet(const Sequence<Reference<XPropertySet>> & _rElements,const IPropertySetComposerCallback * _pPropertyMetaData)60 OComposedPropertySet::OComposedPropertySet( 61 const Sequence< Reference< XPropertySet> > & _rElements, 62 const IPropertySetComposerCallback* _pPropertyMetaData) 63 :m_pInfo(NULL) 64 { 65 // copy the sequence 66 sal_Int32 nSingleSets = _rElements.getLength(); 67 if (nSingleSets) 68 { 69 m_aSingleSets.resize(nSingleSets); 70 const Reference< XPropertySet >* pSingleSets = _rElements.getConstArray(); 71 ::std::copy(pSingleSets, pSingleSets + nSingleSets, m_aSingleSets.begin()); 72 } 73 74 // impl ctor 75 compose(_pPropertyMetaData); 76 } 77 78 //--------------------------------------------------------------------- ~OComposedPropertySet()79 OComposedPropertySet::~OComposedPropertySet() 80 { 81 if (m_pInfo) 82 m_pInfo->release(); 83 } 84 85 //--------------------------------------------------------------------- compose(const IPropertySetComposerCallback * _pMetaData)86 void OComposedPropertySet::compose(const IPropertySetComposerCallback* _pMetaData) 87 { 88 sal_Int32 nSingleSets = m_aSingleSets.size(); 89 90 if (nSingleSets>0) 91 { 92 // get the properties of the first set 93 Reference< XPropertySet > xMasterSet = m_aSingleSets[0]; 94 Sequence< Property> aMasterProps; 95 if (xMasterSet.is()) 96 aMasterProps = xMasterSet->getPropertySetInfo()->getProperties(); 97 sal_Int32 nMasterPropsCount = aMasterProps.getLength(); 98 const Property* pMasterProps = aMasterProps.getConstArray(); 99 100 // check which of the master properties should be included 101 Sequence<sal_Bool> aInclusionFlags(nMasterPropsCount); 102 sal_Bool* pInclusionFlags = aInclusionFlags.getArray(); 103 104 // the states of all these properties 105 Sequence< PropertyState > aPropertyStates(nMasterPropsCount); 106 107 for (sal_Int32 i=0; i<nMasterPropsCount; ++i) 108 pInclusionFlags[i] = sal_True; 109 110 Reference< XPropertySet > xSecondarySet; 111 sal_Int32 nSecondaryPropertyCount; 112 Sequence< Property > aSecondaryProperties; 113 const Property* pPrimaryProperty = aMasterProps.getConstArray(); 114 for (sal_Int32 nPrimary=0; nPrimary<nMasterPropsCount; ++nPrimary, ++pPrimaryProperty) 115 { 116 if (_pMetaData && !_pMetaData->isComposeable(pPrimaryProperty->Name)) 117 // do not include this property 118 pInclusionFlags[nPrimary] = sal_False; 119 else 120 { 121 // search the property in all secondary sets 122 for (sal_Int32 i=1; i<nSingleSets; ++i) 123 { 124 xSecondarySet = m_aSingleSets[i]; 125 aSecondaryProperties = xSecondarySet->getPropertySetInfo()->getProperties(); 126 nSecondaryPropertyCount = aSecondaryProperties.getLength(); 127 const Property* pSecondaryProperties = aSecondaryProperties.getConstArray(); 128 129 // search the current primary property in the secondary property sequence 130 sal_Int32 k=0; 131 while (k<nSecondaryPropertyCount && (pSecondaryProperties[k].Name != pPrimaryProperty->Name)) 132 ++k; 133 134 if (k >= nSecondaryPropertyCount) 135 // not found -> do not include 136 pInclusionFlags[nPrimary] = sal_False; 137 } 138 } 139 } 140 141 // count what's left .... 142 sal_Int32 nOverallProperties = 0; 143 for (sal_Int32 nCounter=0; nCounter<nMasterPropsCount; ++nCounter) 144 { 145 if (pInclusionFlags[nCounter]) 146 ++nOverallProperties; 147 } 148 149 // and finally construct our sequence 150 m_aProperties = Sequence< Property >(nOverallProperties); 151 Property* pProperties = m_aProperties.getArray(); 152 const Property* pMasterProperties = pMasterProps; 153 sal_Int32 nOwnProperties = 0; 154 for (sal_Int32 nCopy = 0; nCopy < nMasterPropsCount; ++nCopy, ++pMasterProperties) 155 { 156 if (pInclusionFlags[nCopy]) 157 pProperties[nOwnProperties++] = *pMasterProperties; 158 } 159 } 160 } 161 162 //------------------------------------------------------------------------------ getPropertySetInfo()163 Reference< XPropertySetInfo > SAL_CALL OComposedPropertySet::getPropertySetInfo( ) throw(RuntimeException) 164 { 165 ::osl::MutexGuard aGuard(m_aMutex); 166 if (!m_pInfo) 167 { 168 m_pInfo = new OComposedPropertySetInfo(m_aProperties); 169 m_pInfo->acquire(); 170 } 171 return m_pInfo; 172 } 173 174 //------------------------------------------------------------------------------ getPropertyState(const::rtl::OUString & _rPropertyName)175 PropertyState SAL_CALL OComposedPropertySet::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException) 176 { 177 // assume DIRECT for the moment 178 PropertyState eState = PropertyState_DIRECT_VALUE; 179 180 sal_Int32 nSingleSets = m_aSingleSets.size(); 181 if (nSingleSets>0) 182 { 183 // check the master state 184 Reference< XPropertySet > xMasterSet(m_aSingleSets[0]); 185 Any aPrimaryValue; 186 if (xMasterSet.is()) 187 { 188 Reference< XPropertyState > xMasterState(xMasterSet,UNO_QUERY); 189 aPrimaryValue = xMasterSet->getPropertyValue(_rPropertyName); 190 191 if (xMasterState.is()) 192 eState = xMasterState->getPropertyState(_rPropertyName); 193 } 194 195 // loop through the secondary sets 196 PropertyState eSecondaryState; 197 for (sal_Int32 i=1; i<nSingleSets; ++i) 198 { 199 Reference< XPropertySet > xSecondary(m_aSingleSets[i]); 200 Reference< XPropertyState > xSecondaryState(xSecondary, UNO_QUERY); 201 202 // the secondary state 203 eSecondaryState = PropertyState_DIRECT_VALUE; 204 if(xSecondaryState.is()) 205 eSecondaryState = xSecondaryState->getPropertyState(_rPropertyName); 206 207 // the secondary value 208 Any aSecondaryValue(xSecondary->getPropertyValue(_rPropertyName)); 209 210 if ( (PropertyState_AMBIGUOUS_VALUE == eSecondaryState) // secondary is ambiguous 211 || !::comphelper::compare(aPrimaryValue, aSecondaryValue) // unequal values 212 ) 213 { 214 eState = PropertyState_AMBIGUOUS_VALUE; 215 break; 216 } 217 } 218 } 219 else 220 { 221 throw UnknownPropertyException( _rPropertyName, *this ); 222 } 223 224 return eState; 225 } 226 227 //--------------------------------------------------------------------- getPropertyStates(const Sequence<::rtl::OUString> & _rPropertyName)228 Sequence< PropertyState > SAL_CALL OComposedPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyName ) throw(UnknownPropertyException, RuntimeException) 229 { 230 sal_Int32 nCount = _rPropertyName.getLength(); 231 Sequence< PropertyState > aReturn(nCount); 232 const ::rtl::OUString* pNames = _rPropertyName.getConstArray(); 233 PropertyState* pStates = aReturn.getArray(); 234 for (sal_Int32 i=0; i<nCount; ++i, ++pNames, ++pStates) 235 *pStates = getPropertyState(*pNames); 236 return aReturn; 237 } 238 239 //--------------------------------------------------------------------- setPropertyToDefault(const::rtl::OUString & _rPropertyName)240 void SAL_CALL OComposedPropertySet::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException) 241 { 242 sal_Int32 nSingleSets = m_aSingleSets.size(); 243 for (sal_Int32 i=0; i<nSingleSets; ++i) 244 { 245 Reference< XPropertyState > xState(m_aSingleSets[i], UNO_QUERY); 246 if(xState.is()) 247 xState->setPropertyToDefault(_rPropertyName); 248 } 249 } 250 251 //--------------------------------------------------------------------- getPropertyDefault(const::rtl::OUString &)252 Any SAL_CALL OComposedPropertySet::getPropertyDefault( const ::rtl::OUString& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 253 { 254 return Any(); 255 } 256 257 //------------------------------------------------------------------------------ setPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rValue)258 void SAL_CALL OComposedPropertySet::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) 259 { 260 sal_Int32 nSingleSets = m_aSingleSets.size(); 261 for (sal_Int32 i=0; i<nSingleSets; ++i) 262 { 263 if (m_aSingleSets[i].is()) 264 m_aSingleSets[i]->setPropertyValue(_rPropertyName, _rValue); 265 } 266 } 267 268 //------------------------------------------------------------------------------ getPropertyValue(const::rtl::OUString & _rPropertyName)269 Any SAL_CALL OComposedPropertySet::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 270 { 271 sal_Int32 nSingleSets = m_aSingleSets.size(); 272 273 if ((nSingleSets>0) && (m_aSingleSets[0].is())) 274 return m_aSingleSets[0]->getPropertyValue(_rPropertyName); 275 return Any(); 276 } 277 278 //------------------------------------------------------------------------------ addPropertyChangeListener(const::rtl::OUString &,const Reference<XPropertyChangeListener> &)279 void SAL_CALL OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 280 { 281 // TODO: 282 // hold the single property sets weak 283 // be a property change listener on all single property sets (for all composed properties) 284 // upon property change 285 // determine the new state/value of the composed property 286 // broadcast the new composed property value 287 } 288 289 //------------------------------------------------------------------------------ removePropertyChangeListener(const::rtl::OUString &,const Reference<XPropertyChangeListener> &)290 void SAL_CALL OComposedPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 291 { 292 // TODO 293 } 294 295 //------------------------------------------------------------------------------ addVetoableChangeListener(const::rtl::OUString &,const Reference<XVetoableChangeListener> &)296 void SAL_CALL OComposedPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 297 { 298 OSL_ENSURE(sal_False, "OComposedPropertySet::addVetoableChangeListener: no implemented (yet)!"); 299 } 300 301 //------------------------------------------------------------------------------ removeVetoableChangeListener(const::rtl::OUString &,const Reference<XVetoableChangeListener> &)302 void SAL_CALL OComposedPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 303 { 304 OSL_ENSURE(sal_False, "OComposedPropertySet::removeVetoableChangeListener: no implemented (yet)!"); 305 } 306 307 //------------------------------------------------------------------------------ OComposedPropertySetInfo(const Sequence<Property> & rSeq)308 OComposedPropertySetInfo::OComposedPropertySetInfo(const Sequence< Property>& rSeq) 309 :m_aProperties(rSeq) 310 { 311 } 312 313 //------------------------------------------------------------------------------ getProperties()314 Sequence< Property> SAL_CALL OComposedPropertySetInfo::getProperties() throw(RuntimeException) 315 { 316 return m_aProperties; 317 } 318 319 //------------------------------------------------------------------------------ getPropertyByName(const::rtl::OUString & _rName)320 Property SAL_CALL OComposedPropertySetInfo::getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException) 321 { 322 sal_Int32 nLength = m_aProperties.getLength(); 323 const Property* pProps = m_aProperties.getConstArray(); 324 // TODO TODO TODO: this O(n) search really sucks ... 325 for (sal_Int32 i=0; i<nLength; ++i, ++pProps) 326 { 327 if (pProps->Name == _rName) 328 return *pProps; 329 } 330 331 throw UnknownPropertyException( _rName, *this ); 332 } 333 334 //------------------------------------------------------------------------------ hasPropertyByName(const::rtl::OUString & _rName)335 sal_Bool SAL_CALL OComposedPropertySetInfo::hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException) 336 { 337 sal_Int32 nLength = m_aProperties.getLength(); 338 const Property* pProps = m_aProperties.getConstArray(); 339 // TODO TODO TODO: this O(n) search really sucks ... 340 for( sal_Int32 i=0; i<nLength; ++i,++pProps ) 341 { 342 if(pProps->Name == _rName) 343 return sal_True; 344 } 345 346 return sal_False; 347 } 348 349 //......................................................................... 350 } // namespace comphelper 351 //......................................................................... 352 353 354