update dev300-m58
[ooovba.git] / configmgr / source / treemgr / viewstrategy.cxx
blob0b0fa04229d5759c80330f225798517037b4c714
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: viewstrategy.cxx,v $
10 * $Revision: 1.13 $
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 "viewstrategy.hxx"
35 #include "valuenodeimpl.hxx"
36 #include "groupnodeimpl.hxx"
37 #include "setnodeimpl.hxx"
38 #include "change.hxx"
39 #include "nodevisitor.hxx"
40 #include "nodechange.hxx"
41 #include "nodechangeimpl.hxx"
42 #include "nodeconverter.hxx"
43 //-----------------------------------------------------------------------------
44 namespace configmgr
46 //-----------------------------------------------------------------------------
47 namespace view
49 //-----------------------------------------------------------------------------
50 static
51 inline
52 sharable::ValueNode * getMemberValueAccess( GroupNode const & _aGroupNode, rtl::OUString const & _aName )
54 configuration::GroupNodeImpl* pGroupData = _aGroupNode.get_impl();
55 return pGroupData->getOriginalValueNode(_aName);
58 //-----------------------------------------------------------------------------
59 void ViewStrategy::checkInstance(configuration::Tree * tree) const
61 (void) tree; // avoid warnings
62 OSL_ENSURE( getViewBehavior(tree).get() == this,
63 "Tree operation dispatched to wrong strategy instance");
65 //-----------------------------------------------------------------------------
66 void ViewStrategy::collectChanges(configuration::Tree * tree, configuration::NodeChanges& rChanges) const
68 checkInstance(tree);
69 doCollectChanges( getRootNode(tree), rChanges );
72 bool ViewStrategy::hasChanges(configuration::Tree * tree) const
74 checkInstance(tree);
75 return hasChanges( getRootNode(tree) );
78 // mark the given node and all its ancestors (we can stop when we hit a node that already is marked)
79 void ViewStrategy::markChanged(Node const& _aNode)
81 configuration::Tree * tree = _aNode.tree();
82 checkInstance(tree);
84 Node aNode = _aNode;
85 if (aNode.is())
89 this->doMarkChanged(aNode);
91 aNode = aNode.getParent();
93 while (aNode.is() && !this->hasChanges( aNode ));
96 if (!aNode.is()) // just marked the root
98 configuration::Tree* pContext = tree->getContextTree();
99 unsigned int nContext = tree->getContextNode();
100 if (pContext)
102 OSL_ASSERT(pContext->isValidNode(nContext));
104 view::Node aContextNode(pContext,nContext);
105 pContext->getViewBehavior()->markChanged(aContextNode);
110 //-----------------------------------------------------------------------------
111 std::auto_ptr<SubtreeChange> ViewStrategy::preCommitChanges(configuration::Tree * tree, std::vector< rtl::Reference<configuration::ElementTree> >& _rRemovedElements)
113 checkInstance(tree);
114 return doPreCommitChanges( tree, _rRemovedElements);
117 void ViewStrategy::finishCommit(configuration::Tree * tree, SubtreeChange& rRootChange)
119 checkInstance(tree);
120 doFinishCommit(tree, rRootChange);
123 void ViewStrategy::revertCommit(configuration::Tree * tree, SubtreeChange& rRootChange)
125 checkInstance(tree);
126 doRevertCommit(tree, rRootChange);
129 void ViewStrategy::recoverFailedCommit(configuration::Tree * tree, SubtreeChange& rRootChange)
131 checkInstance(tree);
132 doFailedCommit(tree, rRootChange);
135 //-----------------------------------------------------------------------------
136 void ViewStrategy::adjustToChanges(configuration::NodeChangesInformation& rLocalChanges, Node const& _aNode, SubtreeChange const& aExternalChange)
138 OSL_PRECOND( isValidNode(_aNode), "ERROR: Valid node required for adjusting to changes" );
139 OSL_PRECOND( getSimpleNodeName(_aNode) == aExternalChange.getNodeName(), "name of change does not match actual node" );
141 checkInstance(_aNode.tree());
143 configuration::Tree * pTreeData = _aNode.tree();
145 if (_aNode.isSetNode())
147 OSL_ENSURE(aExternalChange.isSetNodeChange(),"ERROR: Change type GROUP does not match set");
149 unsigned int nDepth = pTreeData->getRemainingDepth(_aNode.get_offset());
151 implAdjustToElementChanges( rLocalChanges, SetNode(_aNode), aExternalChange, nDepth);
153 else if (_aNode.isGroupNode())
155 OSL_ENSURE(!aExternalChange.isSetNodeChange(),"ERROR: Change type SET does not match group");
157 GroupNode aGroupNode(_aNode);
159 implAdjustToValueChanges(rLocalChanges, aGroupNode, aExternalChange);
160 implAdjustToSubChanges( rLocalChanges, aGroupNode, aExternalChange);
162 else // might occur on external change (?)
164 OSL_ENSURE(_aNode.isValueNode(), "Tree: Unknown node type to adjust to changes");
166 OSL_ENSURE(_aNode.get_offset() == configuration::Tree::ROOT, "Tree: Unexpected node type - non-root value element");
168 OSL_ENSURE(false,"ERROR: Change type does not match node: Trying to apply subtree change to value element.");
172 //-----------------------------------------------------------------------------
174 void ViewStrategy::addLocalChangeHelper( configuration::NodeChangesInformation& rLocalChanges_, configuration::NodeChange const& aChange_)
176 aChange_.getChangeInfos(rLocalChanges_);
179 //-----------------------------------------------------------------------------
180 // TO DO: create CommitAction class, which is returned by precommit (if applicable)
182 std::auto_ptr<SubtreeChange> ViewStrategy::doPreCommitChanges(configuration::Tree * tree, std::vector< rtl::Reference<configuration::ElementTree> >& )
184 (void) tree; // avoid warnings
185 OSL_ENSURE(!hasChanges(getRootNode(tree)),"Unexpected changes in View");
186 return std::auto_ptr<SubtreeChange>();
189 void ViewStrategy::doFinishCommit(configuration::Tree * tree, SubtreeChange& )
191 (void) tree; // avoid warnings
192 OSL_ENSURE(!hasChanges(getRootNode(tree)),"Unexpected changes in View");
193 OSL_ENSURE(false,"ERROR: Cannot finish commit for unexpected changes");
196 void ViewStrategy::doRevertCommit(configuration::Tree * tree, SubtreeChange& )
198 (void) tree; // avoid warnings
199 OSL_ENSURE(!hasChanges(getRootNode(tree)),"Unexpected changes in View");
200 OSL_ENSURE(false,"ERROR: Cannot revert commit for unexpected changes");
203 void ViewStrategy::doFailedCommit(configuration::Tree * tree, SubtreeChange& )
205 (void) tree; // avoid warnings
206 OSL_ENSURE(!hasChanges(getRootNode(tree)),"Unexpected changes in View");
207 OSL_ENSURE(false,"ERROR: Cannot recover commit for unexpected changes");
210 //-----------------------------------------------------------------------------
211 void ViewStrategy::implAdjustToElementChange(configuration::NodeChangesInformation& rLocalChanges, SetNode const& _aSetNode, Change const& rElementChange, unsigned int nDepth)
213 configuration::SetNodeImpl * pSetData = _aSetNode.get_impl();
215 OSL_ENSURE( pSetData->implHasLoadedElements() , "Unexpected call: Processing element change in uninitialized set");
217 rtl::OUString aName( rElementChange.getNodeName() );
219 configuration::SetElementChangeImpl* pThisChange = 0;
220 if (AddNode const * addNode = dynamic_cast< AddNode const *>(&rElementChange))
222 configuration::ElementTreeData aNewElement = pSetData->makeAdditionalElement(this, *addNode, nDepth);
224 pThisChange = pSetData->doAdjustToAddedElement(aName, *addNode, aNewElement);
226 else if (RemoveNode const * removeNode = dynamic_cast< RemoveNode const * >(&rElementChange))
228 pThisChange = pSetData->doAdjustToRemovedElement(aName, *removeNode);
230 else
232 if (nDepth > 0 || (NULL != pSetData->doFindElement(aName)) )// found even beyond nDepth ?
234 pThisChange = pSetData->doAdjustChangedElement(rLocalChanges,aName, rElementChange);
238 if (pThisChange)
240 addLocalChangeHelper( rLocalChanges, configuration::NodeChange(pThisChange) );
244 void ViewStrategy::implAdjustToElementChanges(configuration::NodeChangesInformation& rLocalChanges, SetNode const& _aSetNode, SubtreeChange const& rExternalChanges, unsigned int nDepth)
247 if (nDepth > 0)
249 configuration::SetNodeImpl * pSetData = _aSetNode.get_impl();
251 OSL_ENSURE( pSetData->getTemplateProvider().isValid(), "Cannot adjust SetNode to changes - node was never initialized" );
253 if (pSetData->implHasLoadedElements())
255 unsigned int const nElementDepth = configuration::childDepth(nDepth);
256 for (SubtreeChange::ChildIterator it = rExternalChanges.begin(); it != rExternalChanges.end(); ++it)
258 this->implAdjustToElementChange(rLocalChanges, _aSetNode, *it, nElementDepth);
261 else
263 OSL_ENSURE( !hasChanges(_aSetNode.node()),"Cannot have changes to consider when no elements are loaded");
265 pSetData->convertChanges( rLocalChanges, rExternalChanges, nDepth);
270 configuration::ValueChangeImpl* ViewStrategy::doAdjustToValueChange(GroupNode const& _aGroupNode, rtl::OUString const& _aName, ValueChange const& _rExternalChange)
272 configuration::ValueChangeImpl* pChangeImpl = NULL;
274 sharable::ValueNode * localNode = getMemberValueAccess(_aGroupNode,_aName);
275 if (localNode != 0)
277 switch( _rExternalChange. getMode() )
279 case ValueChange::wasDefault:
280 case ValueChange::changeValue:
281 pChangeImpl = new configuration::ValueReplaceImpl( _rExternalChange.getNewValue(), _rExternalChange.getOldValue() );
282 break;
284 case ValueChange::setToDefault:
285 pChangeImpl = new configuration::ValueResetImpl( _rExternalChange.getNewValue(), _rExternalChange.getOldValue() );
286 break;
288 default: OSL_ENSURE(false, "Unknown change mode");
289 // fall thru to next case for somewhat meaningful return value
290 case ValueChange::changeDefault:
292 com::sun::star::uno::Any aLocalValue = localNode->getValue();
294 pChangeImpl = new configuration::ValueReplaceImpl( aLocalValue, aLocalValue );
296 break;
298 OSL_ASSERT( pChangeImpl );
300 else
302 OSL_ENSURE(false, "ERROR: Notification tries to change nonexistent value within group");
305 return pChangeImpl;
308 void ViewStrategy::implAdjustToValueChanges(configuration::NodeChangesInformation& rLocalChanges, GroupNode const& _aGroupNode, SubtreeChange const& rExternalChanges)
310 for (SubtreeChange::ChildIterator it = rExternalChanges.begin(); it != rExternalChanges.end(); ++it)
312 if (ValueChange const * valueChange = dynamic_cast< ValueChange const * >(&*it))
314 rtl::OUString aValueName( valueChange->getNodeName() );
316 if (configuration::ValueChangeImpl* pThisChange = doAdjustToValueChange(_aGroupNode, aValueName, *valueChange))
318 pThisChange->setTarget(_aGroupNode,aValueName);
319 addLocalChangeHelper(rLocalChanges, configuration::NodeChange(pThisChange));
321 else
322 OSL_TRACE("WARNING: Configuration: derived class hides an external value member change from listeners");
324 else
325 OSL_ENSURE(dynamic_cast< SubtreeChange const * >(&*it) != 0, "Unexpected change type within group");
329 void ViewStrategy::implAdjustToSubChanges(configuration::NodeChangesInformation& rLocalChanges, GroupNode const& _aGroupNode, SubtreeChange const& rExternalChanges)
331 #if (OSL_DEBUG_LEVEL > 0)
332 configuration::Tree * pTreeData = _aGroupNode.tree();
333 #endif
334 for(SubtreeChange::ChildIterator it = rExternalChanges.begin(); it != rExternalChanges.end(); ++it)
336 if (SubtreeChange const * subtreeChange = dynamic_cast< SubtreeChange const * >(&*it))
338 Node aSubNode = _aGroupNode.findChild( it->getNodeName() );
339 OSL_ENSURE( aSubNode.is() || pTreeData->depthTo(_aGroupNode.node().get_offset()) >= pTreeData->getAvailableDepth(), "Changed node not found in tree");
341 if (aSubNode.is())
343 OSL_ENSURE( pTreeData->getRemainingDepth(_aGroupNode.node().get_offset()) > 0, "Depth is smaller than expected for tree");
344 this->adjustToChanges(rLocalChanges, aSubNode, *subtreeChange);
347 else
349 OSL_ENSURE(dynamic_cast< ValueChange const * >(&*it) != 0, "Unexpected change type for child of group node; change is ignored");
350 OSL_ENSURE( !_aGroupNode.findChild(it->getNodeName()).is(),
351 "Found sub(tree) node where a value was expected");
355 //-----------------------------------------------------------------------------
356 void ViewStrategy::doCollectChanges(Node const& _aNode, configuration::NodeChanges& ) const
358 { (void)_aNode; }
359 // no-op: there are no changes to collect
360 OSL_ENSURE(!hasChanges(_aNode),"Unexpected changes in View");
364 //-----------------------------------------------------------------------------
365 com::sun::star::uno::Any ViewStrategy::getValue(ValueNode const& _aNode) const
367 checkInstance(_aNode.tree());
368 return _aNode.get_impl()->getValue();
370 #if OSL_DEBUG_LEVEL > 0
371 com::sun::star::uno::Type ViewStrategy::getValueType(ValueNode const& _aNode) const
373 checkInstance(_aNode.tree());
374 return _aNode.get_impl()->getValueType();
376 #endif
377 //-----------------------------------------------------------------------------
378 // group member access
380 //-----------------------------------------------------------------------------
381 namespace { // helpers
382 struct GroupMemberDispatch : data::NodeVisitor
384 GroupMemberDispatch(ViewStrategy& _rStrategy, GroupNode const& _aGroup, configuration::GroupMemberVisitor& rVisitor)
385 : m_rStrategy(_rStrategy)
386 , m_aGroup(_aGroup)
387 , m_rVisitor(rVisitor)
390 static bool mapResult(configuration::GroupMemberVisitor::Result _aResult)
392 return _aResult == configuration::GroupMemberVisitor::DONE;
395 static configuration::GroupMemberVisitor::Result unmapResult(bool done)
397 return done
398 ? configuration::GroupMemberVisitor::DONE
399 : configuration::GroupMemberVisitor::CONTINUE;
402 using NodeVisitor::handle;
403 virtual bool handle(sharable::Node * node);
404 virtual bool handle(sharable::ValueNode * node);
405 #if (OSL_DEBUG_LEVEL > 0)
406 bool test_value(sharable::Node * node) const;
407 #endif
408 ViewStrategy& m_rStrategy;
409 GroupNode m_aGroup;
410 configuration::GroupMemberVisitor& m_rVisitor;
412 configuration::GroupMemberVisitor::Result m_aResult;
415 #if (OSL_DEBUG_LEVEL > 0)
416 bool GroupMemberDispatch::test_value(sharable::Node * node) const
418 return m_rStrategy.hasValue(m_aGroup, node->getName());
420 #endif
422 bool GroupMemberDispatch::handle(sharable::ValueNode * node)
424 OSL_ENSURE( test_value(sharable::node(node)), "ERROR: Group MemberDispatch:Did not find a ValueMember for a value child.");
426 rtl::OUString aValueName = node->info.getName();
428 return mapResult( m_rVisitor.visit( m_rStrategy.getValue(m_aGroup,aValueName) ) );
431 bool GroupMemberDispatch::handle(sharable::Node * node)
433 (void) node; // avoid warnings
434 OSL_ENSURE( !test_value(node), "ERROR: Group MemberDispatch:Found a ValueMember for a subtree child.");
436 return false;
439 //-----------------------------------------------------------------------------
440 configuration::ValueMemberNode ViewStrategy::doGetValueMember(GroupNode const& _aNode, rtl::OUString const& _aName, bool ) const
442 sharable::ValueNode * valueData = getMemberValueAccess(_aNode,_aName);
443 return _aNode.get_impl()->makeValueMember(valueData);
446 bool ViewStrategy::hasValue(GroupNode const& _aNode, rtl::OUString const& _aName) const
448 checkInstance(_aNode.tree());
449 return getMemberValueAccess(_aNode,_aName) != 0;
452 bool ViewStrategy::hasValue(GroupNode const& _aNode) const
454 checkInstance(_aNode.tree());
455 configuration::GroupNodeImpl* pGroupNode=_aNode.get_impl();
456 sharable::GroupNode * group = pGroupNode->getDataAccess();
457 return group->numDescendants > 0;
461 bool ViewStrategy::areValueDefaultsAvailable(GroupNode const& _aNode) const
463 checkInstance(_aNode.tree());
465 return _aNode.get_impl()->areValueDefaultsAvailable();
468 configuration::ValueMemberNode ViewStrategy::getValue(GroupNode const& _aNode, rtl::OUString const& _aName) const
470 checkInstance(_aNode.tree());
471 return doGetValueMember(_aNode,_aName,false);
474 configuration::ValueMemberUpdate ViewStrategy::getValueForUpdate(GroupNode const & _aNode, rtl::OUString const& _aName)
476 checkInstance(_aNode.tree());
477 return configuration::ValueMemberUpdate( doGetValueMember(_aNode,_aName,true), *this );
480 configuration::GroupMemberVisitor::Result ViewStrategy::dispatchToValues(GroupNode const& _aNode, configuration::GroupMemberVisitor& _aVisitor)
482 checkInstance(_aNode.tree());
484 GroupMemberDispatch aDispatch(*this,_aNode,_aVisitor);
486 bool done = aDispatch.visitChildren( _aNode.getAccess() );
488 return aDispatch.unmapResult(done);
491 //-----------------------------------------------------------------------------
492 configuration::ElementTreeData ViewStrategy::implMakeElement(SetNode const& _aNode, configuration::SetEntry const& anEntry) const
494 configuration::SetNodeImpl * pNodeData = _aNode.get_impl();
495 return pNodeData->implValidateElement(pNodeData->entryToElement(anEntry));
497 //-----------------------------------------------------------------------------
498 configuration::SetEntry ViewStrategy::implFindElement(SetNode const& _aNode, rtl::OUString const& aName) const
500 configuration::SetNodeImpl * pNodeData = _aNode.get_impl();
502 OSL_ENSURE(pNodeData->implHasLoadedElements(),"Cannot find elements in set that is not loaded");
503 configuration::ElementTree * pElement = pNodeData->doFindElement(aName);
505 return configuration::SetEntry(pElement);
508 configuration::SetEntry ViewStrategy::findElement(SetNode const& _aNode, rtl::OUString const& aName) const
510 checkInstance(_aNode.tree());
511 _aNode.get_impl()->implEnsureElementsLoaded();
512 return implFindElement(_aNode,aName);
515 configuration::SetEntry ViewStrategy::findAvailableElement(SetNode const& _aNode, rtl::OUString const& aName) const
517 checkInstance(_aNode.tree());
518 if (_aNode.get_impl()->implHasLoadedElements())
519 return implFindElement(_aNode,aName);
520 else
521 return configuration::SetEntry(0);
524 static
525 inline
526 std::auto_ptr<SubtreeChange> makeChangeToDefault(sharable::SetNode * setNode)
528 return std::auto_ptr<SubtreeChange>(
529 new SubtreeChange(
530 setNode->info.getName(),
531 setNode->getElementTemplateName(),
532 setNode->getElementTemplateModule(),
533 sharable::node(setNode)->getAttributes(),
534 true // to default
535 ) );
538 std::auto_ptr<SubtreeChange> ViewStrategy::differenceToDefaultState(SetNode const& _aNode, ISubtree& _rDefaultTree) const
540 checkInstance(_aNode.tree());
541 std::auto_ptr<SubtreeChange> aResult;
543 sharable::SetNode * originalSetNode = _aNode.getAccess();
544 OSL_ASSERT(originalSetNode != 0);
545 if (!originalSetNode->info.isDefault())
547 aResult = makeChangeToDefault(originalSetNode);
549 configuration::SetNodeImpl * pNodeData = _aNode.get_impl();
550 if (this->hasChanges(_aNode.node()))
552 OSL_ENSURE(pNodeData->implHasLoadedElements(),"Unexpected: Found set with changes but elements are not loaded");
553 pNodeData->doDifferenceToDefaultState(*aResult,_rDefaultTree);
555 else
556 pNodeData->implDifferenceToDefaultState(*aResult,_rDefaultTree);
558 return aResult;
561 rtl::Reference<configuration::Template> ViewStrategy::getElementTemplate(SetNode const& _aNode) const
563 checkInstance(_aNode.tree());
564 return _aNode.get_impl()->getElementTemplate();
567 configuration::TemplateProvider ViewStrategy::getTemplateProvider(SetNode const& _aNode) const
569 checkInstance(_aNode.tree());
570 return _aNode.get_impl()->getTemplateProvider();
573 node::Attributes ViewStrategy::getNodeAttributes(Node const& _aNode) const
575 checkInstance(_aNode.tree());
576 return _aNode.getAccessRef()->getAttributes();
579 //-----------------------------------------------------------------------------
580 configuration::SetNodeVisitor::Result ViewStrategy::dispatchToElements(SetNode const& _aNode, configuration::SetNodeVisitor& _aVisitor)
582 checkInstance(_aNode.tree());
584 configuration::SetNodeImpl * pNodeData = _aNode.get_impl();
586 if (pNodeData->implLoadElements())
587 return pNodeData->doDispatchToElements(_aVisitor);
589 else
590 return configuration::SetNodeVisitor::CONTINUE;
593 bool ViewStrategy::isEmpty(SetNode const& _aNode) const
595 checkInstance(_aNode.tree());
597 configuration::SetNodeImpl * pNodeData = _aNode.get_impl();
599 return !pNodeData->implLoadElements() || pNodeData->doIsEmpty();
601 //-----------------------------------------------------------------------------
603 void ViewStrategy::insertElement(SetNode const& _aNode, rtl::OUString const& _aName, configuration::SetEntry const& _aNewEntry)
605 // cannot insert, if we cannot check for collisions
606 checkInstance(_aNode.tree());
607 _aNode.get_impl()->implEnsureElementsLoaded();
608 doInsertElement(_aNode,_aName,_aNewEntry);
611 void ViewStrategy::removeElement(SetNode const& _aNode, rtl::OUString const& _aName)
613 // cannot remove, if we cannot check for existance
614 checkInstance(_aNode.tree());
615 _aNode.get_impl()->implEnsureElementsLoaded();
616 doRemoveElement(_aNode,_aName);
619 //-----------------------------------------------------------------------------
621 //-----------------------------------------------------------------------------