public void processNodes() { // Loop through the template and accumulate the output while (templateParser.HasNextNode()) { XmlNode currentNode = templateParser.GetNextNode(); switch (templateParser.GetNodeType(currentNode)) { case NodeType.Data: dataElement.EvaluateData(currentNode); break; case NodeType.If: conditionEvaluator.EvaluateCondition(currentNode); break; case NodeType.ForEach: loopEvaluator.EvaluateLoop(currentNode); break; case NodeType.ForEachRows: table.FetchTable(currentNode); break; default: if (currentNode.NodeType == XmlNodeType.Element) { ExportCore.WriteLog("Node type [" + ((XmlElement)currentNode).Name + "] not supported. Will be ignored"); } break; } } }
private void processNodes(XmlNode loopNode, bool batchLevel) { foreach (XmlNode node in loopNode.ChildNodes) { switch (node.Name) { case Constants.NodeTypeString.SE_IF: conditionEvaluator.EvaluateCondition(node); break; case Constants.NodeTypeString.SE_FOREACH: if (batchLevel) { EvaluateLoopForPagesOfFile(node); } else { new SmartExportException("Node type [" + ((XmlElement)node).Name + "] not supported in levels lower than page."); } break; case Constants.NodeTypeString.SE_ROWS: if (node.Attributes == null || node.Attributes.Count > 0 || string.IsNullOrEmpty(node.Attributes["tablename"].Value)) { string message = ""; if (batchLevel) { message = "Its mandatory to specify the table name " + "when the for-each-rows tag " + "is used within se:for-each tag for document."; } else { message = "Its mandatory to specify the " + "table name when the for-each-rows tag " + "is used within se:for-each tag for pages."; } new SmartExportException(message); } table.FetchTable(node); break; case Constants.NodeTypeString.SE_DATA: dataElement.EvaluateData(node); break; default: if (node.NodeType == XmlNodeType.Element) { ExportCore.WriteLog("Node type [" + ((XmlElement)node).Name + "] not supported. Will be ignored"); } break; } } }
private void initializeTableObjectForBatch(XmlNode tableNode) { DCODataRetrieverWithoutDoc dCODataRetriever = new DCODataRetrieverWithoutDoc(); string filename = (string)Globals.Instance.GetData(Constants.forLoopString.CURRENTFILE); if (!string.IsNullOrEmpty(filename)) { // when association is at batch level its mandatory to specify table name if (tableNode.Attributes != null && tableNode.Attributes.Count > 0 && !string.IsNullOrEmpty(tableNode.Attributes["tablename"].Value)) { //the table objects of the specified table name that are present across multiple pages //of the file are fetched tableDCOs.AddRange( dCODataRetriever.getTablesForFile(filename, tableNode.Attributes["tablename"].Value)); if (tableDCOs.Count == 0) { ExportCore.WriteLog(tableNode.Attributes["tablename"] + " table is not found in document " + DCO.ID); } } else { string message = "Its mandatory to specify the table name when the for-each-rows" + " tag is associated at batch level."; ExportCore.WriteLog(message); new SmartExportException(message); } } }
/// <summary> /// The method value of the DCO expression from the current file. /// <param name="DCOTree" >DCO expression that refers to a field in the file.</param> /// </summary> public string getDCOValueForFile(string DCOTree) { string filename = (string)Globals.Instance.GetData(Constants.forLoopString.CURRENTFILE); Dictionary <string, List <string> > filePageMap = (Dictionary <string, List <string> >)Globals.Instance.GetData(Constants.FILE_PAGE_MAP); List <string> pages = (List <string>)filePageMap[filename]; string output = ""; DCOTree = DCOTree.Replace("[", "").Replace("]", ""); char[] sep = { '.' }; string[] dcoArray = DCOTree.Split(sep); if (CurrentDCO.ObjectType() != Constants.Batch) { throw new SmartExportException("getDCOValueForFile(" + DCOTree + ") can be used at batch level only. "); } foreach (string pageID in pages) { TDCOLib.DCO page = CurrentDCO.FindChild(pageID); // Validate DCOTree expression against the current DCO // match page type and parent type of page if (page.Parent().ObjectType() == Constants.Batch && dcoArray[1] == page.Type) { output += page.FindChild(dcoArray[2]).Text; if (!string.IsNullOrEmpty(output)) { break; } } else { ExportCore.WriteLog(" The expression " + DCOTree + " is not valid for page " + pageID); } } return(output); }
public void processNodes() { DCODataRetrieverWithoutDoc dCODataRetriever = new DCODataRetrieverWithoutDoc(); if (CurrentDCO.ObjectType() == Constants.Batch) { dCODataRetriever.createFilePageMap(); } // Loop through the template and accumulate the output while (templateParser.HasNextNode()) { XmlNode currentNode = templateParser.GetNextNode(); switch (templateParser.GetNodeType(currentNode)) { case NodeType.Header: dataElement.setIsHeader(true); dataElement.EvaluateData(currentNode); dataElement.setIsHeader(false); break; case NodeType.Data: dataElement.EvaluateData(currentNode); break; case NodeType.If: conditionEvaluator.EvaluateCondition(currentNode); break; case NodeType.ForEach: loopEvaluator.EvaluateLoop(currentNode); break; case NodeType.ForEachRows: table.FetchTable(currentNode); break; default: if (currentNode.NodeType == XmlNodeType.Element) { ExportCore.WriteLog("Node type [" + ((XmlElement)currentNode).Name + "] not supported. Will be ignored"); } break; } } }
/// <summary> /// The method Evaluates for loop. /// <param name="loopNode">XML node of Foreach</param> /// <param name="DCO">Current iteration DCO of the parent for-each loop</param> /// </summary> public void EvaluateLoop(XmlNode loopNode, TDCOLib.IDCO DCO) { Stopwatch sw = Stopwatch.StartNew(); DataElement dataElement = new DataElement(); Conditions conditionEvaluator = new Conditions(); Tables table = new Tables(); try { int forEachlevel = getIntValueForEachObjectType(loopNode.Attributes["select"].Value); nestingLevel = setAndValidateNestingLevel(loopNode); validateForLoop(forEachlevel, DCO); for (int i = 0; i < DCO.NumOfChildren(); i++) { //setting the currentIterationDCO , so that it can be used in DCODataRetreiver to get the data. Globals.Instance.SetData(Constants.forLoopString.CURRENTITERATIONDCO, DCO.GetChild(i)); foreach (XmlNode node in loopNode.ChildNodes) { switch (node.Name) { case Constants.NodeTypeString.SE_IF: conditionEvaluator.EvaluateCondition(node); break; case Constants.NodeTypeString.SE_FOREACH: Loops loopEvaluator = new Loops(); loopEvaluator.EvaluateLoop(node, DCO.GetChild(i)); break; case Constants.NodeTypeString.SE_ROWS: if (node.Attributes == null || node.Attributes.Count > 0 || string.IsNullOrEmpty(node.Attributes["tablename"].Value)) { new SmartExportException("Its mandatory to specify the table name when the for-each-rows tag " + "is used within se:for-each tag for tables."); } if (node.Attributes["tablename"].Value == DCO.GetChild(i).ID) { table.FetchTable(node); } break; case Constants.NodeTypeString.SE_DATA: dataElement.EvaluateData(node); break; default: if (node.NodeType == XmlNodeType.Element) { ExportCore.WriteLog("Node type [" + ((XmlElement)node).Name + "] not supported. Will be ignored"); } break; } } //setting it to empty after every iteration. Globals.Instance.SetData(Constants.forLoopString.CURRENTITERATIONDCO, Constants.EMPTYSTRING); } } catch (System.Exception exp) { string message = exp.Message; //if the problem was already caught at the child node level the line number // information would be already present in the exception message if (!message.Contains("Problem found at line number")) { TemplateParser templateParser = (TemplateParser)Globals.Instance.GetData(Constants.GE_TEMPLATE_PARSER); message = "Problem found at line number : " + templateParser.GetLineNumberForNode(loopNode) + "\n" + exp.Message; } //setting it to empty after every iteration. Globals.Instance.SetData(Constants.forLoopString.CURRENTITERATIONDCO, Constants.EMPTYSTRING); throw new SmartExportException(message); } ExportCore.WriteDebugLog(" EvaluateLoop " + loopNode + " completed in " + sw.ElapsedMilliseconds + " ms."); sw.Stop(); }
public void writeToFile(Dictionary <String, String> singleOutputFileNameMap) { try { // this ckeck is done to prevent empty file getting generated if (outputStringList.Count == 0 && !tempFileNameMap.ContainsKey(templateParser.GetOutputFileName())) { exportCore.WriteLog("Empty content. Skipping writing to file: " + templateParser.GetOutputFileName()); return; } bool clearBuffer = false; string outputFileName = null; string outputFilePath = null; //this scenario happens only when the project doesn't have document and the action is attached at batch level //and the collate batch output flag is false if (null == singleOutputFileNameMap) { string prefix = ""; //names output file with the name of the input file if true if (templateParser.NameBatchOutputAfterInput()) { prefix = Path.GetFileNameWithoutExtension((string)Globals.Instance.GetData(Constants.forLoopString.CURRENTFILE)); } else { //names output file with thevalue sepcified in filename tag or use the default name prefix = templateParser.GetOutputFileName(); } outputFileName = prefix + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-fffffff") + '.' + templateParser.GetOutputFileExt(); outputFilePath = Path.Combine(templateParser.GetOutputDirectory(), outputFileName); clearBuffer = true; } else { outputFileName = templateParser.GetOutputFileName() + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-fffffff") + '.' + templateParser.GetOutputFileExt(); outputFilePath = Path.Combine(templateParser.GetOutputDirectory(), templateParser.AppendToFile() ? singleOutputFileNameMap[templateParser.GetOutputFileName()] + "." + templateParser.GetOutputFileExt() : outputFileName); } //If append to file is false and one iteration is complete, then code will rename temp file to actual file name //and delete the entry in the map, so in next iteration new temp file is created for this template //as append to file is false if (!templateParser.AppendToFile() && tempFileNameMap.ContainsKey(templateParser.GetOutputFileName())) { string tempPath = tempFileNameMap[templateParser.GetOutputFileName()]; createOrAppendToFile(tempPath, clearBuffer); File.Move(tempPath, outputFilePath); tempFileNameMap.Remove(templateParser.GetOutputFileName()); return; } //if appendtofile is true and temp map has an entry for temp file, for first iteration data is written in temp file //and then renamed to actual file, for all next iteration the data from the list is added to the actual file //not in temp file. //this condition will pass only for first iteration. if (templateParser.AppendToFile() && tempFileNameMap.ContainsKey(templateParser.GetOutputFileName()) && !File.Exists(outputFilePath)) { string tempPath = tempFileNameMap[templateParser.GetOutputFileName()]; createOrAppendToFile(tempPath, clearBuffer); File.Move(tempPath, outputFilePath); tempFileNameMap[templateParser.GetOutputFileName()] = outputFilePath; return; } //if there are no temp file created then data is flushed to output file here. createOrAppendToFile(outputFilePath, clearBuffer); } catch (System.Exception exp) { exportCore.WriteErrorLog(exp.StackTrace); throw new SmartExportException("Error while writing output to file: " + exp.Message); } }
private bool EvaluateIndividualCondition(string conditionText) { ExportCore.WriteLog(" Evaluating condition " + conditionText); bool response = false; List <string> operands = new List <string>(Regex.Split(conditionText, Constants.ALLOWED_OPERATORS)); // check if there are 2 operands if (3 != operands.Count) { throw new SmartExportException("Unsupported syntax. Check documentation: " + conditionText); } //check if allowed operator are used if (!Regex.Match(operands[1].Trim(), Constants.ALLOWED_OPERATORS).Success) { throw new SmartExportException("Unsupported syntax. Check documentation: " + conditionText); } if (operands[1].Trim() == Constants.Operators.CONTAINS && !operands[0].Trim().Equals(Constants.ConditionString.FILE_PAGE_TYPES)) { throw new SmartExportException("CONTAINS operator can be used only with " + Constants.ConditionString.FILE_PAGE_TYPES + ". Invalid usage: " + conditionText); } Regex rx = new Regex(pattern); for (int i = 0; i < operands.Count; i++) { //replace DCO referencing expressions if (rx.IsMatch(operands[i].Trim())) { string expr = operands[i]; operands[i] = dCODataRetriever.getDCOValue(operands[i].Trim()); if ("" == operands[i]) { ExportCore.WriteLog("Could not find value for " + expr + " in " + conditionText); return(false); } } else if (Constants.ConditionString.DOCUMENT_TYPE == operands[i].Trim()) { operands[i] = dCODataRetriever.getDocumentType(); } else if (Constants.ConditionString.PAGE_TYPE == operands[i].Trim()) { operands[i] = dCODataRetriever.getPageType(); } else if (Constants.ConditionString.TABLE_TYPE == operands[i].Trim()) { operands[i] = dCODataRetriever.getTableType(); } else if (Constants.ConditionString.FILE_PAGE_TYPES == operands[i].Trim()) { operands[i] = dCODataRetriever.getPageTypesInFile(); } else { operands[i] = operands[i].Trim(); } } //check if comparisons are done for same data types string operandOneType = dataTypeChecker.getType(operands[0].Trim()); string operandTwoType = dataTypeChecker.getType(operands[2].Trim()); // allow operations on numeric opernads even if they are not of the same data type if (operandOneType != operandTwoType && dataTypeChecker.numericTypes.Contains(operandOneType) && dataTypeChecker.numericTypes.Contains(operandTwoType)) { operandTwoType = operandOneType = castNumericDataTypes(operandOneType, operandTwoType); } if (operandOneType != operandTwoType) { throw new SmartExportException("Invalid comparisons in : " + conditionText + " " + operandOneType + " " + operands[1] + " " + operandTwoType); } try { response = ExpressionEvaluator.evaluateExpression(operands[0].Trim(), operands[2].Trim(), operandOneType, operands[1].Trim()); } catch (Exception exp) { // Evaluating conditions using this technique is risky (injections) // Moreover, this API is deprecated. This is for the timebeing (to prototype and define the POV) // If conditions do not evaluate properly, write log and skip the condition // TODO: Lexical parser to get the conditions and transform them to c# code constructs string message = "Condition evalution failed for condition:" + conditionText; ExportCore.WriteErrorLog(message); ExportCore.WriteErrorLog(exp.StackTrace); throw new SmartExportException(message); } ExportCore.WriteLog(" Condition " + conditionText + " is evaluated as " + response); return(response); }
/// <summary> /// The method returns the value corresponding to the DCO expression specified, from the current DCO. /// <param name="DCOTree">DCO Expression in the format [DCO].[document_type].[page_type].[field_name]</param> /// <returns>The value corresponding to the DCO expression specified, from the current DCO.</returns> /// </summary> public virtual string getDCOValue(string DCOTree) { Stopwatch sw = Stopwatch.StartNew(); string output = ""; TDCOLib.IDCO currentIterationDCO = null; int objectType = CurrentDCO.ObjectType(); //If the call is from ForEach, this will be having a currentIterationDCO object. if (!Globals.Instance.GetData(Constants.forLoopString.CURRENTITERATIONDCO).Equals(Constants.EMPTYSTRING)) { currentIterationDCO = (TDCOLib.IDCO)Globals.Instance.GetData(Constants.forLoopString.CURRENTITERATIONDCO); objectType = currentIterationDCO.ObjectType(); } switch (objectType) { case Constants.Batch: string message = "Unable to find DCO reference at batch level due to ambiguity."; ExportCore.WriteLog(message); throw new SmartExportException(message); case Constants.Document: output = currentIterationDCO == null?getDCOValueForDocument(DCOTree) : getDCOValueForDocument(currentIterationDCO, DCOTree); break; case Constants.Page: output = currentIterationDCO == null?getDCOValueForPage(DCOTree) : getDCOValueForPage(DCOTree, currentIterationDCO.ID); break; case Constants.Field: output = currentIterationDCO == null?getDCOValueForField(DCOTree) : getDCOValueForField(currentIterationDCO, DCOTree); break; } ExportCore.WriteDebugLog(" getDCOValue(" + DCOTree + ") completed in " + sw.ElapsedMilliseconds + " ms."); sw.Stop(); return(output); }
public void EvaluateCondition(XmlNode ConditionNode) { Stopwatch sw = Stopwatch.StartNew(); bool ConditionEvaluated = false; try { //Evaluate the IF string CondText = ((XmlElement)ConditionNode).GetAttribute(Constants.SE_ATTRIBUTE_COND_TEST); ConditionEvaluation conditionEvaluation = new ConditionEvaluation(CondText); if (conditionEvaluation.CanEvaluate()) { processChildNodes(ConditionNode); ConditionEvaluated = true; } // Evaluate the ELSIFs if IF has not satisfied if (!ConditionEvaluated) { XmlNodeList elseIfNodeList = ConditionNode.ChildNodes; foreach (XmlNode elseIfNode in elseIfNodeList) { if (elseIfNode.Name == Constants.NodeTypeString.SE_ELSIF) { CondText = ((XmlElement)elseIfNode).GetAttribute(Constants.SE_ATTRIBUTE_COND_TEST); conditionEvaluation = new ConditionEvaluation(CondText); if (conditionEvaluation.CanEvaluate()) { processChildNodes(elseIfNode); ConditionEvaluated = true; break; } // reaching else node indicates there are no more nodes with node name ELSIF if (elseIfNode.Name == Constants.NodeTypeString.SE_ELSE) { break; } } } } // Evaluate the Else if (!ConditionEvaluated) { XmlNodeList elseNodeList = ConditionNode.ChildNodes; foreach (XmlNode elseNode in elseNodeList) { if (elseNode.Name == Constants.NodeTypeString.SE_ELSE) { processChildNodes(elseNode); ConditionEvaluated = true; break; } } } if (!ConditionEvaluated) { ExportCore.WriteLog("None of the conditions evaluated for the Node with test: " + CondText); } } catch (System.Exception exp) { string message = exp.Message; //if the problem was already caught at the child node level the line number // information would be already present in the exception message if (!message.Contains("Problem found at line number")) { TemplateParser templateParser = (TemplateParser)Globals.Instance.GetData(Constants.GE_TEMPLATE_PARSER); message = "Problem found at line number : " + templateParser.GetLineNumberForNode(ConditionNode) + "\n" + exp.Message; } throw new SmartExportException(message); } ExportCore.WriteDebugLog(" EvaluateCondition(" + ConditionNode + ") completed in " + sw.ElapsedMilliseconds + " ms."); sw.Stop(); }