summaryrefslogtreecommitdiff
path: root/configmgr
diff options
context:
space:
mode:
authorLars Langhans <lla@openoffice.org>2001-01-17 14:02:34 +0000
committerLars Langhans <lla@openoffice.org>2001-01-17 14:02:34 +0000
commitc34914cf86fdab6162e754a128c45012c3e326d9 (patch)
treef5fff5f704e5440a757649e897e1d73fe30acca5 /configmgr
parentefb3ac864d869f573b0fa0091931d091c319fb2f (diff)
#82734# lasy writing
Diffstat (limited to 'configmgr')
-rw-r--r--configmgr/source/api2/broadcaster.cxx9
-rw-r--r--configmgr/source/api2/providerimpl.cxx12
-rw-r--r--configmgr/source/inc/change.hxx23
-rw-r--r--configmgr/source/inc/mergechange.hxx156
-rw-r--r--configmgr/source/inc/rttimacros.hxx6
-rw-r--r--configmgr/source/inc/treeprovider.hxx24
-rw-r--r--configmgr/source/misc/makefile.mk5
-rw-r--r--configmgr/source/misc/mergechange.cxx949
-rw-r--r--configmgr/source/tree/changes.cxx41
-rw-r--r--configmgr/source/tree/cmtreemodel.cxx26
-rw-r--r--configmgr/source/treecache/disposetimer.cxx189
-rw-r--r--configmgr/source/treecache/disposetimer.hxx81
12 files changed, 1479 insertions, 42 deletions
diff --git a/configmgr/source/api2/broadcaster.cxx b/configmgr/source/api2/broadcaster.cxx
index ea80de7317c8..ead33c1bcb1c 100644
--- a/configmgr/source/api2/broadcaster.cxx
+++ b/configmgr/source/api2/broadcaster.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: broadcaster.cxx,v $
*
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
*
- * last change: $Author: jb $ $Date: 2000-12-07 14:09:32 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:27 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -986,7 +986,10 @@ namespace configmgr
}
}
- if( !aNewChange.resolveObjects(rFactory) ) OSL_TRACE("Cannot find affected elements of Change");
+ if( !aNewChange.resolveObjects(rFactory) )
+ {
+ OSL_TRACE("Cannot find affected elements of Change");
+ }
}
diff --git a/configmgr/source/api2/providerimpl.cxx b/configmgr/source/api2/providerimpl.cxx
index c5c02a4ef431..5897be0fed43 100644
--- a/configmgr/source/api2/providerimpl.cxx
+++ b/configmgr/source/api2/providerimpl.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: providerimpl.cxx,v $
*
- * $Revision: 1.16 $
+ * $Revision: 1.17 $
*
- * last change: $Author: jb $ $Date: 2000-12-19 17:35:00 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:27 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -188,7 +188,7 @@ namespace configmgr
// m_pTreeMgr->releaseSubtree(ssUserProfile, m_xDefaultOptions);
}
}
- catch (container::NoSuchElementException&)
+ catch (uno::Exception&)
{
// could not read default locale
// default locale is en-US
@@ -224,7 +224,7 @@ namespace configmgr
// ITreeProvider /ITreeManager
//-----------------------------------------------------------------------------
ISubtree* OProviderImpl::requestSubtree( OUString const& aSubtreePath, const vos::ORef < OOptions >& _xOptions,
- sal_Int16 nMinLevels) throw (container::NoSuchElementException)
+ sal_Int16 nMinLevels) throw (uno::Exception)
{
return m_pTreeMgr->requestSubtree(aSubtreePath, _xOptions, nMinLevels);
}
@@ -359,7 +359,7 @@ namespace configmgr
OSL_ASSERT(sal_Int16(nMinLevels) == nMinLevels);
pTree = requestSubtree(_rAccessor,_xOptions, sal_Int16(nMinLevels));
}
- catch(container::NoSuchElementException&e)
+ catch(uno::Exception&e)
{
sErrorMessage = e.Message;
}
@@ -401,7 +401,7 @@ namespace configmgr
OSL_ASSERT(sal_Int16(nMinLevels) == nMinLevels);
pTree = requestSubtree(_rAccessor, _xOptions, sal_Int16(nMinLevels));
}
- catch(container::NoSuchElementException&e)
+ catch(uno::Exception &e)
{
sErrorMessage = e.Message;
}
diff --git a/configmgr/source/inc/change.hxx b/configmgr/source/inc/change.hxx
index c33a3f282154..24bf26919558 100644
--- a/configmgr/source/inc/change.hxx
+++ b/configmgr/source/inc/change.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: change.hxx,v $
*
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
*
- * last change: $Author: jb $ $Date: 2000-12-04 09:14:33 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -141,6 +141,7 @@ namespace configmgr
// some kind of simple rtti
RTTI_BASE(Change);
+ virtual Change* clone() const = 0;
private:
virtual Change* doGetChild(rtl::OUString const& ) const { return 0; }
@@ -164,9 +165,10 @@ namespace configmgr
public:
ValueChange(rtl::OUString const& _rName, uno::Any aNewValue, const configuration::Attributes& _rAttributes,
Mode aMode = changeValue, uno::Any aOldValue = uno::Any());
- ValueChange(const ValueChange&);
ValueChange(uno::Any aNewValue, ValueNode const& aOldValue);
ValueChange(SetToDefault, ValueNode const& aOldValue);
+ ValueChange(const ValueChange&);
+ virtual Change* clone() const;
uno::Any getNewValue() const { return m_aValue; }
uno::Any getOldValue() const { return m_aOldValue; }
@@ -206,12 +208,13 @@ namespace configmgr
bool m_bReplacing;
// don't create CopyCTor automatically
- AddNode(AddNode const&);
void operator=(AddNode const&);
public:
AddNode(std::auto_ptr<INode> aNewNode_,rtl::OUString const& _rName);
~AddNode();
+ AddNode(AddNode const&);
+ virtual Change* clone() const;
/// marks this as not merely adding a node but replacing another
void setReplacing() { m_bReplacing = true; }
@@ -275,8 +278,11 @@ namespace configmgr
std::auto_ptr<INode> m_aOwnOldNode;
public:
- RemoveNode(rtl::OUString const& _rName) ;
- ~RemoveNode() ;
+ RemoveNode(rtl::OUString const& _rName);
+ ~RemoveNode();
+ RemoveNode(const RemoveNode&);
+ virtual Change* clone() const;
+
virtual void dispatch(ChangeTreeAction& anAction) const { anAction.handle(*this); }
virtual void dispatch(ChangeTreeModification& anAction) { anAction.handle(*this); }
@@ -320,7 +326,6 @@ namespace configmgr
configuration::Attributes m_aAttributes;
// don't create CopyCTor automatically
- SubtreeChange(SubtreeChange&);
void operator=(SubtreeChange&);
public:
@@ -356,6 +361,9 @@ namespace configmgr
~SubtreeChange();
+ SubtreeChange(const SubtreeChange&);
+ virtual Change* clone() const;
+
void swap(SubtreeChange& aOther);
bool isReplacing() const {return m_aAttributes.bReplacing;}
@@ -457,6 +465,7 @@ namespace configmgr
//==========================================================================
/** a specialized SubtreeChange, which, upon desctruction, does not delete the changes
it holds
+
<BR>
This implies that when using this class, you have to beware of the lifetime of the involved objects
*/
diff --git a/configmgr/source/inc/mergechange.hxx b/configmgr/source/inc/mergechange.hxx
new file mode 100644
index 000000000000..e83b5b4beb7d
--- /dev/null
+++ b/configmgr/source/inc/mergechange.hxx
@@ -0,0 +1,156 @@
+/*************************************************************************
+ *
+ * $RCSfile: mergechange.hxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:30 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include "change.hxx"
+#include "treeprovider.hxx"
+
+namespace configmgr
+{
+
+ class ONameCreator
+ {
+ std::vector<rtl::OUString> m_aNameList;
+ public:
+ ONameCreator(){}
+ void init(const ConfigurationName &_aName);
+ rtl::OUString createName(const rtl::OUString &aPlusName);
+ void pushName(const rtl::OUString &aName);
+ void popName();
+ };
+
+ // -----------------------------------------------------------------------------
+
+ // Helperclass to search a change in a given changetree
+ class OMergeSearchChange : private ChangeTreeModification, public ONameCreator
+ {
+ rtl::OUString m_aSearchName;
+ bool m_bFound;
+ Change* m_pFoundChange;
+
+ protected:
+ bool isFound() { return m_bFound; }
+ virtual void handle(ValueChange& _rValueNode);
+ virtual void handle(AddNode& _rAddNode);
+ virtual void handle(RemoveNode& _rRemoveNode);
+ virtual void handle(SubtreeChange& _rSubtree);
+
+ public:
+ OMergeSearchChange(const rtl::OUString &_aName);
+ Change* searchForChange(Change &aChange);
+ };
+
+ // -----------------------------------------------------------------------------
+ class OMergeTreeChangeList : private ChangeTreeAction, public ONameCreator
+ {
+ TreeChangeList &m_aTreeChangeList; // ChangeList, which will be grown
+ SubtreeChange *m_pCurrentParent; // our current position
+ vector<SubtreeChange*> m_aTreePathStack; // how the name says, a stack for the given path
+
+
+ // ------- Helper for Path stack -------
+ void pushTree(SubtreeChange* _pTree);
+ void popTree();
+ public:
+ // CTor
+ OMergeTreeChangeList(TreeChangeList& _aTree);
+ SubtreeChange* check(const ConfigurationName &_aName);
+
+ // start function, with the Change we want to do.
+ // WARNING this could be a big tree, because a change can contain subtreechanges!
+ void handleChange(TreeChangeList &_rList);
+
+
+ private:
+ virtual void handle(ValueChange const& _rValueNode);
+ virtual void handle(AddNode const& _rAddNode);
+ virtual void handle(RemoveNode const& _rRemoveNode);
+ virtual void handle(SubtreeChange const& _rSubtree);
+ };
+
+ // -----------------------------------------------------------------------------
+ class OMergeChanges : private ChangeTreeAction, public ONameCreator
+ {
+ SubtreeChange &m_aSubtreeChange; // ChangeList, which will be grown
+ SubtreeChange *m_pCurrentParent; // our current position
+ vector<SubtreeChange*> m_aTreePathStack; // how the name says, a stack for the given path
+
+ // ------- Helper for Path stack -------
+ void pushTree(SubtreeChange* _pTree);
+ void popTree();
+
+ public:
+ // CTor
+ OMergeChanges(SubtreeChange& _aTree);
+
+ SubtreeChange* check(const ConfigurationName &_aName);
+
+ // start function, with the Change we want to do.
+ // WARNING this could be a big tree, because a change can contain subtreechanges!
+ void handleChange(const SubtreeChange &_rList, const rtl::OUString &_aPathToRoot);
+
+ private:
+ virtual void handle(ValueChange const& _rValueNode);
+ virtual void handle(AddNode const& _rAddNode);
+ virtual void handle(RemoveNode const& _rRemoveNode);
+ virtual void handle(SubtreeChange const& _rSubtree);
+
+ };
+} // namespace configmgr
diff --git a/configmgr/source/inc/rttimacros.hxx b/configmgr/source/inc/rttimacros.hxx
index 74ab8f5fec70..6e95e4d62259 100644
--- a/configmgr/source/inc/rttimacros.hxx
+++ b/configmgr/source/inc/rttimacros.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: rttimacros.hxx,v $
*
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
- * last change: $Author: lla $ $Date: 2000-11-15 07:14:58 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -70,7 +70,7 @@
{ \
return 0 == strcmp(_pName, getStaticType()); \
} \
- const sal_Char* getType() const { return #classname; } \
+ virtual const sal_Char* getType() const { return #classname; } \
static const sal_Char* getStaticType() { return #classname; }
#define RTTI(classname, baseclassname) \
diff --git a/configmgr/source/inc/treeprovider.hxx b/configmgr/source/inc/treeprovider.hxx
index eaec0b905589..a41f06d3f25f 100644
--- a/configmgr/source/inc/treeprovider.hxx
+++ b/configmgr/source/inc/treeprovider.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: treeprovider.hxx,v $
*
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
*
- * last change: $Author: jb $ $Date: 2000-12-14 16:11:19 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -129,6 +129,17 @@ namespace configmgr
SubtreeChange root; // changes made within this sub tree
// TreeChangeList(): root(::rtl::OUString(), configuration::Attributes()){}
+ TreeChangeList(const vos::ORef < OOptions >& _xOptions, const rtl::OUString& _rPathToRoot, const SubtreeChange& _aSubtree)
+ : m_xOptions(_xOptions),
+ pathToRoot(_rPathToRoot),
+ root(_aSubtree) /* EXPENSIVE!!! (deep copy) */
+ {}
+
+ TreeChangeList(const vos::ORef < OOptions >& _xOptions, const rtl::OUString& _rPathToRoot, auto_ptr<SubtreeChange> _pSubtreeChange)
+ : m_xOptions(_xOptions),
+ pathToRoot(_rPathToRoot),
+ root(*_pSubtreeChange.release()) /* EXPENSIVE!!! (deep copy) */
+ {}
/** ctor
@param _rPathToRoot path to the root of the whole to-be-updated subtree
@param _rLocalName relative path within the to-be-updated subtree
@@ -153,7 +164,9 @@ namespace configmgr
: m_xOptions(_xOptions)
, pathToRoot(_rPathToRoot)
, root(_rTree)
- {}
+ {
+ OSL_ENSHURE(false, "Test only, because deep copy of subtreechange is very expensive.");
+ }
/** ctor
@param _rTreeList list to initialize the path, no childs are copied
@@ -163,6 +176,7 @@ namespace configmgr
, pathToRoot(_rTree.pathToRoot)
, root(_rTree.root, _rNoCopy)
{}
+
};
//==========================================================================
@@ -175,8 +189,8 @@ namespace configmgr
virtual ISubtree * requestSubtree(OUString const& aSubtreePath,
const vos::ORef < OOptions >& _xOptions,
- sal_Int16 nMinLevels = ALL_LEVELS) throw (container::NoSuchElementException) = 0;
- virtual void updateTree(TreeChangeList& aChanges) throw (lang::WrappedTargetException, uno::RuntimeException) = 0;
+ sal_Int16 nMinLevels = ALL_LEVELS) throw (uno::Exception) = 0;
+ virtual void updateTree(TreeChangeList& aChanges) throw (uno::Exception) = 0;
};
diff --git a/configmgr/source/misc/makefile.mk b/configmgr/source/misc/makefile.mk
index 84c7283ae60d..e9c466919d62 100644
--- a/configmgr/source/misc/makefile.mk
+++ b/configmgr/source/misc/makefile.mk
@@ -2,9 +2,9 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.3 $
+# $Revision: 1.4 $
#
-# last change: $Author: fs $ $Date: 2000-12-01 14:06:03 $
+# last change: $Author: lla $ $Date: 2001-01-17 15:02:32 $
#
# The Contents of this file are made available subject to the terms of
# either of the following licenses
@@ -96,6 +96,7 @@ SLOFILES= \
$(SLO)$/strimpl.obj \
$(SLO)$/strconverter.obj \
$(SLO)$/treemap.obj \
+ $(SLO)$/mergechange.obj \
# --- Targets ----------------------------------
diff --git a/configmgr/source/misc/mergechange.cxx b/configmgr/source/misc/mergechange.cxx
new file mode 100644
index 000000000000..8e253b8ac8b3
--- /dev/null
+++ b/configmgr/source/misc/mergechange.cxx
@@ -0,0 +1,949 @@
+/*************************************************************************
+ *
+ * $RCSfile: mergechange.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+
+#ifndef CONFIGMGR_CONFNAME_HXX_
+#include "confname.hxx"
+#endif
+
+
+#include "mergechange.hxx"
+
+#include "change.hxx"
+#include "treeprovider.hxx"
+#include "treeactions.hxx"
+#include "tracer.hxx"
+
+#ifndef _COM_SUN_STAR_UNO_ANY_H_
+#include <com/sun/star/uno/Any.h>
+#endif
+
+#define ASCII(x) rtl::OUString::createFromAscii(x)
+
+namespace configmgr
+{
+ using namespace com::sun::star::uno;
+
+ void ONameCreator::init(const ConfigurationName &_aName)
+ {
+ // HACK!
+ if (!(_aName.fullName().equals(ASCII("/"))))
+ {
+ // initial Name
+ for(ConfigurationName::Iterator it = _aName.begin();
+ it != _aName.end();
+ ++it)
+ {
+ m_aNameList.push_back(*it);
+ }
+ }
+ }
+
+ rtl::OUString ONameCreator::createName(const rtl::OUString &aPlusName)
+ {
+ // create a name
+ OUString aName;
+ for (vector<OUString>::const_iterator it = m_aNameList.begin();
+ it != m_aNameList.end();
+ it++)
+ {
+ aName += *it;
+ aName += OUString::createFromAscii("/");
+ }
+ if (aPlusName.getLength() == 0)
+ {
+ aName = aName.copy(0, aName.getLength() - 1);
+ }
+ else
+ {
+ aName += aPlusName;
+ }
+
+ return aName;
+ }
+ void ONameCreator::pushName(const rtl::OUString &aName)
+ {
+ m_aNameList.push_back(aName);
+ }
+ void ONameCreator::popName()
+ {
+ m_aNameList.pop_back();
+ }
+
+
+ // -----------------------------------------------------------------------------
+
+ // Helperclass to search a change in a given changetree
+ OMergeSearchChange::OMergeSearchChange(const rtl::OUString &_aName)
+ : m_aSearchName(_aName), m_bFound(false), m_pFoundChange(NULL) {}
+
+ void OMergeSearchChange::handle(ValueChange& _rValueNode)
+ {
+ rtl::OUString aName = createName(_rValueNode.getNodeName());
+ if (aName.equals(m_aSearchName))
+ {
+ m_bFound = true;
+ m_pFoundChange = &_rValueNode;
+ }
+ }
+
+ void OMergeSearchChange::handle(AddNode& _rAddNode)
+ {
+ rtl::OUString aName = createName(_rAddNode.getNodeName());
+ if (aName.equals(m_aSearchName))
+ {
+ m_bFound = true;
+ m_pFoundChange = &_rAddNode;
+ }
+ }
+
+ void OMergeSearchChange::handle(RemoveNode& _rRemoveNode)
+ {
+ rtl::OUString aName = createName(_rRemoveNode.getNodeName());
+ if (aName.equals(m_aSearchName))
+ {
+ m_bFound = true;
+ m_pFoundChange = &_rRemoveNode;
+ }
+ }
+
+ void OMergeSearchChange::handle(SubtreeChange& _rSubtree)
+ {
+ rtl::OUString aName = createName(_rSubtree.getNodeName());
+ if (aName.equals(m_aSearchName))
+ {
+ m_bFound = true;
+ m_pFoundChange = &_rSubtree;
+ }
+ if (!m_bFound)
+ {
+ // recursive descent
+ pushName(_rSubtree.getNodeName());
+ _rSubtree.forEachChange(*this);
+ popName();
+ }
+ }
+
+ Change* OMergeSearchChange::searchForChange(Change &aChange)
+ {
+ applyToChange(aChange);
+ if (isFound())
+ {
+ return m_pFoundChange;
+ }
+ return NULL;
+ }
+ // -----------------------------------------------------------------------------
+ class OMergeValueChange : private ChangeTreeModification
+ {
+ const ValueChange& m_aValueChange;
+ public:
+ OMergeValueChange(const ValueChange& _aValueChange)
+ :m_aValueChange(_aValueChange)
+ {
+
+ }
+ void handleChange(Change &_rNode)
+ {
+ applyToChange(_rNode);
+ }
+ private:
+ virtual void handle(ValueChange& _rValueChange)
+ {
+ // POST: Handle ValueChange
+ _rValueChange.setNewValue(m_aValueChange.getNewValue(), m_aValueChange.getMode());
+ }
+ virtual void handle(RemoveNode& _rRemoveNode)
+ {
+ OSL_ENSHURE(false, "OMergeValueChange::handle(ValueChange): have a ValueChange for a removed node!");
+ // should never happen. How did the user change a value for a node which is obviously flagged as removed?
+ }
+ virtual void handle(AddNode& _rAddNode)
+ {
+ // POST: Handle ValueChange in AddNode
+ INode* pINode = _rAddNode.getAddedNode();
+ ValueNode *pValueNode = pINode->asValueNode();
+ if (pValueNode)
+ pValueNode->setValue(m_aValueChange.getNewValue());
+ else
+ OSL_ENSURE(sal_False, "OMergeValueChange:handle(AddNode): have a ValueChange a for non-value node!");
+ }
+ virtual void handle(SubtreeChange& _rSubtree)
+ {
+ OSL_ENSHURE(false, "OMergeValueChange:handle(SubtreeChange): have a ValueChange for a sub tree!");
+ }
+ };
+
+ // -----------------------------------------------------------------------------
+ class OMergeRemoveNode : private ChangeTreeModification
+ {
+ public:
+ // actions to take with the remove node change
+ enum Action
+ {
+ RemoveCompletely,
+ FlagDeleted,
+ Undetermined
+ };
+
+ protected:
+ Action m_eAction;
+
+ public:
+ OMergeRemoveNode() : m_eAction(Undetermined) { }
+
+ Action getAction() const { return m_eAction; }
+
+ void handleChange(Change* _pChange)
+ {
+ if (_pChange)
+ applyToChange(*_pChange);
+ else
+ // no change -> flag as deleted
+ m_eAction = FlagDeleted;
+ }
+
+ private:
+ virtual void handle(ValueChange& aValueChange)
+ {
+ OSL_ENSHURE(false, "OMergeRemoveNode::handle(ValueChange): remove a value node?");
+ }
+
+ virtual void handle(RemoveNode& _rRemoveNode)
+ {
+ OSL_ENSHURE(false, "OMergeRemoveNode::handle(RemoveNode): should never happen!");
+ // how can a RemoveNode change exist if in the file we're merging it into
+ // there already is such a RemoveNode change (_rRemoveNode)?
+ }
+
+ virtual void handle(AddNode& _rAddNode)
+ {
+ // though this is suspicious, as currently no AddNode changes are created ...
+ m_eAction = RemoveCompletely;
+ }
+
+ virtual void handle(SubtreeChange& _rSubtree)
+ {
+ m_eAction = FlagDeleted;
+ // TODO: need an extra state to distinguish between nodes which are overwritten in the user layer
+ // and nodes which are added to the user layer, but not existent in the share layer
+ // In the latter case m_eAction could be set to RemoveCompletely
+ }
+ };
+
+
+ // -----------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------
+ class OMergeSubtreeChange : private ChangeTreeModification,public ONameCreator
+ {
+ const SubtreeChange& m_aSubtreeChange;
+ public:
+ OMergeSubtreeChange(const SubtreeChange& _aSubtreeChange)
+ :m_aSubtreeChange(_aSubtreeChange)
+ {
+
+ }
+ void handleChange(Change& _pChange)
+ {
+ applyToChange(_pChange);
+ }
+
+ private:
+ virtual void handle(ValueChange& aValueChange)
+ {
+ OSL_ENSHURE(false, "OMergeSubtreeChange::handle(ValueChange): remove a value node?");
+ }
+
+ virtual void handle(RemoveNode& _rRemoveNode)
+ {
+ OSL_ENSHURE(false, "OMergeSubtreeChange::handle(RemoveNode): should never happen!");
+ }
+
+ virtual void handle(AddNode& _rAddNode)
+ {
+ }
+
+ virtual void handle(SubtreeChange& _rSubtree)
+ {
+ // we will run through the exist tree and insert the new one.
+ pushName(_rSubtree.getNodeName());
+ _rSubtree.forEachChange(*this);
+ popName();
+ }
+ };
+
+ // -----------------------------------------------------------------------------
+ // Main class for merging treechangelists
+
+ // ------- Helper for Path stack -------
+ void OMergeTreeChangeList::pushTree(SubtreeChange* _pTree)
+ {
+ m_pCurrentParent = _pTree;
+ OSL_ENSHURE(m_pCurrentParent, "OMergeTreeChangeList::pushTree: must not be NULL!");
+ m_aTreePathStack.push_back(_pTree);
+ }
+ void OMergeTreeChangeList::popTree()
+ {
+ m_aTreePathStack.pop_back();
+ m_pCurrentParent = m_aTreePathStack.back();
+ }
+
+ // CTor
+ OMergeTreeChangeList::OMergeTreeChangeList(TreeChangeList& _aTree)
+ :m_aTreeChangeList(_aTree), m_pCurrentParent(NULL)
+ {
+ }
+
+ SubtreeChange* OMergeTreeChangeList::check(const ConfigurationName &_aName)
+ {
+ // First check, if the aName is in the treechangelist
+ ONameCreator aNameCreator;
+
+ SubtreeChange* pCurrentParent = &m_aTreeChangeList.root;
+
+ if (!(_aName.fullName().equals(ASCII("/"))))
+ {
+ for(ConfigurationName::Iterator it = _aName.begin();
+ it != _aName.end();
+ ++it)
+ {
+ aNameCreator.pushName(*it);
+ rtl::OUString aSearchName = aNameCreator.createName(OUString());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aTreeChangeList.root);
+
+ if (!pChange)
+ {
+ // create a correspondens for the name, we not found.
+ auto_ptr<SubtreeChange> pNewChange(new SubtreeChange(*it, OUString(), configuration::Attributes()));
+ pCurrentParent->addChange(auto_ptr<Change>(pNewChange.release()));
+
+ pChange = a.searchForChange(m_aTreeChangeList.root);
+ }
+ pCurrentParent = SAL_STATIC_CAST(SubtreeChange*, pChange);
+ }
+ }
+ return pCurrentParent;
+ }
+
+ // start function, with the Change we want to do.
+ // WARNING this could be a big tree, because a change can contain subtreechanges!
+ void OMergeTreeChangeList::handleChange(TreeChangeList &_rList)
+ {
+ rtl::OUString aPath = _rList.pathToRoot;
+ ConfigurationName aName(aPath, ConfigurationName::Absolute());
+ init(aName); // our Name start with pathToRoot
+ m_pCurrentParent = check(aName); // pathToRoot must exist or will be created
+
+ applyToChange(_rList.root);
+ }
+
+ // Algorithm: search the actual path in the out m_aTreeChangeList
+ // if we found something, we must merge/convert the Node with our Node
+ // if we found nothing, we must create a new Node with our change
+ // thats it.
+
+ // the merge is contructed with helper classes because, it's possible that we
+ // are a ValueChange but in the TreeChangeList this change is an AddNode, so
+ // we have something to do.
+
+ void OMergeTreeChangeList::handle(ValueChange const& _rValueNode)
+ {
+ // Handle a ValueChange,
+ rtl::OUString aSearchName = createName(_rValueNode.getNodeName()); // this construct is only for better debugging
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aTreeChangeList.root);
+ if (pChange)
+ {
+ // Value found, merge content
+ OMergeValueChange a(_rValueNode);
+ a.handleChange(*pChange);
+ }
+ else
+ {
+ // there is no ValueChange in the List, insert new one
+ auto_ptr<Change> pNewChange(new ValueChange(_rValueNode));
+ m_pCurrentParent->addChange(pNewChange);
+ }
+ }
+
+ void OMergeTreeChangeList::handle(AddNode const& _rAddNode)
+ {
+ // Handle an AddNode
+ rtl::OUString aSearchName = createName(_rAddNode.getNodeName());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aTreeChangeList.root);
+
+ if (pChange)
+ {
+ OSL_ENSURE(pChange->ISA(RemoveNode) || _rAddNode.isReplacing(), "OMergeTreeChangeList::handle(AddNode): the changes tree given already contains a change for this!");
+
+ m_pCurrentParent->removeChange(pChange->getNodeName());
+ }
+ // insert manually
+ auto_ptr<INode> pNode = auto_ptr<INode>(_rAddNode.getAddedNode()->clone());
+ auto_ptr<Change> pNewChange(new AddNode(pNode, _rAddNode.getNodeName()));
+ m_pCurrentParent->addChange(pNewChange);
+ }
+
+ void OMergeTreeChangeList::handle(RemoveNode const& _rRemoveNode)
+ {
+ // Handle a RemoveNode
+ rtl::OUString aSearchName = createName(_rRemoveNode.getNodeName());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aTreeChangeList.root);
+
+ // examine what to do with this change
+ OMergeRemoveNode aExaminer;
+ aExaminer.handleChange(pChange);
+
+ // remove the change from it's parent (may it's re-inserted in another form below)
+ if (pChange)
+ m_pCurrentParent->removeChange(pChange->getNodeName());
+
+ // insert a new change if necessary
+ switch (aExaminer.getAction())
+ {
+ case OMergeRemoveNode::RemoveCompletely:
+ // nothing to do, we already removed it
+ break;
+ default:
+ OSL_ENSURE(sal_False, "OMergeTreeChangeList::handle(RemoveNode): don't know what to do with this!");
+ // NO BREAK.
+ // defaulting this so that the node will be marked as deleted
+ case OMergeRemoveNode::FlagDeleted:
+ {
+ auto_ptr<Change> pNewChange(new RemoveNode(_rRemoveNode.getNodeName()));
+ m_pCurrentParent->addChange(pNewChange);
+ }
+ break;
+ }
+ }
+
+ void OMergeTreeChangeList::handle(SubtreeChange const& _rSubtree)
+ {
+ // Handle a SubtreeChange
+ // we must check if exact this SubtreeChange is in the TreeChangeList, if not,
+ // we must add this SubtreeChange to the TreeChangeList
+ // with the pointer m_pCurrentParent we remember our SubtreeChange in witch we
+ // add all other Changes.
+
+ rtl::OUString aSearchName = createName(_rSubtree.getNodeName());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aTreeChangeList.root);
+ /*
+ if (pChange)
+ {
+ // Value found, merge content
+ OMergeSubtreeChange a(_rSubtree);
+ a.handleChange(*pChange);
+ }
+ else
+ {
+ // Value not found, create a new SubtreeChange
+ auto_ptr<SubtreeChange> pNewChange(new SubtreeChange(_rSubtree, SubtreeChange::NoChildCopy()));
+ // add the new SubtreeChange in m_aTreeChangeList
+ m_pCurrentParent->addChange(auto_ptr<Change>(pNewChange.release()));
+ }
+ */
+
+ // const sal_Char* pType = pChange ? pChange->getType() : NULL;
+ SubtreeChange* pSubtreeChange = NULL;
+ if (pChange == NULL || pChange->ISA(SubtreeChange))
+ {
+ // hard cast(!) to SubtreeChange because we are a SubtreeChange
+ pSubtreeChange = SAL_STATIC_CAST(SubtreeChange*, pChange);
+ if (pSubtreeChange)
+ {
+ // Value found, nothing to be done, because we are a SubtreeChange
+ // we only must go downstairs
+ }
+ else
+ {
+ // create a new SubtreeChange
+ auto_ptr<SubtreeChange> pNewChange(new SubtreeChange(_rSubtree, SubtreeChange::NoChildCopy()));
+ // add the new SubtreeChange in m_aTreeChangeList
+ m_pCurrentParent->addChange(auto_ptr<Change>(pNewChange.release()));
+ // check list and get this new SubtreeChange
+ pChange = a.searchForChange(m_aTreeChangeList.root);
+ pSubtreeChange = SAL_STATIC_CAST(SubtreeChange*, pChange);
+ }
+ // save this SubtreeChange so we allways have the last Subtree
+ pushTree(pSubtreeChange); // remember the SubtreeChange Pointer
+ pushName(_rSubtree.getNodeName()); // pathstack
+ _rSubtree.forEachChange(*this);
+ popName();
+ popTree();
+ }
+ else if (pChange->ISA(AddNode))
+ {
+ AddNode* pAddNode = SAL_STATIC_CAST(AddNode*, pChange);
+ INode* pNode = pAddNode->getAddedNode();
+ ISubtree* pSubtree = pNode ? pNode->asISubtree() : 0;
+
+ OSL_ENSURE(pSubtree, "BLA");
+ if (pSubtree)
+ {
+ OSL_ENSHURE(false, "DANGER, THIS CODE IS WRONG!");
+ // because, the important Node is the _rSubtree, which will not insert anywhere
+
+ // Merge _rSubtree into pSubtree using a TreeUpdate object
+ TreeUpdate aTreeUpdate(pSubtree);
+ TreeChangeList aMergeChangeList(m_aTreeChangeList, SubtreeChange::NoChildCopy());
+ OMergeTreeAction aChangeHandler(aMergeChangeList.root, pSubtree);
+ m_aTreeChangeList.root.forEachChange(aChangeHandler);
+ // now check the real modifications
+ OChangeActionCounter aChangeCounter;
+ aChangeCounter.handle(aMergeChangeList.root);
+ CFG_TRACE_INFO("cache manager: counted changes from notification : additions: %i , removes: %i, value changes: %i", aChangeCounter.nAdds, aChangeCounter.nRemoves, aChangeCounter.nValues);
+ if (aChangeCounter.hasChanges())
+ {
+ // aTree.updateTree(aMergeChangeList);
+ aMergeChangeList.root.forEachChange(aTreeUpdate);
+ }
+ }
+ else
+ {
+ /* wrong type of node found: bse ASSERTEN/WERFEN */;
+ }
+
+ }
+ else
+ {
+ /* wrong type of node found: bse ASSERTEN/WERFEN */;
+ }
+ }
+
+
+
+ // -----------------------------------------------------------------------------
+
+ // ------- Helper for Path stack -------
+ void OMergeChanges::pushTree(SubtreeChange* _pTree)
+ {
+ m_pCurrentParent = _pTree;
+ OSL_ENSHURE(m_pCurrentParent, "OMergeChanges::pushTree: must not be NULL!");
+ m_aTreePathStack.push_back(_pTree);
+ }
+ void OMergeChanges::popTree()
+ {
+ m_aTreePathStack.pop_back();
+ m_pCurrentParent = m_aTreePathStack.back();
+ }
+
+ // CTor
+ OMergeChanges::OMergeChanges(SubtreeChange& _aTree)
+ :m_aSubtreeChange(_aTree), m_pCurrentParent(NULL)
+ {
+ }
+
+ SubtreeChange* OMergeChanges::check(const ConfigurationName &_aName)
+ {
+ // First check, if the aName is in the subtreechange
+ ONameCreator aNameCreator;
+
+ SubtreeChange* pCurrentParent = &m_aSubtreeChange;
+
+ if (!(_aName.fullName().equals(ASCII("/"))))
+ {
+ for(ConfigurationName::Iterator it = _aName.begin();
+ it != _aName.end();
+ ++it)
+ {
+ aNameCreator.pushName(*it);
+ rtl::OUString aSearchName = aNameCreator.createName(OUString());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aSubtreeChange);
+
+ if (!pChange)
+ {
+ // create a correspondens for the name, we not found.
+ auto_ptr<SubtreeChange> pNewChange(new SubtreeChange(*it, OUString(), configuration::Attributes()));
+ pCurrentParent->addChange(auto_ptr<Change>(pNewChange.release()));
+
+ pChange = a.searchForChange(m_aSubtreeChange);
+ }
+ pCurrentParent = SAL_STATIC_CAST(SubtreeChange*, pChange);
+
+ // HACK!
+ // no descent to anything, we are flat!
+ break;
+ }
+ }
+ return pCurrentParent;
+ }
+
+ // start function, with the Change we want to do.
+ // WARNING this could be a big tree, because a change can contain subtreechanges!
+ void OMergeChanges::handleChange(const SubtreeChange &_rList, const rtl::OUString &_aPathToRoot)
+ {
+ rtl::OUString aPath = _aPathToRoot;
+ ConfigurationName aName(aPath, ConfigurationName::Absolute());
+ // try to use an empty List.
+ // init(aName); // our Name start with pathToRoot
+ m_pCurrentParent = check(aName); // pathToRoot must exist or will be created
+
+ applyToChange(_rList);
+ }
+
+ // Algorithm: search the actual path in the out m_aSubtreeChange
+ // if we found something, we must merge/convert the Node with our Node
+ // if we found nothing, we must create a new Node with our change
+ // thats it.
+
+ // the merge is contructed with helper classes because, it's possible that we
+ // are a ValueChange but in the TreeChangeList this change is an AddNode, so
+ // we have something to do.
+
+ void OMergeChanges::handle(ValueChange const& _rValueNode)
+ {
+ // Handle a ValueChange,
+ rtl::OUString aSearchName = createName(_rValueNode.getNodeName()); // this construct is only for better debugging
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aSubtreeChange);
+ if (pChange)
+ {
+ // Value found, merge content
+ OMergeValueChange a(_rValueNode);
+ a.handleChange(*pChange);
+ }
+ else
+ {
+ // there is no ValueChange in the List, insert new one
+ auto_ptr<Change> pNewChange(new ValueChange(_rValueNode));
+ m_pCurrentParent->addChange(pNewChange);
+ }
+ }
+
+ void OMergeChanges::handle(AddNode const& _rAddNode)
+ {
+ // Handle an AddNode
+ rtl::OUString aSearchName = createName(_rAddNode.getNodeName());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aSubtreeChange);
+
+ if (pChange)
+ {
+ OSL_ENSURE(pChange->ISA(RemoveNode) || _rAddNode.isReplacing(), "OMergeTreeChangeList::handle(AddNode): the changes tree given already contains a change for this!");
+
+ m_pCurrentParent->removeChange(pChange->getNodeName());
+ }
+ // insert manually
+ auto_ptr<INode> pNode = auto_ptr<INode>(_rAddNode.getAddedNode()->clone());
+ auto_ptr<Change> pNewChange(new AddNode(pNode, _rAddNode.getNodeName()));
+ m_pCurrentParent->addChange(pNewChange);
+ }
+
+ void OMergeChanges::handle(RemoveNode const& _rRemoveNode)
+ {
+ // Handle a RemoveNode
+ rtl::OUString aSearchName = createName(_rRemoveNode.getNodeName());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aSubtreeChange);
+
+ // examine what to do with this change
+ OMergeRemoveNode aExaminer;
+ aExaminer.handleChange(pChange);
+
+ // remove the change from it's parent (may it's re-inserted in another form below)
+ if (pChange)
+ m_pCurrentParent->removeChange(pChange->getNodeName());
+
+ // insert a new change if necessary
+ switch (aExaminer.getAction())
+ {
+ case OMergeRemoveNode::RemoveCompletely:
+ // nothing to do, we already removed it
+ break;
+ default:
+ OSL_ENSURE(sal_False, "OMergeChanges::handle(RemoveNode): don't know what to do with this!");
+ // NO BREAK.
+ // defaulting this so that the node will be marked as deleted
+ case OMergeRemoveNode::FlagDeleted:
+ {
+ auto_ptr<Change> pNewChange(new RemoveNode(_rRemoveNode.getNodeName()));
+ m_pCurrentParent->addChange(pNewChange);
+ }
+ break;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+ class TreeUpdater : public ChangeTreeModification
+ {
+ ISubtree* m_pCurrentSubtree;
+#if DEBUG
+ std::vector<rtl::OString> aLog;
+#endif
+
+ public:
+ TreeUpdater(ISubtree* pSubtree):m_pCurrentSubtree(pSubtree){}
+
+ void handle(ValueChange& aValueNode);
+ void handle(AddNode& aAddNode);
+ void handle(RemoveNode& aRemoveNode);
+ void handle(SubtreeChange& aSubtree);
+ };
+
+// -----------------------------------------------------------------------------
+
+
+ void OMergeChanges::handle(SubtreeChange const& _rSubtreeChange)
+ {
+ // Handle a SubtreeChange
+ // we must check if exact this SubtreeChange is in the TreeChangeList, if not,
+ // we must add this SubtreeChange to the TreeChangeList
+ // with the pointer m_pCurrentParent we remember our SubtreeChange in witch we
+ // add all other Changes.
+
+ rtl::OUString aSearchName = createName(_rSubtreeChange.getNodeName());
+ OMergeSearchChange a(aSearchName);
+ Change *pChange = a.searchForChange(m_aSubtreeChange);
+
+ SubtreeChange* pSubtreeChange = NULL;
+ if (pChange == NULL || pChange->ISA(SubtreeChange))
+ {
+ // hard cast(!) to SubtreeChange because we are a SubtreeChange
+ pSubtreeChange = SAL_STATIC_CAST(SubtreeChange*, pChange);
+ if (pSubtreeChange)
+ {
+ // Value found, nothing to be done, because we are a SubtreeChange
+ // we only must go downstairs
+ }
+ else
+ {
+ // create a new SubtreeChange
+ auto_ptr<SubtreeChange> pNewChange(new SubtreeChange(_rSubtreeChange, SubtreeChange::NoChildCopy()));
+ // add the new SubtreeChange in m_aTreeChangeList
+ m_pCurrentParent->addChange(auto_ptr<Change>(pNewChange.release()));
+ // check list and get this new SubtreeChange
+ pChange = a.searchForChange(m_aSubtreeChange);
+ pSubtreeChange = SAL_STATIC_CAST(SubtreeChange*, pChange);
+ }
+ // save this SubtreeChange so we allways have the last Subtree
+ pushTree(pSubtreeChange); // remember the SubtreeChange Pointer
+ pushName(_rSubtreeChange.getNodeName()); // pathstack
+ _rSubtreeChange.forEachChange(*this);
+ popName();
+ popTree();
+ }
+ else if (pChange->ISA(AddNode))
+ {
+ // OSL_ENSHURE(false, "sorry, no addnode in subtreechange! can't supported yet.");
+
+ AddNode* pAddNode = SAL_STATIC_CAST(AddNode*, pChange);
+ INode* pNode = pAddNode->getAddedNode();
+ ISubtree* pISubtree = pNode ? pNode->asISubtree() : 0;
+
+ OSL_ENSURE(pISubtree, "Warning: there is no Subtree in the AddNode");
+ if (pISubtree)
+ {
+ // ----------------------------
+ // pISubtree += _rSubtreeChange
+ // ----------------------------
+
+ // Merge _rSubtreeChange into pSubtree using a TreeUpdate object
+ SubtreeChange *pSubtreeChange = SAL_STATIC_CAST(SubtreeChange*, _rSubtreeChange.clone());
+ TreeUpdater aTreeUpdate(pISubtree);
+ pSubtreeChange->forEachChange(aTreeUpdate);
+
+//
+// // auto_ptr<SubtreeChange> pNewChange(new SubtreeChange(_rSubtreeChange, SubtreeChange::NoChildCopy()));
+// // OMergeTreeAction aChangeHandler(*pNewChange.get(), pISubtree);
+// // pNewChange.get()->forEachChange(aChangeHandler);
+//
+// TreeChangeList aMergeChangeList(NULL, _rSubtreeChange.getNodeName(), _rSubtreeChange);
+//
+// OMergeTreeAction aChangeHandler(aMergeChangeList.root, pISubtree);
+// m_aSubtreeChange.forEachChange(aChangeHandler);
+//
+// // now check the real modifications
+// OChangeActionCounter aChangeCounter;
+// // aChangeCounter.handle(*pNewChange.get());
+// aChangeCounter.handle(aMergeChangeList.root);
+//
+// CFG_TRACE_INFO("cache manager: counted changes from notification : additions: %i , removes: %i, value changes: %i", aChangeCounter.nAdds, aChangeCounter.nRemoves, aChangeCounter.nValues);
+// if (aChangeCounter.hasChanges())
+// {
+// // pNewChange.get()->forEachChange(aTreeUpdate);
+// aMergeChangeList.root.forEachChange(aTreeUpdate);
+// }
+ }
+ else
+ {
+ // wrong type of node found: bse ASSERTEN/WERFEN
+ }
+ }
+ else
+ {
+ // wrong type of node found: bse ASSERTEN/WERFEN
+ }
+ }
+
+
+
+ // --------------------------------- updateTree ---------------------------------
+ void TreeUpdater::handle(ValueChange& aValueNode)
+ {
+ // Change a Value
+ OSL_ENSURE(m_pCurrentSubtree,"Cannot apply ValueChange without subtree");
+
+ INode* pBaseNode = m_pCurrentSubtree ? m_pCurrentSubtree->getChild(aValueNode.getNodeName()) : 0;
+ OSL_ENSURE(pBaseNode,"Cannot apply Change: No node to change");
+
+ ValueNode* pValue = pBaseNode ? pBaseNode->asValueNode() : 0;
+ OSL_ENSURE(pValue,"Cannot apply ValueChange: Node is not a value");
+
+ if (pValue)
+ aValueNode.applyTo(*pValue);
+#ifdef DEBUG
+ else
+ {
+ ::rtl::OString aStr("TreeUpdater: Can't find value with name:=");
+ aStr += rtl::OUStringToOString(aValueNode.getNodeName(),RTL_TEXTENCODING_ASCII_US);
+ OSL_ENSHURE(pValue, aStr.getStr());
+ aLog.push_back(aStr);
+ }
+#endif
+ }
+
+ void TreeUpdater::handle(AddNode& aAddNode)
+ {
+ // Add a new Value
+ if (m_pCurrentSubtree)
+ {
+ if (aAddNode.isReplacing())
+ {
+ std::auto_ptr<INode> aOldNode = m_pCurrentSubtree->removeChild(aAddNode.getNodeName());
+
+#ifdef DEBUG
+ OSL_ENSHURE(aOldNode.get(), "TreeUpdater:AddNode: can't recover node being replaced");
+ if (aOldNode.get() == NULL)
+ aLog.push_back(rtl::OString("TreeUpdater: can't recover node being replaced (for AddNode)"));
+#endif
+ if (aOldNode.get() != NULL)
+ {
+ OIdRemover::removeIds(*aOldNode);
+ }
+
+ aAddNode.takeReplacedNode( aOldNode );
+ }
+
+ m_pCurrentSubtree->addChild(aAddNode.releaseAddedNode());
+
+ OIdPropagator::propagateIdToChildren(*m_pCurrentSubtree);
+ }
+#ifdef DEBUG
+ else
+ aLog.push_back(rtl::OString("TreeUpdater: no CurrentSubtree for AddNode"));
+#endif
+
+ }
+
+ void TreeUpdater::handle(RemoveNode& aRemoveNode)
+ {
+ // remove a Value
+ if (m_pCurrentSubtree)
+ {
+ std::auto_ptr<INode> aOldNode = m_pCurrentSubtree->removeChild(aRemoveNode.getNodeName());
+
+ sal_Bool bOk = (NULL != aOldNode.get());
+ if (bOk)
+ {
+ OIdRemover::removeIds(*aOldNode);
+ }
+ aRemoveNode.takeRemovedNode( aOldNode );
+
+#ifdef DEBUG
+ if (!bOk)
+ {
+ ::rtl::OString aStr("TreeUpdater: Can't remove child with name:=");
+ aStr += rtl::OUStringToOString(aRemoveNode.getNodeName(),RTL_TEXTENCODING_ASCII_US);
+ OSL_ENSHURE(bOk, aStr.getStr());
+ aLog.push_back(aStr);
+ }
+#endif
+ }
+ }
+
+ void TreeUpdater::handle(SubtreeChange& _aSubtree)
+ {
+ // handle traversion
+ ISubtree *pOldSubtree = m_pCurrentSubtree;
+ rtl::OUString aNodeName = _aSubtree.getNodeName();
+ OSL_ENSHURE(m_pCurrentSubtree->getChild(aNodeName), "TreeUpdater::handle : invalid subtree change ... this will crash !");
+ m_pCurrentSubtree = m_pCurrentSubtree->getChild(aNodeName)->asISubtree();
+
+#if DEBUG
+ ::rtl::OString aStr("TreeUpdater: there is no Subtree for name:=");
+ aStr += rtl::OUStringToOString(_aSubtree.getNodeName(),RTL_TEXTENCODING_ASCII_US);
+ OSL_ENSHURE(m_pCurrentSubtree, aStr.getStr());
+ if (!m_pCurrentSubtree)
+ aLog.push_back(aStr);
+#endif
+
+ _aSubtree.forEachChange(*this);
+ m_pCurrentSubtree = pOldSubtree;
+ }
+
+} // namespace configmgr
diff --git a/configmgr/source/tree/changes.cxx b/configmgr/source/tree/changes.cxx
index 5cefc49c3e1e..dd90cca63298 100644
--- a/configmgr/source/tree/changes.cxx
+++ b/configmgr/source/tree/changes.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: changes.cxx,v $
*
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
*
- * last change: $Author: dg $ $Date: 2000-11-30 08:31:49 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:33 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -108,6 +108,11 @@ ValueChange::ValueChange(const ValueChange& _rChange)
,m_aAttributes(_rChange.getAttributes())
{}
+// -----------------------------------------------------------------------------
+Change* ValueChange::clone() const
+{
+ return new ValueChange(*this);
+}
// -------------------------------------------------------------------------
namespace tree_changes_internal {
inline void doAdjust(uno::Any& aActual, uno::Any const& aTarget)
@@ -204,6 +209,24 @@ AddNode::~AddNode()
{
}
+// -----------------------------------------------------------------------------
+AddNode::AddNode(const AddNode& _aObj)
+ : Change(_aObj), m_bReplacing(_aObj.m_bReplacing)
+{
+ m_pNewNode = _aObj.m_pNewNode ? _aObj.m_pNewNode->clone() : NULL;
+ m_pOldNode = _aObj.m_pOldNode ? _aObj.m_pOldNode->clone() : NULL;
+ if (_aObj.m_aOwnNewNode.get())
+ m_aOwnNewNode.reset(_aObj.m_aOwnNewNode.get()->clone());
+ if (_aObj.m_aOwnOldNode.get())
+ m_aOwnOldNode.reset(_aObj.m_aOwnOldNode.get()->clone());
+}
+
+// -----------------------------------------------------------------------------
+Change* AddNode::clone() const
+{
+ return new AddNode(*this);
+}
+
//--------------------------------------------------------------------------
void AddNode::expectReplacedNode(INode* pOldNode)
{
@@ -238,6 +261,20 @@ RemoveNode::RemoveNode(OUString const& _rName)
RemoveNode::~RemoveNode()
{
}
+// -----------------------------------------------------------------------------
+RemoveNode::RemoveNode(const RemoveNode& _aObj)
+ :Change(_aObj)
+{
+ m_pOldNode = _aObj.m_pOldNode ? _aObj.m_pOldNode->clone() : NULL;
+ if (_aObj.m_aOwnOldNode.get())
+ m_aOwnOldNode.reset(_aObj.m_aOwnOldNode.get()->clone());
+}
+
+// -----------------------------------------------------------------------------
+Change* RemoveNode::clone() const
+{
+ return new RemoveNode(*this);
+}
//--------------------------------------------------------------------------
void RemoveNode::expectRemovedNode(INode* pOldNode)
diff --git a/configmgr/source/tree/cmtreemodel.cxx b/configmgr/source/tree/cmtreemodel.cxx
index 7adbe4babadd..a3e1ea6c0dc4 100644
--- a/configmgr/source/tree/cmtreemodel.cxx
+++ b/configmgr/source/tree/cmtreemodel.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: cmtreemodel.cxx,v $
*
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
*
- * last change: $Author: lla $ $Date: 2000-12-12 17:00:40 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:33 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -105,10 +105,32 @@ SubtreeChange::~SubtreeChange()
}
}
+// -----------------------------------------------------------------------------
+SubtreeChange::SubtreeChange(const SubtreeChange& _aObj)
+ :Change(_aObj),
+ m_sTemplateName(_aObj.m_sTemplateName),
+ m_aAttributes(_aObj.m_aAttributes)
+{
+ for(Children::const_iterator aIter = _aObj.m_aChanges.begin();
+ aIter != _aObj.m_aChanges.end();
+ ++aIter)
+ {
+ OSL_ASSERT(aIter->second);
+ Children::value_type aCopy(aIter->first, aIter->second->clone());
+ m_aChanges.insert(m_aChanges.end(), aCopy);
+ }
+}
+
+// -----------------------------------------------------------------------------
+Change* SubtreeChange::clone() const
+{
+ return new SubtreeChange(*this);
+}
//--------------------------------------------------------------------------
void SubtreeChange::addChange(std::auto_ptr<Change> aChange)
{
OUString aNodeName(aChange->getNodeName());
+ m_aChanges.find(aNodeName);
OSL_ENSHURE(m_aChanges.end() == m_aChanges.find(aNodeName),
"SubtreeChange::addChange : overwriting an existent change !");
delete m_aChanges[aNodeName];
diff --git a/configmgr/source/treecache/disposetimer.cxx b/configmgr/source/treecache/disposetimer.cxx
index 75e28f89c93c..e3b121388eb3 100644
--- a/configmgr/source/treecache/disposetimer.cxx
+++ b/configmgr/source/treecache/disposetimer.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: disposetimer.cxx,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: dg $ $Date: 2000-12-20 10:54:23 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:34 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -230,13 +230,13 @@ TimeStamp OTreeDisposeScheduler::runDisposer(TimeStamp const& _aActualTime)
osl::ClearableMutexGuard aGuard( m_rTreeManager.m_aTreeListMutex );
- vos::ORef< OOptions > xTask = this->getTask( _aActualTime, aNextTime );
- if (xTask.isValid())
+ vos::ORef< OOptions > xTaskOption = this->getTask( _aActualTime, aNextTime );
+ if (xTaskOption.isValid())
{
CFG_TRACE_INFO("Found cleanup task for user %s and locale %s",
- OUSTRING2ASCII(xTask->getUser()), OUSTRING2ASCII(xTask->getLocale()));
+ OUSTRING2ASCII(xTaskOption->getUser()), OUSTRING2ASCII(xTaskOption->getLocale()));
- if (TreeInfo* pInfo = m_rTreeManager.requestTreeInfo(xTask,false))
+ if (TreeInfo* pInfo = m_rTreeManager.requestTreeInfo(xTaskOption,false))
{
CFG_TRACE_INFO_NI("- Found matching data container (TreeInfo) - collecting data");
@@ -258,7 +258,7 @@ TimeStamp OTreeDisposeScheduler::runDisposer(TimeStamp const& _aActualTime)
CFG_TRACE_INFO_NI("- Rescheduling current option set" );
- aNextTime = this->implAddTask(xTask,aNextTaskTime);
+ aNextTime = this->implAddTask(xTaskOption,aNextTaskTime);
}
else if (pInfo->isEmpty())// may have been the last one - check that
@@ -268,7 +268,7 @@ TimeStamp OTreeDisposeScheduler::runDisposer(TimeStamp const& _aActualTime)
// get rid of it - see TreeManager::disposeOne
std::auto_ptr<TreeInfo> pDisposeInfo(pInfo);
- m_rTreeManager.m_aTreeList.erase(xTask);
+ m_rTreeManager.m_aTreeList.erase(xTaskOption);
// got it out of reachability - now dispose/notify without lock
@@ -294,14 +294,14 @@ TimeStamp OTreeDisposeScheduler::runDisposer(TimeStamp const& _aActualTime)
if (aNodeList.getLength() > 0)
{
CFG_TRACE_INFO_NI("- Stoping notifications for %d Nodes", int(aNodeList.getLength()) );
- m_rTreeManager.cancelNotify(aNodeList, xTask);
+ m_rTreeManager.cancelNotify(aNodeList, xTaskOption);
}
uno::Sequence< OUString > aCloseList = TreeInfo::collectNodeIds(aDisposeList);
if (aCloseList.getLength() > 0)
{
CFG_TRACE_INFO_NI("- Closing %d NodeIds", int(aCloseList.getLength()) );
- m_rTreeManager.closeNodes(aCloseList,xTask);
+ m_rTreeManager.closeNodes(aCloseList,xTaskOption);
}
}
CFG_TRACE_INFO_NI("- Now disposing %d module trees", int(aDisposeList.size()) );
@@ -373,5 +373,174 @@ TimeStamp OTreeDisposeScheduler::implAddTask(vos::ORef< OOptions > const& _xOpti
}
// -------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
// =========================================================================
+OTreeCacheWriteScheduler::~OTreeCacheWriteScheduler()
+{
+ stopAndWriteCache();
+}
+
+void OTreeCacheWriteScheduler::stopAndWriteCache()
+{
+ osl::MutexGuard aOwnGuard( m_aMutex );
+
+ CFG_TRACE_INFO("Cancelling all cache writings, Stopping timer");
+
+ if (m_xTimer.isValid())
+ {
+ m_xTimer->stop(); // just to be sure
+ m_xTimer.unbind(); // just to be sure
+ }
+ runDisposer();
+}
+// -------------------------------------------------------------------------
+void OTreeCacheWriteScheduler::Timer::onShot()
+{
+ rParent.onTimerShot();
+}
+// -----------------------------------------------------------------------------
+void OTreeCacheWriteScheduler::onTimerShot()
+{
+ //m_aTimer.stop();
+
+ CFG_TRACE_INFO("Cleanup Timer invoked - executing dispose task");
+
+ try
+ {
+ runDisposer();
+ }
+
+ catch (uno::Exception& ue)
+ {
+ OSL_ENSURE(false, "ERROR: UNO Exception left a disposer");
+ ue;
+ }
+ catch (configuration::Exception& ce)
+ {
+ OSL_ENSURE(false, "ERROR: configuration::Exception left a disposer");
+ ce;
+ }
+ catch (...)
+ {
+ OSL_ENSURE(false, "ERROR: Unknown Exception left a disposer");
+ }
+
+ TimeStamp aNewTime = implGetCleanupTime(TimeStamp::getCurrentTime(), m_aCleanupInterval);
+
+ osl::MutexGuard aGuard(m_aMutex);
+ implStartBefore(aNewTime);
+}
+// -------------------------------------------------------------------------
+void OTreeCacheWriteScheduler::runDisposer()
+{
+ // Write Cache
+ CFG_TRACE_INFO("Starting lasy write");
+ osl::ClearableMutexGuard aGuard( m_rTreeManager.m_aUpdateMutex );
+
+ for (CacheWriteList::iterator it = m_aWriteList.begin();
+ it != m_aWriteList.end();
+ ++it)
+ {
+ vos::ORef< OOptions > xTaskOption = *it;
+ if (xTaskOption.isValid())
+ {
+ if (TreeInfo* pInfo = m_rTreeManager.requestTreeInfo(xTaskOption,false))
+ {
+ CFG_TRACE_INFO_NI("- Found matching data container (TreeInfo) - collecting data");
+
+ PendingList aList;
+ sal_Int32 nCount = pInfo->syncPending(xTaskOption, aList);
+ if (nCount > 0)
+ {
+ CFG_TRACE_INFO_NI("write down %d pendings", nCount);
+ for(PendingList::iterator it = aList.begin();
+ it != aList.end();
+ ++it)
+ {
+ rtl::OUString sName = it->first;
+ auto_ptr<SubtreeChange> aSubtreeChange = it->second;
+ ConfigurationName aName; // MUST be empty, we have the ptr to the root obj
+ m_rTreeManager.sessionUpdate(xTaskOption, aName, aSubtreeChange);
+ }
+ }
+ }
+ }
+ else
+ {
+ CFG_TRACE_WARNING_NI("runDisposer: TaskOption not valid");
+ }
+
+ }
+ m_aWriteList.clear();
+}
+
+// -----------------------------------------------------------------------------
+// should be called guarded only
+void OTreeCacheWriteScheduler::implStartBefore(TimeStamp const& _aTime)
+{
+ // check if we were cleared
+ if (!m_aWriteList.empty())
+ {
+ if (m_xTimer.isEmpty())
+ m_xTimer = new Timer(*this);
+
+ if (!m_xTimer->isTicking())
+ {
+ m_xTimer->setAbsoluteTime(_aTime.getTimeValue());
+
+ if (!m_xTimer->isTicking())
+ m_xTimer->start();
+
+ OSL_ASSERT( m_xTimer->isTicking() );
+ }
+ CFG_TRACE_INFO_NI("- Cleanup timer running - next execution in %d seconds", int (m_xTimer->getRemainingTime().Seconds) );
+ CFG_TRACE_INFO_NI("- %d cleanup tasks are pending", int(m_aWriteList.size()) );
+ }
+ else
+ {
+ if (!m_xTimer.isEmpty())
+ {
+ m_xTimer->stop();
+ CFG_TRACE_INFO_NI("- Stopped timer - no more open cleanup tasks");
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+void OTreeCacheWriteScheduler::scheduleWrite(vos::ORef< OOptions > const& _xOptions, bool _bSync)
+{
+ OSL_ASSERT(_xOptions.isValid());
+ OSL_ENSURE(_xOptions->getLocale().getLength() >0, "ERROR: OTreeDisposeScheduler: cannot handle complete user scheduling");
+
+ osl::MutexGuard aGuard( m_aMutex );
+
+ CFG_TRACE_INFO("Scheduling cache write for user '%s' with locale '%s'",
+ OUSTRING2ASCII(_xOptions->getUser()), OUSTRING2ASCII(_xOptions->getLocale()));
+
+ CFG_TRACE_INFO_NI("- cache write will be started in about %d seconds", int(m_aCleanupInterval.getTimeValue().Seconds));
+
+ m_aWriteList.push_back(_xOptions);
+
+
+ if (_bSync || m_bSyncron)
+ {
+ // write now!
+ runDisposer();
+ }
+ else
+ {
+ // lasy writing
+ TimeStamp aNewTime = implGetCleanupTime(TimeStamp::getCurrentTime(), m_aCleanupInterval);
+ implStartBefore(aNewTime);
+ }
+}
+
} // namespace
diff --git a/configmgr/source/treecache/disposetimer.hxx b/configmgr/source/treecache/disposetimer.hxx
index f65590a14971..f597526a523a 100644
--- a/configmgr/source/treecache/disposetimer.hxx
+++ b/configmgr/source/treecache/disposetimer.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: disposetimer.hxx,v $
*
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
- * last change: $Author: jb $ $Date: 2000-12-15 16:14:03 $
+ * last change: $Author: lla $ $Date: 2001-01-17 15:02:34 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -74,6 +74,10 @@ namespace configmgr
{
class TreeManager;
////////////////////////////////////////////////////////////////////////////////
+/* OTreeDisposeScheduler:
+ does something special????
+*/
+
class OTreeDisposeScheduler
{
typedef std::multimap< TimeStamp, vos::ORef< OOptions >, ltTimeStamp > Agenda;
@@ -187,6 +191,79 @@ namespace configmgr
{ return aBaseTime + aDelay; }
};
+
+ // -----------------------------------------------------------------------------
+
+ // Write down the Cache, much less complex than caching Nodes
+ // (better control)
+ class OTreeCacheWriteScheduler
+ {
+ typedef std::vector<vos::ORef< OOptions > > CacheWriteList; // fire and forget!
+
+ class Timer : public vos::OTimer
+ {
+ public:
+ OTreeCacheWriteScheduler& rParent;
+
+ Timer(OTreeCacheWriteScheduler& _rParent) : rParent(_rParent) {};
+
+ // vos::OTimer
+ virtual void SAL_CALL onShot();
+ };
+ friend void Timer::onShot();
+ private:
+ mutable osl::Mutex m_aMutex;
+ vos::ORef<Timer> m_xTimer;
+ TreeManager& m_rTreeManager;
+
+ CacheWriteList m_aWriteList;
+ // TimeInterval m_aCleanupDelay;
+ TimeInterval m_aCleanupInterval;
+
+ bool m_bSyncron; // if true, write syncron only, no timer thread
+
+ public:
+ //-------- Construction and destruction -----------------------------------
+ explicit
+ OTreeCacheWriteScheduler(TreeManager& _rTreeManager, TimeInterval const& _aCleanupDelay, bool _bSyncron)
+ : m_xTimer(0)
+ , m_rTreeManager(_rTreeManager)
+ , m_aCleanupInterval(_aCleanupDelay)
+ , m_bSyncron(_bSyncron)
+ {}
+ ~OTreeCacheWriteScheduler();
+
+ //-------- Delay and Interval ---------------------------------------------
+ /// retrieves the recurrance interval used for cleanup
+ TimeInterval const& getCleanupInterval() const
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ return m_aCleanupInterval;
+ }
+ /// calculate the time when to cleanup an pbject that became eligible at <var>aBaseTime</var>.
+ TimeStamp getCleanupTime(TimeStamp const& aBaseTime = TimeStamp::getCurrentTime())
+ {
+ return implGetCleanupTime(aBaseTime, getCleanupInterval());
+ }
+ static TimeStamp implGetCleanupTime(TimeStamp const& aBaseTime, TimeInterval const& aDelay)
+ {
+ return aBaseTime + aDelay;
+ }
+ //-------- Control of execution ------------------------------------------
+ /// stop and discard pending activities for _xOptions
+ // void writeCache(vos::ORef< OOptions > const& _xOptions);
+ void scheduleWrite(vos::ORef< OOptions > const& _xOptions, bool _bSync = false);
+
+ /// stop and discard pending activities
+ void stopAndWriteCache();
+ private:
+ // vos::OTimer
+ void onTimerShot();
+
+ void runDisposer();
+ void implStartBefore(TimeStamp const& _aTime);
+
+ };
////////////////////////////////////////////////////////////////////////////////
} // namespace configmgr