diff options
Diffstat (limited to 'xfa/fxfa/parser/xfa_document_datamerger_imp.cpp')
-rw-r--r-- | xfa/fxfa/parser/xfa_document_datamerger_imp.cpp | 1454 |
1 files changed, 4 insertions, 1450 deletions
diff --git a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp index ac14731bb1..c63a8e24e4 100644 --- a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp +++ b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp @@ -6,493 +6,10 @@ #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h" -#include <map> -#include <utility> -#include <vector> - -#include "core/fxcrt/fx_extension.h" -#include "core/fxcrt/fx_fallthrough.h" -#include "core/fxcrt/xml/cfx_xmlelement.h" -#include "core/fxcrt/xml/cfx_xmlnode.h" -#include "fxjs/cfxjse_engine.h" -#include "fxjs/xfa/cjx_object.h" -#include "third_party/base/logging.h" -#include "third_party/base/stl_util.h" -#include "xfa/fxfa/parser/cxfa_bind.h" -#include "xfa/fxfa/parser/cxfa_datagroup.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_exdata.h" -#include "xfa/fxfa/parser/cxfa_form.h" -#include "xfa/fxfa/parser/cxfa_image.h" -#include "xfa/fxfa/parser/cxfa_items.h" -#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_localemgr.h" #include "xfa/fxfa/parser/cxfa_node.h" -#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" -#include "xfa/fxfa/parser/cxfa_occur.h" -#include "xfa/fxfa/parser/cxfa_pageset.h" -#include "xfa/fxfa/parser/cxfa_subform.h" -#include "xfa/fxfa/parser/cxfa_template.h" -#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h" -#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h" -#include "xfa/fxfa/parser/cxfa_value.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -namespace { - -class CXFA_TraverseStrategy_DDGroup { - public: - static CXFA_Node* GetFirstChild(CXFA_Node* pDDGroupNode) { - return pDDGroupNode->GetFirstChildByName(XFA_HASHCODE_Group); - } - static CXFA_Node* GetNextSibling(CXFA_Node* pDDGroupNode) { - return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group); - } - static CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) { - return pDDGroupNode->GetParent(); - } -}; - -struct RecurseRecord { - CXFA_Node* pTemplateChild; - CXFA_Node* pDataChild; -}; - -CXFA_Node* FormValueNode_CreateChild(CXFA_Node* pValueNode, XFA_Element iType) { - CXFA_Node* pChildNode = pValueNode->GetFirstChild(); - if (!pChildNode) { - if (iType == XFA_Element::Unknown) - return nullptr; - - pChildNode = - pValueNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, iType); - } - return pChildNode; -} - -void FormValueNode_MatchNoneCreateChild(CXFA_Node* pFormNode) { - ASSERT(pFormNode->IsWidgetReady()); - // GetUIChildNode has the side effect of creating the UI child. - pFormNode->GetUIChildNode(); -} - -bool FormValueNode_SetChildContent(CXFA_Node* pValueNode, - const WideString& wsContent, - XFA_Element iType = XFA_Element::Unknown) { - if (!pValueNode) - return false; - - ASSERT(pValueNode->GetPacketType() == XFA_PacketType::Form); - CXFA_Node* pChildNode = FormValueNode_CreateChild(pValueNode, iType); - if (!pChildNode) - return false; - - switch (pChildNode->GetObjectType()) { - case XFA_ObjectType::ContentNode: { - CXFA_Node* pContentRawDataNode = pChildNode->GetFirstChild(); - if (!pContentRawDataNode) { - XFA_Element element = XFA_Element::Sharptext; - if (pChildNode->GetElementType() == XFA_Element::ExData) { - Optional<WideString> contentType = - pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType, - false); - if (contentType) { - if (*contentType == L"text/html") - element = XFA_Element::SharpxHTML; - else if (*contentType == L"text/xml") - element = XFA_Element::Sharpxml; - } - } - pContentRawDataNode = pChildNode->CreateSamePacketNode(element); - pChildNode->InsertChild(pContentRawDataNode, nullptr); - } - pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, - false, false); - break; - } - case XFA_ObjectType::NodeC: - case XFA_ObjectType::TextNode: - case XFA_ObjectType::NodeV: { - pChildNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, false, - false); - break; - } - default: - NOTREACHED(); - break; - } - return true; -} - -void CreateDataBinding(CXFA_Node* pFormNode, - CXFA_Node* pDataNode, - bool bDataToForm) { - pFormNode->SetBindingNode(pDataNode); - pDataNode->AddBindItem(pFormNode); - XFA_Element eType = pFormNode->GetElementType(); - if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) - return; - - ASSERT(pFormNode->IsWidgetReady()); - auto* defValue = pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>( - 0, XFA_Element::Value); - if (!bDataToForm) { - WideString wsValue; - switch (pFormNode->GetFFWidgetType()) { - case XFA_FFWidgetType::kImageEdit: { - CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr; - WideString wsContentType; - WideString wsHref; - if (image) { - wsValue = image->GetContent(); - wsContentType = image->GetContentType(); - wsHref = image->GetHref(); - } - CFX_XMLElement* pXMLDataElement = - static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode()); - ASSERT(pXMLDataElement); - - pDataNode->JSObject()->SetAttributeValue( - wsValue, pFormNode->GetFormatDataValue(wsValue), false, false); - pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType, - wsContentType, false, false); - if (!wsHref.IsEmpty()) - pXMLDataElement->SetString(L"href", wsHref); - - break; - } - case XFA_FFWidgetType::kChoiceList: - wsValue = defValue ? defValue->GetChildValueContent() : L""; - if (pFormNode->IsChoiceListMultiSelect()) { - std::vector<WideString> wsSelTextArray = - pFormNode->GetSelectedItemsValue(); - if (!wsSelTextArray.empty()) { - for (const auto& text : wsSelTextArray) { - CXFA_Node* pValue = - pDataNode->CreateSamePacketNode(XFA_Element::DataValue); - pValue->JSObject()->SetCData(XFA_Attribute::Name, L"value", false, - false); - pValue->CreateXMLMappingNode(); - pDataNode->InsertChild(pValue, nullptr); - pValue->JSObject()->SetCData(XFA_Attribute::Value, text, false, - false); - } - } else { - CFX_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); - ASSERT(pXMLNode->GetType() == FX_XMLNODE_Element); - static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode", - L"dataGroup"); - } - } else if (!wsValue.IsEmpty()) { - pDataNode->JSObject()->SetAttributeValue( - wsValue, pFormNode->GetFormatDataValue(wsValue), false, false); - } - break; - case XFA_FFWidgetType::kCheckButton: - wsValue = defValue ? defValue->GetChildValueContent() : L""; - if (wsValue.IsEmpty()) - break; - - pDataNode->JSObject()->SetAttributeValue( - wsValue, pFormNode->GetFormatDataValue(wsValue), false, false); - break; - case XFA_FFWidgetType::kExclGroup: { - CXFA_Node* pChecked = nullptr; - CXFA_Node* pChild = pFormNode->GetFirstChild(); - for (; pChild; pChild = pChild->GetNextSibling()) { - if (pChild->GetElementType() != XFA_Element::Field) - continue; - - auto* pValue = - pChild->GetChild<CXFA_Value>(0, XFA_Element::Value, false); - if (!pValue) - continue; - - wsValue = pValue->GetChildValueContent(); - if (wsValue.IsEmpty()) - continue; - - CXFA_Items* pItems = - pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItems) - continue; - - CXFA_Node* pText = pItems->GetFirstChild(); - if (!pText) - continue; - - WideString wsContent = pText->JSObject()->GetContent(false); - if (wsContent == wsValue) { - pChecked = pChild; - pDataNode->JSObject()->SetAttributeValue(wsValue, wsValue, false, - false); - pFormNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, - false, false); - break; - } - } - if (!pChecked) - break; - - pChild = pFormNode->GetFirstChild(); - for (; pChild; pChild = pChild->GetNextSibling()) { - if (pChild == pChecked) - continue; - if (pChild->GetElementType() != XFA_Element::Field) - continue; - - CXFA_Value* pValue = - pChild->JSObject()->GetOrCreateProperty<CXFA_Value>( - 0, XFA_Element::Value); - CXFA_Items* pItems = - pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - CXFA_Node* pText = pItems ? pItems->GetFirstChild() : nullptr; - if (pText) - pText = pText->GetNextSibling(); - - WideString wsContent; - if (pText) - wsContent = pText->JSObject()->GetContent(false); - - FormValueNode_SetChildContent(pValue, wsContent, XFA_Element::Text); - } - break; - } - case XFA_FFWidgetType::kNumericEdit: { - wsValue = defValue ? defValue->GetChildValueContent() : L""; - if (wsValue.IsEmpty()) - break; - - wsValue = pFormNode->NormalizeNumStr(wsValue); - pDataNode->JSObject()->SetAttributeValue( - wsValue, pFormNode->GetFormatDataValue(wsValue), false, false); - CXFA_Value* pValue = - pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>( - 0, XFA_Element::Value); - FormValueNode_SetChildContent(pValue, wsValue, XFA_Element::Float); - break; - } - default: - wsValue = defValue ? defValue->GetChildValueContent() : L""; - if (wsValue.IsEmpty()) - break; - - pDataNode->JSObject()->SetAttributeValue( - wsValue, pFormNode->GetFormatDataValue(wsValue), false, false); - break; - } - return; - } - - WideString wsXMLValue = pDataNode->JSObject()->GetContent(false); - WideString wsNormalizeValue = pFormNode->GetNormalizeDataValue(wsXMLValue); - - pDataNode->JSObject()->SetAttributeValue(wsNormalizeValue, wsXMLValue, false, - false); - switch (pFormNode->GetFFWidgetType()) { - case XFA_FFWidgetType::kImageEdit: { - FormValueNode_SetChildContent(defValue, wsNormalizeValue, - XFA_Element::Image); - CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr; - if (image) { - CFX_XMLElement* pXMLDataElement = - static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode()); - ASSERT(pXMLDataElement); - - WideString wsContentType = - pXMLDataElement->GetString(L"xfa:contentType"); - if (!wsContentType.IsEmpty()) { - pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType, - wsContentType, false, false); - image->SetContentType(wsContentType); - } - - WideString wsHref = pXMLDataElement->GetString(L"href"); - if (!wsHref.IsEmpty()) - image->SetHref(wsHref); - } - break; - } - case XFA_FFWidgetType::kChoiceList: - if (pFormNode->IsChoiceListMultiSelect()) { - std::vector<CXFA_Node*> items = pDataNode->GetNodeList( - XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties, - XFA_Element::Unknown); - if (!items.empty()) { - bool single = items.size() == 1; - wsNormalizeValue.clear(); - - for (CXFA_Node* pNode : items) { - WideString wsItem = pNode->JSObject()->GetContent(false); - if (single) - wsItem += L"\n"; - - wsNormalizeValue += wsItem; - } - CXFA_ExData* exData = - defValue ? defValue->GetExDataIfExists() : nullptr; - ASSERT(exData); - - exData->SetContentType(single ? L"text/plain" : L"text/xml"); - } - FormValueNode_SetChildContent(defValue, wsNormalizeValue, - XFA_Element::ExData); - } else { - FormValueNode_SetChildContent(defValue, wsNormalizeValue, - XFA_Element::Text); - } - break; - case XFA_FFWidgetType::kExclGroup: { - pFormNode->SetSelectedMemberByValue(wsNormalizeValue.AsStringView(), - false, false, false); - break; - } - case XFA_FFWidgetType::kDateTimeEdit: - FormValueNode_SetChildContent(defValue, wsNormalizeValue, - XFA_Element::DateTime); - break; - case XFA_FFWidgetType::kNumericEdit: { - WideString wsPicture = - pFormNode->GetPictureContent(XFA_VALUEPICTURE_DataBind); - if (wsPicture.IsEmpty()) - wsNormalizeValue = pFormNode->NormalizeNumStr(wsNormalizeValue); - - FormValueNode_SetChildContent(defValue, wsNormalizeValue, - XFA_Element::Float); - break; - } - default: - FormValueNode_SetChildContent(defValue, wsNormalizeValue, - XFA_Element::Text); - break; - } -} -CXFA_Node* GetGlobalBinding(CXFA_Document* pDocument, uint32_t dwNameHash) { - auto it = pDocument->m_rgGlobalBinding.find(dwNameHash); - return it != pDocument->m_rgGlobalBinding.end() ? it->second : nullptr; -} - -void RegisterGlobalBinding(CXFA_Document* pDocument, - uint32_t dwNameHash, - CXFA_Node* pDataNode) { - pDocument->m_rgGlobalBinding[dwNameHash] = pDataNode; -} - -CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope, - uint32_t dwNameHash, - XFA_Element eMatchDataNodeType, - bool bUpLevel) { - for (CXFA_Node *pCurDataScope = pDataScope, *pLastDataScope = nullptr; - pCurDataScope && - pCurDataScope->GetPacketType() == XFA_PacketType::Datasets; - pLastDataScope = pCurDataScope, - pCurDataScope = pCurDataScope->GetParent()) { - for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash); - pDataChild; - pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) { - if (pDataChild == pLastDataScope || - (eMatchDataNodeType != XFA_Element::DataModel && - pDataChild->GetElementType() != eMatchDataNodeType) || - pDataChild->HasBindItem()) { - continue; - } - return pDataChild; - } - - for (CXFA_DataGroup* pDataChild = - pCurDataScope->GetFirstChildByClass<CXFA_DataGroup>( - XFA_Element::DataGroup); - pDataChild; - pDataChild = pDataChild->GetNextSameClassSibling<CXFA_DataGroup>( - XFA_Element::DataGroup)) { - CXFA_Node* pDataNode = ScopeMatchGlobalBinding(pDataChild, dwNameHash, - eMatchDataNodeType, false); - if (pDataNode) - return pDataNode; - } - if (!bUpLevel) - break; - } - return nullptr; -} - -CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument, - const WideString& wsName, - CXFA_Node* pDataScope, - XFA_Element eMatchNodeType) { - if (wsName.IsEmpty()) - return nullptr; - - uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false); - CXFA_Node* pBounded = GetGlobalBinding(pDocument, dwNameHash); - if (!pBounded) { - pBounded = - ScopeMatchGlobalBinding(pDataScope, dwNameHash, eMatchNodeType, true); - if (pBounded) - RegisterGlobalBinding(pDocument, dwNameHash, pBounded); - } - return pBounded; -} - -CXFA_Node* FindOnceDataNode(CXFA_Document* pDocument, - const WideString& wsName, - CXFA_Node* pDataScope, - XFA_Element eMatchNodeType) { - if (wsName.IsEmpty()) - return nullptr; - - uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false); - CXFA_Node* pLastDataScope = nullptr; - for (CXFA_Node* pCurDataScope = pDataScope; - pCurDataScope && - pCurDataScope->GetPacketType() == XFA_PacketType::Datasets; - pCurDataScope = pCurDataScope->GetParent()) { - for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash); - pDataChild; - pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) { - if (pDataChild == pLastDataScope || pDataChild->HasBindItem() || - (eMatchNodeType != XFA_Element::DataModel && - pDataChild->GetElementType() != eMatchNodeType)) { - continue; - } - return pDataChild; - } - pLastDataScope = pCurDataScope; - } - return nullptr; -} - -CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument, - const WideString& wsRef, - CXFA_Node* pDataScope, - XFA_Element eMatchNodeType, - CXFA_Node* pTemplateNode, - bool bForceBind, - bool bUpLevel) { - uint32_t dFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_BindNew; - if (bUpLevel || wsRef != L"name") - dFlags |= (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings); - - XFA_RESOLVENODE_RS rs; - pDocument->GetScriptContext()->ResolveObjects( - pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode); - if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeAll || - rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeMidAll || - rs.objects.size() > 1) { - return pDocument->GetNotBindNode(rs.objects); - } - - if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) { - CXFA_Object* pObject = !rs.objects.empty() ? rs.objects.front() : nullptr; - CXFA_Node* pNode = ToNode(pObject); - return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr; - } - return nullptr; -} - -bool NeedGenerateForm(CXFA_Node* pTemplateChild, bool bUseInstanceManager) { +bool XFA_DataMerge_NeedGenerateForm(CXFA_Node* pTemplateChild, + bool bUseInstanceManager) { XFA_Element eType = pTemplateChild->GetElementType(); if (eType == XFA_Element::Variables) return true; @@ -505,741 +22,6 @@ bool NeedGenerateForm(CXFA_Node* pTemplateChild, bool bUseInstanceManager) { return true; } -CXFA_Node* CloneOrMergeInstanceManager(CXFA_Document* pDocument, - CXFA_Node* pFormParent, - CXFA_Node* pTemplateNode, - std::vector<CXFA_Node*>* subforms) { - WideString wsSubformName = - pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name); - WideString wsInstMgrNodeName = L"_" + wsSubformName; - uint32_t dwInstNameHash = - FX_HashCode_GetW(wsInstMgrNodeName.AsStringView(), false); - CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance( - pDocument, XFA_Element::InstanceManager, dwInstNameHash, pFormParent); - if (pExistingNode) { - uint32_t dwNameHash = pTemplateNode->GetNameHash(); - for (CXFA_Node* pNode = pExistingNode->GetNextSibling(); pNode;) { - XFA_Element eCurType = pNode->GetElementType(); - if (eCurType == XFA_Element::InstanceManager) - break; - - if ((eCurType != XFA_Element::Subform) && - (eCurType != XFA_Element::SubformSet)) { - pNode = pNode->GetNextSibling(); - continue; - } - if (dwNameHash != pNode->GetNameHash()) - break; - - CXFA_Node* pNextNode = pNode->GetNextSibling(); - pFormParent->RemoveChild(pNode, true); - subforms->push_back(pNode); - pNode = pNextNode; - } - pFormParent->RemoveChild(pExistingNode, true); - pFormParent->InsertChild(pExistingNode, nullptr); - pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode); - pExistingNode->SetTemplateNode(pTemplateNode); - return pExistingNode; - } - - CXFA_Node* pNewNode = - pDocument->CreateNode(XFA_PacketType::Form, XFA_Element::InstanceManager); - wsInstMgrNodeName = - L"_" + pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name); - pNewNode->JSObject()->SetCData(XFA_Attribute::Name, wsInstMgrNodeName, false, - false); - pFormParent->InsertChild(pNewNode, nullptr); - pNewNode->SetTemplateNode(pTemplateNode); - return pNewNode; -} - -CXFA_Node* FindMatchingDataNode( - CXFA_Document* pDocument, - CXFA_Node* pTemplateNode, - CXFA_Node* pDataScope, - bool& bAccessedDataDOM, - bool bForceBind, - CXFA_NodeIteratorTemplate<CXFA_Node, - CXFA_TraverseStrategy_XFAContainerNode>* - pIterator, - bool& bSelfMatch, - XFA_AttributeEnum& eBindMatch, - bool bUpLevel) { - CXFA_Node* pResult = nullptr; - CXFA_Node* pCurTemplateNode = pIterator->GetCurrent(); - while (pCurTemplateNode) { - XFA_Element eMatchNodeType; - switch (pCurTemplateNode->GetElementType()) { - case XFA_Element::Subform: - eMatchNodeType = XFA_Element::DataGroup; - break; - case XFA_Element::Field: { - eMatchNodeType = XFA_FieldIsMultiListBox(pCurTemplateNode) - ? XFA_Element::DataGroup - : XFA_Element::DataValue; - } break; - case XFA_Element::ExclGroup: - eMatchNodeType = XFA_Element::DataValue; - break; - default: - pCurTemplateNode = pIterator->MoveToNext(); - continue; - } - - CXFA_Occur* pTemplateNodeOccur = - pCurTemplateNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); - if (pTemplateNodeOccur) { - int32_t iMin; - int32_t iMax; - int32_t iInit; - std::tie(iMin, iMax, iInit) = pTemplateNodeOccur->GetOccurInfo(); - if (iMax == 0) { - pCurTemplateNode = pIterator->MoveToNext(); - continue; - } - } - - CXFA_Bind* pTemplateNodeBind = - pCurTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind); - XFA_AttributeEnum eMatch = - pTemplateNodeBind - ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match) - : XFA_AttributeEnum::Once; - eBindMatch = eMatch; - switch (eMatch) { - case XFA_AttributeEnum::None: - pCurTemplateNode = pIterator->MoveToNext(); - continue; - case XFA_AttributeEnum::Global: - bAccessedDataDOM = true; - if (!bForceBind) { - pCurTemplateNode = pIterator->MoveToNext(); - continue; - } - if (eMatchNodeType == XFA_Element::DataValue || - (eMatchNodeType == XFA_Element::DataGroup && - XFA_FieldIsMultiListBox(pTemplateNodeBind))) { - CXFA_Node* pGlobalBindNode = FindGlobalDataNode( - pDocument, - pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name), - pDataScope, eMatchNodeType); - if (!pGlobalBindNode) { - pCurTemplateNode = pIterator->MoveToNext(); - continue; - } - pResult = pGlobalBindNode; - break; - } - FX_FALLTHROUGH; - case XFA_AttributeEnum::Once: { - bAccessedDataDOM = true; - CXFA_Node* pOnceBindNode = FindOnceDataNode( - pDocument, - pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name), - pDataScope, eMatchNodeType); - if (!pOnceBindNode) { - pCurTemplateNode = pIterator->MoveToNext(); - continue; - } - pResult = pOnceBindNode; - break; - } - case XFA_AttributeEnum::DataRef: { - bAccessedDataDOM = true; - CXFA_Node* pDataRefBindNode = FindDataRefDataNode( - pDocument, - pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref), - pDataScope, eMatchNodeType, pTemplateNode, bForceBind, bUpLevel); - if (pDataRefBindNode && - pDataRefBindNode->GetElementType() == eMatchNodeType) { - pResult = pDataRefBindNode; - } - if (!pResult) { - pCurTemplateNode = pIterator->SkipChildrenAndMoveToNext(); - continue; - } - break; - } - default: - break; - } - if (pCurTemplateNode == pTemplateNode && pResult) - bSelfMatch = true; - break; - } - return pResult; -} - -void SortRecurseRecord(std::vector<RecurseRecord>* rgRecords, - CXFA_Node* pDataScope, - bool bChoiceMode) { - std::vector<RecurseRecord> rgResultRecord; - for (CXFA_Node* pNode = pDataScope->GetFirstChild(); pNode; - pNode = pNode->GetNextSibling()) { - auto it = std::find_if(rgRecords->begin(), rgRecords->end(), - [pNode](const RecurseRecord& record) { - return pNode == record.pDataChild; - }); - if (it != rgRecords->end()) { - rgResultRecord.push_back(*it); - rgRecords->erase(it); - if (bChoiceMode) - break; - } - } - if (rgResultRecord.empty()) - return; - - if (!bChoiceMode) { - rgResultRecord.insert(rgResultRecord.end(), rgRecords->begin(), - rgRecords->end()); - } - *rgRecords = rgResultRecord; -} - -CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, - CXFA_Node* pTemplateNode, - CXFA_Node* pFormParentNode, - CXFA_Node* pDataScope, - bool bOneInstance, - bool bDataMerge) { - XFA_Element eType = pTemplateNode->GetElementType(); - CXFA_Node* pOccurNode = nullptr; - CXFA_Node* pFirstInstance = nullptr; - bool bUseInstanceManager = - pFormParentNode->GetElementType() != XFA_Element::Area; - CXFA_Node* pInstMgrNode = nullptr; - std::vector<CXFA_Node*> subformArray; - std::vector<CXFA_Node*>* pSearchArray = nullptr; - if (!bOneInstance && - (eType == XFA_Element::SubformSet || eType == XFA_Element::Subform)) { - pInstMgrNode = bUseInstanceManager ? CloneOrMergeInstanceManager( - pDocument, pFormParentNode, - pTemplateNode, &subformArray) - : nullptr; - if (CXFA_Occur* pOccurTemplateNode = - pTemplateNode->GetFirstChildByClass<CXFA_Occur>( - XFA_Element::Occur)) { - pOccurNode = pInstMgrNode ? XFA_NodeMerge_CloneOrMergeContainer( - pDocument, pInstMgrNode, - pOccurTemplateNode, false, nullptr) - : pOccurTemplateNode; - } else if (pInstMgrNode) { - pOccurNode = - pInstMgrNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); - if (pOccurNode) - pOccurNode->ClearFlag(XFA_NodeFlag_UnusedNode); - } - if (pInstMgrNode) { - pInstMgrNode->SetFlagAndNotify(XFA_NodeFlag_Initialized); - pSearchArray = &subformArray; - if (pFormParentNode->GetElementType() == XFA_Element::PageArea) { - bOneInstance = true; - if (subformArray.empty()) - pSearchArray = nullptr; - } else if (pTemplateNode->GetNameHash() == 0 && subformArray.empty()) { - pSearchArray = nullptr; - } - } - } - - int32_t iMax = 1; - int32_t iInit = 1; - int32_t iMin = 1; - if (!bOneInstance && pOccurNode) { - std::tie(iMin, iMax, iInit) = - static_cast<CXFA_Occur*>(pOccurNode)->GetOccurInfo(); - } - - XFA_AttributeEnum eRelation = - eType == XFA_Element::SubformSet - ? pTemplateNode->JSObject()->GetEnum(XFA_Attribute::Relation) - : XFA_AttributeEnum::Ordered; - int32_t iCurRepeatIndex = 0; - XFA_AttributeEnum eParentBindMatch = XFA_AttributeEnum::None; - if (bDataMerge) { - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode> - sNodeIterator(pTemplateNode); - bool bAccessedDataDOM = false; - if (eType == XFA_Element::SubformSet || eType == XFA_Element::Area) { - sNodeIterator.MoveToNext(); - } else { - std::map<CXFA_Node*, CXFA_Node*> subformMapArray; - std::vector<CXFA_Node*> nodeArray; - for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) { - bool bSelfMatch = false; - XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None; - CXFA_Node* pDataNode = FindMatchingDataNode( - pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, false, - &sNodeIterator, bSelfMatch, eBindMatch, true); - if (!pDataNode || sNodeIterator.GetCurrent() != pTemplateNode) - break; - - eParentBindMatch = eBindMatch; - CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer( - pDocument, pFormParentNode, pTemplateNode, false, pSearchArray); - if (!pFirstInstance) - pFirstInstance = pSubformNode; - - CreateDataBinding(pSubformNode, pDataNode, true); - ASSERT(pSubformNode); - subformMapArray[pSubformNode] = pDataNode; - nodeArray.push_back(pSubformNode); - } - - for (CXFA_Node* pSubform : nodeArray) { - CXFA_Node* pDataNode = nullptr; - auto it = subformMapArray.find(pSubform); - if (it != subformMapArray.end()) - pDataNode = it->second; - for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); - pTemplateChild; - pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { - XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubform, - pTemplateChild, true, nullptr); - } else if (pTemplateChild->IsContainerNode()) { - pDocument->DataMerge_CopyContainer(pTemplateChild, pSubform, - pDataNode, false, true, false); - } - } - } - subformMapArray.clear(); - } - - for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) { - bool bSelfMatch = false; - XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None; - if (!FindMatchingDataNode(pDocument, pTemplateNode, pDataScope, - bAccessedDataDOM, false, &sNodeIterator, - bSelfMatch, eBindMatch, true)) { - break; - } - if (eBindMatch == XFA_AttributeEnum::DataRef && - eParentBindMatch == XFA_AttributeEnum::DataRef) { - break; - } - - if (eRelation == XFA_AttributeEnum::Choice || - eRelation == XFA_AttributeEnum::Unordered) { - CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer( - pDocument, pFormParentNode, pTemplateNode, false, pSearchArray); - ASSERT(pSubformSetNode); - if (!pFirstInstance) - pFirstInstance = pSubformSetNode; - - std::vector<RecurseRecord> rgItemMatchList; - std::vector<CXFA_Node*> rgItemUnmatchList; - for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); - pTemplateChild; - pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { - XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode, - pTemplateChild, true, nullptr); - } else if (pTemplateChild->IsContainerNode()) { - bSelfMatch = false; - eBindMatch = XFA_AttributeEnum::None; - if (eRelation != XFA_AttributeEnum::Ordered) { - CXFA_NodeIteratorTemplate<CXFA_Node, - CXFA_TraverseStrategy_XFAContainerNode> - sChildIter(pTemplateChild); - CXFA_Node* pDataMatch = FindMatchingDataNode( - pDocument, pTemplateChild, pDataScope, bAccessedDataDOM, - false, &sChildIter, bSelfMatch, eBindMatch, true); - if (pDataMatch) { - RecurseRecord sNewRecord = {pTemplateChild, pDataMatch}; - if (bSelfMatch) - rgItemMatchList.insert(rgItemMatchList.begin(), sNewRecord); - else - rgItemMatchList.push_back(sNewRecord); - } else { - rgItemUnmatchList.push_back(pTemplateChild); - } - } else { - rgItemUnmatchList.push_back(pTemplateChild); - } - } - } - - switch (eRelation) { - case XFA_AttributeEnum::Choice: { - ASSERT(!rgItemMatchList.empty()); - SortRecurseRecord(&rgItemMatchList, pDataScope, true); - pDocument->DataMerge_CopyContainer( - rgItemMatchList.front().pTemplateChild, pSubformSetNode, - pDataScope, false, true, true); - break; - } - case XFA_AttributeEnum::Unordered: { - if (!rgItemMatchList.empty()) { - SortRecurseRecord(&rgItemMatchList, pDataScope, false); - for (const auto& matched : rgItemMatchList) { - pDocument->DataMerge_CopyContainer(matched.pTemplateChild, - pSubformSetNode, pDataScope, - false, true, true); - } - } - for (auto* unmatched : rgItemUnmatchList) { - pDocument->DataMerge_CopyContainer(unmatched, pSubformSetNode, - pDataScope, false, true, true); - } - break; - } - default: - break; - } - } else { - CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer( - pDocument, pFormParentNode, pTemplateNode, false, pSearchArray); - ASSERT(pSubformSetNode); - if (!pFirstInstance) - pFirstInstance = pSubformSetNode; - - for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); - pTemplateChild; - pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { - XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode, - pTemplateChild, true, nullptr); - } else if (pTemplateChild->IsContainerNode()) { - pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, - pDataScope, false, true, true); - } - } - } - } - - if (iCurRepeatIndex == 0 && bAccessedDataDOM == false) { - int32_t iLimit = iMax; - if (pInstMgrNode && pTemplateNode->GetNameHash() == 0) { - iLimit = pdfium::CollectionSize<int32_t>(subformArray); - if (iLimit < iMin) - iLimit = iInit; - } - - for (; (iLimit < 0 || iCurRepeatIndex < iLimit); iCurRepeatIndex++) { - if (pInstMgrNode) { - if (pSearchArray && pSearchArray->empty()) { - if (pTemplateNode->GetNameHash() != 0) - break; - pSearchArray = nullptr; - } - } else if (!XFA_DataMerge_FindFormDOMInstance( - pDocument, pTemplateNode->GetElementType(), - pTemplateNode->GetNameHash(), pFormParentNode)) { - break; - } - CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer( - pDocument, pFormParentNode, pTemplateNode, false, pSearchArray); - ASSERT(pSubformNode); - if (!pFirstInstance) - pFirstInstance = pSubformNode; - - for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); - pTemplateChild; - pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { - XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformNode, - pTemplateChild, true, nullptr); - } else if (pTemplateChild->IsContainerNode()) { - pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformNode, - pDataScope, false, true, true); - } - } - } - } - } - - int32_t iMinimalLimit = iCurRepeatIndex == 0 ? iInit : iMin; - for (; iCurRepeatIndex < iMinimalLimit; iCurRepeatIndex++) { - CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer( - pDocument, pFormParentNode, pTemplateNode, false, pSearchArray); - ASSERT(pSubformSetNode); - if (!pFirstInstance) - pFirstInstance = pSubformSetNode; - - bool bFound = false; - for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); - pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { - XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode, - pTemplateChild, true, nullptr); - } else if (pTemplateChild->IsContainerNode()) { - if (bFound && eRelation == XFA_AttributeEnum::Choice) - continue; - - pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, - pDataScope, false, bDataMerge, true); - bFound = true; - } - } - } - return pFirstInstance; -} - -CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument, - CXFA_Node* pTemplateNode, - CXFA_Node* pFormNode, - CXFA_Node* pDataScope, - bool bDataMerge, - bool bUpLevel) { - CXFA_Node* pFieldNode = XFA_NodeMerge_CloneOrMergeContainer( - pDocument, pFormNode, pTemplateNode, false, nullptr); - ASSERT(pFieldNode); - for (CXFA_Node* pTemplateChildNode = pTemplateNode->GetFirstChild(); - pTemplateChildNode; - pTemplateChildNode = pTemplateChildNode->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChildNode, true)) { - XFA_NodeMerge_CloneOrMergeContainer(pDocument, pFieldNode, - pTemplateChildNode, true, nullptr); - } else if (pTemplateNode->GetElementType() == XFA_Element::ExclGroup && - pTemplateChildNode->IsContainerNode()) { - if (pTemplateChildNode->GetElementType() == XFA_Element::Field) { - CopyContainer_Field(pDocument, pTemplateChildNode, pFieldNode, nullptr, - false, true); - } - } - } - if (bDataMerge) { - bool bAccessedDataDOM = false; - bool bSelfMatch = false; - XFA_AttributeEnum eBindMatch; - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode> - sNodeIter(pTemplateNode); - CXFA_Node* pDataNode = FindMatchingDataNode( - pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, true, - &sNodeIter, bSelfMatch, eBindMatch, bUpLevel); - if (pDataNode) - CreateDataBinding(pFieldNode, pDataNode, true); - } else { - FormValueNode_MatchNoneCreateChild(pFieldNode); - } - return pFieldNode; -} - -CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument, - CXFA_Node* pDataParent, - XFA_Element eNodeType, - const WideString& wsName) { - if (!pDataParent) - return nullptr; - - CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode(); - if (!pParentDDNode) { - CXFA_Node* pDataNode = - pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType); - pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false); - pDataNode->CreateXMLMappingNode(); - pDataParent->InsertChild(pDataNode, nullptr); - pDataNode->SetFlag(XFA_NodeFlag_Initialized); - return pDataNode; - } - - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup> sIterator( - pParentDDNode); - for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode; - pDDGroupNode = sIterator.MoveToNext()) { - if (pDDGroupNode != pParentDDNode) { - if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup) - continue; - - Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace(); - if (!ns || *ns != L"http://ns.adobe.com/data-description/") - continue; - } - - CXFA_Node* pDDNode = - pDDGroupNode->GetFirstChildByName(wsName.AsStringView()); - if (!pDDNode) - continue; - if (pDDNode->GetElementType() != eNodeType) - break; - - CXFA_Node* pDataNode = - pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType); - pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false); - pDataNode->CreateXMLMappingNode(); - if (eNodeType == XFA_Element::DataValue && - pDDNode->JSObject()->GetEnum(XFA_Attribute::Contains) == - XFA_AttributeEnum::MetaData) { - pDataNode->JSObject()->SetEnum(XFA_Attribute::Contains, - XFA_AttributeEnum::MetaData, false); - } - pDataParent->InsertChild(pDataNode, nullptr); - pDataNode->SetDataDescriptionNode(pDDNode); - pDataNode->SetFlag(XFA_NodeFlag_Initialized); - return pDataNode; - } - return nullptr; -} - -void UpdateBindingRelations(CXFA_Document* pDocument, - CXFA_Node* pFormNode, - CXFA_Node* pDataScope, - bool bDataRef, - bool bParentDataRef) { - bool bMatchRef = true; - XFA_Element eType = pFormNode->GetElementType(); - CXFA_Node* pDataNode = pFormNode->GetBindData(); - if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup || - eType == XFA_Element::Field) { - CXFA_Node* pTemplateNode = pFormNode->GetTemplateNodeIfExists(); - CXFA_Bind* pTemplateNodeBind = - pTemplateNode - ? pTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind) - : nullptr; - XFA_AttributeEnum eMatch = - pTemplateNodeBind - ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match) - : XFA_AttributeEnum::Once; - switch (eMatch) { - case XFA_AttributeEnum::None: - if (!bDataRef || bParentDataRef) - FormValueNode_MatchNoneCreateChild(pFormNode); - break; - case XFA_AttributeEnum::Once: - if (!bDataRef || bParentDataRef) { - if (!pDataNode) { - if (pFormNode->GetNameHash() != 0 && - pFormNode->JSObject()->GetEnum(XFA_Attribute::Scope) != - XFA_AttributeEnum::None) { - XFA_Element eDataNodeType = (eType == XFA_Element::Subform || - XFA_FieldIsMultiListBox(pFormNode)) - ? XFA_Element::DataGroup - : XFA_Element::DataValue; - pDataNode = MaybeCreateDataNode( - pDocument, pDataScope, eDataNodeType, - WideString( - pFormNode->JSObject()->GetCData(XFA_Attribute::Name))); - if (pDataNode) - CreateDataBinding(pFormNode, pDataNode, false); - } - if (!pDataNode) - FormValueNode_MatchNoneCreateChild(pFormNode); - - } else { - CXFA_Node* pDataParent = pDataNode->GetParent(); - if (pDataParent != pDataScope) { - ASSERT(pDataParent); - pDataParent->RemoveChild(pDataNode, true); - pDataScope->InsertChild(pDataNode, nullptr); - } - } - } - break; - case XFA_AttributeEnum::Global: - if (!bDataRef || bParentDataRef) { - uint32_t dwNameHash = pFormNode->GetNameHash(); - if (dwNameHash != 0 && !pDataNode) { - pDataNode = GetGlobalBinding(pDocument, dwNameHash); - if (!pDataNode) { - XFA_Element eDataNodeType = (eType == XFA_Element::Subform || - XFA_FieldIsMultiListBox(pFormNode)) - ? XFA_Element::DataGroup - : XFA_Element::DataValue; - CXFA_Node* pRecordNode = - ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record)); - pDataNode = MaybeCreateDataNode( - pDocument, pRecordNode, eDataNodeType, - WideString( - pFormNode->JSObject()->GetCData(XFA_Attribute::Name))); - if (pDataNode) { - CreateDataBinding(pFormNode, pDataNode, false); - RegisterGlobalBinding(pDocument, pFormNode->GetNameHash(), - pDataNode); - } - } else { - CreateDataBinding(pFormNode, pDataNode, true); - } - } - if (!pDataNode) - FormValueNode_MatchNoneCreateChild(pFormNode); - } - break; - case XFA_AttributeEnum::DataRef: { - bMatchRef = bDataRef; - bParentDataRef = true; - if (!pDataNode && bDataRef) { - WideString wsRef = - pTemplateNodeBind - ? pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref) - : L""; - uint32_t dFlags = - XFA_RESOLVENODE_Children | XFA_RESOLVENODE_CreateNode; - XFA_RESOLVENODE_RS rs; - pDocument->GetScriptContext()->ResolveObjects( - pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode); - CXFA_Object* pObject = - !rs.objects.empty() ? rs.objects.front() : nullptr; - pDataNode = ToNode(pObject); - if (pDataNode) { - CreateDataBinding(pFormNode, pDataNode, - rs.dwFlags == XFA_ResolveNode_RSType_ExistNodes); - } else { - FormValueNode_MatchNoneCreateChild(pFormNode); - } - } - break; - } - default: - break; - } - } - - if (bMatchRef && - (eType == XFA_Element::Subform || eType == XFA_Element::SubformSet || - eType == XFA_Element::Area || eType == XFA_Element::PageArea || - eType == XFA_Element::PageSet)) { - for (CXFA_Node* pFormChild = pFormNode->GetFirstChild(); pFormChild; - pFormChild = pFormChild->GetNextSibling()) { - if (!pFormChild->IsContainerNode()) - continue; - if (pFormChild->IsUnusedNode()) - continue; - - UpdateBindingRelations(pDocument, pFormChild, - pDataNode ? pDataNode : pDataScope, bDataRef, - bParentDataRef); - } - } -} - -void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) { - ASSERT(pDataDescriptionNode); - for (CXFA_Node* pDataChild = pDataNode->GetFirstChild(); pDataChild; - pDataChild = pDataChild->GetNextSibling()) { - uint32_t dwNameHash = pDataChild->GetNameHash(); - if (!dwNameHash) - continue; - - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup> - sIterator(pDataDescriptionNode); - for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode; - pDDGroupNode = sIterator.MoveToNext()) { - if (pDDGroupNode != pDataDescriptionNode) { - if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup) - continue; - - Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace(); - if (!ns || *ns != L"http://ns.adobe.com/data-description/") - continue; - } - - CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash); - if (!pDDNode) - continue; - if (pDDNode->GetElementType() != pDataChild->GetElementType()) - break; - - pDataChild->SetDataDescriptionNode(pDDNode); - UpdateDataRelation(pDataChild, pDDNode); - break; - } - } -} - -} // namespace CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument, XFA_Element eType, @@ -1282,7 +64,7 @@ CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer( if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) { for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, true)) { + if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) { XFA_NodeMerge_CloneOrMergeContainer( pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr); } @@ -1297,7 +79,7 @@ CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer( if (bRecursive) { for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, true)) { + if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) { CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true); pNewNode->InsertChild(pNewChild, nullptr); } @@ -1318,231 +100,3 @@ CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) { pParentFormNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Data)); } -CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode, - CXFA_Node* pFormNode, - CXFA_Node* pDataScope, - bool bOneInstance, - bool bDataMerge, - bool bUpLevel) { - switch (pTemplateNode->GetElementType()) { - case XFA_Element::SubformSet: - case XFA_Element::Subform: - case XFA_Element::Area: - case XFA_Element::PageArea: - return CopyContainer_SubformSet(this, pTemplateNode, pFormNode, - pDataScope, bOneInstance, bDataMerge); - case XFA_Element::ExclGroup: - case XFA_Element::Field: - case XFA_Element::Draw: - case XFA_Element::ContentArea: - return CopyContainer_Field(this, pTemplateNode, pFormNode, pDataScope, - bDataMerge, bUpLevel); - case XFA_Element::PageSet: - case XFA_Element::Variables: - break; - default: - NOTREACHED(); - break; - } - return nullptr; -} - -void CXFA_Document::DataMerge_UpdateBindingRelations( - CXFA_Node* pFormUpdateRoot) { - CXFA_Node* pDataScope = - XFA_DataMerge_FindDataScope(pFormUpdateRoot->GetParent()); - if (!pDataScope) - return; - - UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, false, false); - UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, true, false); -} - -CXFA_Node* CXFA_Document::GetNotBindNode( - const std::vector<CXFA_Object*>& arrayObjects) const { - for (CXFA_Object* pObject : arrayObjects) { - CXFA_Node* pNode = pObject->AsNode(); - if (pNode && !pNode->HasBindItem()) - return pNode; - } - return nullptr; -} - -void CXFA_Document::DoDataMerge() { - CXFA_Node* pDatasetsRoot = ToNode(GetXFAObject(XFA_HASHCODE_Datasets)); - if (!pDatasetsRoot) { - // Ownership will be passed in the AppendChild below to the XML tree. - auto pDatasetsXMLNode = pdfium::MakeUnique<CFX_XMLElement>(L"xfa:datasets"); - pDatasetsXMLNode->SetString(L"xmlns:xfa", - L"http://www.xfa.org/schema/xfa-data/1.0/"); - pDatasetsRoot = - CreateNode(XFA_PacketType::Datasets, XFA_Element::DataModel); - pDatasetsRoot->JSObject()->SetCData(XFA_Attribute::Name, L"datasets", false, - false); - - CFX_XMLElement* ref = pDatasetsXMLNode.get(); - m_pRootNode->GetXMLMappingNode()->AppendChild(pDatasetsXMLNode.release()); - m_pRootNode->InsertChild(pDatasetsRoot, nullptr); - pDatasetsRoot->SetXMLMappingNode(ref); - } - - CXFA_Node *pDataRoot = nullptr, *pDDRoot = nullptr; - WideString wsDatasetsURI = - pDatasetsRoot->JSObject()->TryNamespace().value_or(WideString()); - for (CXFA_Node* pChildNode = pDatasetsRoot->GetFirstChild(); pChildNode; - pChildNode = pChildNode->GetNextSibling()) { - if (pChildNode->GetElementType() != XFA_Element::DataGroup) - continue; - - if (!pDDRoot && pChildNode->GetNameHash() == XFA_HASHCODE_DataDescription) { - Optional<WideString> namespaceURI = - pChildNode->JSObject()->TryNamespace(); - if (!namespaceURI) - continue; - if (*namespaceURI == L"http://ns.adobe.com/data-description/") - pDDRoot = pChildNode; - } else if (!pDataRoot && pChildNode->GetNameHash() == XFA_HASHCODE_Data) { - Optional<WideString> namespaceURI = - pChildNode->JSObject()->TryNamespace(); - if (!namespaceURI) - continue; - if (*namespaceURI == wsDatasetsURI) - pDataRoot = pChildNode; - } - if (pDataRoot && pDDRoot) - break; - } - - if (!pDataRoot) { - pDataRoot = CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup); - pDataRoot->JSObject()->SetCData(XFA_Attribute::Name, L"data", false, false); - pDataRoot->SetXMLMappingNode( - pdfium::MakeUnique<CFX_XMLElement>(L"xfa:data")); - pDatasetsRoot->InsertChild(pDataRoot, nullptr); - } - - CXFA_DataGroup* pDataTopLevel = - pDataRoot->GetFirstChildByClass<CXFA_DataGroup>(XFA_Element::DataGroup); - uint32_t dwNameHash = pDataTopLevel ? pDataTopLevel->GetNameHash() : 0; - CXFA_Template* pTemplateRoot = - m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template); - if (!pTemplateRoot) - return; - - CXFA_Node* pTemplateChosen = - dwNameHash != 0 ? pTemplateRoot->GetFirstChildByName(dwNameHash) - : nullptr; - if (!pTemplateChosen || - pTemplateChosen->GetElementType() != XFA_Element::Subform) { - pTemplateChosen = - pTemplateRoot->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); - } - if (!pTemplateChosen) - return; - - CXFA_Form* pFormRoot = - m_pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form); - bool bEmptyForm = false; - if (!pFormRoot) { - bEmptyForm = true; - pFormRoot = static_cast<CXFA_Form*>( - CreateNode(XFA_PacketType::Form, XFA_Element::Form)); - ASSERT(pFormRoot); - pFormRoot->JSObject()->SetCData(XFA_Attribute::Name, L"form", false, false); - m_pRootNode->InsertChild(pFormRoot, nullptr); - } else { - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> - sIterator(pFormRoot); - for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode; - pNode = sIterator.MoveToNext()) { - pNode->SetFlag(XFA_NodeFlag_UnusedNode); - } - } - - CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer( - this, pFormRoot, pTemplateChosen, false, nullptr); - ASSERT(pSubformSetNode); - if (!pDataTopLevel) { - WideString wsFormName = - pSubformSetNode->JSObject()->GetCData(XFA_Attribute::Name); - WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" : wsFormName); - - pDataTopLevel = static_cast<CXFA_DataGroup*>( - CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup)); - pDataTopLevel->JSObject()->SetCData(XFA_Attribute::Name, wsDataTopLevelName, - false, false); - pDataTopLevel->SetXMLMappingNode( - pdfium::MakeUnique<CFX_XMLElement>(wsDataTopLevelName)); - - CXFA_Node* pBeforeNode = pDataRoot->GetFirstChild(); - pDataRoot->InsertChild(pDataTopLevel, pBeforeNode); - } - - ASSERT(pDataTopLevel); - CreateDataBinding(pSubformSetNode, pDataTopLevel, true); - for (CXFA_Node* pTemplateChild = pTemplateChosen->GetFirstChild(); - pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { - if (NeedGenerateForm(pTemplateChild, true)) { - XFA_NodeMerge_CloneOrMergeContainer(this, pSubformSetNode, pTemplateChild, - true, nullptr); - } else if (pTemplateChild->IsContainerNode()) { - DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, pDataTopLevel, - false, true, true); - } - } - if (pDDRoot) - UpdateDataRelation(pDataRoot, pDDRoot); - - DataMerge_UpdateBindingRelations(pSubformSetNode); - CXFA_PageSet* pPageSetNode = - pSubformSetNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet); - while (pPageSetNode) { - m_pPendingPageSet.push_back(pPageSetNode); - CXFA_PageSet* pNextPageSetNode = - pPageSetNode->GetNextSameClassSibling<CXFA_PageSet>( - XFA_Element::PageSet); - pSubformSetNode->RemoveChild(pPageSetNode, true); - pPageSetNode = pNextPageSetNode; - } - - if (bEmptyForm) - return; - - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( - pFormRoot); - CXFA_Node* pNode = sIterator.MoveToNext(); - while (pNode) { - if (pNode->IsUnusedNode()) { - if (pNode->IsContainerNode() || - pNode->GetElementType() == XFA_Element::InstanceManager) { - CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext(); - pNode->GetParent()->RemoveChild(pNode, true); - pNode = pNext; - } else { - pNode->ClearFlag(XFA_NodeFlag_UnusedNode); - pNode->SetFlagAndNotify(XFA_NodeFlag_Initialized); - pNode = sIterator.MoveToNext(); - } - } else { - pNode->SetFlagAndNotify(XFA_NodeFlag_Initialized); - pNode = sIterator.MoveToNext(); - } - } -} - -void CXFA_Document::DoDataRemerge(bool bDoDataMerge) { - CXFA_Node* pFormRoot = ToNode(GetXFAObject(XFA_HASHCODE_Form)); - if (pFormRoot) { - while (CXFA_Node* pNode = pFormRoot->GetFirstChild()) - pFormRoot->RemoveChild(pNode, true); - - pFormRoot->SetBindingNode(nullptr); - } - m_rgGlobalBinding.clear(); - - if (bDoDataMerge) - DoDataMerge(); - - CXFA_LayoutProcessor* pLayoutProcessor = GetLayoutProcessor(); - pLayoutProcessor->SetForceReLayout(true); -} |