update dev300-m58
[ooovba.git] / configmgr / source / treecache / cacheline.cxx
blob6125401aafbf1f944f8b994bcf01d4f9c81b3f89
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cacheline.cxx,v $
10 * $Revision: 1.11 $
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_configmgr.hxx"
34 #include "cacheline.hxx"
35 #include "builddata.hxx"
36 #include "treechangefactory.hxx"
37 #include "mergechange.hxx"
38 #include "configexcept.hxx"
39 #include "tracer.hxx"
40 #include <osl/diagnose.h>
42 namespace configmgr
44 // -----------------------------------------------------------------------------
45 static inline rtl::OUString implExtractModuleName(configuration::AbsolutePath const& _aConfigPath)
47 return _aConfigPath.getModuleName();
51 // -----------------------------------------------------------------------------
52 // class CacheLine
53 // -----------------------------------------------------------------------------
55 // -----------------------------------------------------------------------------
57 CacheLine::CacheLine(rtl::OUString const & _aModuleName)
58 : m_base(NULL)
59 , m_name(_aModuleName)
60 , m_nDataRefs(0)
63 // -----------------------------------------------------------------------------
65 CacheLine::CacheLine(rtl::OUString const & _aModuleName, sharable::TreeFragment * _pSegment)
66 : m_base(_pSegment)
67 , m_name(_aModuleName)
68 , m_nDataRefs(0)
72 // -----------------------------------------------------------------------------
74 void CacheLine::setBase(sharable::TreeFragment * _base)
76 OSL_PRECOND(m_base == NULL, "CacheLine: Data base address was already set");
77 OSL_PRECOND( _base != NULL, "CacheLine: Cannot set NULL base address");
78 m_base = _base;
80 // -----------------------------------------------------------------------------
82 rtl::Reference<CacheLine> CacheLine::createAttached( rtl::OUString const & _aModuleName,
83 sharable::TreeFragment * _aSegment
84 ) SAL_THROW((com::sun::star::uno::RuntimeException))
86 if (_aModuleName.getLength() == 0)
88 OSL_ENSURE(false, "Cannot make a cache line without a name");
89 return NULL;
91 if (_aSegment == NULL)
93 OSL_ENSURE(false, "Cannot attach a cache line to a NULL segment");
94 return NULL;
97 rtl::Reference<CacheLine> xResult = new CacheLine(_aModuleName,_aSegment);
99 return xResult;
101 // -----------------------------------------------------------------------------
103 rtl::Reference<CacheLine> CacheLine::createNew( rtl::OUString const & _aModuleName
104 ) SAL_THROW((com::sun::star::uno::RuntimeException))
106 if (_aModuleName.getLength() == 0)
108 OSL_ENSURE(false, "Cannot make a cache line without a name");
109 return NULL;
112 rtl::Reference<CacheLine> xResult = new CacheLine(_aModuleName);
114 return xResult;
116 // -------------------------------------------------------------------------
118 rtl::OUString CacheLine::getModuleName() const
120 return m_name;
122 // -----------------------------------------------------------------------------
124 sharable::TreeFragment * CacheLine::getPartialTree(configuration::AbsolutePath const& aConfigName) const
126 sharable::Node * parent = internalGetNode(aConfigName.getParentPath());
128 if (parent != 0 && parent->isSet())
129 return parent->set.getElement(aConfigName.getLocalName().getName());
130 else
131 return NULL;
133 // -----------------------------------------------------------------------------
135 bool CacheLine::hasDefaults() const
137 return m_base != 0 && m_base->hasDefaultsAvailable();
139 // -----------------------------------------------------------------------------
140 sharable::Node * CacheLine::internalGetNode(configuration::AbsolutePath const& aConfigName) const
142 OSL_ASSERT(m_base != 0);
143 sharable::Node * node = m_base->getRootNode();
144 OSL_ASSERT(node != 0);
145 std::vector< configuration::Path::Component >::const_reverse_iterator i(
146 aConfigName.begin());
147 OSL_ASSERT(
148 i != aConfigName.end() && node->getName() == i->getInternalName());
149 while (node != 0 && ++i != aConfigName.end()) {
150 node = node->getSubnode(i->getName());
152 return node;
154 // -----------------------------------------------------------------------------
156 sharable::Node * CacheLine::getNode(configuration::AbsolutePath const& aConfigName) const
158 return internalGetNode(aConfigName);
160 // -------------------------------------------------------------------------
162 sharable::TreeFragment * CacheLine::setComponentData( backend::ComponentDataStruct const & _aComponentInstance,
163 bool _bWithDefaults
164 ) SAL_THROW((com::sun::star::uno::RuntimeException))
166 OSL_PRECOND(_aComponentInstance.data.get(), "CacheLine::insertDefaults: inserting NULL defaults !");
167 OSL_PRECOND(_aComponentInstance.name == this->getModuleName(),"Data location does not match module");
169 OSL_PRECOND(base() == NULL, "Data is already loaded");
171 if (base() == NULL) // no data yet
173 this->setBase( data::buildTree(_aComponentInstance.data->getName(), *_aComponentInstance.data, _bWithDefaults) );
176 return this->base();
178 // -----------------------------------------------------------------------------
180 sharable::TreeFragment * CacheLine::insertDefaults( backend::NodeInstance const & _aDefaultInstance
181 ) SAL_THROW((com::sun::star::uno::RuntimeException))
183 OSL_PRECOND(_aDefaultInstance.data().get(), "CacheLine::insertDefaults: inserting NULL defaults !");
184 OSL_PRECOND(_aDefaultInstance.root().getDepth() == 1, "Should have complete component to fill tree with defaults");
185 OSL_PRECOND(_aDefaultInstance.root().getModuleName() == this->getModuleName(),"Data location does not match module");
187 OSL_PRECOND(m_base != NULL, "Data must already be loaded to insert defaults");
189 if (m_base != NULL)
191 data::mergeDefaults(m_base,*_aDefaultInstance.data());
194 return m_base;
196 // -----------------------------------------------------------------------------
197 // -----------------------------------------------------------------------------
199 ExtendedCacheLine::ExtendedCacheLine(rtl::OUString const & _aModuleName)
200 : CacheLine(_aModuleName)
201 , m_pPending()
205 // -----------------------------------------------------------------------------
207 ExtendedCacheLine::ExtendedCacheLine(rtl::OUString const & _aModuleName,
208 sharable::TreeFragment * _aSegment)
209 : CacheLine(_aModuleName,_aSegment)
210 , m_pPending()
214 // -----------------------------------------------------------------------------
216 rtl::Reference<ExtendedCacheLine> ExtendedCacheLine::createAttached( rtl::OUString const & _aModuleName,
217 sharable::TreeFragment * _aSegment
218 ) SAL_THROW((com::sun::star::uno::RuntimeException))
220 if (_aModuleName.getLength() == 0)
222 OSL_ENSURE(false, "Cannot make a cache line without a name");
223 return NULL;
225 if (_aSegment == NULL)
227 OSL_ENSURE(false, "Cannot attach a cache line to a NULL segment");
228 return NULL;
231 rtl::Reference<ExtendedCacheLine> xResult = new ExtendedCacheLine(_aModuleName,_aSegment);
233 return xResult;
235 // -----------------------------------------------------------------------------
237 rtl::Reference<ExtendedCacheLine> ExtendedCacheLine::createNew( rtl::OUString const & _aModuleName
238 ) SAL_THROW((com::sun::star::uno::RuntimeException))
240 if (_aModuleName.getLength() == 0)
242 OSL_ENSURE(false, "Cannot make a cache line without a name");
243 return NULL;
246 rtl::Reference<ExtendedCacheLine> xResult = new ExtendedCacheLine(_aModuleName);
248 return xResult;
250 // -------------------------------------------------------------------------
252 void ExtendedCacheLine::addPending(backend::ConstUpdateInstance const & _anUpdate) SAL_THROW((com::sun::star::uno::RuntimeException))
254 configuration::AbsolutePath aRootLocation = _anUpdate.root();
256 OSL_PRECOND(!aRootLocation.isRoot(),"Pending change cannot be located at root");
257 OSL_PRECOND(aRootLocation.getModuleName() == this->getModuleName(),"Pending change location does not match module");
259 OSL_PRECOND(_anUpdate.data() != NULL,"Adding NULL 'pending' change");
260 OSL_PRECOND(_anUpdate.data()->getNodeName() == aRootLocation.getLocalName().getName(),
261 "Path to pending change does not match change name");
263 using std::auto_ptr;
265 // first make the _pSubtreeChange a full tree starting at the module root
266 auto_ptr<SubtreeChange> pRootChange;
267 SubtreeChange *pExistingEntry = NULL;
269 std::vector<configuration::Path::Component>::const_reverse_iterator last = aRootLocation.end();
271 OSL_ASSERT(last != aRootLocation.begin());
272 --last;
274 for (std::vector<configuration::Path::Component>::const_reverse_iterator it = aRootLocation.begin();
275 it != last;
276 ++it)
278 OSL_ASSERT( it != aRootLocation.end());
279 OSL_ASSERT( it+1 != aRootLocation.end());
280 // We need to create a new SubtreeChange
281 rtl::OUString const aChangeName = it->getName();
282 rtl::OUString const aElementTypeName = (it+1)->getTypeName();
284 auto_ptr<SubtreeChange> pNewChange =
285 OTreeChangeFactory::createDummyChange(aChangeName, aElementTypeName);
287 if (pExistingEntry == NULL)
289 OSL_ASSERT(pRootChange.get() == NULL);
291 pRootChange = pNewChange;
292 pExistingEntry = pRootChange.get();
294 else
296 OSL_ASSERT(pRootChange.get() != NULL);
298 pExistingEntry->addChange(base_ptr(pNewChange));
300 Change* pChange = pExistingEntry->getChange(aChangeName);
301 pExistingEntry = static_cast<SubtreeChange*>(pChange);
303 OSL_ENSURE(dynamic_cast< SubtreeChange * >(pChange) != 0, "ERROR: Cannot recover change just added");
307 auto_ptr<SubtreeChange> pAddedChange( new SubtreeChange(*_anUpdate.data(), treeop::DeepChildCopy()) );
309 if (aRootLocation.getDepth() > 1)
311 OSL_ASSERT(pRootChange.get() != NULL && pExistingEntry != NULL);
313 // the _pSubtreeChange did not start at root, so add its clone to the built dummies
314 pExistingEntry->addChange(base_ptr(pAddedChange));
316 else
318 OSL_ASSERT(pRootChange.get() == NULL && pExistingEntry == NULL);
320 // the _pSubtreeChange starts at root, so just reset pRootChange
321 pRootChange = pAddedChange;
323 OSL_ASSERT(pRootChange.get() != NULL);
325 if (m_pPending.get() == NULL)
327 // no merge is need, because the existing pending changes are empty
328 m_pPending = pRootChange;
330 else
334 // We need to merge the new rebased changes into the m_pPending
335 combineUpdates(*pRootChange,*m_pPending);
337 catch (configuration::Exception& e)
339 rtl::OUString sMessage(RTL_CONSTASCII_USTRINGPARAM("Update cache for module: Could not add pending changes at"));
341 sMessage += aRootLocation.toString();
343 sMessage += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(". Internal Exception:")) + e.message();
345 throw uno::RuntimeException(sMessage,0);
349 OSL_POSTCOND(m_pPending.get() != NULL, "Could not insert new pending changes");
351 // -----------------------------------------------------------------------------
354 } // namespace configmgr