private int HandleNotKnownManOptPos(string firstTokenString, int dependencyType) { if (dependencyType != 0) { if (firstTokenString.Contains("NOT")) { dependencyType |= DependencyType.GetNot(); } if (firstTokenString.Contains("KNOWN")) { dependencyType |= DependencyType.GetKnown(); } if (firstTokenString.Contains("MANDATORY")) { dependencyType |= DependencyType.GetMandatory(); } if (firstTokenString.Contains("OPTIONALLY")) { dependencyType |= DependencyType.GetOptional(); } if (firstTokenString.Contains("POSSIBLY")) { dependencyType |= DependencyType.GetPossible(); } } return(dependencyType); }
/* * this method is to create virtual nodes where a certain node has 'AND' or 'MANDATORY_AND', and 'OR' children at the same time. * when a virtual node is created, all 'AND' children should be connected to the virtual node as 'AND' children * and the virtual node should be a 'OR' child of the original parent node */ public Dictionary <string, Node> HandlingVirtualNode(List <Dependency> dependencyList) { Dictionary <string, Node> virtualNodeMap = new Dictionary <string, Node>(); nodeSet.GetNodeMap().Values.ToList().ForEach((node) => { virtualNodeMap.Add(node.GetNodeName(), node); List <Dependency> dpList = dependencyList.Where(dp => node.GetNodeName().Equals(dp.GetParentNode().GetNodeName())).ToList(); /* * need to handle Mandatory, optionally, possibly NodeOptions */ int and = 0; int mandatoryAnd = 0; int or = 0; if (dpList.Count != 0) { foreach (Dependency dp in dpList) //can this for each loop be converted to dpList.stream().forEachOrdered() ? { if ((dp.GetDependencyType() & DependencyType.GetAnd()) == DependencyType.GetAnd()) { and++; if (dp.GetDependencyType() == (DependencyType.GetMandatory() | DependencyType.GetAnd())) { mandatoryAnd++; } } else if ((dp.GetDependencyType() & DependencyType.GetOr()) == DependencyType.GetOr()) { or++; } } bool hasAndOr = (and > 0 && or > 0) ? true : false; if (hasAndOr) { string parentNodeOfVirtualNodeName = node.GetNodeName(); Node virtualNode = new ValueConclusionLine("VirtualNode-" + parentNodeOfVirtualNodeName, Tokenizer.GetTokens("VirtualNode-" + parentNodeOfVirtualNodeName)); this.nodeSet.GetNodeIdMap().Add(virtualNode.GetNodeId(), "VirtualNode-" + parentNodeOfVirtualNodeName); virtualNodeMap.Add("VirtualNode-" + parentNodeOfVirtualNodeName, virtualNode); if (mandatoryAnd > 0) { dependencyList.Add(new Dependency(node, virtualNode, (DependencyType.GetMandatory() | DependencyType.GetOr()))); } else { dependencyList.Add(new Dependency(node, virtualNode, DependencyType.GetOr())); } dpList.Where(dp => dp.GetDependencyType() == DependencyType.GetAnd() || dp.GetDependencyType() == (DependencyType.GetMandatory() | DependencyType.GetAnd())) .ToList().ForEach(dp => dp.SetParentNode(virtualNode)); } } }); return(virtualNodeMap); }
public void HandleChild(string parentText, string childText, string firstKeywordsGroup, int lineNumber) { /* * the reason for using '*' at the last group of pattern within comparison is that * the last group contains No, Da, De, Ha, Url, Id. * In order to track more than one character within the square bracket of last group '*'(Matches 0 or more occurrences of the preceding expression) needs to be used. * */ int dependencyType = 0; // is 'ITEM' child line if (Regex.Match(childText, "(ITEM)(.*)").Success) { if (!Regex.Match(parentText, "(.*)(AS LIST)").Success) { HandleWarning(childText); return; } // is an indented item child childText = childText.Remove(childText.IndexOf("ITEM", StringComparison.CurrentCulture), "ITEM".Length).Trim(); MetaType?metaType = null; if (Regex.Match(parentText, "^(INPUT)(.*)").Success) { metaType = MetaType.INPUT; } else if (Regex.Match(parentText, "^(FIXED)(.*)").Success) { metaType = MetaType.FIXED; } HandleListItem(parentText, childText, metaType); } else // is 'A-statement', 'A IS B', 'A <= B', or 'A IS CALC (B * C)' child line { if (Regex.Match(firstKeywordsGroup, "^(AND\\s?)(.*)").Success) { dependencyType = HandleNotKnownManOptPos(firstKeywordsGroup, DependencyType.GetAnd()); // 8-AND | 1-KNOWN? 2-NOT? 64-MANDATORY? 32-OPTIONALLY? 16-POSSIBLY? } else if (Regex.Match(firstKeywordsGroup, "^(OR\\s?)(.*)").Success) { dependencyType = HandleNotKnownManOptPos(firstKeywordsGroup, DependencyType.GetOr()); // 4-OR | 1-KNOWN? 2-NOT? 64-MANDATORY? 32-OPTIONALLY? 16-POSSIBLY? } else if (Regex.Match(firstKeywordsGroup, "^(WANTS)").Success) { dependencyType = DependencyType.GetOr(); // 4-OR } else if (Regex.Match(firstKeywordsGroup, "^(NEEDS)").Success) { dependencyType = DependencyType.GetMandatory() | DependencyType.GetAnd(); // 8-AND | 64-MANDATORY } /* * the keyword of 'AND' or 'OR' should be removed individually. * it should NOT be removed by using firstToken string in Tokens.tokensList.get(0) * because firstToken string may have something else. * (e.g. string: 'AND NOT ALL Males' name should sound Male', then Token string will be 'UMLM', and 'U' contains 'AND NOT ALL'. * so if we used 'firstToken string' to remove 'AND' in this case as 'string.replace(firstTokenString)' * then it will remove 'AND NOT ALL' even we only need to remove 'AND' * */ Node data = null; nodeSet.GetNodeMap().TryGetValue(childText, out data); Tokens tokens = Tokenizer.GetTokens(childText); if (data == null) { Regex[] matchPatterns = { VALUE_MATCHER, COMPARISON_MATCHER, ITERATE_MATCHER, EXPRESSION_CONCLUSION_MATCHER, WARNING_MATCHER }; Node tempNode; List <string> possibleChildNodeKeyList; for (int i = 0; i < matchPatterns.Length; i++) { Regex regex = matchPatterns[i]; Match match = regex.Match(tokens.tokensString); if (match.Success) { switch (i) { case 4: // warningMatcher case HandleWarning(childText); break; case 0: // valueConclusionMatcher case data = new ValueConclusionLine(childText, tokens); tempNode = data; possibleChildNodeKeyList = nodeSet.GetNodeMap().Keys.Where(key => Regex.Match(key, "^(" + tempNode.GetVariableName() + ")(\\s+(IS(?!(\\s+IN\\s+LIST))).*)*$").Success).ToList(); if (possibleChildNodeKeyList.Count != 0) { possibleChildNodeKeyList.ForEach(item => { this.dependencyList.Add(new Dependency(tempNode, nodeSet.GetNodeMap()[item], DependencyType.GetOr())); //Dependency Type :OR }); } if (FactValue.GetValueInString(data.GetFactValue().GetFactValueType(), data.GetFactValue()).Equals("WARNING")) { HandleWarning(parentText); } break; case 1: // comparisonMatcher case data = new ComparisonLine(childText, tokens); FactValueType rhsType = ((ComparisonLine)data).GetRHS().GetFactValueType(); string rhsString = FactValue.GetValueInString(((ComparisonLine)data).GetRHS().GetFactValueType(), ((ComparisonLine)data).GetRHS()); string lhsString = ((ComparisonLine)data).GetLHS(); tempNode = data; possibleChildNodeKeyList = rhsType.Equals(FactValueType.STRING) ? nodeSet.GetNodeMap().Keys.Where(key => Regex.Match(key, "^(" + lhsString + ")(\\s+(IS(?!(\\s+IN\\s+LIST))).*)*$").Success || Regex.Match(key, "^(" + rhsString + ")(\\s+(IS(?!(\\s+IN\\s+LIST))).*)*$").Success).ToList() : nodeSet.GetNodeMap().Keys.Where(key => Regex.Match(key, "^(" + lhsString + ")(\\s+(IS(?!(\\s+IN\\s+LIST))).*)*$").Success).ToList(); if (possibleChildNodeKeyList.Count != 0) { possibleChildNodeKeyList.ForEach(item => { this.dependencyList.Add(new Dependency(tempNode, nodeSet.GetNodeMap()[item], DependencyType.GetOr())); //Dependency Type :OR }); } if (FactValue.GetValueInString(data.GetFactValue().GetFactValueType(), data.GetFactValue()).Equals("WARNING")) { HandleWarning(parentText); } break; case 2: // iteratenMatcher case data = new IterateLine(childText, tokens); if (FactValue.GetValueInString(data.GetFactValue().GetFactValueType(), data.GetFactValue()).Equals("WARNING")) { HandleWarning(parentText); } break; case 3: //exprConclusionMatcher case data = new ExprConclusionLine(childText, tokens); /* * In this case, there is no mechanism to find possible parent nodes. * I have brought 'local variable' concept for this case due to it may massed up with structuring node dependency tree with topological sort * If ExprConclusion node is used as a child, then it means that this node is a local node which has to be strictly bound to its parent node only. */ if (FactValue.GetValueInString(data.GetFactValue().GetFactValueType(), data.GetFactValue()).Equals("WARNING")) { HandleWarning(parentText); } break; } data.SetNodeLine(lineNumber); this.nodeSet.GetNodeMap().Add(data.GetNodeName(), data); this.nodeSet.GetNodeIdMap().Add(data.GetNodeId(), data.GetNodeName()); break; } } } this.dependencyList.Add(new Dependency(this.nodeSet.GetNode(parentText), data, dependencyType)); } }