// The original Events list was created to exchange data from RAD with // other tools, such as INCC. A columnar text file was defined, where the // first row in the file representing the columns and titles. // The RADEventsXML class maintains an array of strings, indexed by the // type RADEventField, declaring the same column titles. These titles // are represented in the XML document processed by the class. // // Returns: // IXMLDOMElement: the constructed Columns node, // or a NULL pointer if processing failed. // /////////////////////////////////////////////////////// IXMLDOMElement* RADEventsXML::ConstructColumnsNode() { IXMLDOMElement *pColumns = NULL; IXMLDOMElement *pTitle = NULL; IXMLDOMNode *pIXMLDOMNode = NULL; _bstr_t bstr1; _bstr_t bstr2; HRESULT hr = 0; try { // create <Columns> bstr1 = "Columns"; hr = m_pXMLDom->createElement(bstr1,&pColumns); TESTHR(hr); AddWhiteSpaceToNode(bstr_wsnt, pColumns); // for each title element // create <Title>value</Title> bstr2 = "Title"; for (int i = 0; i < eRADAttMax; i++) { pTitle = NULL; // create <Title>value</Title> hr = m_pXMLDom->createElement(bstr2,&pTitle); TESTHR(hr); bstr1 = RADEventsList::Titles[i]; hr = pTitle->put_text(bstr1); TESTHR(hr); // append it as a child to <Columns> hr = pColumns->appendChild(pTitle, &pIXMLDOMNode); TESTHR(hr); AddWhiteSpaceToNode(bstr_wsnt, pColumns); } } catch(...) { dprintf( "%s:%d HRCALL Failed: %s\n 0x%.8x = %s\n", __FILE__, __LINE__, "ConstructColumnsNode Exception" , hr); } return pColumns; }
/////////////////////////////////////////////////////// // RADEventsXML::ConstructEventParentNodeTree // // Creates an XMLEvent node for the root of the XML document. // The root node is named "IR", // the Events container node is a child of "IR": // <?xml version="1.0" ?> // <IR> // <Events> // </Events> // <IR> // // // Returns: // IXMLDOMElement: the constructed IR/Eevents node, // or a NULL pointer if processing failed. // /////////////////////////////////////////////////////// IXMLDOMElement* RADEventsXML::ConstructEventParentNodeTree() { IXMLDOMNode *pIXMLDOMNode = NULL; IXMLDOMElement *pIR = NULL; IXMLDOMElement *pEvents = NULL; IXMLDOMProcessingInstruction *pi=NULL; _bstr_t bstr1; _bstr_t bstr2; HRESULT hr; // Create a processing instruction element. <?xml version="1.0" ?> bstr1 = "xml"; bstr2 = "version='1.0'"; HRCALL(m_pXMLDom->createProcessingInstruction( bstr1,bstr2, &pi), "createProcessingInstruction:"); m_pXMLDom->appendChild(pi, &pIXMLDOMNode); // put it first // construct <IR><Events></Events></IR> bstr1 = "Events"; HRCALL(m_pXMLDom->createElement(bstr1,&pEvents),"create <Events> "); bstr1 = "IR"; HRCALL(m_pXMLDom->createElement(bstr1,&pIR),"create <IR>"); HRCALL(pIR->appendChild(pEvents, &pIXMLDOMNode), ""); AddWhiteSpaceToNode(bstr_wsnt, pIR); m_pXMLDom->appendChild(pIR, &pIXMLDOMNode); // attach to DOM clean: if (pi) pi->Release(); if (pIR) pIR->Release(); return pEvents; }
/////////////////////////////////////////////////////// // RADEventsXML::ConstructXMLDoc // // Constructs the XML document from the RADEventList 'rel'. // Note: the current XML document is replaced, not updated, // by this operation. // // Input/Output: // rel - the RADEventsList instance that is converted to an // XML document. // /////////////////////////////////////////////////////// bool RADEventsXML::ConstructXMLDoc(RADEventsList& rel) { _bstr_t bstr; HRESULT hr; IXMLDOMNode *pColNode = NULL; IXMLDOMNode *pIXMLDOMNode = NULL; if (this->m_pXMLDom != NULL) { if (this->m_pIRNode == NULL) // might need to create the entire tree, the file didn't exist // or might need to just create the tree down to the Events level { this->m_pIRNode = ConstructEventParentNodeTree(); } if (this->m_pIRNode == NULL ) return false; // attempt to create IR/Events has failed bstr = m_xcolpath; HRCALL(m_pXMLDom->selectSingleNode(bstr, &pColNode), "selectSingleNode"); if (pColNode == NULL) { pColNode = ConstructColumnsNode(); if (pColNode) { HRCALL(m_pIRNode->appendChild(pColNode,&pIXMLDOMNode), ""); AddWhiteSpaceToNode(bstr_wsnt, m_pIRNode); } else // if (pColNode == NULL) return false; // forced re-selection of the newly constructed node tree has failed } } else return false; // no DOM means punt clean: return ProcessEvents(rel, false); // build the event list on the IR/Events tree }
//add Id array to a document fragment node HRESULT AddIdsNode( IXMLDOMDocument* pDOM, BSTR indentBstr, const wchar_t* wszIdsNodeName, const wchar_t* wszIdsNodeAttribute, const wchar_t* wszIdNode, const std::vector<int>& ids, IXMLDOMDocumentFragment* pdf // Release is completed outside ) { VARIANT var; BSTR bstr = NULL; BSTR bstr_wst = SysAllocString(L"\t"); IXMLDOMElement* pe = NULL; IXMLDOMDocumentFragment* pdfSub = NULL; IXMLDOMAttribute *pa = NULL; IXMLDOMAttribute *pa1 = NULL; HRESULT hr = S_OK; do { //create a Node to hold ids. bstr = SysAllocString(wszIdsNodeName); HR_SUCCESSCALL( pDOM->createElement(bstr, &pe), hr ); SAFE_BSTR_RELEASE(bstr); //create a attribute for the <wszIdsNodeName> element, and //assign the element num as the attribute value. //get ids num string size_t idsNum = ids.size(); const int radix = 10; const size_t sizeOfstr = 30; wchar_t wszIdsNumString[sizeOfstr] = {0}; _ultow_s(static_cast<unsigned long>(idsNum), wszIdsNumString, sizeOfstr, radix); //put num string into attribute bstr = SysAllocString(wszIdsNodeAttribute); VariantInit(&var); V_BSTR(&var) = SysAllocString(wszIdsNumString); V_VT(&var) = VT_BSTR; HR_SUCCESSCALL( pDOM->createAttribute(bstr, &pa), hr ); HR_SUCCESSCALL( pa->put_value(var), hr ); HR_SUCCESSCALL( pe->setAttributeNode(pa, &pa1), hr ); //create a document fragment to hold ids sub-elements. HR_SUCCESSCALL( pDOM->createDocumentFragment(&pdfSub), hr ); //add ids to pdfSub for( size_t i=0; i < idsNum; ++i ) { int id = ids[i]; WCHAR wszIdString[sizeOfstr] = {0}; _itow_s(id, wszIdString, sizeOfstr, radix); //add white space before <id> HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr ); HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr ); HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, wszIdNode, wszIdString, pdfSub), hr ); } //test whether it is successful in "add ids to pdfSub" HR_SUCCESSCALL( hr, hr ); //add ids array to document fragment node HR_SUCCESSCALL( AppendChildToParent(pdfSub, pe), hr ); HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pe), hr ); HR_SUCCESSCALL( AppendChildToParent(pe, pdf), hr ); }while(0); //release the com objects SAFE_COM_RELEASE(pa1); SAFE_COM_RELEASE(pa); SAFE_COM_RELEASE(pdfSub); SAFE_COM_RELEASE(pe); //release the bstr and variant SAFE_BSTR_RELEASE(bstr); SAFE_BSTR_RELEASE(bstr_wst); VariantClear(&var); return hr; }
//add boundary to shot or sub shot fragment node HRESULT AddBoundaryNodeToDocumentFragment( IXMLDOMDocument* pDOM, BSTR indentBstr, IXMLDOMDocumentFragment* pdf, // Release is completed outside unsigned int bgnFrameId, unsigned int endFrameId, __int64 bgnFrameTime, __int64 endFrameTime) { BSTR bstr = NULL; BSTR bstr_wst = SysAllocString(L"\t"); IXMLDOMElement* pe = NULL; IXMLDOMDocumentFragment* pdfSub = NULL; HRESULT hr = S_OK; do { //create a Node to hold boundary. bstr = SysAllocString(L"Boundary"); HR_SUCCESSCALL( pDOM->createElement(bstr, &pe), hr ); SAFE_BSTR_RELEASE(bstr); //create a document fragment to hold boundary's sub-elements. HR_SUCCESSCALL( pDOM->createDocumentFragment(&pdfSub), hr ); //add sub elements to pdfSub //add white space before <BgnFrameId> HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr ); HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr ); const int radix = 10; const size_t sizeOfstr = 30; wchar_t wszBgnFrmIdString[sizeOfstr] = {0}; _itow_s(bgnFrameId, wszBgnFrmIdString, sizeOfstr, radix); HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"BgnFrameId", wszBgnFrmIdString, pdfSub), hr ); //<EndFrameId> HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr ); HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr ); wchar_t wszEndFrmIdString[sizeOfstr] = {0}; _itow_s(endFrameId, wszEndFrmIdString, sizeOfstr, radix); HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"EndFrameId", wszEndFrmIdString, pdfSub), hr ); //<BgnFrameTime> HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr ); HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr ); //begintime wchar_t wszBgnFrmTimeString[sizeOfstr*2] = {0}; _i64tow_s(bgnFrameTime, wszBgnFrmTimeString, sizeOfstr*2, 10); HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"BgnFrameTime", wszBgnFrmTimeString, pdfSub), hr ); //<EndFrameId> HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr ); HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr ); //endtime wchar_t wszEndFrmTimeString[sizeOfstr*2] = {0}; _i64tow_s(endFrameTime, wszEndFrmTimeString, sizeOfstr*2, 10); HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"EndFrameTime", wszEndFrmTimeString, pdfSub), hr ); //add Boundary to document fragment node HR_SUCCESSCALL( AppendChildToParent(pdfSub, pe), hr ); HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pe), hr ); HR_SUCCESSCALL( AppendChildToParent(pe, pdf), hr ); }while(0); //release com object SAFE_COM_RELEASE(pdfSub); SAFE_COM_RELEASE(pe); //release bstr SAFE_BSTR_RELEASE(bstr); SAFE_BSTR_RELEASE(bstr_wst); return hr; }
/////////////////////////////////////////////////////// // RADEventsXML::ProcessEvents // // Method to process a list of events, either transforming XML // into RADEvents, or RADEvents into XML event nodes. // Invoked by the Populate and Persist methods. // // When transforming the RADEvent objects on the list 'rel' into // XML Event nodes, a new XML Event node is created, and appended // to the XML Events node of the XML document. // // When transforming the XML Events node with XML Event nodes, each // XML Event node is transformed to a RADEvent object, and the RADEvent // object is appended to the RADEventsList 'rel'. // // Input/Output: // rel - the RADEventsList instance // bExtract - processing toggle: // When true, run through the XML event nodes, creating // RADEvent objects on 'rel'. // When false, run through the RADEvent objects, creating // XML event nodes on the XML document. // /////////////////////////////////////////////////////// bool RADEventsXML::ProcessEvents(RADEventsList& rel, bool bExtract) { // if bExtract, we want to read the XML events and populate the list of event objects // first: get count of events nodes // second: // for each event node // get the node // create a RADEvent, using the node attributes to populate it // insert the RADEvent object into the RADEventsList 'rel' // end // else, not bExtract, we want to transform the list of RADEvent objects into an XML document // for each RADEvent on the RADEventsList 'rel, // create a new XML Event Node, using each stirng value as an attribute value // append the XML Event node to the <IR/Events> node // end HRESULT hr; _bstr_t xbstr = m_xirevsevpath; if (bExtract) // converting from XML <Event> to RADEvent { IXMLDOMNodeList* pXMLDomNodeList = NULL; HRCALL(m_pXMLDom->selectNodes(xbstr, &pXMLDomNodeList), "selectNodes"); if (pXMLDomNodeList) { long count = 0; HRCALL(pXMLDomNodeList->get_length(&count), "get_length"); IXMLDOMNode *pEventNode=NULL; for (long i=0; i<count; i++) { HRCALL(pXMLDomNodeList->get_item(i, &pEventNode), "get_item: "); if (bDebug) { BSTR dbg1str; BSTR dbg2str; HRCALL(pEventNode->get_nodeName(&dbg1str), "get_nodeName: "); dprintf("Node (%d), <%S>:\n",i, static_cast<wchar_t*>(dbg1str)); HRCALL(pEventNode->get_xml(&dbg2str), "get_xml: "); dprintf("\t%S\n", static_cast<wchar_t*>(dbg2str)); } RADEvent* p = XMLToEvent(pEventNode); rel.AddToEnd(p); if (bDebug) { dprintf(p->Image()); } if (pEventNode) pEventNode->Release(); } pXMLDomNodeList->Release(); } else { ReportParseError(m_pXMLDom, "Error while calling ProcessEvents/selectNodes "); } } else // converting from RADEvent to XML <Event> { IXMLDOMElement * pE; IXMLDOMNode *pIXMLDOMNode = NULL; long i = 0; POSITION pos = rel.GetHeadPosition(); while( pos != NULL ) { RADEvent* p = (RADEvent*)rel.GetNext( pos ); pE = ConstructEventNode(p); if (pE) { HRCALL(m_pIRNode->appendChild(pE,&pIXMLDOMNode), ""); AddWhiteSpaceToNode(bstr_wsnt, m_pIRNode); i++; } } } clean: if (FAILED(hr)) return false; else return true; }