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>
29 BufferNode::BufferNode( css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> xXMLElement
)
32 m_bAllReceived(false),
33 m_xXMLElement(std::move(xXMLElement
))
37 bool BufferNode::isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId
) const
38 /****** BufferNode/isECOfBeforeModifyIncluded ********************************
41 * isECOfBeforeModifyIncluded -- checks whether there is some
42 * ElementCollector on this BufferNode, that has BEFORE-MODIFY priority.
45 * bExist = isECOfBeforeModifyIncluded(nIgnoredSecurityId);
48 * checks each ElementCollector on this BufferNode, if all following
49 * conditions are satisfied, then returns true:
50 * 1. the ElementCollector's priority is BEFOREMODIFY;
51 * 2. the ElementCollector's securityId can't be ignored.
52 * otherwise, returns false.
55 * nIgnoredSecurityId - the security Id to be ignored. If it equals
56 * to UNDEFINEDSECURITYID, then no security Id
60 * bExist - true if a match found, false otherwise
61 ******************************************************************************/
63 return std::any_of(m_vElementCollectors
.cbegin(), m_vElementCollectors
.cend(),
64 [nIgnoredSecurityId
](const ElementCollector
* pElementCollector
) {
65 return (nIgnoredSecurityId
== css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
||
66 pElementCollector
->getSecurityId() != nIgnoredSecurityId
) &&
67 (pElementCollector
->getPriority() == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY
);
71 void BufferNode::setReceivedAll()
72 /****** BufferNode/setReceiveAll *********************************************
75 * setReceivedAll -- indicates that the element in this BufferNode has
76 * been completely buffered.
82 * sets the all-received flag and launches ElementCollector's notify
90 ******************************************************************************/
92 m_bAllReceived
= true;
93 elementCollectorNotify();
97 void BufferNode::addElementCollector(const ElementCollector
* pElementCollector
)
98 /****** BufferNode/addElementCollector ***************************************
101 * addElementCollector -- adds a new ElementCollector to this BufferNode.
104 * addElementCollector(pElementCollector);
110 * pElementCollector - the ElementCollector to be added
114 ******************************************************************************/
116 m_vElementCollectors
.push_back( pElementCollector
);
117 const_cast<ElementCollector
*>(pElementCollector
)->setBufferNode(this);
120 void BufferNode::removeElementCollector(const ElementCollector
* pElementCollector
)
121 /****** BufferNode/removeElementCollector ************************************
124 * removeElementCollector -- removes an ElementCollector from this
128 * removeElementCollector(pElementCollector);
134 * pElementCollector - the ElementCollector to be removed
138 ******************************************************************************/
140 auto ii
= std::find(m_vElementCollectors
.begin(), m_vElementCollectors
.end(), pElementCollector
);
141 if (ii
!= m_vElementCollectors
.end())
143 m_vElementCollectors
.erase( ii
);
144 const_cast<ElementCollector
*>(pElementCollector
)->setBufferNode(nullptr);
149 void BufferNode::setBlocker(const ElementMark
* pBlocker
)
150 /****** BufferNode/setBlocker ************************************************
153 * setBlocker -- adds a blocker to this BufferNode.
156 * setBlocker(pBlocker);
162 * pBlocker - the new blocker to be attached
168 * Because there is only one blocker permitted for a BufferNode, so the
169 * old blocker on this BufferNode, if there is one, will be overcasted.
170 ******************************************************************************/
172 OSL_ASSERT(!(m_pBlocker
!= nullptr && pBlocker
!= nullptr));
174 m_pBlocker
= const_cast<ElementMark
*>(pBlocker
);
175 if (m_pBlocker
!= nullptr)
177 m_pBlocker
->setBufferNode(this);
181 OUString
BufferNode::printChildren() const
182 /****** BufferNode/printChildren *********************************************
185 * printChildren -- prints children information into a string.
188 * result = printChildren();
197 * result - the information string
198 ******************************************************************************/
202 for( const ElementCollector
* ii
: m_vElementCollectors
)
204 rc
.append("BufID=" + OUString::number(ii
->getBufferId()));
213 switch (ii
->getPriority())
215 case css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY
:
216 rc
.append("BEFOREMODIFY");
218 case css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY
:
219 rc
.append("AFTERMODIFY");
222 rc
.append("UNKNOWN");
226 rc
.append("(SecID=" + OUString::number(ii
->getSecurityId()) + ") ");
229 return rc
.makeStringAndClear();
232 bool BufferNode::hasAnything() const
233 /****** BufferNode/hasAnything ***********************************************
236 * hasAnything -- checks whether there is any ElementCollector or blocker
237 * on this BufferNode.
240 * bExist = hasAnything();
249 * bExist - true if there is, false otherwise.
250 ******************************************************************************/
252 return (m_pBlocker
|| !m_vElementCollectors
.empty());
255 bool BufferNode::hasChildren() const
256 /****** BufferNode/hasChildren ***********************************************
259 * hasChildren -- checks whether this BufferNode has any child
263 * bExist = hasChildren();
272 * bExist - true if there is, false otherwise.
273 ******************************************************************************/
275 return (!m_vChildren
.empty());
278 std::vector
< std::unique_ptr
<BufferNode
> > const & BufferNode::getChildren() const
283 std::vector
< std::unique_ptr
<BufferNode
> > BufferNode::releaseChildren()
285 return std::move(m_vChildren
);
288 const BufferNode
* BufferNode::getFirstChild() const
289 /****** BufferNode/getFirstChild *********************************************
292 * getFirstChild -- retrieves the first child BufferNode.
295 * child = getFirstChild();
304 * child - the first child BufferNode, or NULL if there is no child
306 ******************************************************************************/
308 BufferNode
* rc
= nullptr;
310 if (!m_vChildren
.empty())
312 rc
= m_vChildren
.front().get();
318 void BufferNode::addChild(std::unique_ptr
<BufferNode
> pChild
, sal_Int32 nPosition
)
319 /****** BufferNode/addChild(pChild,nPosition) ********************************
322 * addChild -- inserts a child BufferNode at specific position.
325 * addChild(pChild, nPosition);
331 * pChild - the child BufferNode to be added.
332 * nPosition - the position where the new child locates.
338 * If the nPosition is -1, then the new child BufferNode is appended
340 ******************************************************************************/
344 m_vChildren
.push_back( std::move(pChild
) );
348 m_vChildren
.insert(m_vChildren
.begin() + nPosition
, std::move(pChild
));
352 void BufferNode::addChild(std::unique_ptr
<BufferNode
> pChild
)
353 /****** BufferNode/addChild() ************************************************
356 * addChild -- add a new child BufferNode.
365 * pChild - the child BufferNode to be added.
371 * The new child BufferNode is appended at the end.
372 ******************************************************************************/
374 addChild(std::move(pChild
), -1);
377 void BufferNode::removeChild(const BufferNode
* pChild
)
378 /****** BufferNode/removeChild ***********************************************
381 * removeChild -- removes and deletes a child BufferNode from the children list.
384 * removeChild(pChild);
390 * pChild - the child BufferNode to be removed
394 ******************************************************************************/
396 auto ii
= std::find_if(m_vChildren
.begin(), m_vChildren
.end(),
397 [pChild
] (const std::unique_ptr
<BufferNode
>& i
)
398 { return i
.get() == pChild
; });
399 if (ii
!= m_vChildren
.end())
400 m_vChildren
.erase( ii
);
403 sal_Int32
BufferNode::indexOfChild(const BufferNode
* pChild
) const
404 /****** BufferNode/indexOfChild **********************************************
407 * indexOfChild -- gets the index of a child BufferNode.
410 * index = indexOfChild(pChild);
416 * pChild - the child BufferNode whose index to be gotten
419 * index - the index of that child BufferNode. If that child BufferNode
420 * is not found, -1 is returned.
421 ******************************************************************************/
423 auto ii
= std::find_if(m_vChildren
.begin(), m_vChildren
.end(),
424 [pChild
] (const std::unique_ptr
<BufferNode
>& i
)
425 { return i
.get() == pChild
; });
426 if (ii
== m_vChildren
.end())
429 return std::distance(m_vChildren
.begin(), ii
);
433 void BufferNode::setParent(const BufferNode
* pParent
)
435 m_pParent
= const_cast<BufferNode
*>(pParent
);
438 const BufferNode
* BufferNode::getNextSibling() const
439 /****** BufferNode/getNextSibling ********************************************
442 * getNextSibling -- retrieves the next sibling BufferNode.
445 * sibling = getNextSibling();
454 * sibling - the next sibling BufferNode, or NULL if there is none.
455 ******************************************************************************/
457 BufferNode
* rc
= nullptr;
459 if (m_pParent
!= nullptr)
461 rc
= const_cast<BufferNode
*>(m_pParent
->getNextChild(this));
467 const BufferNode
* BufferNode::isAncestor(const BufferNode
* pDescendant
) const
468 /****** BufferNode/isAncestor ************************************************
471 * isAncestor -- checks whether this BufferNode is an ancestor of another
475 * bIs = isAncestor(pDescendant);
481 * pDescendant - the BufferNode to be checked as a descendant
484 * bIs - true if this BufferNode is an ancestor of the pDescendant,
486 ******************************************************************************/
488 BufferNode
* rc
= nullptr;
490 if (pDescendant
!= nullptr)
492 auto ii
= std::find_if(m_vChildren
.cbegin(), m_vChildren
.cend(),
493 [&pDescendant
](const std::unique_ptr
<BufferNode
>& pChild
) {
494 return (pChild
.get() == pDescendant
) || (pChild
->isAncestor(pDescendant
) != nullptr);
497 if (ii
!= m_vChildren
.end())
504 bool BufferNode::isPrevious(const BufferNode
* pFollowing
) const
505 /****** BufferNode/isPrevious ************************************************
508 * isPrevious -- checks whether this BufferNode is ahead of another
509 * BufferNode in the tree order.
512 * bIs = isPrevious(pFollowing);
518 * pFollowing - the BufferNode to be checked as a following
521 * bIs - true if this BufferNode is ahead in the tree order, false
523 ******************************************************************************/
527 BufferNode
* pNextBufferNode
= const_cast<BufferNode
*>(getNextNodeByTreeOrder());
528 while (pNextBufferNode
!= nullptr)
530 if (pNextBufferNode
== pFollowing
)
536 pNextBufferNode
= const_cast<BufferNode
*>(pNextBufferNode
->getNextNodeByTreeOrder());
542 const BufferNode
* BufferNode::getNextNodeByTreeOrder() const
543 /****** BufferNode/getNextNodeByTreeOrder ************************************
546 * getNextNodeByTreeOrder -- retrieves the next BufferNode in the tree
550 * next = getNextNodeByTreeOrder();
559 * next - the BufferNode following this BufferNode in the tree order,
560 * or NULL if there is none.
563 * The "next" node in tree order is defined as:
564 * 1. If a node has children, then the first child is;
565 * 2. otherwise, if it has a following sibling, then this sibling node is;
566 * 3. otherwise, if it has a parent node, the parent's next sibling
568 * 4. otherwise, no "next" node exists.
569 ******************************************************************************/
572 * If this buffer node has m_vChildren, then return the first
577 return getFirstChild();
581 * Otherwise, it this buffer node has a following sibling,
582 * then return that sibling.
584 BufferNode
* pNextSibling
= const_cast<BufferNode
*>(getNextSibling());
585 if (pNextSibling
!= nullptr)
591 * Otherwise, it this buffer node has parent, then return
592 * its parent's following sibling.
594 BufferNode
* pNode
= const_cast<BufferNode
*>(this);
596 BufferNode
* pNextSiblingParent
= nullptr;
600 if (pNode
== nullptr)
605 pParent
= const_cast<BufferNode
*>(pNode
->getParent());
606 if (pParent
!= nullptr)
608 pNextSiblingParent
= const_cast<BufferNode
*>(pParent
->getNextSibling());
612 } while (pNextSiblingParent
== nullptr);
614 return pNextSiblingParent
;
618 void BufferNode::setXMLElement( const css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
>& xXMLElement
)
620 m_xXMLElement
= xXMLElement
;
623 void BufferNode::notifyBranch()
624 /****** BufferNode/notifyBranch **********************************************
627 * notifyBranch -- notifies each BufferNode in the branch of this
628 * BufferNode in the tree order.
641 ******************************************************************************/
643 for( std::unique_ptr
<BufferNode
>& pBufferNode
: m_vChildren
)
645 pBufferNode
->elementCollectorNotify();
646 pBufferNode
->notifyBranch();
650 void BufferNode::elementCollectorNotify()
651 /****** BufferNode/elementCollectorNotify ************************************
654 * elementCollectorNotify -- notifies this BufferNode.
657 * elementCollectorNotify();
660 * Notifies this BufferNode if the notification is not suppressed.
666 * child - the first child BufferNode, or NULL if there is no child
668 ******************************************************************************/
670 if (m_vElementCollectors
.empty())
673 css::xml::crypto::sax::ElementMarkPriority nMaxPriority
= css::xml::crypto::sax::ElementMarkPriority_MINIMUM
;
674 css::xml::crypto::sax::ElementMarkPriority nPriority
;
677 * get the max priority among ElementCollectors on this BufferNode
679 for( const ElementCollector
* pElementCollector
: m_vElementCollectors
)
681 nPriority
= pElementCollector
->getPriority();
682 if (nPriority
> nMaxPriority
)
684 nMaxPriority
= nPriority
;
688 std::vector
< const ElementCollector
* > vElementCollectors( m_vElementCollectors
);
690 for( const ElementCollector
* ii
: vElementCollectors
)
692 ElementCollector
* pElementCollector
= const_cast<ElementCollector
*>(ii
);
693 nPriority
= pElementCollector
->getPriority();
694 bool bToModify
= pElementCollector
->getModify();
697 * Only ElementCollector with the max priority can
698 * perform notify operation.
699 * Moreover, if any blocker exists in the subtree of
700 * this BufferNode, this ElementCollector can't do notify
701 * unless its priority is BEFOREMODIFY.
703 if (nPriority
== nMaxPriority
&&
704 (nPriority
== css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY
||
705 !isBlockerInSubTreeIncluded(pElementCollector
->getSecurityId())))
708 * If this ElementCollector will modify the buffered element, then
709 * special attention must be paid.
711 * If there is any ElementCollector in the subtree or any ancestor
712 * ElementCollector with PRI_BEFPREMODIFY priority, this
713 * ElementCollector can't perform notify operation, otherwise, it
714 * will destroy the buffered element, in turn, ElementCollectors
715 * mentioned above can't perform their mission.
717 //if (!(nMaxPriority == css::xml::crypto::sax::ElementMarkPriority_PRI_MODIFY &&
719 (isECInSubTreeIncluded(pElementCollector
->getSecurityId()) ||
720 isECOfBeforeModifyInAncestorIncluded(pElementCollector
->getSecurityId()))
723 pElementCollector
->notifyListener();
729 bool BufferNode::isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId
) const
730 /****** BufferNode/isECInSubTreeIncluded *************************************
733 * isECInSubTreeIncluded -- checks whether there is any ElementCollector
734 * in the branch of this BufferNode.
737 * bExist = isECInSubTreeIncluded(nIgnoredSecurityId);
740 * checks each BufferNode in the branch of this BufferNode, if there is
741 * an ElementCollector whose signatureId is not ignored, then return
742 * true, otherwise, false returned.
745 * nIgnoredSecurityId - the security Id to be ignored. If it equals
746 * to UNDEFINEDSECURITYID, then no security Id
750 * bExist - true if a match found, false otherwise.
751 ******************************************************************************/
753 bool rc
= std::any_of(m_vElementCollectors
.begin(), m_vElementCollectors
.end(),
754 [nIgnoredSecurityId
](const ElementCollector
* pElementCollector
) {
755 return nIgnoredSecurityId
== css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
||
756 pElementCollector
->getSecurityId() != nIgnoredSecurityId
;
761 rc
= std::any_of(m_vChildren
.begin(), m_vChildren
.end(),
762 [nIgnoredSecurityId
](const std::unique_ptr
<BufferNode
>& pBufferNode
) {
763 return pBufferNode
->isECInSubTreeIncluded(nIgnoredSecurityId
);
770 bool BufferNode::isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId
) const
771 /****** BufferNode/isECOfBeforeModifyInAncestorIncluded **********************
774 * isECOfBeforeModifyInAncestorIncluded -- checks whether there is some
775 * ancestor BufferNode which has ElementCollector with PRI_BEFPREMODIFY
779 * bExist = isECOfBeforeModifyInAncestorIncluded(nIgnoredSecurityId);
782 * checks each ancestor BufferNode through the parent link, if there is
783 * an ElementCollector with PRI_BEFPREMODIFY priority and its
784 * signatureId is not ignored, then return true, otherwise, false
788 * nIgnoredSecurityId - the security Id to be ignored. If it equals
789 * to UNDEFINEDSECURITYID, then no security Id
793 * bExist - true if a match found, false otherwise.
794 ******************************************************************************/
798 BufferNode
* pParentNode
= m_pParent
;
799 while (pParentNode
!= nullptr)
801 if (pParentNode
->isECOfBeforeModifyIncluded(nIgnoredSecurityId
))
807 pParentNode
= const_cast<BufferNode
*>(pParentNode
->getParent());
813 bool BufferNode::isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId
) const
814 /****** BufferNode/isBlockerInSubTreeIncluded ********************************
817 * isBlockerInSubTreeIncluded -- checks whether there is some BufferNode
818 * which has blocker on it
821 * bExist = isBlockerInSubTreeIncluded(nIgnoredSecurityId);
824 * checks each BufferNode in the branch of this BufferNode, if one has
825 * a blocker on it, and the blocker's securityId is not ignored, then
826 * returns true; otherwise, false returns.
829 * nIgnoredSecurityId - the security Id to be ignored. If it equals
830 * to UNDEFINEDSECURITYID, then no security Id
834 * bExist - true if a match found, false otherwise.
835 ******************************************************************************/
837 return std::any_of(m_vChildren
.begin(), m_vChildren
.end(),
838 [nIgnoredSecurityId
](const std::unique_ptr
<BufferNode
>& pBufferNode
) {
839 ElementMark
* pBlocker
= pBufferNode
->getBlocker();
840 return (pBlocker
!= nullptr &&
841 (nIgnoredSecurityId
== css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
||
842 pBlocker
->getSecurityId() != nIgnoredSecurityId
)) ||
843 pBufferNode
->isBlockerInSubTreeIncluded(nIgnoredSecurityId
);
847 const BufferNode
* BufferNode::getNextChild(const BufferNode
* pChild
) const
848 /****** BufferNode/getNextChild **********************************************
851 * getNextChild -- get the next child BufferNode.
854 * nextChild = getNextChild();
860 * pChild - the child BufferNode whose next node is retrieved.
863 * nextChild - the next child BufferNode after the pChild, or NULL if
865 ******************************************************************************/
867 BufferNode
* rc
= nullptr;
868 bool bChildFound
= false;
870 for( std::unique_ptr
<BufferNode
> const & i
: m_vChildren
)
878 if( i
.get() == pChild
)
887 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */