xref: /aosp_15_r20/external/pdfium/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
8 
9 #include "xfa/fxfa/parser/cxfa_document.h"
10 #include "xfa/fxfa/parser/cxfa_node.h"
11 
XFA_DataMerge_NeedGenerateForm(CXFA_Node * pTemplateChild,bool bUseInstanceManager)12 bool XFA_DataMerge_NeedGenerateForm(CXFA_Node* pTemplateChild,
13                                     bool bUseInstanceManager) {
14   XFA_Element eType = pTemplateChild->GetElementType();
15   if (eType == XFA_Element::Variables)
16     return true;
17   if (pTemplateChild->IsContainerNode())
18     return false;
19   if (eType == XFA_Element::Proto ||
20       (bUseInstanceManager && eType == XFA_Element::Occur)) {
21     return false;
22   }
23   return true;
24 }
25 
XFA_DataMerge_FindFormDOMInstance(CXFA_Document * pDocument,XFA_Element eType,uint32_t dwNameHash,CXFA_Node * pFormParent)26 CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument,
27                                              XFA_Element eType,
28                                              uint32_t dwNameHash,
29                                              CXFA_Node* pFormParent) {
30   CXFA_Node* pFormChild = pFormParent->GetFirstChild();
31   for (; pFormChild; pFormChild = pFormChild->GetNextSibling()) {
32     if (pFormChild->GetElementType() == eType &&
33         pFormChild->GetNameHash() == dwNameHash && pFormChild->IsUnusedNode()) {
34       return pFormChild;
35     }
36   }
37   return nullptr;
38 }
39 
XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,bool bRecursive,std::vector<CXFA_Node * > * pSubformArray)40 CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(
41     CXFA_Document* pDocument,
42     CXFA_Node* pFormParent,
43     CXFA_Node* pTemplateNode,
44     bool bRecursive,
45     std::vector<CXFA_Node*>* pSubformArray) {
46   CXFA_Node* pExistingNode = nullptr;
47   if (!pSubformArray) {
48     pExistingNode = XFA_DataMerge_FindFormDOMInstance(
49         pDocument, pTemplateNode->GetElementType(),
50         pTemplateNode->GetNameHash(), pFormParent);
51   } else if (!pSubformArray->empty()) {
52     pExistingNode = pSubformArray->front();
53     pSubformArray->erase(pSubformArray->begin());
54   }
55   if (pExistingNode) {
56     if (pSubformArray) {
57       pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
58     } else if (pExistingNode->IsContainerNode()) {
59       pFormParent->RemoveChildAndNotify(pExistingNode, true);
60       pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
61     }
62     pExistingNode->ClearFlag(XFA_NodeFlag::kUnusedNode);
63     pExistingNode->SetTemplateNode(pTemplateNode);
64     if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) {
65       for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
66            pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
67         if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
68           XFA_NodeMerge_CloneOrMergeContainer(
69               pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr);
70         }
71       }
72     }
73     pExistingNode->SetInitializedFlagAndNotify();
74     return pExistingNode;
75   }
76 
77   CXFA_Node* pNewNode = pTemplateNode->CloneTemplateToForm(false);
78   pFormParent->InsertChildAndNotify(pNewNode, nullptr);
79   if (bRecursive) {
80     for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
81          pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
82       if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
83         CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true);
84         pNewNode->InsertChildAndNotify(pNewChild, nullptr);
85       }
86     }
87   }
88   return pNewNode;
89 }
90 
XFA_DataMerge_FindDataScope(CXFA_Node * pParentFormNode)91 CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) {
92   if (!pParentFormNode)
93     return nullptr;
94 
95   for (CXFA_Node* pRootBoundNode = pParentFormNode;
96        pRootBoundNode && pRootBoundNode->IsContainerNode();
97        pRootBoundNode = pRootBoundNode->GetParent()) {
98     CXFA_Node* pDataScope = pRootBoundNode->GetBindData();
99     if (pDataScope)
100       return pDataScope;
101   }
102   return ToNode(
103       pParentFormNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Data));
104 }
105