1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "elementmark.hxx"
22 #include "elementcollector.hxx"
23 #include "buffernode.hxx"
24 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
25 #include <osl/diagnose.h>
26 #include <rtl/ustrbuf.hxx>
28 namespace cssu
= com::sun::star::uno
;
29 namespace cssxw
= com::sun::star::xml::wrapper
;
30 namespace cssxc
= com::sun::star::xml::crypto
;
32 BufferNode::BufferNode( const cssu::Reference
< cssxw::XXMLElementWrapper
>& xXMLElement
)
35 m_bAllReceived(false),
36 m_xXMLElement(xXMLElement
)
40 bool BufferNode::isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId
) const
41 /****** BufferNode/isECOfBeforeModifyIncluded ********************************
44 * isECOfBeforeModifyIncluded -- checks whether there is some
45 * ElementCollector on this BufferNode, that has BEFORE-MODIFY priority.
48 * bExist = isECOfBeforeModifyIncluded(nIgnoredSecurityId);
51 * checks each ElementCollector on this BufferNode, if all following
52 * conditions are satisfied, then returns true:
53 * 1. the ElementCollector's priority is BEFOREMODIFY;
54 * 2. the ElementCollector's securityId can't be ignored.
55 * otherwise, returns false.
58 * nIgnoredSecurityId - the security Id to be ignored. If it equals
59 * to UNDEFINEDSECURITYID, then no security Id
63 * bExist - true if a match found, false otherwise
64 ******************************************************************************/
66 return std::any_of(m_vElementCollectors
.cbegin(), m_vElementCollectors
.cend(),
67 [nIgnoredSecurityId
](const ElementCollector
* pElementCollector
) {
68 return (nIgnoredSecurityId
== cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
||
69 pElementCollector
->getSecurityId() != nIgnoredSecurityId
) &&
70 (pElementCollector
->getPriority() == cssxc::sax::ElementMarkPriority_BEFOREMODIFY
);
74 void BufferNode::setReceivedAll()
75 /****** BufferNode/setReceiveAll *********************************************
78 * setReceivedAll -- indicates that the element in this BufferNode has
79 * been completely buffered.
85 * sets the all-received flag and launches ElementCollector's notify
93 ******************************************************************************/
95 m_bAllReceived
= true;
96 elementCollectorNotify();
100 void BufferNode::addElementCollector(const ElementCollector
* pElementCollector
)
101 /****** BufferNode/addElementCollector ***************************************
104 * addElementCollector -- adds a new ElementCollector to this BufferNode.
107 * addElementCollector(pElementCollector);
113 * pElementCollector - the ElementCollector to be added
117 ******************************************************************************/
119 m_vElementCollectors
.push_back( pElementCollector
);
120 const_cast<ElementCollector
*>(pElementCollector
)->setBufferNode(this);
123 void BufferNode::removeElementCollector(const ElementCollector
* pElementCollector
)
124 /****** BufferNode/removeElementCollector ************************************
127 * removeElementCollector -- removes an ElementCollector from this
131 * removeElementCollector(pElementCollector);
137 * pElementCollector - the ElementCollector to be removed
141 ******************************************************************************/
143 auto ii
= std::find(m_vElementCollectors
.begin(), m_vElementCollectors
.end(), pElementCollector
);
144 if (ii
!= m_vElementCollectors
.end())
146 m_vElementCollectors
.erase( ii
);
147 const_cast<ElementCollector
*>(pElementCollector
)->setBufferNode(nullptr);
152 void BufferNode::setBlocker(const ElementMark
* pBlocker
)
153 /****** BufferNode/setBlocker ************************************************
156 * setBlocker -- adds a blocker to this BufferNode.
159 * setBlocker(pBlocker);
165 * pBlocker - the new blocker to be attached
171 * Because there is only one blocker permitted for a BufferNode, so the
172 * old blocker on this BufferNode, if there is one, will be overcasted.
173 ******************************************************************************/
175 OSL_ASSERT(!(m_pBlocker
!= nullptr && pBlocker
!= nullptr));
177 m_pBlocker
= const_cast<ElementMark
*>(pBlocker
);
178 if (m_pBlocker
!= nullptr)
180 m_pBlocker
->setBufferNode(this);
184 OUString
BufferNode::printChildren() const
185 /****** BufferNode/printChildren *********************************************
188 * printChildren -- prints children information into a string.
191 * result = printChildren();
200 * result - the information string
201 ******************************************************************************/
205 for( const ElementCollector
* ii
: m_vElementCollectors
)
207 rc
.append("BufID=").append(OUString::number(ii
->getBufferId()));
216 switch (ii
->getPriority())
218 case cssxc::sax::ElementMarkPriority_BEFOREMODIFY
:
219 rc
.append("BEFOREMODIFY");
221 case cssxc::sax::ElementMarkPriority_AFTERMODIFY
:
222 rc
.append("AFTERMODIFY");
225 rc
.append("UNKNOWN");
229 rc
.append("(SecID=").append(OUString::number(ii
->getSecurityId())).append(") ");
232 return rc
.makeStringAndClear();
235 bool BufferNode::hasAnything() const
236 /****** BufferNode/hasAnything ***********************************************
239 * hasAnything -- checks whether there is any ElementCollector or blocker
240 * on this BufferNode.
243 * bExist = hasAnything();
252 * bExist - true if there is, false otherwise.
253 ******************************************************************************/
255 return (m_pBlocker
|| !m_vElementCollectors
.empty());
258 bool BufferNode::hasChildren() const
259 /****** BufferNode/hasChildren ***********************************************
262 * hasChildren -- checks whether this BufferNode has any child
266 * bExist = hasChildren();
275 * bExist - true if there is, false otherwise.
276 ******************************************************************************/
278 return (!m_vChildren
.empty());
281 std::vector
< std::unique_ptr
<BufferNode
> > const & BufferNode::getChildren() const
286 std::vector
< std::unique_ptr
<BufferNode
> > BufferNode::releaseChildren()
288 return std::move(m_vChildren
);
291 const BufferNode
* BufferNode::getFirstChild() const
292 /****** BufferNode/getFirstChild *********************************************
295 * getFirstChild -- retrieves the first child BufferNode.
298 * child = getFirstChild();
307 * child - the first child BufferNode, or NULL if there is no child
309 ******************************************************************************/
311 BufferNode
* rc
= nullptr;
313 if (!m_vChildren
.empty())
315 rc
= m_vChildren
.front().get();
321 void BufferNode::addChild(std::unique_ptr
<BufferNode
> pChild
, sal_Int32 nPosition
)
322 /****** BufferNode/addChild(pChild,nPosition) ********************************
325 * addChild -- inserts a child BufferNode at specific position.
328 * addChild(pChild, nPosition);
334 * pChild - the child BufferNode to be added.
335 * nPosition - the position where the new child locates.
341 * If the nPosition is -1, then the new child BufferNode is appended
343 ******************************************************************************/
347 m_vChildren
.push_back( std::move(pChild
) );
351 m_vChildren
.insert(m_vChildren
.begin() + nPosition
, std::move(pChild
));
355 void BufferNode::addChild(std::unique_ptr
<BufferNode
> pChild
)
356 /****** BufferNode/addChild() ************************************************
359 * addChild -- add a new child BufferNode.
368 * pChild - the child BufferNode to be added.
374 * The new child BufferNode is appended at the end.
375 ******************************************************************************/
377 addChild(std::move(pChild
), -1);
380 void BufferNode::removeChild(const BufferNode
* pChild
)
381 /****** BufferNode/removeChild ***********************************************
384 * removeChild -- removes and deletes a child BufferNode from the children list.
387 * removeChild(pChild);
393 * pChild - the child BufferNode to be removed
397 ******************************************************************************/
399 auto ii
= std::find_if(m_vChildren
.begin(), m_vChildren
.end(),
400 [pChild
] (const std::unique_ptr
<BufferNode
>& i
)
401 { return i
.get() == pChild
; });
402 if (ii
!= m_vChildren
.end())
403 m_vChildren
.erase( ii
);
406 sal_Int32
BufferNode::indexOfChild(const BufferNode
* pChild
) const
407 /****** BufferNode/indexOfChild **********************************************
410 * indexOfChild -- gets the index of a child BufferNode.
413 * index = indexOfChild(pChild);
419 * pChild - the child BufferNode whose index to be gotten
422 * index - the index of that child BufferNode. If that child BufferNode
423 * is not found, -1 is returned.
424 ******************************************************************************/
426 auto ii
= std::find_if(m_vChildren
.begin(), m_vChildren
.end(),
427 [pChild
] (const std::unique_ptr
<BufferNode
>& i
)
428 { return i
.get() == pChild
; });
429 if (ii
== m_vChildren
.end())
432 return std::distance(m_vChildren
.begin(), ii
);
436 void BufferNode::setParent(const BufferNode
* pParent
)
438 m_pParent
= const_cast<BufferNode
*>(pParent
);
441 const BufferNode
* BufferNode::getNextSibling() const
442 /****** BufferNode/getNextSibling ********************************************
445 * getNextSibling -- retrieves the next sibling BufferNode.
448 * sibling = getNextSibling();
457 * sibling - the next sibling BufferNode, or NULL if there is none.
458 ******************************************************************************/
460 BufferNode
* rc
= nullptr;
462 if (m_pParent
!= nullptr)
464 rc
= const_cast<BufferNode
*>(m_pParent
->getNextChild(this));
470 const BufferNode
* BufferNode::isAncestor(const BufferNode
* pDescendant
) const
471 /****** BufferNode/isAncestor ************************************************
474 * isAncestor -- checks whether this BufferNode is an ancestor of another
478 * bIs = isAncestor(pDescendant);
484 * pDescendant - the BufferNode to be checked as a descendant
487 * bIs - true if this BufferNode is an ancestor of the pDescendant,
489 ******************************************************************************/
491 BufferNode
* rc
= nullptr;
493 if (pDescendant
!= nullptr)
495 auto ii
= std::find_if(m_vChildren
.cbegin(), m_vChildren
.cend(),
496 [&pDescendant
](const std::unique_ptr
<BufferNode
>& pChild
) {
497 return (pChild
.get() == pDescendant
) || (pChild
->isAncestor(pDescendant
) != nullptr);
500 if (ii
!= m_vChildren
.end())
507 bool BufferNode::isPrevious(const BufferNode
* pFollowing
) const
508 /****** BufferNode/isPrevious ************************************************
511 * isPrevious -- checks whether this BufferNode is ahead of another
512 * BufferNode in the tree order.
515 * bIs = isPrevious(pFollowing);
521 * pFollowing - the BufferNode to be checked as a following
524 * bIs - true if this BufferNode is ahead in the tree order, false
526 ******************************************************************************/
530 BufferNode
* pNextBufferNode
= const_cast<BufferNode
*>(getNextNodeByTreeOrder());
531 while (pNextBufferNode
!= nullptr)
533 if (pNextBufferNode
== pFollowing
)
539 pNextBufferNode
= const_cast<BufferNode
*>(pNextBufferNode
->getNextNodeByTreeOrder());
545 const BufferNode
* BufferNode::getNextNodeByTreeOrder() const
546 /****** BufferNode/getNextNodeByTreeOrder ************************************
549 * getNextNodeByTreeOrder -- retrieves the next BufferNode in the tree
553 * next = getNextNodeByTreeOrder();
562 * next - the BufferNode following this BufferNode in the tree order,
563 * or NULL if there is none.
566 * The "next" node in tree order is defined as:
567 * 1. If a node has children, then the first child is;
568 * 2. otherwise, if it has a following sibling, then this sibling node is;
569 * 3. otherwise, if it has a parent node, the parent's next sibling
571 * 4. otherwise, no "next" node exists.
572 ******************************************************************************/
575 * If this buffer node has m_vChildren, then return the first
580 return getFirstChild();
584 * Otherwise, it this buffer node has a following sibling,
585 * then return that sibling.
587 BufferNode
* pNextSibling
= const_cast<BufferNode
*>(getNextSibling());
588 if (pNextSibling
!= nullptr)
594 * Otherwise, it this buffer node has parent, then return
595 * its parent's following sibling.
597 BufferNode
* pNode
= const_cast<BufferNode
*>(this);
599 BufferNode
* pNextSiblingParent
= nullptr;
603 if (pNode
== nullptr)
608 pParent
= const_cast<BufferNode
*>(pNode
->getParent());
609 if (pParent
!= nullptr)
611 pNextSiblingParent
= const_cast<BufferNode
*>(pParent
->getNextSibling());
615 } while (pNextSiblingParent
== nullptr);
617 return pNextSiblingParent
;
621 void BufferNode::setXMLElement( const cssu::Reference
< cssxw::XXMLElementWrapper
>& xXMLElement
)
623 m_xXMLElement
= xXMLElement
;
626 void BufferNode::notifyBranch()
627 /****** BufferNode/notifyBranch **********************************************
630 * notifyBranch -- notifies each BufferNode in the branch of this
631 * BufferNode in the tree order.
644 ******************************************************************************/
646 for( std::unique_ptr
<BufferNode
>& pBufferNode
: m_vChildren
)
648 pBufferNode
->elementCollectorNotify();
649 pBufferNode
->notifyBranch();
653 void BufferNode::elementCollectorNotify()
654 /****** BufferNode/elementCollectorNotify ************************************
657 * elementCollectorNotify -- notifies this BufferNode.
660 * elementCollectorNotify();
663 * Notifies this BufferNode if the notification is not suppressed.
669 * child - the first child BufferNode, or NULL if there is no child
671 ******************************************************************************/
673 if (!m_vElementCollectors
.empty())
675 cssxc::sax::ElementMarkPriority nMaxPriority
= cssxc::sax::ElementMarkPriority_MINIMUM
;
676 cssxc::sax::ElementMarkPriority nPriority
;
679 * get the max priority among ElementCollectors on this BufferNode
681 for( const ElementCollector
* pElementCollector
: m_vElementCollectors
)
683 nPriority
= pElementCollector
->getPriority();
684 if (nPriority
> nMaxPriority
)
686 nMaxPriority
= nPriority
;
690 std::vector
< const ElementCollector
* > vElementCollectors( m_vElementCollectors
);
692 for( const ElementCollector
* ii
: vElementCollectors
)
694 ElementCollector
* pElementCollector
= const_cast<ElementCollector
*>(ii
);
695 nPriority
= pElementCollector
->getPriority();
696 bool bToModify
= pElementCollector
->getModify();
699 * Only ElementCollector with the max priority can
700 * perform notify operation.
701 * Moreover, if any blocker exists in the subtree of
702 * this BufferNode, this ElementCollector can't do notify
703 * unless its priority is BEFOREMODIFY.
705 if (nPriority
== nMaxPriority
&&
706 (nPriority
== cssxc::sax::ElementMarkPriority_BEFOREMODIFY
||
707 !isBlockerInSubTreeIncluded(pElementCollector
->getSecurityId())))
710 * If this ElementCollector will modify the buffered element, then
711 * special attention must be paid.
713 * If there is any ElementCollector in the subtree or any ancestor
714 * ElementCollector with PRI_BEFPREMODIFY priority, this
715 * ElementCollector can't perform notify operation, otherwise, it
716 * will destroy the buffered element, in turn, ElementCollectors
717 * mentioned above can't perform their mission.
719 //if (!(nMaxPriority == cssxc::sax::ElementMarkPriority_PRI_MODIFY &&
721 (isECInSubTreeIncluded(pElementCollector
->getSecurityId()) ||
722 isECOfBeforeModifyInAncestorIncluded(pElementCollector
->getSecurityId()))
725 pElementCollector
->notifyListener();
732 bool BufferNode::isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId
) const
733 /****** BufferNode/isECInSubTreeIncluded *************************************
736 * isECInSubTreeIncluded -- checks whether there is any ElementCollector
737 * in the branch of this BufferNode.
740 * bExist = isECInSubTreeIncluded(nIgnoredSecurityId);
743 * checks each BufferNode in the branch of this BufferNode, if there is
744 * an ElementCollector whose signatureId is not ignored, then return
745 * true, otherwise, false returned.
748 * nIgnoredSecurityId - the security Id to be ignored. If it equals
749 * to UNDEFINEDSECURITYID, then no security Id
753 * bExist - true if a match found, false otherwise.
754 ******************************************************************************/
756 bool rc
= std::any_of(m_vElementCollectors
.begin(), m_vElementCollectors
.end(),
757 [nIgnoredSecurityId
](const ElementCollector
* pElementCollector
) {
758 return nIgnoredSecurityId
== cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
||
759 pElementCollector
->getSecurityId() != nIgnoredSecurityId
;
764 rc
= std::any_of(m_vChildren
.begin(), m_vChildren
.end(),
765 [nIgnoredSecurityId
](const std::unique_ptr
<BufferNode
>& pBufferNode
) {
766 return pBufferNode
->isECInSubTreeIncluded(nIgnoredSecurityId
);
773 bool BufferNode::isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId
) const
774 /****** BufferNode/isECOfBeforeModifyInAncestorIncluded **********************
777 * isECOfBeforeModifyInAncestorIncluded -- checks whether there is some
778 * ancestor BufferNode which has ElementCollector with PRI_BEFPREMODIFY
782 * bExist = isECOfBeforeModifyInAncestorIncluded(nIgnoredSecurityId);
785 * checks each ancestor BufferNode through the parent link, if there is
786 * an ElementCollector with PRI_BEFPREMODIFY priority and its
787 * signatureId is not ignored, then return true, otherwise, false
791 * nIgnoredSecurityId - the security Id to be ignored. If it equals
792 * to UNDEFINEDSECURITYID, then no security Id
796 * bExist - true if a match found, false otherwise.
797 ******************************************************************************/
801 BufferNode
* pParentNode
= m_pParent
;
802 while (pParentNode
!= nullptr)
804 if (pParentNode
->isECOfBeforeModifyIncluded(nIgnoredSecurityId
))
810 pParentNode
= const_cast<BufferNode
*>(pParentNode
->getParent());
816 bool BufferNode::isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId
) const
817 /****** BufferNode/isBlockerInSubTreeIncluded ********************************
820 * isBlockerInSubTreeIncluded -- checks whether there is some BufferNode
821 * which has blocker on it
824 * bExist = isBlockerInSubTreeIncluded(nIgnoredSecurityId);
827 * checks each BufferNode in the branch of this BufferNode, if one has
828 * a blocker on it, and the blocker's securityId is not ignored, then
829 * returns true; otherwise, false returns.
832 * nIgnoredSecurityId - the security Id to be ignored. If it equals
833 * to UNDEFINEDSECURITYID, then no security Id
837 * bExist - true if a match found, false otherwise.
838 ******************************************************************************/
840 return std::any_of(m_vChildren
.begin(), m_vChildren
.end(),
841 [nIgnoredSecurityId
](const std::unique_ptr
<BufferNode
>& pBufferNode
) {
842 ElementMark
* pBlocker
= pBufferNode
->getBlocker();
843 return (pBlocker
!= nullptr &&
844 (nIgnoredSecurityId
== cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
||
845 pBlocker
->getSecurityId() != nIgnoredSecurityId
)) ||
846 pBufferNode
->isBlockerInSubTreeIncluded(nIgnoredSecurityId
);
850 const BufferNode
* BufferNode::getNextChild(const BufferNode
* pChild
) const
851 /****** BufferNode/getNextChild **********************************************
854 * getNextChild -- get the next child BufferNode.
857 * nextChild = getNextChild();
863 * pChild - the child BufferNode whose next node is retrieved.
866 * nextChild - the next child BufferNode after the pChild, or NULL if
868 ******************************************************************************/
870 BufferNode
* rc
= nullptr;
871 bool bChildFound
= false;
873 for( std::unique_ptr
<BufferNode
> const & i
: m_vChildren
)
881 if( i
.get() == pChild
)
890 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */