1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: mergechange.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "builddata.hxx"
35 #include "mergechange.hxx"
36 #include "updatehelper.hxx"
37 #include "treeactions.hxx"
38 #include "treefragment.hxx"
40 #include "treechangefactory.hxx"
41 #include "treechangelist.hxx"
42 #include "configexcept.hxx"
45 #define ASCII(x) rtl::OUString::createFromAscii(x)
49 // -----------------------------------------------------------------------------
50 // -----------------------------------------------------------------------------
52 // -----------------------------------------------------------------------------
53 class OMergeChanges
: private ChangeTreeAction
, private OPathCreator
<configuration::RelativePath
>
55 SubtreeChange
&m_rSubtreeChange
; // ChangeList, which will be grown
56 SubtreeChange
*m_pCurrentParent
; // our current position
58 // ------- Helper for Path stack -------
59 SubtreeChange
* pushTree(SubtreeChange
& _rTree
);
60 void popTree(SubtreeChange
* _pSaveTree
);
64 OMergeChanges(SubtreeChange
& _rTree
);
66 // start function, with the Change we want to do.
67 // WARNING this could be a big tree, because a change can contain subtreechanges!
68 void mergeChanges(const SubtreeChange
&_rChange
, const configuration::RelativePath
& _aPathToChange
);
69 void mergeChanges(const SubtreeChange
&_rChange
);
72 void initRoot(const SubtreeChange
&_rRootChange
, const configuration::RelativePath
& _aPathToChange
);
74 virtual void handle(ValueChange
const& _rValueNode
);
75 virtual void handle(AddNode
const& _rAddNode
);
76 virtual void handle(RemoveNode
const& _rRemoveNode
);
77 virtual void handle(SubtreeChange
const& _rSubtree
);
80 // -----------------------------------------------------------------------------
81 void combineUpdates(SubtreeChange
const& _anUpdate
, SubtreeChange
& _aCombinedUpdate
)
83 OMergeChanges
aCombined(_aCombinedUpdate
);
84 aCombined
.mergeChanges(_anUpdate
);
86 // -----------------------------------------------------------------------------
88 configuration::Path::Component
ONameCreator::createName(Change
const& _rChange
, SubtreeChange
const* _pParent
)
90 OSL_ENSURE(_pParent
, "ONameCreator: Cannot create proper name without a parent");
91 if (_pParent
&& _pParent
->isSetNodeChange())
93 rtl::OUString sElementName
= _rChange
.getNodeName();
94 rtl::OUString sTypeName
= _pParent
->getElementTemplateName();
96 return configuration::Path::makeCompositeName(sElementName
, sTypeName
);
100 rtl::OUString sElementName
= _rChange
.getNodeName();
102 // OSL_ENSURE(isSimpleName(sElementName),"Unexpected: Non-simple name in non-set node");
104 return configuration::Path::wrapSafeName(sElementName
);
109 // -----------------------------------------------------------------------------
110 class OMergeValueChange
: private ChangeTreeModification
112 SubtreeChange
& m_rTargetParent
;
113 const ValueChange
& m_aValueChange
;
115 OMergeValueChange(SubtreeChange
& _rTargetParent
, const ValueChange
& _aValueChange
)
116 :m_rTargetParent(_rTargetParent
)
117 ,m_aValueChange(_aValueChange
)
121 void handleChange(Change
&_rNode
)
123 this->applyToChange(_rNode
);
126 virtual void handle(ValueChange
& _rValueChange
)
128 // POST: Handle ValueChange
129 _rValueChange
.setNewValue(m_aValueChange
.getNewValue(), m_aValueChange
.getMode());
131 virtual void handle(RemoveNode
& /*_rRemoveNode*/)
133 OSL_ENSURE(false, "OMergeValueChange::handle(ValueChange): have a ValueChange for a removed node!");
134 // should never happen. How did the user change a value for a node which is obviously flagged as removed?
136 virtual void handle(AddNode
& _rAddNode
);
137 virtual void handle(SubtreeChange
& _rSubtree
)
139 if ( isLocalizedValueSet(_rSubtree
) )
141 std::auto_ptr
<ValueChange
> pNewValueChange( new ValueChange(m_aValueChange
) );
142 OSL_ENSURE(pNewValueChange
->isLocalizedValue(), "OMergeValueChange:handle(SubtreeChange): have a non-localized ValueChange a for a localized node!");
144 std::auto_ptr
<Change
> pNewChange( pNewValueChange
.release() );
146 replaceExistingEntry(pNewChange
);
149 OSL_ENSURE(false, "OMergeValueChange:handle(SubtreeChange): have a ValueChange for a sub tree!");
152 void replaceExistingEntry(std::auto_ptr
<Change
> pNewChange
)
154 m_rTargetParent
.removeChange(pNewChange
->getNodeName());
155 m_rTargetParent
.addChange(pNewChange
);
157 static std::auto_ptr
<ValueNode
> createNodeFromChange(ValueChange
const& rChange
)
159 std::auto_ptr
<ValueNode
> aRet
;
161 uno::Any aNewValue
= rChange
.getNewValue();
163 // currently not supporting change modes !
164 if (aNewValue
.hasValue())
165 aRet
.reset( new ValueNode(rChange
.getNodeName(), aNewValue
, rChange
.getAttributes()) );
169 aRet
.reset( new ValueNode(rChange
.getNodeName(), rChange
.getValueType(), rChange
.getAttributes()) );
171 OSL_ENSURE(aRet
->isValid(), "Cannot recover type for change to NULL");
178 // -----------------------------------------------------------------------------
179 // -----------------------------------------------------------------------------
180 // TODO: operate directly on new data structures
182 void OMergeValueChange::handle(AddNode
& _rAddNode
)
184 if (m_aValueChange
.isToDefault())
186 std::auto_ptr
<Change
> aChangeToDefault(m_aValueChange
.clone());
187 m_rTargetParent
.removeChange(_rAddNode
.getNodeName());
188 m_rTargetParent
.addChange( aChangeToDefault
);
192 // POST: Handle ValueChange in AddNode
193 rtl::Reference
< data::TreeSegment
> seg(_rAddNode
.getNewTree());
194 std::auto_ptr
<INode
> pAddedNode
= data::convertTree(seg
.is() ? seg
->fragment
: 0, false);
196 if (ValueNode
*pValueNode
= pAddedNode
->asValueNode())
198 m_aValueChange
.applyChangeNoRecover(*pValueNode
);
201 else if (ISubtree
* pValueSetNode
= pAddedNode
->asISubtree() )
203 if ( isLocalizedValueSet(*pValueSetNode
) )
205 std::auto_ptr
<ValueNode
> pNewValueNode
= createNodeFromChange(m_aValueChange
);
206 if (pNewValueNode
.get())
208 OSL_ENSURE(pNewValueNode
->isLocalized(), "OMergeValueChange:handle(AddNode): have a non-localized ValueChange a for a localized node!");
209 pNewValueNode
->setName(pAddedNode
->getName());
212 OSL_ENSURE(false, "OMergeValueChange:handle(SubtreeChange): Creating a NULL node to replace a localized value set not yet supported");
215 pAddedNode
.reset(pNewValueNode
.release());
219 OSL_ENSURE(sal_False
, "OMergeValueChange:handle(AddNode): have a ValueChange a for non-value node!");
220 pAddedNode
.reset(); // leave unchanged
226 OSL_ENSURE(sal_False
, "OMergeValueChange:handle(AddNode): Found unknown node type!");
227 pAddedNode
.reset(); // leave unchanged
230 if (pAddedNode
.get() != NULL
)
232 rtl::Reference
< data::TreeSegment
> aNewTree
= data::TreeSegment::create(_rAddNode
.getNodeName(),pAddedNode
);
234 std::auto_ptr
<AddNode
> pNewAdd( new AddNode(aNewTree
,m_aValueChange
.getNodeName(), m_aValueChange
.isToDefault()) );
235 if (_rAddNode
.isReplacing())
236 pNewAdd
->setReplacing();
238 std::auto_ptr
<Change
> pNewChange( pNewAdd
.release() );
239 replaceExistingEntry(pNewChange
);
243 // -----------------------------------------------------------------------------
244 // -----------------------------------------------------------------------------
245 // -----------------------------------------------------------------------------
246 class OMergeRemoveNode
: private ChangeTreeModification
249 // actions to take with the remove node change
261 OMergeRemoveNode() : m_eAction(Undetermined
) { }
263 Action
getAction() const { return m_eAction
; }
265 void handleChange(Change
* _pChange
)
268 applyToChange(*_pChange
);
270 // no change -> flag as deleted
271 m_eAction
= FlagDeleted
;
275 virtual void handle(ValueChange
& aValueChange
)
277 if (aValueChange
.getAttributes().existsInDefault())
278 m_eAction
= FlagDeleted
;
280 m_eAction
= RemoveCompletely
;
283 virtual void handle(RemoveNode
& /*_rRemoveNode*/)
285 OSL_ENSURE(false, "OMergeRemoveNode::handle(RemoveNode): should never happen!");
286 // how can a RemoveNode change exist if in the file we're merging it into
287 // there already is such a RemoveNode change (_rRemoveNode)?
290 virtual void handle(AddNode
& _rAddNode
)
292 if (_rAddNode
.isReplacing())
293 m_eAction
= FlagDeleted
;
295 m_eAction
= RemoveCompletely
;
298 virtual void handle(SubtreeChange
& _rSubtree
)
300 if (_rSubtree
.getAttributes().existsInDefault())
301 m_eAction
= FlagDeleted
;
303 m_eAction
= RemoveCompletely
;
306 // -----------------------------------------------------------------------------
307 // -----------------------------------------------------------------------------
311 Change
* findExistingChange(SubtreeChange
* pCurrentParent
, configuration::Path::Component
const & _aName
)
313 OSL_ASSERT(pCurrentParent
);
315 Change
*pChange
= pCurrentParent
->getChange(_aName
.getName());
317 if (!pChange
&& !_aName
.isSimpleName())
319 pChange
= pCurrentParent
->getChange(_aName
.toPathString());
320 OSL_ENSURE(!pChange
, "Update trouble: Existing node found only by composite name while merging");
328 Change
* findExistingChange(SubtreeChange
* pCurrentParent
, rtl::OUString
const & _aName
)
330 OSL_ASSERT(pCurrentParent
);
332 Change
*pChange
= pCurrentParent
->getChange(_aName
);
336 // -----------------------------------------------------------------------------
338 void adjustElementTemplate(SubtreeChange
& _rChange
, const rtl::OUString
& _rName
, const rtl::OUString
& _rModule
)
340 if (!_rChange
.isSetNodeChange() || isGenericSetElementType(_rChange
.getElementTemplateName()))
342 _rChange
.setElementTemplate(_rName
,_rModule
);
344 else if ( isDummySetElementModule(_rChange
.getElementTemplateModule()) &&
345 !isGenericSetElementType(_rName
) && !isDummySetElementModule(_rModule
))
347 OSL_ENSURE(_rChange
.getElementTemplateName() == _rName
, "Adjusting: Template modules do not match");
349 _rChange
.setElementTemplate(_rName
,_rModule
);
351 OSL_POSTCOND(_rChange
.getElementTemplateName() == _rName
|| isGenericSetElementType(_rName
),
352 "Adjusting: Template modules do not match");
353 OSL_POSTCOND(_rChange
.getElementTemplateModule() == _rModule
|| isDummySetElementModule(_rModule
),
354 "Adjusting: Template modules do not match");
356 // -----------------------------------------------------------------------------
358 inline void adjustElementTemplate(SubtreeChange
& _rChange
, SubtreeChange
const& _rSource
)
360 if (_rSource
.isSetNodeChange())
361 adjustElementTemplate(_rChange
, _rSource
.getElementTemplateName(), _rSource
.getElementTemplateModule());
364 // -----------------------------------------------------------------------------
367 OMergeChanges::OMergeChanges(SubtreeChange
& _rTree
)
368 : m_rSubtreeChange(_rTree
), m_pCurrentParent(NULL
)
371 // -----------------------------------------------------------------------------
373 void OMergeChanges::initRoot(const SubtreeChange
&_rRootChange
, const configuration::RelativePath
& _aPathToChange
)
375 SubtreeChange
* pCurrentParent
= &m_rSubtreeChange
;
377 if (!_aPathToChange
.isEmpty())
379 OSL_PRECOND(_aPathToChange
.getLocalName().getName() == _rRootChange
.getNodeName(),
380 "Path to change root does not match change being merged" );
382 std::vector
<configuration::Path::Component
>::const_reverse_iterator
const firstEnsure
= _aPathToChange
.begin();
383 std::vector
<configuration::Path::Component
>::const_reverse_iterator lastEnsure
= _aPathToChange
.end();
384 std::vector
<configuration::Path::Component
>::const_reverse_iterator it
;
386 OSL_ASSERT( firstEnsure
!= lastEnsure
);
387 --lastEnsure
; // last to ensure is the actual root
389 for( it
= firstEnsure
; it
!= lastEnsure
; ++it
)
391 OSL_ASSERT( it
!= _aPathToChange
.end() );
393 Change
*pChange
= findExistingChange(pCurrentParent
,*it
);
397 OSL_ASSERT( it
+1 != _aPathToChange
.end());
398 rtl::OUString
const aElementTypeName
= (it
+1)->getTypeName();
400 // create a correspondens for the name, we did not find.
401 std::auto_ptr
<SubtreeChange
> pNewChange
=
402 OTreeChangeFactory::createDummyChange(it
->getName(), aElementTypeName
);
404 pChange
= pNewChange
.get();
406 pCurrentParent
->addChange(base_ptr(pNewChange
));
408 OSL_ENSURE(pChange
== findExistingChange(pCurrentParent
,*it
),
409 "ERROR: Newly added change cannot be found in parent change");
412 pCurrentParent
= dynamic_cast<SubtreeChange
*>( pChange
);
413 if (pCurrentParent
== 0)
415 OSL_ENSURE(false, "Change to merge does not point to a Subtree Change");
416 throw configuration::InvalidName(_aPathToChange
.toString(), "points to a non- subtree change in this changes list, but a subtree change is required as root.");
420 Change
*pRootChange
= findExistingChange(pCurrentParent
,*lastEnsure
);
424 // create a correspondens for the name, we did not find.
425 std::auto_ptr
<SubtreeChange
> pNewChange(
426 new SubtreeChange(_rRootChange
, treeop::NoChildCopy()) );
428 pRootChange
= pNewChange
.get();
430 pCurrentParent
->addChange(base_ptr(pNewChange
));
432 OSL_ENSURE(pRootChange
== findExistingChange(pCurrentParent
,*it
),
433 "ERROR: Newly added change cannot be found in parent change");
436 pCurrentParent
= dynamic_cast<SubtreeChange
*>( pRootChange
);
437 if (pCurrentParent
== 0)
439 OSL_ENSURE(false, "Change to merge does not point to a Subtree Change");
440 throw configuration::InvalidName(_aPathToChange
.toString(), "points to a non-subtree change in this changes list, but a subtree change is required as root.");
444 OSL_ENSURE(pCurrentParent
->getNodeName() == _rRootChange
.getNodeName(),
445 "Change being merged has a different name");
447 adjustElementTemplate(*pCurrentParent
,_rRootChange
);
449 this->init(_aPathToChange
);
451 m_pCurrentParent
= pCurrentParent
;
453 // -----------------------------------------------------------------------------
455 // ------- Helper for Path stack -------
456 SubtreeChange
* OMergeChanges::pushTree(SubtreeChange
& _rTree
)
458 pushName( ONameCreator::createName(_rTree
,m_pCurrentParent
) );
460 SubtreeChange
* pSave
= m_pCurrentParent
;
461 m_pCurrentParent
= &_rTree
;
464 void OMergeChanges::popTree(SubtreeChange
* _pSaveTree
)
466 m_pCurrentParent
= _pSaveTree
;
470 // -----------------------------------------------------------------------------
472 // start function, with the Change we want to do.
473 // WARNING this could be a big tree, because a change can contain subtreechanges!
474 void OMergeChanges::mergeChanges(const SubtreeChange
&_rChange
)
476 mergeChanges(_rChange
, configuration::RelativePath());
478 // -----------------------------------------------------------------------------
480 // start function, with the Change we want to do.
481 // WARNING this could be a big tree, because a change can contain subtreechanges!
482 void OMergeChanges::mergeChanges(const SubtreeChange
&_rChange
, const configuration::RelativePath
& _aPathToChange
)
484 initRoot(_rChange
, _aPathToChange
); // path location being merged must exist
486 this->applyToChildren(_rChange
); //- semantics ?
488 // -----------------------------------------------------------------------------
490 // Algorithm: search the actual path in the out m_aSubtreeChange
491 // if we found something, we must merge/convert the Node with our Node
492 // if we found nothing, we must create a new Node with our change
495 // the merge is contructed with helper classes because, it's possible that we
496 // are a ValueChange but in the TreeChangeList this change is an AddNode, so
497 // we have something to do.
499 void OMergeChanges::handle(ValueChange
const& _rValueNode
)
501 // Handle a ValueChange,
502 rtl::OUString aNodeName
= _rValueNode
.getNodeName();
504 if (Change
*pChange
= findExistingChange(m_pCurrentParent
,aNodeName
))
506 // Value found, merge content
507 OMergeValueChange
aMergeValue(*m_pCurrentParent
,_rValueNode
);
508 aMergeValue
.handleChange(*pChange
);
512 // there is no ValueChange in the List, insert new one
513 std::auto_ptr
<Change
> pNewChange(new ValueChange(_rValueNode
));
514 m_pCurrentParent
->addChange(pNewChange
);
517 // -----------------------------------------------------------------------------
519 void OMergeChanges::handle(AddNode
const& _rAddNode
)
522 bool bReplacing
= _rAddNode
.isReplacing();
524 rtl::OUString aNodeName
= _rAddNode
.getNodeName();
526 if (Change
*pChange
= findExistingChange(m_pCurrentParent
,aNodeName
))
528 OSL_ENSURE(dynamic_cast< RemoveNode
* >(pChange
) != 0 || bReplacing
, "OMergeChanges::handle(AddNode): the changes tree given already contains a change for this!");
530 m_pCurrentParent
->removeChange(pChange
->getNodeName());
536 rtl::Reference
< data::TreeSegment
> aAddedTree
= data::TreeSegment::create(_rAddNode
.getNewTree());
538 std::auto_ptr
<AddNode
> pNewAdd(new AddNode(aAddedTree
, _rAddNode
.getNodeName(), _rAddNode
.isToDefault()));
540 pNewAdd
->setReplacing();
542 std::auto_ptr
<Change
> pNewChange( pNewAdd
.release() );
543 m_pCurrentParent
->addChange(pNewChange
);
545 // -----------------------------------------------------------------------------
547 void OMergeChanges::handle(RemoveNode
const& _rRemoveNode
)
549 // Handle a RemoveNode
550 rtl::OUString aNodeName
= _rRemoveNode
.getNodeName();
552 Change
*pChange
= findExistingChange(m_pCurrentParent
,aNodeName
);
554 // examine what to do with this change
555 OMergeRemoveNode aExaminer
;
556 aExaminer
.handleChange(pChange
);
558 // remove the change from it's parent (may it's re-inserted in another form below)
560 m_pCurrentParent
->removeChange(pChange
->getNodeName());
562 // insert a new change if necessary
563 switch (aExaminer
.getAction())
565 case OMergeRemoveNode::RemoveCompletely
:
566 // nothing to do, we already removed it
569 OSL_ENSURE(sal_False
, "OMergeChanges::handle(RemoveNode): don't know what to do with this!");
571 // defaulting this so that the node will be marked as deleted
572 case OMergeRemoveNode::FlagDeleted
:
574 std::auto_ptr
<Change
> pNewChange(new RemoveNode(_rRemoveNode
.getNodeName(),_rRemoveNode
.isToDefault()));
575 m_pCurrentParent
->addChange(pNewChange
);
581 // -----------------------------------------------------------------------------
583 void OStripDefaults::stripOne(Change
& _rChange
)
585 m_rParent
.removeChange(_rChange
.getNodeName());
588 void OStripDefaults::handle(ValueChange
& _rValueNode
)
590 if (_rValueNode
.isToDefault())
591 stripOne(_rValueNode
);
593 void OStripDefaults::handle(AddNode
& _rAddNode
)
595 if (_rAddNode
.isToDefault())
597 sharable::TreeFragment
const * pAdded
= _rAddNode
.getNewTreeData();
598 OSL_ENSURE(pAdded
,"No Data in AddNode");
599 if (pAdded
== NULL
|| pAdded
->getAttributes().isDefault())
602 // else we should strip the defaults from the added node
605 void OStripDefaults::handle(RemoveNode
& _rRemoveNode
)
607 if (_rRemoveNode
.isToDefault())
608 stripOne(_rRemoveNode
);
610 void OStripDefaults::handle(SubtreeChange
& _rSubtree
)
612 if ( strip(_rSubtree
) )
613 if (_rSubtree
.isToDefault() || !_rSubtree
.isSetNodeChange())
617 OStripDefaults
& OStripDefaults::strip()
619 SubtreeChange::MutatingChildIterator it
= m_rParent
.begin_changes(), stop
= m_rParent
.end_changes();
623 this->applyToChange(*it
++);
630 // -----------------------------------------------------------------------------
631 class TreeUpdater
: public ChangeTreeAction
633 ISubtree
* m_pCurrentSubtree
;
634 #if OSL_DEBUG_LEVEL > 1
635 std::vector
<rtl::OString
> aLog
;
639 TreeUpdater(ISubtree
* pSubtree
):m_pCurrentSubtree(pSubtree
){}
641 void handle(ValueChange
const& aValueNode
);
642 void handle(AddNode
const& aAddNode
);
643 void handle(RemoveNode
const& aRemoveNode
);
644 void handle(SubtreeChange
const& aSubtree
);
647 // -----------------------------------------------------------------------------
650 void OMergeChanges::handle(SubtreeChange
const& _rSubtree
)
652 // Handle a SubtreeChange
653 // we must check if exact this SubtreeChange is in the TreeChangeList, if not,
654 // we must add this SubtreeChange to the TreeChangeList
655 // with the pointer m_pCurrentParent we remember our SubtreeChange in witch we
656 // add all other Changes.
658 rtl::OUString aNodeName
= _rSubtree
.getNodeName();
660 Change
*pChange
= findExistingChange(m_pCurrentParent
,aNodeName
);
662 // const sal_Char* pType = pChange ? pChange->getType() : NULL;
663 SubtreeChange
* pSubtreeChange
= NULL
;
664 if (pChange
== NULL
|| dynamic_cast< SubtreeChange
* >(pChange
) != 0)
666 // need to create a new Subtreechange
669 // create a new SubtreeChange
670 std::auto_ptr
<SubtreeChange
> pNewChange(new SubtreeChange(_rSubtree
, treeop::NoChildCopy()));
671 pSubtreeChange
= pNewChange
.get();
673 // add the new SubtreeChange in m_aTreeChangeList
674 m_pCurrentParent
->addChange(std::auto_ptr
<Change
>(pNewChange
.release()));
675 // check list for this new SubtreeChange
676 OSL_ASSERT(pSubtreeChange
== findExistingChange(m_pCurrentParent
,aNodeName
));
680 pSubtreeChange
= dynamic_cast<SubtreeChange
*>(pChange
);
681 OSL_ASSERT(pSubtreeChange
!= 0);
682 adjustElementTemplate(*pSubtreeChange
,_rSubtree
);
685 // save this SubtreeChange so we allways have the last Subtree
686 SubtreeChange
* pSaveParent
= pushTree(*pSubtreeChange
);
687 this->applyToChildren(_rSubtree
);
688 popTree( pSaveParent
);
690 else if (AddNode
* pAddNode
= dynamic_cast<AddNode
*>(pChange
))
692 rtl::Reference
< data::TreeSegment
> seg(pAddNode
->getNewTree());
693 std::auto_ptr
<INode
> pAddedNode
= data::convertTree(seg
.is() ? seg
->fragment
: 0, false);
694 ISubtree
* pSubtree
= pAddedNode
.get() ? pAddedNode
->asISubtree() : 0;
697 pSubtree
->markAsDefault( _rSubtree
.isToDefault() );
699 // Now apply _rSubtree to the subtree
700 TreeUpdater
aTreeUpdate(pSubtree
);
701 aTreeUpdate
.applyToChildren(_rSubtree
);
703 // make a new subtree with the changed data
704 rtl::Reference
< data::TreeSegment
> aNewTree
= data::TreeSegment::create(pAddNode
->getNodeName(), pAddedNode
);
706 std::auto_ptr
<AddNode
> pNewAdd( new AddNode(aNewTree
, pAddNode
->getNodeName(), pAddNode
->isToDefault()) );
707 if (pAddNode
->isReplacing())
708 pNewAdd
->setReplacing();
710 std::auto_ptr
<Change
> pNewChange( pNewAdd
.release() );
712 m_pCurrentParent
->removeChange(pAddNode
->getNodeName());
713 m_pCurrentParent
->addChange( pNewChange
);
717 OSL_ENSURE(false, "OMergeChanges: Unexpected node type found in an AddNode.");
718 /* wrong type of node found: böse ASSERTEN/WERFEN */;
720 // -----------------------------------------------------------------------------
721 // -----------------------------------------------------------------------------
725 OSL_ENSURE(false, "OMergeChanges: Unexpected change type found for a subtree.");
726 /* wrong type of node found: böse ASSERTEN/WERFEN */;
730 // --------------------------------- updateTree ---------------------------------
731 void TreeUpdater::handle(ValueChange
const& aValueNode
)
734 OSL_ENSURE(m_pCurrentSubtree
,"Cannot apply ValueChange without subtree");
736 INode
* pBaseNode
= m_pCurrentSubtree
? m_pCurrentSubtree
->getChild(aValueNode
.getNodeName()) : 0;
737 OSL_ENSURE(pBaseNode
,"Cannot apply Change: No node to change");
739 ValueNode
* pValue
= pBaseNode
? pBaseNode
->asValueNode() : 0;
740 OSL_ENSURE(pValue
,"Cannot apply ValueChange: Node is not a value");
743 aValueNode
.applyChangeNoRecover(*pValue
);
744 #if OSL_DEBUG_LEVEL > 1
747 ::rtl::OString
aStr("TreeUpdater: Can't find value with name:=");
748 aStr
+= rtl::OUStringToOString(aValueNode
.getNodeName(),RTL_TEXTENCODING_ASCII_US
);
749 OSL_ENSURE(pValue
, aStr
.getStr());
750 aLog
.push_back(aStr
);
755 void TreeUpdater::handle(AddNode
const& aAddNode
)
758 if (m_pCurrentSubtree
)
760 if (aAddNode
.isReplacing())
762 std::auto_ptr
<INode
> aOldNode
= m_pCurrentSubtree
->removeChild(aAddNode
.getNodeName());
764 #if OSL_DEBUG_LEVEL > 1
765 OSL_ENSURE(aOldNode
.get(), "TreeUpdater:AddNode: can't recover node being replaced");
766 if (aOldNode
.get() == NULL
)
767 aLog
.push_back(rtl::OString("TreeUpdater: can't recover node being replaced (for AddNode)"));
771 rtl::Reference
< data::TreeSegment
> seg(aAddNode
.getNewTree());
772 std::auto_ptr
<INode
> pNode(data::convertTree(seg
.is() ? seg
->fragment
: 0, true));
774 m_pCurrentSubtree
->addChild(pNode
);
776 #if OSL_DEBUG_LEVEL > 1
778 aLog
.push_back(rtl::OString("TreeUpdater: no CurrentSubtree for AddNode"));
783 void TreeUpdater::handle(RemoveNode
const& aRemoveNode
)
786 if (m_pCurrentSubtree
)
788 std::auto_ptr
<INode
> aOldNode
= m_pCurrentSubtree
->removeChild(aRemoveNode
.getNodeName());
790 #if OSL_DEBUG_LEVEL > 1
791 if (NULL
== aOldNode
.get())
793 ::rtl::OString
aStr("TreeUpdater: Can't remove child with name:=");
794 aStr
+= rtl::OUStringToOString(aRemoveNode
.getNodeName(),RTL_TEXTENCODING_ASCII_US
);
795 OSL_ENSURE(false, aStr
.getStr());
796 aLog
.push_back(aStr
);
802 void TreeUpdater::handle(SubtreeChange
const& _aSubtree
)
805 ISubtree
*pOldSubtree
= m_pCurrentSubtree
;
806 rtl::OUString aNodeName
= _aSubtree
.getNodeName();
808 INode
* pChild
= m_pCurrentSubtree
->getChild(aNodeName
);
809 OSL_ENSURE(pChild
, "TreeUpdater::handle : invalid subtree change ... no child for change !");
810 m_pCurrentSubtree
= pChild
? pChild
->asISubtree() : NULL
;
812 #if OSL_DEBUG_LEVEL > 1
813 if (!m_pCurrentSubtree
)
815 ::rtl::OString
aStr("TreeUpdater: there is no Subtree for name:=");
816 aStr
+= rtl::OUStringToOString(_aSubtree
.getNodeName(),RTL_TEXTENCODING_ASCII_US
);
817 OSL_ENSURE(false, aStr
.getStr());
818 aLog
.push_back(aStr
);
822 if (m_pCurrentSubtree
)
824 m_pCurrentSubtree
->markAsDefault( _aSubtree
.isToDefault() );
825 _aSubtree
.forEachChange(*this);
828 m_pCurrentSubtree
= pOldSubtree
;
831 } // namespace configmgr