merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / treemgr / setnodeimpl.cxx
blob91dabe58a56d6bfef4a0e52b7dca582b7e824c36
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: setnodeimpl.cxx,v $
10 * $Revision: 1.26 $
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"
33 #include <stdio.h>
35 #include "builddata.hxx"
36 #include "setnodeimpl.hxx"
37 #include "treefragment.hxx"
38 #include "viewfactory.hxx"
39 #include "configpath.hxx"
40 #include "tree.hxx"
41 #include "valuenodeimpl.hxx"
42 #include "nodechange.hxx"
43 #include "nodechangeimpl.hxx"
44 #include "nodevisitor.hxx"
45 #include "change.hxx"
46 #include "viewaccess.hxx"
47 #include "nodeconverter.hxx"
48 #include "treeactions.hxx"
49 #include "treechangefactory.hxx"
50 #include "collectchanges.hxx"
51 #include <osl/diagnose.h>
53 #ifndef INCLUDED_VECTOR
54 #include <vector>
55 #define INCLUDED_VECTOR
56 #endif
58 namespace configmgr
60 namespace configuration
62 //-------------------------------------------------------------------------
63 // initialization helpers
64 //-------------------------------------------------------------------------
65 namespace
67 class CollectElementTrees : data::SetVisitor
69 public:
70 CollectElementTrees(rtl::Reference<view::ViewStrategy> const& _xStrategy,
71 Tree* pParentTree, unsigned int nPos,
72 unsigned int nDepth,
73 rtl::Reference<Template> const& aTemplate,
74 TemplateProvider const& aTemplateProvider)
75 : m_aTemplate(aTemplate)
76 , m_aTemplateProvider(aTemplateProvider)
77 , m_xStrategy(_xStrategy)
78 , m_pParentTree(pParentTree)
79 , m_nPos(nPos)
80 , m_nDepth(nDepth)
82 OSL_ENSURE(m_aTemplate.is(),"WARNING: Collecting a set without a template");
85 void collect(sharable::SetNode * node)
87 visitElements(node);
90 ElementTreeData create(sharable::TreeFragment * elementTree)
92 OSL_ENSURE(collection.empty(),"warning: trying to reuse a full collection");
94 collection.resize(1); // make an empty one for case of failure
95 this->visitTree(elementTree);
97 OSL_ENSURE(collection.size()==2,"warning: could not create an element");
98 return collection.back();
101 std::vector<ElementTreeData> collection;
103 private:
104 using SetVisitor::handle;
106 virtual bool handle(sharable::Node * node);
108 virtual bool handle(sharable::ValueNode * node);
110 virtual bool handle(sharable::TreeFragment * tree);
112 void add(sharable::TreeFragment * node);
114 rtl::Reference<Template> m_aTemplate;
115 TemplateProvider m_aTemplateProvider;
116 rtl::Reference<view::ViewStrategy> m_xStrategy;
117 Tree* m_pParentTree;
118 unsigned int m_nPos;
119 unsigned int m_nDepth;
121 //-------------------------------------------------------------------------
123 static
124 rtl::OUString validatedName(ElementTreeData const& aTree)
126 OSL_ENSURE(aTree.isValid(), "INTERNAL ERROR: Unexpected null tree constructed in set node");
127 if (!aTree.isValid()) throw Exception("INTERNAL ERROR: Unexpected null tree in set node");
129 OSL_ENSURE(aTree->nodeCount(), "INTERNAL ERROR: Unexpected empty (!) tree constructed in set node");
130 OSL_ENSURE(aTree->isValidNode(Tree::ROOT), "INTERNAL ERROR: Corrupt tree constructed in set node");
132 return aTree->getSimpleRootName();
134 //-------------------------------------------------------------------------
136 static
137 bool isInDefault(SetEntry const& _anEntry)
139 if (!_anEntry.isValid()) return false;
141 node::Attributes aAttributes = _anEntry.getTreeView().getRootAttributes();
143 bool bReplaced = aAttributes.isReplacedForUser();
145 return !bReplaced;
147 //-------------------------------------------------------------------------
148 bool CollectElementTrees::handle(sharable::ValueNode * node)
150 if (m_aTemplate.is())
152 OSL_ENSURE(m_aTemplate->isInstanceTypeKnown(),"ERROR: Template must have a validated type when building a set.");
153 OSL_ENSURE(m_aTemplate->isInstanceValue(),"ERROR: Found a value node in a Complex Template Set");
155 if (!m_aTemplate->isInstanceValue())
156 throw Exception("INTERNAL ERROR: Corrupt tree contains a value node within a template-set");
158 com::sun::star::uno::Type aValueType = node->getValueType();
159 com::sun::star::uno::Type aExpectedType = m_aTemplate->getInstanceType();
161 if (aValueType.getTypeClass() != aExpectedType.getTypeClass() &&
162 aExpectedType.getTypeClass() != uno::TypeClass_ANY &&
163 aValueType.getTypeClass() != uno::TypeClass_VOID)
165 OSL_ENSURE(false, "WARNING: ValueType of set node does not match the template type");
166 // throw TypeMismatch(aValueType.getTypeName(),aExpectedType.getTypeName(), "INTERNAL ERROR: - Corrupt tree contains mistyped value node within a value-set")));
169 return false;
171 //-------------------------------------------------------------------------
172 bool CollectElementTrees::handle(sharable::Node * node)
174 (void) node; // avoid warnings
175 OSL_ENSURE(!node->isValue(), "Unexpected: Value-node dispatched to wrong handler");
176 if (m_aTemplate.is())
178 OSL_ENSURE(m_aTemplate->isInstanceTypeKnown(),"ERROR: Template must have a validated type when building a set.");
179 OSL_ENSURE(!m_aTemplate->isInstanceValue(),"ERROR: Found a non-leaf node in a Value Set");
181 if (m_aTemplate->isInstanceValue())
182 throw Exception("INTERNAL ERROR: Corrupt tree contains a non-leaf node within a value-set");
185 return false;
187 //-------------------------------------------------------------------------
188 bool CollectElementTrees::handle(sharable::TreeFragment * tree)
190 bool done = visitNode(tree->getRootNode());
191 if (!done) {
192 add(tree);
194 return done;
196 //-------------------------------------------------------------------------
197 void CollectElementTrees::add(sharable::TreeFragment * tree)
199 node::Attributes const aAttributes = tree->getAttributes();
201 bool bReadonly = aAttributes.isReadonly();
202 bool bInDefault = !aAttributes.isReplacedForUser();
204 rtl::Reference<view::ViewStrategy> xStrategy = !bReadonly ? m_xStrategy : view::createReadOnlyStrategy();
206 ElementTree * pNewTree;
207 if (m_pParentTree)
208 pNewTree = new ElementTree(xStrategy, *m_pParentTree, m_nPos, tree, m_nDepth, m_aTemplate, m_aTemplateProvider);
210 else
211 pNewTree = new ElementTree(xStrategy, tree, m_nDepth, m_aTemplate, m_aTemplateProvider);
213 collection.push_back( ElementTreeData(pNewTree,bInDefault));
217 //-------------------------------------------------------------------------
218 // class ElementSet
219 //-------------------------------------------------------------------------
221 bool ElementSet::hasElement(rtl::OUString const& aName) const
223 return m_aData.find(aName) != m_aData.end();
225 //-------------------------------------------------------------------------
227 ElementTreeData* ElementSet::getElement(rtl::OUString const& aName)
229 Data::iterator it = m_aData.find(aName);
230 if (it != m_aData.end())
231 return &it->second;
232 else
233 return 0;
235 //-------------------------------------------------------------------------
238 ElementTreeData const* ElementSet::getElement(rtl::OUString const& aName) const
240 Data::const_iterator it = m_aData.find(aName);
241 if (it != m_aData.end())
242 return &it->second;
243 else
244 return 0;
246 //-------------------------------------------------------------------------
248 ElementTreeData ElementSet::findElement(rtl::OUString const& aName)
250 ElementTreeData aRet;
252 Data::iterator it = m_aData.find(aName);
253 if (it != m_aData.end())
254 aRet = it->second;
256 return aRet;
258 //-------------------------------------------------------------------------
260 void ElementSet::insertElement(rtl::OUString const& aName, ElementTreeData const& aNewEntry)
262 bool bInserted = m_aData.insert(Data::value_type(aName, aNewEntry)).second;
264 OSL_ENSURE(bInserted,"INTERNAL ERROR: Inserted set Element was already present");
265 if (!bInserted) throw Exception("INTERNAL ERROR: Inserted set Element was already present");
267 //-------------------------------------------------------------------------
269 ElementTreeData ElementSet::replaceElement(rtl::OUString const& aName, ElementTreeData const& aNewEntry)
271 OSL_ENSURE(m_aData.find(aName) != m_aData.end(),"INTERNAL ERROR: Replaced set Element is not present");
273 ElementTreeData& rElement = m_aData[aName];
275 ElementTreeData aOld = rElement;
276 rElement = aNewEntry;
278 return aOld;
280 //-------------------------------------------------------------------------
282 ElementTreeData ElementSet::removeElement(rtl::OUString const& aName)
284 Data::iterator it = m_aData.find(aName);
285 OSL_ENSURE(it != m_aData.end(),"INTERNAL ERROR: Removed set Element is not present");
287 ElementTreeData aOld;
288 if (it != m_aData.end())
290 aOld = it->second;
291 m_aData.erase(it);
293 return aOld;
295 //-------------------------------------------------------------------------
297 //-----------------------------------------------------------------------------
298 // class SetEntry
299 //-----------------------------------------------------------------------------
301 SetEntry::SetEntry(ElementTree* pTree_)
302 : m_pTree(pTree_)
304 OSL_ENSURE(pTree_ == 0 || pTree_->isValidNode(Tree::ROOT),
305 "INTERNAL ERROR: Invalid empty tree used for SetEntry ");
308 //-----------------------------------------------------------------------------
310 view::ViewTreeAccess SetEntry::getTreeView() const
312 OSL_ENSURE(isValid(), "Cannot get View Access for NULL SetEntry");
313 return view::ViewTreeAccess(m_pTree);
316 //-----------------------------------------------------------------------------
317 //-------------------------------------------------------------------------
319 //-------------------------------------------------------------------------
320 // class SetNodeImpl
321 //-------------------------------------------------------------------------
323 SetNodeImpl::SetNodeImpl(sharable::SetNode * _pNodeRef,Template* pTemplate)
324 : NodeImpl(reinterpret_cast<sharable::Node *>(_pNodeRef))
325 ,m_aTemplate(pTemplate)
326 ,m_aTemplateProvider()
327 ,m_pParentTree(0)
328 ,m_nContextPos(0)
329 ,m_aInit(0)
332 // unbind the original
333 //-----------------------------------------------------------------------------
335 SetNodeImpl::~SetNodeImpl()
338 //-----------------------------------------------------------------------------
340 void SetNodeImpl::rebuildFrom(SetNodeImpl& rOldData, sharable::SetNode * newNode)
342 m_aTemplate = rOldData.m_aTemplate;
343 m_aTemplateProvider = rOldData.m_aTemplateProvider;
344 m_pParentTree = rOldData.m_pParentTree;
345 m_nContextPos = rOldData.m_nContextPos;
346 m_aInit = rOldData.m_aInit;
348 if (rOldData.implHasLoadedElements())
350 rOldData.doTransferElements(m_aDataSet);
351 implRebuildElements(newNode);
352 OSL_ASSERT(this->implHasLoadedElements());
354 else
355 OSL_ASSERT(!this->implHasLoadedElements());
357 rOldData.m_aTemplate.clear();
358 rOldData.m_aTemplateProvider = TemplateProvider();
359 rOldData.m_pParentTree = 0;
360 rOldData.m_nContextPos = 0;
364 //-----------------------------------------------------------------------------
365 void SetNodeImpl::doTransferElements(ElementSet& rReplacement)
367 m_aDataSet.swap(rReplacement);
369 //-----------------------------------------------------------------------------
371 void SetNodeImpl::implRebuildElements(sharable::SetNode * newNode)
373 OSL_ENSURE(m_pParentTree,"Cannot rebuild set without context tree");
374 rtl::Reference<view::ViewStrategy> xNewStrategy = m_pParentTree->getViewBehavior();
376 for(ElementSet::Iterator it = m_aDataSet.begin(), stop = m_aDataSet.end();
377 it != stop;
378 ++it)
380 OSL_ASSERT(it->isValid());
381 if (!it->isValid()) continue;
383 ElementTreeData aElement = *it;
384 rtl::OUString aName = aElement->getSimpleRootName();
386 sharable::TreeFragment * aNewElementAccess = newNode->getElement(aName);
387 OSL_ASSERT(
388 aNewElementAccess != 0 && aElement->getOriginalTreeAccess() != 0);
390 aElement->rebuild(xNewStrategy,aNewElementAccess);
393 //-----------------------------------------------------------------------------
395 sharable::SetNode * SetNodeImpl::getDataAccess() const
397 sharable::Node * node = getOriginalNodeAccess();
398 OSL_ASSERT(node != 0 && node->isSet());
399 return &node->set;
401 //-----------------------------------------------------------------------------
403 Tree* SetNodeImpl::getParentTree() const
405 OSL_ENSURE(m_pParentTree,"Set Node: Parent tree not set !");
406 return m_pParentTree;
408 //-----------------------------------------------------------------------------
410 unsigned int SetNodeImpl::getContextOffset() const
412 OSL_ENSURE(m_nContextPos,"Set Node: Position within parent tree not set !");
413 return m_nContextPos;
415 //-----------------------------------------------------------------------------
417 bool SetNodeImpl::doIsEmpty() const
420 for(ElementSet::Iterator it = m_aDataSet.begin(), stop = m_aDataSet.end();
421 it != stop;
422 ++it)
424 if (!it->isEmpty())
425 return false;
427 return true;
429 return m_aDataSet.isEmpty();
431 //-------------------------------------------------------------------------
433 ElementTree* SetNodeImpl::doFindElement(rtl::OUString const& aName)
435 return m_aDataSet.findElement(aName).get();
437 //-------------------------------------------------------------------------
438 void SetNodeImpl::doDifferenceToDefaultState(SubtreeChange& _rChangeToDefault, ISubtree& _rDefaultTree)
440 OSL_ENSURE(implHasLoadedElements(),"Should not query difference to default state for set that is not loaded");
441 implDifferenceToDefaultState(_rChangeToDefault,_rDefaultTree);
443 //-----------------------------------------------------------------------------
445 SetElementChangeImpl* SetNodeImpl::doAdjustToAddedElement(rtl::OUString const& aName, AddNode const& aAddNodeChange, ElementTreeData const & aNewElement)
447 return implAdjustToAddedElement(aName,aNewElement,aAddNodeChange.isReplacing());
449 //-------------------------------------------------------------------------
451 SetElementChangeImpl* SetNodeImpl::implAdjustToAddedElement(rtl::OUString const& aName, ElementTreeData const & aNewElement, bool _bReplacing)
453 { (void)_bReplacing; }
454 OSL_ENSURE( validatedName(aNewElement) == aName, "Unexpected name on new element" );
456 if (hasStoredElement(aName))
458 OSL_ENSURE( _bReplacing, "Added Element already exists - replacing" );
460 ElementTreeData aOldElement = this->replaceElement(aName,aNewElement);
462 return implCreateReplace(aName,aNewElement,aOldElement);
464 else
466 OSL_ENSURE( !_bReplacing, "Replaced Element doesn't exist - simply adding" );
467 this->insertElement(aName,aNewElement);
469 return implCreateInsert(aName,aNewElement);
472 //-------------------------------------------------------------------------
474 SetElementChangeImpl* SetNodeImpl::doAdjustToRemovedElement(rtl::OUString const& aName, RemoveNode const& /*aRemoveNodeChange*/)
476 return implAdjustToRemovedElement(aName);
478 //-------------------------------------------------------------------------
480 SetElementChangeImpl* SetNodeImpl::implAdjustToRemovedElement(rtl::OUString const& aName)
482 if (ElementTreeData* pOriginal = getStoredElement(aName))
484 ElementTreeData aOldElement = *pOriginal;
485 this->removeElement(aName);
487 return implCreateRemove(aName,aOldElement);
489 else
491 OSL_ENSURE( false, "Removed Element doesn't exist - ignoring" );
492 return 0;
495 //-------------------------------------------------------------------------
497 SetElementChangeImpl* SetNodeImpl::implCreateInsert(rtl::OUString const& aName, ElementTreeData const& aNewElement) const
499 Path::Component aFullName = Path::makeCompositeName(aName, this->getElementTemplate()->getName());
501 SetElementChangeImpl* pRet = new SetInsertImpl(aFullName, aNewElement.tree, true);
502 pRet->setTarget( getParentTree(), getContextOffset() );
503 return pRet;
505 //-------------------------------------------------------------------------
507 SetElementChangeImpl* SetNodeImpl::implCreateReplace(rtl::OUString const& aName, ElementTreeData const& aNewElement, ElementTreeData const& aOldElement) const
509 Path::Component aFullName = Path::makeCompositeName(aName, this->getElementTemplate()->getName());
511 SetElementChangeImpl* pRet = new SetReplaceImpl(aFullName, aNewElement.tree, aOldElement.tree);
512 pRet->setTarget( getParentTree(), getContextOffset() );
513 return pRet;
515 //-------------------------------------------------------------------------
517 SetElementChangeImpl* SetNodeImpl::implCreateRemove(rtl::OUString const& aName, ElementTreeData const& aOldElement) const
519 Path::Component aFullName = Path::makeCompositeName(aName, this->getElementTemplate()->getName());
521 SetElementChangeImpl* pRet = new SetRemoveImpl(aFullName, aOldElement.tree);
522 pRet->setTarget( getParentTree(), getContextOffset() );
523 return pRet;
525 //-------------------------------------------------------------------------
527 void SetNodeImpl::insertElement(rtl::OUString const& aName, ElementTreeData const& aNewElement)
529 attach(aNewElement,aName);
530 try
532 m_aDataSet.insertElement(aName,aNewElement);
534 catch (std::exception&)
536 detach(aNewElement);
537 throw;
540 //-------------------------------------------------------------------------
542 ElementTreeData SetNodeImpl::replaceElement(rtl::OUString const& aName, ElementTreeData const& aNewElement)
544 attach(aNewElement,aName);
545 try
547 ElementTreeData aOldElement = m_aDataSet.replaceElement(aName,aNewElement);
548 detach(aOldElement);
549 return aOldElement;
551 catch (std::exception&)
553 detach(aNewElement);
554 throw;
557 //-------------------------------------------------------------------------
559 ElementTreeData SetNodeImpl::removeElement(rtl::OUString const& aName)
561 ElementTreeData aOldElement = m_aDataSet.removeElement(aName);
562 detach(aOldElement);
563 return aOldElement;
565 //-------------------------------------------------------------------------
566 SetNodeVisitor::Result SetNodeImpl::doDispatchToElements(SetNodeVisitor& aVisitor)
568 SetNodeVisitor::Result eRet = SetNodeVisitor::CONTINUE;
569 for(ElementSet::Iterator it = m_aDataSet.begin(), stop = m_aDataSet.end();
570 it != stop && eRet != SetNodeVisitor::DONE;
571 ++it)
573 eRet = aVisitor.visit( SetEntry(it->get()) );
575 return eRet;
577 //-----------------------------------------------------------------------------
579 void SetNodeImpl::attach(ElementTreeData const& aNewElement, rtl::OUString const& aName)
581 // check for name (this also reject NULLs, therefore it should go first)
582 rtl::OUString aActualName = validatedName(aNewElement);
584 Tree* pParentContext = getParentTree();
585 unsigned int nParentOffset = getContextOffset();
587 OSL_ENSURE(nParentOffset != 0 && pParentContext != 0,"INTERNAL ERROR: Set has no context");
589 bool bHasContext = (aNewElement->getContextTree() != 0);
591 if (bHasContext)
593 if (aNewElement->getContextTree() != pParentContext)
595 OSL_ENSURE(false,"INTERNAL ERROR: New set element belongs to another context tree" );
596 throw Exception("INTERNAL ERROR: New set element belongs to another context tree" );
598 if (aNewElement->getContextNode() != nParentOffset)
600 OSL_ENSURE(false,"INTERNAL ERROR: New set element belongs to another context node" );
601 throw Exception("INTERNAL ERROR: New set element belongs to another context node" );
604 else
606 OSL_ENSURE(aNewElement->getContextNode() == 0, "INTERNAL ERROR: New element has context position without a parent");
607 aNewElement->moveTree(pParentContext,nParentOffset);
610 // check for and correct a misnomer - do only after parenthood is assured (else we don't own it anyways)
611 if (aName != aActualName)
613 // OSL_ENSURE(aActualName.isEmpty(), "WARNING: Wrongly named tree inserted in set node");
614 aNewElement->renameTree(aName);
616 aActualName = validatedName(aNewElement);
617 if (aName !=aActualName )
619 OSL_ENSURE(false, "INTERNAL ERROR: Cannot rename tree in set node");
620 throw Exception("INTERNAL ERROR: Cannot rename tree for insertion into set node");
624 //-------------------------------------------------------------------------
626 void SetNodeImpl::detach(ElementTreeData const& aOldElement)
628 if (aOldElement.isValid())
630 aOldElement->detachTree();
633 //-------------------------------------------------------------------------
635 ElementTreeData SetNodeImpl::entryToElement(SetEntry const& _anEntry)
637 ElementTree * pTree = _anEntry.tree();
638 return ElementTreeData(pTree, isInDefault(_anEntry));
640 //-------------------------------------------------------------------------
643 SetElementChangeImpl* SetNodeImpl::doAdjustChangedElement(NodeChangesInformation& rLocalChanges, rtl::OUString const& aName, Change const& _aElementChange)
645 SetElementChangeImpl* pThisChange = NULL;
647 if (ElementTreeData* pElement = getStoredElement(aName))
649 OSL_ASSERT(pElement->isValid());
651 if (SubtreeChange const * subtreeChange = dynamic_cast< SubtreeChange const * >(&_aElementChange))
653 // recurse to element tree
654 Tree * elementTree = pElement->get();
656 view::getViewBehavior(elementTree)->adjustToChanges(rLocalChanges, view::getRootNode(elementTree), *subtreeChange);
658 else if (ValueChange const * valueChange = dynamic_cast< ValueChange const * >(&_aElementChange))
660 // make an element for the old element
661 std::auto_ptr<ValueNode> aOldNode = OTreeNodeConverter().createCorrespondingNode(*valueChange);
662 aOldNode->setValue(valueChange->getOldValue());
664 bool bWasDefault = (valueChange->getMode() == ValueChange::wasDefault);
666 std::auto_ptr<INode> aBasePtr(aOldNode.release());
667 rtl::OUString aElementTypeName = getElementTemplate()->getName();
668 rtl::Reference< data::TreeSegment > aOldBaseTree = data::TreeSegment::create( aBasePtr, aElementTypeName );
670 rtl::Reference<ElementTree> aOldElement = new ElementTree(aOldBaseTree, getElementTemplate(), getTemplateProvider());
672 OSL_ASSERT(aOldBaseTree.is()); // the tree took ownership
673 OSL_ASSERT(aOldElement->isFree()); // the tree is free-floating
675 pThisChange = implCreateReplace(aName,*pElement,ElementTreeData(aOldElement,bWasDefault));
677 else
678 OSL_ENSURE( false, "Unexpected kind of change to set element" );
681 else
683 // could be changed to do an insert instead (?)
684 OSL_ENSURE( false, "Changed Element doesn't exist - (and not adding now)" );
686 return pThisChange;
688 //-------------------------------------------------------------------------
690 bool SetNodeImpl::implHasLoadedElements() const
692 return m_aInit == 0; // cannot check whether init was called though ...
694 //-----------------------------------------------------------------------------
696 void SetNodeImpl::initElements(TemplateProvider const& aTemplateProvider,Tree& rParentTree,unsigned int nPos,unsigned int nDepth)
698 OSL_ENSURE(m_pParentTree == 0 || m_pParentTree == &rParentTree, "WARNING: Set Node: Changing parent");
699 OSL_ENSURE(m_nContextPos == 0 || m_nContextPos == nPos, "WARNING: Set Node: Changing location within parent");
700 m_pParentTree = &rParentTree;
701 m_nContextPos = nPos;
703 OSL_ENSURE(!m_aTemplateProvider.isValid() || !implHasLoadedElements(),"ERROR: Reinitializing set"); //doClearElements();
704 OSL_ASSERT(doIsEmpty()); //doClearElements();
706 OSL_ENSURE(!m_aTemplate.is() || m_aTemplate->isInstanceTypeKnown(),"ERROR: Need a type-validated template to fill a set");
707 OSL_ENSURE(aTemplateProvider.isValid() || nDepth == 0 || m_aTemplate->isInstanceValue(), "ERROR: Need a template provider to fill a non-primitive set");
709 if (nDepth > 0) // dont set a template provider for zero-depth sets
711 m_aInit = nDepth;
712 m_aTemplateProvider = aTemplateProvider;
715 //-----------------------------------------------------------------------------
717 bool SetNodeImpl::implLoadElements()
719 if (m_aInit > 0)
721 OSL_ENSURE(!getElementTemplate().is() || getElementTemplate()->isInstanceTypeKnown(),"ERROR: Need a type-validated template to fill a set");
722 OSL_ENSURE(getTemplateProvider().isValid() || getElementTemplate()->isInstanceValue(), "ERROR: Need a template provider to fill a non-primitive set");
724 unsigned int nDepth = m_aInit;
725 implInitElements(this->getDataAccess(),nDepth);
726 m_aInit = 0;
728 OSL_ASSERT(implHasLoadedElements());
730 return m_aInit == 0;
732 //-----------------------------------------------------------------------------
734 void SetNodeImpl::implEnsureElementsLoaded()
736 if (!implLoadElements())
737 throw ConstraintViolation("Trying to access set elements beyond the loaded nestíng level");
739 //-----------------------------------------------------------------------------
741 void SetNodeImpl::implInitElements(sharable::SetNode * node, unsigned int nDepth)
743 Tree* pThisTree = getParentTree();
745 OSL_ENSURE(pThisTree,"Cannot load elements of a set that has no parent tree");
747 CollectElementTrees aCollector( pThisTree->getViewBehavior(), pThisTree, getContextOffset(),
748 nDepth, getElementTemplate(), getTemplateProvider() );
749 aCollector.collect(node);
751 for(std::vector<ElementTreeData>::const_iterator it = aCollector.collection.begin(), stop = aCollector.collection.end();
752 it != stop; ++it)
754 implInitElement(implValidateElement(*it));
757 //-------------------------------------------------------------------------
759 void SetNodeImpl::implInitElement(ElementTreeData const& aNewElement)
761 OSL_PRECOND(aNewElement.isValid(),"INTERNAL ERROR: Set element is NULL");
762 OSL_ENSURE(!aNewElement->isFree(),"INTERNAL ERROR: Set element is free-floating");
764 OSL_ENSURE(aNewElement->getContextTree() == getParentTree(),"INTERNAL ERROR: Set element has wrong context tree");
765 OSL_ENSURE(aNewElement->getContextNode() == getContextOffset(),"INTERNAL ERROR: Set element has wrong context node");
767 rtl::OUString aName = validatedName(aNewElement);
769 OSL_ENSURE(aName.getLength() != 0,"INTERNAL ERROR: Unnamed element in set");
770 OSL_ENSURE(m_aDataSet.getElement(aName) == 0,"INTERNAL ERROR: Duplicate element name in set");
772 m_aDataSet.insertElement(aName,aNewElement);
774 //-------------------------------------------------------------------------
776 ElementTreeData SetNodeImpl::makeAdditionalElement(rtl::Reference<view::ViewStrategy> const& _xStrategy, AddNode const& aAddNodeChange, unsigned int nDepth)
778 OSL_ENSURE(aAddNodeChange.wasInserted(), "Cannot integrate element that is not in tree yet");
780 sharable::TreeFragment * aAddedTree = aAddNodeChange.getInsertedTree();
781 // need 'unsafe', because ownership would be gone when notifications are sent
782 if (aAddedTree != NULL)
784 CollectElementTrees aCollector( _xStrategy, getParentTree(), getContextOffset(),
785 nDepth, getElementTemplate(), getTemplateProvider() );
787 return implValidateElement(aCollector.create(aAddedTree));
790 return ElementTreeData();
792 //-------------------------------------------------------------------------
794 ElementTreeData SetNodeImpl::implValidateElement(ElementTreeData const& aNewElement)
796 rtl::Reference<Template> aTemplate = getElementTemplate();
797 OSL_ENSURE(aTemplate.is(),"INTERNAL ERROR: No template in set node");
798 OSL_ENSURE(aTemplate->isInstanceTypeKnown(),"INTERNAL ERROR: Unspecifed template in set node");
800 OSL_ENSURE(aNewElement.isValid(),"INTERNAL ERROR: Unexpected NULL element in set node");
801 if (aNewElement.isValid())
803 if (aTemplate->isInstanceValue())
805 if (aNewElement->nodeCount() == 0)
807 OSL_ENSURE(false,"INTERNAL ERROR: Invalid (empty) element tree in value set");
808 throw Exception("INTERNAL ERROR: Invalid (empty) element tree in value set");
810 if (aNewElement->nodeCount() > 1)
812 OSL_ENSURE(false,"INTERNAL ERROR: Complex element tree in value set");
813 throw Exception("INTERNAL ERROR: Complex element tree in value set");
816 view::Node aElementRoot = view::getRootNode(aNewElement.get());
818 OSL_ENSURE(aElementRoot.isValueNode(),"INTERNAL ERROR: Inserting complex type into value set node");
820 view::ValueNode aValueNode(aElementRoot);
821 com::sun::star::uno::Type aValueType = aValueNode.get_impl()->getValueType();
823 OSL_ENSURE( aValueType.getTypeClass() != uno::TypeClass_INTERFACE,
824 "INTERNAL ERROR: Inserting complex type into value set node");
826 com::sun::star::uno::Type aElementType = aTemplate->getInstanceType();
828 if (aValueType != aElementType)
830 // handle 'Any'
831 if (aElementType.getTypeClass() != uno::TypeClass_ANY)
833 OSL_ENSURE(false,"INTERNAL ERROR: ´Wrong value type inserting into value set");
834 throw TypeMismatch(aValueType.getTypeName(), aElementType.getTypeName(),
835 "- INTERNAL ERROR: Mistyped element in value set");
839 else // a complete tree
841 // TODO: add some validation here
842 if (!aNewElement->isTemplateInstance())
844 throw TypeMismatch( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<Unknown> [Missing Template]")),
845 aTemplate->getName(),
846 " - Trying to insert element without template into set");
848 if (!aNewElement->isInstanceOf(aTemplate))
850 throw TypeMismatch( aNewElement->getTemplate()->getPathString(),
851 aTemplate->getPathString(),
852 " - Trying to insert element with wrong template into set");
856 return aNewElement;
858 //-------------------------------------------------------------------------
860 namespace
862 //-------------------------------------------------------------------------
863 class DiffToDefault : data::SetVisitor
865 SubtreeChange& m_rChange;
866 ISubtree& m_rDefaultTree;
867 OTreeChangeFactory& m_rChangeFactory;
868 public:
869 explicit
870 DiffToDefault(SubtreeChange& _rChange, ISubtree& _rDefaultTree)
871 : m_rChange(_rChange)
872 , m_rDefaultTree(_rDefaultTree)
873 , m_rChangeFactory( getDefaultTreeChangeFactory() )
877 void diff(sharable::SetNode * actualTree)
879 translate(m_rDefaultTree);
880 visitElements(actualTree);
883 private:
884 void translate(ISubtree& _rDefaultTree);
885 void handleDefault(rtl::Reference< data::TreeSegment > const & _pDefaultElement);
886 void handleActual(sharable::TreeFragment * element);
888 using SetVisitor::handle;
889 virtual bool handle(sharable::TreeFragment * tree)
890 { handleActual(tree); return false; }
892 //-------------------------------------------------------------------------
894 void DiffToDefault::translate(ISubtree& _rDefaultTree)
896 rtl::OUString aTypeName = _rDefaultTree.getElementTemplateName();
897 OSL_ENSURE(aTypeName.getLength(),"Cannot get element type for default set");
899 CollectNames aCollector;
900 aCollector.applyToChildren(_rDefaultTree);
902 std::vector<rtl::OUString> const& aNames = aCollector.list();
904 for(std::vector<rtl::OUString>::const_iterator it = aNames.begin(); it != aNames.end(); ++it)
906 std::auto_ptr<INode> aChild = _rDefaultTree.removeChild(*it);
907 handleDefault( data::TreeSegment::create(aChild,aTypeName) );
911 //-------------------------------------------------------------------------
913 void DiffToDefault::handleDefault(rtl::Reference< data::TreeSegment > const &_pDefaultElement)
915 OSL_PRECOND(_pDefaultElement.is(), "Unexpected NULL default node");
917 rtl::OUString sName = _pDefaultElement->fragment->getName();
919 OSL_ENSURE(_pDefaultElement->fragment->getAttributes().isDefault(), "Missing default state on default element tree");
920 OSL_ENSURE(_pDefaultElement->fragment->nodes[0].isDefault(), "Missing default attribute on default node");
922 std::auto_ptr<AddNode> pAddIt( m_rChangeFactory.createAddNodeChange(_pDefaultElement, sName,true) );
924 m_rChange.addChange(base_ptr(pAddIt));
926 //-------------------------------------------------------------------------
928 // -----------------------------------------------------------------------------
929 void DiffToDefault::handleActual(sharable::TreeFragment * element)
931 bool bDefaultElement = element->getRootNode()->isDefault();
933 rtl::OUString sName = element->getName();
935 if (Change* pDefaultNode = m_rChange.getChange(sName) )
938 if (AddNode * addNode = dynamic_cast< AddNode * >(pDefaultNode))
940 if (bDefaultElement)
942 rtl::Reference< data::TreeSegment > aDefaultTree = addNode->getNewTree();
943 m_rDefaultTree.addChild(data::convertTree(aDefaultTree.is() ? aDefaultTree->fragment : 0, true));
945 // no change needed - remove the change and recover the default
946 m_rChange.removeChange(sName);
949 else
951 // should never happen
952 OSL_ASSERT(false);
953 if (bDefaultElement) m_rChange.removeChange(sName);
956 else
958 OSL_ENSURE(!bDefaultElement, "Node marked 'default' not found in actual default data");
960 std::auto_ptr<RemoveNode> pRemoveIt( m_rChangeFactory.createRemoveNodeChange(sName,true) );
961 // pRemoveIt->expectRemovedNode(pActualNode);
962 m_rChange.addChange(base_ptr(pRemoveIt));
965 //-----------------------------------------------------------------------------
967 //-----------------------------------------------------------------------------
968 void SetNodeImpl::implDifferenceToDefaultState(SubtreeChange& _rChangeToDefault, ISubtree& _rDefaultTree) const
970 DiffToDefault(_rChangeToDefault,_rDefaultTree).diff( getDataAccess() );
972 //-----------------------------------------------------------------------------
973 void SetNodeImpl::convertChanges(NodeChangesInformation& rLocalChanges, SubtreeChange const& rExternalChange,
974 unsigned int nDepth)
976 OSL_ASSERT(nDepth > 0);
978 if (Tree* pParentTree = this->getParentTree())
980 unsigned int nNode = getContextOffset();
982 OSL_ENSURE(pParentTree->isValidNode(nNode), "Invalid context node in Set");
983 OSL_ENSURE(view::Node(pParentTree, nNode).get_impl() == this,
984 "Wrong context node in Set");
986 CollectChanges aCollector(rLocalChanges, *pParentTree, nNode, getElementTemplate(), nDepth);
988 aCollector.collectFromChildren(rExternalChange);
990 else
991 OSL_ENSURE(false, "Missing context tree in Set");
993 //-----------------------------------------------------------------------------