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