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: setnodeimpl.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"
35 #include "builddata.hxx"
36 #include "setnodeimpl.hxx"
37 #include "treefragment.hxx"
38 #include "viewfactory.hxx"
39 #include "configpath.hxx"
41 #include "valuenodeimpl.hxx"
42 #include "nodechange.hxx"
43 #include "nodechangeimpl.hxx"
44 #include "nodevisitor.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
55 #define INCLUDED_VECTOR
60 namespace configuration
62 //-------------------------------------------------------------------------
63 // initialization helpers
64 //-------------------------------------------------------------------------
67 class CollectElementTrees
: data::SetVisitor
70 CollectElementTrees(rtl::Reference
<view::ViewStrategy
> const& _xStrategy
,
71 Tree
* pParentTree
, unsigned int nPos
,
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
)
82 OSL_ENSURE(m_aTemplate
.is(),"WARNING: Collecting a set without a template");
85 void collect(sharable::SetNode
* 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
;
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
;
119 unsigned int m_nDepth
;
121 //-------------------------------------------------------------------------
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 //-------------------------------------------------------------------------
137 bool isInDefault(SetEntry
const& _anEntry
)
139 if (!_anEntry
.isValid()) return false;
141 node::Attributes aAttributes
= _anEntry
.getTreeView().getRootAttributes();
143 bool bReplaced
= aAttributes
.isReplacedForUser();
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")));
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");
187 //-------------------------------------------------------------------------
188 bool CollectElementTrees::handle(sharable::TreeFragment
* tree
)
190 bool done
= visitNode(tree
->getRootNode());
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
;
208 pNewTree
= new ElementTree(xStrategy
, *m_pParentTree
, m_nPos
, tree
, m_nDepth
, m_aTemplate
, m_aTemplateProvider
);
211 pNewTree
= new ElementTree(xStrategy
, tree
, m_nDepth
, m_aTemplate
, m_aTemplateProvider
);
213 collection
.push_back( ElementTreeData(pNewTree
,bInDefault
));
217 //-------------------------------------------------------------------------
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())
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())
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())
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
;
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())
295 //-------------------------------------------------------------------------
297 //-----------------------------------------------------------------------------
299 //-----------------------------------------------------------------------------
301 SetEntry::SetEntry(ElementTree
* 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 //-------------------------------------------------------------------------
321 //-------------------------------------------------------------------------
323 SetNodeImpl::SetNodeImpl(sharable::SetNode
* _pNodeRef
,Template
* pTemplate
)
324 : NodeImpl(reinterpret_cast<sharable::Node
*>(_pNodeRef
))
325 ,m_aTemplate(pTemplate
)
326 ,m_aTemplateProvider()
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());
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();
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
);
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());
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();
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
);
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
);
491 OSL_ENSURE( false, "Removed Element doesn't exist - ignoring" );
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() );
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() );
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() );
525 //-------------------------------------------------------------------------
527 void SetNodeImpl::insertElement(rtl::OUString
const& aName
, ElementTreeData
const& aNewElement
)
529 attach(aNewElement
,aName
);
532 m_aDataSet
.insertElement(aName
,aNewElement
);
534 catch (std::exception
&)
540 //-------------------------------------------------------------------------
542 ElementTreeData
SetNodeImpl::replaceElement(rtl::OUString
const& aName
, ElementTreeData
const& aNewElement
)
544 attach(aNewElement
,aName
);
547 ElementTreeData aOldElement
= m_aDataSet
.replaceElement(aName
,aNewElement
);
551 catch (std::exception
&)
557 //-------------------------------------------------------------------------
559 ElementTreeData
SetNodeImpl::removeElement(rtl::OUString
const& aName
)
561 ElementTreeData aOldElement
= m_aDataSet
.removeElement(aName
);
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
;
573 eRet
= aVisitor
.visit( SetEntry(it
->get()) );
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);
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" );
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
));
678 OSL_ENSURE( false, "Unexpected kind of change to set element" );
683 // could be changed to do an insert instead (?)
684 OSL_ENSURE( false, "Changed Element doesn't exist - (and not adding now)" );
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
712 m_aTemplateProvider
= aTemplateProvider
;
715 //-----------------------------------------------------------------------------
717 bool SetNodeImpl::implLoadElements()
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
);
728 OSL_ASSERT(implHasLoadedElements());
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();
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
)
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");
858 //-------------------------------------------------------------------------
862 //-------------------------------------------------------------------------
863 class DiffToDefault
: data::SetVisitor
865 SubtreeChange
& m_rChange
;
866 ISubtree
& m_rDefaultTree
;
867 OTreeChangeFactory
& m_rChangeFactory
;
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
);
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
))
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
);
951 // should never happen
953 if (bDefaultElement
) m_rChange
.removeChange(sName
);
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
,
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
);
991 OSL_ENSURE(false, "Missing context tree in Set");
993 //-----------------------------------------------------------------------------