1 // Copyright 2014 PDFium Authors. All rights reserved.
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
26
XFA_DataMerge_FindFormDOMInstance(CXFA_Document * pDocument,XFA_Element eType,uint32_t dwNameHash,CXFA_Node * pFormParent)27 CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument,
28 XFA_Element eType,
29 uint32_t dwNameHash,
30 CXFA_Node* pFormParent) {
31 CXFA_Node* pFormChild = pFormParent->GetFirstChild();
32 for (; pFormChild; pFormChild = pFormChild->GetNextSibling()) {
33 if (pFormChild->GetElementType() == eType &&
34 pFormChild->GetNameHash() == dwNameHash && pFormChild->IsUnusedNode()) {
35 return pFormChild;
36 }
37 }
38 return nullptr;
39 }
40
XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,bool bRecursive,std::vector<CXFA_Node * > * pSubformArray)41 CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(
42 CXFA_Document* pDocument,
43 CXFA_Node* pFormParent,
44 CXFA_Node* pTemplateNode,
45 bool bRecursive,
46 std::vector<CXFA_Node*>* pSubformArray) {
47 CXFA_Node* pExistingNode = nullptr;
48 if (!pSubformArray) {
49 pExistingNode = XFA_DataMerge_FindFormDOMInstance(
50 pDocument, pTemplateNode->GetElementType(),
51 pTemplateNode->GetNameHash(), pFormParent);
52 } else if (!pSubformArray->empty()) {
53 pExistingNode = pSubformArray->front();
54 pSubformArray->erase(pSubformArray->begin());
55 }
56 if (pExistingNode) {
57 if (pSubformArray) {
58 pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
59 } else if (pExistingNode->IsContainerNode()) {
60 pFormParent->RemoveChildAndNotify(pExistingNode, true);
61 pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
62 }
63 pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
64 pExistingNode->SetTemplateNode(pTemplateNode);
65 if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) {
66 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
67 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
68 if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
69 XFA_NodeMerge_CloneOrMergeContainer(
70 pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr);
71 }
72 }
73 }
74 pExistingNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
75 return pExistingNode;
76 }
77
78 CXFA_Node* pNewNode = pTemplateNode->CloneTemplateToForm(false);
79 pFormParent->InsertChildAndNotify(pNewNode, nullptr);
80 if (bRecursive) {
81 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
82 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
83 if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
84 CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true);
85 pNewNode->InsertChildAndNotify(pNewChild, nullptr);
86 }
87 }
88 }
89 return pNewNode;
90 }
91
XFA_DataMerge_FindDataScope(CXFA_Node * pParentFormNode)92 CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) {
93 if (!pParentFormNode)
94 return nullptr;
95
96 for (CXFA_Node* pRootBoundNode = pParentFormNode;
97 pRootBoundNode && pRootBoundNode->IsContainerNode();
98 pRootBoundNode = pRootBoundNode->GetParent()) {
99 CXFA_Node* pDataScope = pRootBoundNode->GetBindData();
100 if (pDataScope)
101 return pDataScope;
102 }
103 return ToNode(
104 pParentFormNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Data));
105 }
106
107