merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / misc / mergechange.cxx
blob53ff14512d6ac64478a53d03a08ace82a8b370d0
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: mergechange.cxx,v $
10 * $Revision: 1.27 $
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"
39 #include "change.hxx"
40 #include "treechangefactory.hxx"
41 #include "treechangelist.hxx"
42 #include "configexcept.hxx"
43 #include "tracer.hxx"
45 #define ASCII(x) rtl::OUString::createFromAscii(x)
47 namespace configmgr
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);
62 public:
63 // CTor
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);
71 private:
72 void initRoot(const SubtreeChange &_rRootChange, const configuration::RelativePath& _aPathToChange);
73 private:
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);
98 else
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;
114 public:
115 OMergeValueChange(SubtreeChange& _rTargetParent, const ValueChange& _aValueChange)
116 :m_rTargetParent(_rTargetParent)
117 ,m_aValueChange(_aValueChange)
121 void handleChange(Change &_rNode)
123 this->applyToChange(_rNode);
125 private:
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);
148 else
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()) );
167 else // NULL
169 aRet.reset( new ValueNode(rChange.getNodeName(), rChange.getValueType(), rChange.getAttributes()) );
171 OSL_ENSURE(aRet->isValid(), "Cannot recover type for change to NULL");
173 return aRet;
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 );
190 else
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());
211 else
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());
217 else
219 OSL_ENSURE(sal_False, "OMergeValueChange:handle(AddNode): have a ValueChange a for non-value node!");
220 pAddedNode.reset(); // leave unchanged
224 else
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
248 public:
249 // actions to take with the remove node change
250 enum Action
252 RemoveCompletely,
253 FlagDeleted,
254 Undetermined
257 protected:
258 Action m_eAction;
260 public:
261 OMergeRemoveNode() : m_eAction(Undetermined) { }
263 Action getAction() const { return m_eAction; }
265 void handleChange(Change* _pChange)
267 if (_pChange)
268 applyToChange(*_pChange);
269 else
270 // no change -> flag as deleted
271 m_eAction = FlagDeleted;
274 private:
275 virtual void handle(ValueChange& aValueChange)
277 if (aValueChange.getAttributes().existsInDefault())
278 m_eAction = FlagDeleted;
279 else
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;
294 else
295 m_eAction = RemoveCompletely;
298 virtual void handle(SubtreeChange& _rSubtree)
300 if (_rSubtree.getAttributes().existsInDefault())
301 m_eAction = FlagDeleted;
302 else
303 m_eAction = RemoveCompletely;
306 // -----------------------------------------------------------------------------
307 // -----------------------------------------------------------------------------
309 static
310 inline
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");
323 return pChange;
326 static
327 inline
328 Change* findExistingChange(SubtreeChange* pCurrentParent, rtl::OUString const & _aName)
330 OSL_ASSERT(pCurrentParent);
332 Change *pChange = pCurrentParent->getChange(_aName);
334 return pChange;
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 // -----------------------------------------------------------------------------
366 // CTor
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);
395 if (!pChange)
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);
422 if (!pRootChange)
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;
462 return pSave;
464 void OMergeChanges::popTree(SubtreeChange* _pSaveTree)
466 m_pCurrentParent = _pSaveTree;
468 popName();
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
493 // thats it.
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);
510 else
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)
521 // Handle an AddNode
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());
532 bReplacing = true;
535 // insert manually
536 rtl::Reference< data::TreeSegment > aAddedTree = data::TreeSegment::create(_rAddNode.getNewTree());
538 std::auto_ptr<AddNode> pNewAdd(new AddNode(aAddedTree, _rAddNode.getNodeName(), _rAddNode.isToDefault()));
539 if (bReplacing)
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)
559 if (pChange)
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
567 break;
568 default:
569 OSL_ENSURE(sal_False, "OMergeChanges::handle(RemoveNode): don't know what to do with this!");
570 // NO BREAK.
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);
577 break;
581 // -----------------------------------------------------------------------------
582 inline
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())
600 stripOne(_rAddNode);
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())
614 stripOne(_rSubtree);
617 OStripDefaults& OStripDefaults::strip()
619 SubtreeChange::MutatingChildIterator it = m_rParent.begin_changes(), stop = m_rParent.end_changes();
621 while (it != stop)
623 this->applyToChange(*it++);
626 return *this;
630 // -----------------------------------------------------------------------------
631 class TreeUpdater : public ChangeTreeAction
633 ISubtree* m_pCurrentSubtree;
634 #if OSL_DEBUG_LEVEL > 1
635 std::vector<rtl::OString> aLog;
636 #endif
638 public:
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
667 if (!pChange)
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));
678 else
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;
695 if (pSubtree)
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 );
715 else
717 OSL_ENSURE(false, "OMergeChanges: Unexpected node type found in an AddNode.");
718 /* wrong type of node found: böse ASSERTEN/WERFEN */;
720 // -----------------------------------------------------------------------------
721 // -----------------------------------------------------------------------------
723 else
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)
733 // Change a Value
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");
742 if (pValue)
743 aValueNode.applyChangeNoRecover(*pValue);
744 #if OSL_DEBUG_LEVEL > 1
745 else
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);
752 #endif
755 void TreeUpdater::handle(AddNode const& aAddNode)
757 // Add a new Value
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)"));
768 #endif
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
777 else
778 aLog.push_back(rtl::OString("TreeUpdater: no CurrentSubtree for AddNode"));
779 #endif
783 void TreeUpdater::handle(RemoveNode const& aRemoveNode)
785 // remove a Value
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);
798 #endif
802 void TreeUpdater::handle(SubtreeChange const& _aSubtree)
804 // handle traversion
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);
820 #endif
821 // recurse
822 if (m_pCurrentSubtree)
824 m_pCurrentSubtree->markAsDefault( _aSubtree.isToDefault() );
825 _aSubtree.forEachChange(*this);
828 m_pCurrentSubtree = pOldSubtree;
831 } // namespace configmgr