From b5a6c5d4e32c96986fc5abe8c09a2b601c964ce0 Mon Sep 17 00:00:00 2001 From: "Wainaina George (Swagfin)" Date: Thu, 13 Apr 2023 00:27:59 +0300 Subject: [PATCH 1/4] added ignore case on if conditions --- ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs b/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs index 28f9d55..f1d57cc 100644 --- a/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs +++ b/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs @@ -101,7 +101,7 @@ internal static TemplatedContent GenerateTemplateFromFileContents(string fileCon //Match =, !=, >, >=, <, and <=. //Without ElseIf-> {{\s*#if\s*\(\s*(\w+)\s*([!=<>]=?|<|>)\s*([\w\s.-]+)\s*\)\s*}}([\s\S]*?){{\s*#endif\s*}} string _matchWithElseIf = @"{{\s*#if\s*\(\s*(?\w+)\s*(?==|!=|>=|<=|>|<)\s*(?[^)]+)\s*\)\s*}}(?[\s\S]*?)(?:{{\s*#else\s*}}(?[\s\S]*?))?{{\s*#endif\s*}}"; - while (Regex.IsMatch(templatedContent.Template, _matchWithElseIf)) + while (Regex.IsMatch(templatedContent.Template, _matchWithElseIf, RegexOptions.IgnoreCase)) { templatedContent.Template = Regex.Replace(templatedContent.Template, _matchWithElseIf, match => { @@ -117,7 +117,7 @@ internal static TemplatedContent GenerateTemplateFromFileContents(string fileCon }); // Return Replacement return _replaceCode; - }); + }, RegexOptions.IgnoreCase); } #endregion From ac294726433d4cd5ad8f24d9cff3a64dc25f99e8 Mon Sep 17 00:00:00 2001 From: "Wainaina George (Swagfin)" Date: Thu, 13 Apr 2023 02:05:25 +0300 Subject: [PATCH 2/4] added support for single line loop --- .../ObjectSemanticsTests.cs | 152 +++++++++++------- .../Algorithim/GavinsAlgorithim.cs | 101 ++++++------ ObjectSemantics.NET/Algorithim/ReplaceCode.cs | 4 +- .../Extensions/StringExtensions.cs | 14 -- 4 files changed, 150 insertions(+), 121 deletions(-) diff --git a/ObjectSemantics.NET.Tests/ObjectSemanticsTests.cs b/ObjectSemantics.NET.Tests/ObjectSemanticsTests.cs index e849bef..a18e7c0 100644 --- a/ObjectSemantics.NET.Tests/ObjectSemanticsTests.cs +++ b/ObjectSemantics.NET.Tests/ObjectSemanticsTests.cs @@ -47,7 +47,7 @@ public void Should_Map_Enumerable_Collection_In_Object() var template = new ObjectSemanticsTemplate { FileContents = @"{{ StudentName }} Invoices -{{ for-each-start:invoices }} +{{ #foreach(invoices) }} {{ Id }} {{ RefNo }} @@ -55,27 +55,54 @@ public void Should_Map_Enumerable_Collection_In_Object() {{ Amount:N0 }} {{ InvoiceDate:yyyy-MM-dd }} -{{ for-each-end:invoices }}" +{{ #endforeach }}" }; string generatedTemplate = TemplateMapper.Map(student, template); - string expectedResult = "John Doe Invoices" + - "\r\n" + - "\r\n 2" + - "\r\n INV_002" + - "\r\n Grade II Fees Invoice" + - "\r\n 2,000" + - "\r\n 2023-04-01" + - "\r\n" + - "\r\n" + - "\r\n 1" + - "\r\n INV_001" + - "\r\n Grade I Fees Invoice" + - "\r\n 320" + - "\r\n 2022-08-01" + - "\r\n"; + string expectedResult = @"John Doe Invoices + + + 2 + INV_002 + Grade II Fees Invoice + 2,000 + 2023-04-01 + + + + 1 + INV_001 + Grade I Fees Invoice + 320 + 2022-08-01 +"; + Assert.Equal(expectedResult, generatedTemplate, false, true, true); + } + + + [Fact] + public void Should_Map_Enumerable_Collection_SingleLine_Test() + { + //Create Model + Student student = new Student + { + StudentName = "John Doe", + Invoices = new List + { + new Invoice{ Id=2, RefNo="INV_002",Narration="Grade II Fees Invoice", Amount=2000, InvoiceDate= new DateTime(2023, 04, 01) }, + new Invoice{ Id=1, RefNo="INV_001",Narration="Grade I Fees Invoice", Amount=320, InvoiceDate= new DateTime(2022, 08, 01) } + } + }; + //Template + var template = new ObjectSemanticsTemplate + { + FileContents = @"{{ #foreach(invoices) }} [{{RefNo}}] {{ #endforeach }}" + }; + string generatedTemplate = TemplateMapper.Map(student, template); + string expectedResult = " [INV_002] [INV_001] "; Assert.Equal(expectedResult, generatedTemplate, false, true, true); } + [Fact] public void Should_Map_Multiple_Enumerable_Collection_On_Same_Template() { @@ -95,24 +122,27 @@ public void Should_Map_Multiple_Enumerable_Collection_On_Same_Template() FileContents = @" {{ StudentName }} Invoices LOOP #1 -{{ for-each-start:invoices }} +{{ #foreach(invoices) }}
{{ Id }} On Loop #1
-{{ for-each-end:invoices }} +{{ #endforeach }} LOOP #2 -{{ for-each-start:invoices }} +{{ #foreach(invoices) }}
{{ Id }} On Loop #2
-{{ for-each-end:invoices }} -" +{{ #endforeach }}" }; string generatedTemplate = TemplateMapper.Map(student, template); - string expectedResult = "\r\nJohn Doe Invoices" + - "\r\nLOOP #1" + - "\r\n
2 On Loop #1
" + - "\r\n
1 On Loop #1
" + - "\r\nLOOP #2" + - "\r\n
2 On Loop #2
" + - "\r\n
1 On Loop #2
" + - "\r\n"; ; + string expectedResult = @" +John Doe Invoices +LOOP #1 + +
2 On Loop #1
+ +
1 On Loop #1
+LOOP #2 + +
2 On Loop #2
+ +
1 On Loop #2
"; Assert.Equal(expectedResult, generatedTemplate, false, true, true); } @@ -156,7 +186,7 @@ public void Should_Return_Unknown_Properties_If_Not_Found_In_Object() FileContents = @"Unknown Object example: {{StudentIdentityCardXyx}}" }; string generatedTemplate = TemplateMapper.Map(student, template); - string expectedString = "Unknown Object example: {{StudentIdentityCardXyx}}"; + string expectedString = "Unknown Object example: {{ StudentIdentityCardXyx }}"; Assert.Equal(expectedString, generatedTemplate, false, true, true); } @@ -365,24 +395,29 @@ public void Should_Act_On_IfCondition_Having_Loop_As_Child() FileContents = @" {{ #if (invoices != null) }} {{ StudentName }} Invoices -{{ for-each-start:invoices }} +{{ #foreach(invoices) }} {{ Id }} {{ RefNo }} -{{ for-each-end:invoices }} +{{ #endforeach }} {{ #endif }}" }; string generatedTemplate = TemplateMapper.Map(student, template); - string expectedResult = "\r\n\r\nJohn Doe Invoices" + - "\r\n" + - "\r\n 2" + - "\r\n INV_002" + - "\r\n" + - "\r\n" + - "\r\n 1" + - "\r\n INV_001" + - "\r\n\r\n"; ; + string expectedResult = @" + +John Doe Invoices + + + 2 + INV_002 + + + + 1 + INV_001 + +"; Assert.Equal(expectedResult, generatedTemplate, false, true, true); } @@ -667,26 +702,33 @@ public void Should_Act_On_IfCondition_Having_ElseIf_Having_A_LoopBlock(bool popu {{ #if(invoices==null) }} -- no invoices found -- {{ #else }} -{{ for-each-start:invoices }} +{{ #foreach(invoices) }} {{ Id }} {{ RefNo }} -{{ for-each-end:invoices }} +{{ #endforeach }} {{ #endif }}" }; string generatedTemplate = TemplateMapper.Map(student, template); - string expectedResult = (populateInvoices) ? "\r\n" + - "\r\n" + - "\r\n 2" + - "\r\n INV_002" + - "\r\n" + - "\r\n" + - "\r\n 1" + - "\r\n INV_001" + - "\r\n\r\n" - - : "\r\n\r\n-- no invoices found --\r\n"; + string expectedResult = (populateInvoices) ? @" + + + + 2 + INV_002 + + + + 1 + INV_001 + +" + +: @" + +-- no invoices found -- +"; Assert.Equal(expectedResult, generatedTemplate, false, true, true); } diff --git a/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs b/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs index f1d57cc..f52767b 100644 --- a/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs +++ b/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs @@ -88,7 +88,7 @@ public static class GavinsAlgorithim if (property != null) clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, replaceCode.ReplaceRef, GetValueFromPropertyFormatted(property, replaceCode.FormattingCommand)); else - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, replaceCode.ReplaceRef, replaceCode.ReplaceCommand); + clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, replaceCode.ReplaceRef, @"{{ ##command## }}".Replace("##command##", replaceCode.ReplaceCommand)); } #endregion return clonedTemplate.Template; @@ -97,15 +97,16 @@ public static class GavinsAlgorithim internal static TemplatedContent GenerateTemplateFromFileContents(string fileContent, TemplateMapperOptions options) { TemplatedContent templatedContent = new TemplatedContent { Template = fileContent }; + long _replaceKey = 0; #region If Condition - //Match =, !=, >, >=, <, and <=. - //Without ElseIf-> {{\s*#if\s*\(\s*(\w+)\s*([!=<>]=?|<|>)\s*([\w\s.-]+)\s*\)\s*}}([\s\S]*?){{\s*#endif\s*}} + //Matches ==, !=, >, >=, <, and <= string _matchWithElseIf = @"{{\s*#if\s*\(\s*(?\w+)\s*(?==|!=|>=|<=|>|<)\s*(?[^)]+)\s*\)\s*}}(?[\s\S]*?)(?:{{\s*#else\s*}}(?[\s\S]*?))?{{\s*#endif\s*}}"; while (Regex.IsMatch(templatedContent.Template, _matchWithElseIf, RegexOptions.IgnoreCase)) { templatedContent.Template = Regex.Replace(templatedContent.Template, _matchWithElseIf, match => { - string _replaceCode = string.Format("R_IF_BLOCK_{0}", Guid.NewGuid().ToString().ToUpper()); + _replaceKey++; + string _replaceCode = string.Format("RIB_{0}", _replaceKey); templatedContent.ReplaceIfConditionCodes.Add(new ReplaceIfOperationCode { ReplaceRef = _replaceCode, @@ -122,62 +123,62 @@ internal static TemplatedContent GenerateTemplateFromFileContents(string fileCon #endregion #region Generate Obj Looop - Match regexLoopMatch = Regex.Match(templatedContent.Template, "{{\\s*for-each-start:([^()]+?)\\s*}}", RegexOptions.IgnoreCase); - Match regexLoopEnd = Regex.Match(templatedContent.Template, "{{\\s*for-each-end:([^()]+?)\\s*}}", RegexOptions.IgnoreCase); - while (regexLoopMatch.Success && regexLoopEnd.Success) + string _matchLoopBlock = @"{{\s*#\s*foreach\s*\(\s*(\w+)\s*\)\s*\}\}([\s\S]*?)\{\{\s*#\s*endforeach\s*}}"; + while (Regex.IsMatch(templatedContent.Template, _matchLoopBlock, RegexOptions.IgnoreCase)) { - int startAtIndex = templatedContent.Template.IndexOf(regexLoopMatch.Value); //Getting again index just incase it was replaced - int endOfCodeIndex = templatedContent.Template.IndexOf(regexLoopEnd.Value); //Getting again index just incase it was replaced - int endAtIndex = (endOfCodeIndex + regexLoopEnd.Length) - startAtIndex; - string subBlock = templatedContent.Template.Substring(startAtIndex, endAtIndex); - //Replace Code Block - string replaceCode = string.Format("REPLACE_LOOP_{0}", Guid.NewGuid().ToString().ToUpper()); - templatedContent.Template = Regex.Replace(templatedContent.Template, subBlock, replaceCode, RegexOptions.IgnoreCase); - //Loop Target Object Name - string targetObjName = (regexLoopMatch.Groups.Count >= 1) ? regexLoopMatch.Groups[1].Value?.Trim()?.ToString()?.ToLower()?.Replace(" ", string.Empty) : string.Empty; - //Obj - ReplaceObjLoopCode replaceObjLoopCode = new ReplaceObjLoopCode { ReplaceRef = replaceCode, TargetObjectName = targetObjName }; - //Extra Loop Contents - Match subMatch = Regex.Match(subBlock, @"{{(.+?)}}", RegexOptions.IgnoreCase); - while (subMatch.Success) + templatedContent.Template = Regex.Replace(templatedContent.Template, _matchLoopBlock, match => { - //Reclean again - string actualCmdProperty = string.Format(@"{0}{1}{2}", "{{", subMatch.Groups[1].Value.Trim(), "}}"); - //Skip Loop Block - if (!actualCmdProperty.StartsWith("{{for-each-start:") && !actualCmdProperty.StartsWith("{{for-each-end:")) + _replaceKey++; + string _replaceCode = string.Format("RLB_{0}", _replaceKey); + ReplaceObjLoopCode objLoopCode = new ReplaceObjLoopCode { - //Replace Command Occurrence - string replaceSubCode = string.Format("REPLACE_LOOP_RECORD_{0}", Guid.NewGuid().ToString().ToUpper()); - subBlock = ReplaceFirstOccurrence(subBlock, subMatch.Value, replaceSubCode); - replaceObjLoopCode.ReplaceObjCodes.Add(new ReplaceCode { ReplaceCommand = actualCmdProperty, ReplaceRef = replaceSubCode }); + ReplaceRef = _replaceCode, + TargetObjectName = match.Groups[1].Value?.ToString().Trim().ToLower().Replace(" ", string.Empty) + }; + //Determine Forloop Elements + string loopBlock = match.Groups[2].Value?.ToString() ?? string.Empty; + string loopBlockRegex = @"{{(.+?)}}"; + while (Regex.IsMatch(loopBlock, loopBlockRegex, RegexOptions.IgnoreCase)) + { + loopBlock = Regex.Replace(loopBlock, loopBlockRegex, loopBlockMatch => + { + _replaceKey++; + string _replaceLoopBlockCode = string.Format("RLBR_{0}", _replaceKey); + objLoopCode.ReplaceObjCodes.Add(new ReplaceCode + { + ReplaceCommand = loopBlockMatch.Groups[1].Value?.Trim(), + ReplaceRef = _replaceLoopBlockCode + }); + return _replaceLoopBlockCode; + }, RegexOptions.IgnoreCase); } - else - subBlock = ReplaceFirstOccurrence(subBlock, subMatch.Value, string.Empty); - //Proceed To Next - subMatch = subMatch.NextMatch(); - } - - replaceObjLoopCode.ObjLoopTemplate = Regex.Replace(subBlock, @"^\s+$[\r\n]*", string.Empty, RegexOptions.Multiline); //Assigning it here because we are modifying it above - templatedContent.ReplaceObjLoopCodes.Add(replaceObjLoopCode); - //Move Next (Both) - regexLoopMatch = regexLoopMatch.NextMatch(); - regexLoopEnd = regexLoopEnd.NextMatch(); + //#Just before return + objLoopCode.ObjLoopTemplate = loopBlock; + templatedContent.ReplaceObjLoopCodes.Add(objLoopCode); + // Return Replacement + return _replaceCode; + }, RegexOptions.IgnoreCase); } + #endregion #region Generate direct targets - Match regexMatch = Regex.Match(templatedContent.Template, @"{{(.+?)}}", RegexOptions.IgnoreCase); - while (regexMatch.Success) + string _paramRegex = @"{{(.+?)}}"; + while (Regex.IsMatch(templatedContent.Template, _paramRegex, RegexOptions.IgnoreCase)) { - //Reclean again - string actualCmdProperty = string.Format(@"{0}{1}{2}", "{{", regexMatch.Groups[1].Value.Trim(), "}}"); - //Replace Command Occurrence - string replaceCode = string.Format("REPLACE_{0}", Guid.NewGuid().ToString().ToUpper()); - templatedContent.Template = ReplaceFirstOccurrence(templatedContent.Template, regexMatch.Value, replaceCode); - templatedContent.ReplaceCodes.Add(new ReplaceCode { ReplaceCommand = actualCmdProperty, ReplaceRef = replaceCode }); - //Proceed To Next - regexMatch = regexMatch.NextMatch(); + templatedContent.Template = Regex.Replace(templatedContent.Template, _paramRegex, propertyMatch => + { + _replaceKey++; + string _replaceCode = string.Format("RP_{0}", _replaceKey); + templatedContent.ReplaceCodes.Add(new ReplaceCode + { + ReplaceCommand = propertyMatch.Groups[1].Value?.Trim(), + ReplaceRef = _replaceCode + }); + return _replaceCode; + }, RegexOptions.IgnoreCase); } + #endregion return templatedContent; diff --git a/ObjectSemantics.NET/Algorithim/ReplaceCode.cs b/ObjectSemantics.NET/Algorithim/ReplaceCode.cs index 2f8c6d6..5687fb4 100644 --- a/ObjectSemantics.NET/Algorithim/ReplaceCode.cs +++ b/ObjectSemantics.NET/Algorithim/ReplaceCode.cs @@ -10,14 +10,14 @@ public string TargetPropertyName { get { - return ReplaceCommand.Replace("{", string.Empty).Replace("}", string.Empty).Trim().Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); + return ReplaceCommand?.Trim().Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); } } public string FormattingCommand { get { - Match hasFormatting = Regex.Match(ReplaceCommand, "{{--command--:(.+)}}".Replace("--command--", TargetPropertyName), RegexOptions.IgnoreCase); + Match hasFormatting = Regex.Match(ReplaceCommand, "##command##:(.+)".Replace("##command##", TargetPropertyName), RegexOptions.IgnoreCase); if (hasFormatting.Success) return hasFormatting.Groups[1].Value; return string.Empty; diff --git a/ObjectSemantics.NET/Extensions/StringExtensions.cs b/ObjectSemantics.NET/Extensions/StringExtensions.cs index c0c583c..78acaeb 100644 --- a/ObjectSemantics.NET/Extensions/StringExtensions.cs +++ b/ObjectSemantics.NET/Extensions/StringExtensions.cs @@ -15,19 +15,5 @@ public static string RemoveLastInstanceOfString(this string value, params char[] value = value.RemoveLastInstanceOfString(c.ToString()); return value; } - public static string GetSubstringByIndexStartAndEnd(this string str, int startIndex, int endIndex) - { - if (startIndex < 0 || endIndex < 0 || startIndex >= str.Length || endIndex >= str.Length || startIndex > endIndex) - throw new ArgumentException("Invalid start and/or end index"); - return str.Substring(startIndex, endIndex - startIndex + 1); - } - public static string ReplaceByIndexStartAndEnd(this string str, int startIndex, int endIndex, string replacement) - { - if (startIndex < 0 || endIndex > str.Length || startIndex > endIndex) - throw new ArgumentOutOfRangeException("Invalid start and/or end index."); - return (endIndex == str.Length) - ? string.Format("{0}{1}{2}", str.Substring(0, startIndex), replacement, str.Substring(endIndex)) - : string.Format("{0}{1}{2}", str.Substring(0, startIndex), replacement, str.Substring(endIndex + 1)); - } } } From f2b0042f33865ebb4c14396c0bed8a8916722d48 Mon Sep 17 00:00:00 2001 From: "Wainaina George (Swagfin)" Date: Thu, 13 Apr 2023 02:09:41 +0300 Subject: [PATCH 3/4] version changes and readme changes --- ObjectSemantics.NET/ObjectSemantics.NET.csproj | 11 ++++++----- README.md | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ObjectSemantics.NET/ObjectSemantics.NET.csproj b/ObjectSemantics.NET/ObjectSemantics.NET.csproj index 9d0dfff..d967d00 100644 --- a/ObjectSemantics.NET/ObjectSemantics.NET.csproj +++ b/ObjectSemantics.NET/ObjectSemantics.NET.csproj @@ -12,12 +12,13 @@ https://github.com/swagfin/ObjectSemantics.NET Github - v.5.1.5 + v.6.0.1 Added support for if condition statements with ElseIf -Optimized performance - 5.1.5.1 - 5.1.5.1 - 5.1.5 +Single Line ForLoop +[BREAKING CHANGE]: forloop statement changes + 6.0.1.1 + 6.0.1.1 + 6.0.1 false README.md diff --git a/README.md b/README.md index 17fc83a..b0dcbfc 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ class Program StudentName = "George", Invoices = new List { - new Invoice{ Id=2, RefNo="INV_002",Narration="Grade II Fees Invoice", Amount=2000, InvoiceDate=DateTime.Now.Date.AddDays(-1) }, - new Invoice{ Id=1, RefNo="INV_001",Narration="Grade I Fees Invoice", Amount=320, InvoiceDate=DateTime.Now.Date.AddDays(-2) } + new Invoice{ Id=2, RefNo="INV_002",Narration="Grade II Fees Invoice", Amount=2000 }, + new Invoice{ Id=1, RefNo="INV_001",Narration="Grade I Fees Invoice", Amount=320 } } }; @@ -39,9 +39,9 @@ class Program { FileContents = @"
{{ StudentName:uppercase }} Invoices
    - {{ for-each-start:invoices }} + {{ #foreach(invoices) }}
  1. Invoice No: {{ RefNo }} of {{ Narration }} amount {{ Amount:N0 }}
  2. - {{ for-each-end:invoices }} + {{ #endforeach }}
" }; From ab04ab67314f20ece6ee349b92cafc836b6df169 Mon Sep 17 00:00:00 2001 From: "Wainaina George (Swagfin)" Date: Fri, 14 Apr 2023 18:34:57 +0300 Subject: [PATCH 4/4] minor refactoring --- .../Algorithim/GavinsAlgorithim.cs | 54 +++++-------------- .../ExtractedObjPropertyExtensions.cs | 25 +++++++++ .../Extensions/StringExtensions.cs | 7 +++ 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs b/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs index f52767b..e1b0eb3 100644 --- a/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs +++ b/ObjectSemantics.NET/Algorithim/GavinsAlgorithim.cs @@ -26,20 +26,20 @@ public static class GavinsAlgorithim //Condition Passed TemplatedContent templatedIfContent = GenerateTemplateFromFileContents(ifCondition.IfOperationTrueTemplate, options); string templatedIfContentMapped = GenerateFromTemplate(record, templatedIfContent, parameterKeyValues, options); - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, ifCondition.ReplaceRef, templatedIfContentMapped); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(ifCondition.ReplaceRef, templatedIfContentMapped); } else if (!string.IsNullOrEmpty(ifCondition.IfOperationFalseTemplate)) { //If Else Condition Block TemplatedContent templatedIfContent = GenerateTemplateFromFileContents(ifCondition.IfOperationFalseTemplate, options); string templatedIfElseContentMapped = GenerateFromTemplate(record, templatedIfContent, parameterKeyValues, options); - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, ifCondition.ReplaceRef, templatedIfElseContentMapped); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(ifCondition.ReplaceRef, templatedIfElseContentMapped); } else - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, ifCondition.ReplaceRef, string.Empty); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(ifCondition.ReplaceRef, string.Empty); } else - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, ifCondition.ReplaceRef, $"[IF-CONDITION EXCEPTION]: unrecognized property: [{ifCondition.IfPropertyName}]"); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(ifCondition.ReplaceRef, $"[IF-CONDITION EXCEPTION]: unrecognized property: [{ifCondition.IfPropertyName}]"); } #endregion @@ -63,20 +63,19 @@ public static class GavinsAlgorithim { ExtractedObjProperty objProperty = rowRecordValues.FirstOrDefault(x => x.Name.ToUpper().Equals(objLoopCode.TargetPropertyName.ToUpper())); if (objProperty != null) - activeRow = ReplaceFirstOccurrence(activeRow, objLoopCode.ReplaceRef, GetValueFromPropertyFormatted(objProperty, objLoopCode.FormattingCommand)); + activeRow = activeRow.ReplaceFirstOccurrence(objLoopCode.ReplaceRef, objProperty.GetValueFromPropertyFormatted(objLoopCode.FormattingCommand)); else - activeRow = ReplaceFirstOccurrence(activeRow, objLoopCode.ReplaceRef, objLoopCode.ReplaceCommand); + activeRow = activeRow.ReplaceFirstOccurrence(objLoopCode.ReplaceRef, objLoopCode.ReplaceCommand); } //Append Record row rowContentTemplater.Append(activeRow); } - objLoop.ObjLoopTemplate = rowContentTemplater.ToString().RemoveLastInstanceOfString('\r', '\n'); //Assign Auto Generated //Replace the main Loop area - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, objLoop.ReplaceRef, objLoop.ObjLoopTemplate); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(objLoop.ReplaceRef, objLoop.ObjLoopTemplate); } else - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, objLoop.ReplaceRef, string.Empty); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(objLoop.ReplaceRef, string.Empty); } #endregion @@ -86,9 +85,9 @@ public static class GavinsAlgorithim { ExtractedObjProperty property = objProperties.FirstOrDefault(x => x.Name.ToUpper().Equals(replaceCode.TargetPropertyName.ToUpper())); if (property != null) - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, replaceCode.ReplaceRef, GetValueFromPropertyFormatted(property, replaceCode.FormattingCommand)); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(replaceCode.ReplaceRef, property.GetValueFromPropertyFormatted(replaceCode.FormattingCommand)); else - clonedTemplate.Template = ReplaceFirstOccurrence(clonedTemplate.Template, replaceCode.ReplaceRef, @"{{ ##command## }}".Replace("##command##", replaceCode.ReplaceCommand)); + clonedTemplate.Template = clonedTemplate.Template.ReplaceFirstOccurrence(replaceCode.ReplaceRef, @"{{ ##command## }}".Replace("##command##", replaceCode.ReplaceCommand)); } #endregion return clonedTemplate.Template; @@ -184,13 +183,7 @@ internal static TemplatedContent GenerateTemplateFromFileContents(string fileCon return templatedContent; } - private static string ReplaceFirstOccurrence(this string text, string search, string replace) - { - int pos = text.IndexOf(search); - if (pos < 0) - return text; - return string.Format("{0}{1}{2}", text.Substring(0, pos), replace, text.Substring(pos + search.Length)); - } + private static List GetObjectProperties(T value, List parameters = null) where T : new() { List extractedObjProperties = new List(); @@ -236,28 +229,5 @@ private static List GetObjPropertiesFromUnknown(object val return list; } - private static string GetValueFromPropertyFormatted(ExtractedObjProperty p, string customFormattingValue) - { - if (string.IsNullOrWhiteSpace(customFormattingValue)) - return p.StringFormatted; - if (p.Type.Equals(typeof(int))) - return int.Parse(p.StringFormatted).ToString(customFormattingValue); - else if (p.Type.Equals(typeof(double))) - return double.Parse(p.StringFormatted).ToString(customFormattingValue); - else if (p.Type.Equals(typeof(long))) - return long.Parse(p.StringFormatted).ToString(customFormattingValue); - else if (p.Type.Equals(typeof(float))) - return float.Parse(p.StringFormatted).ToString(customFormattingValue); - else if (p.Type.Equals(typeof(decimal))) - return decimal.Parse(p.StringFormatted).ToString(customFormattingValue); - else if (p.Type.Equals(typeof(DateTime))) - return DateTime.Parse(p.StringFormatted).ToString(customFormattingValue); - //Custom Formats - else if (customFormattingValue.ToLower().Equals("uppercase")) - return p.StringFormatted?.ToUpper(); - else if (customFormattingValue.ToLower().Equals("lowercase")) - return p.StringFormatted?.ToLower(); - else - return p.StringFormatted?.ToUpper(); - } + } \ No newline at end of file diff --git a/ObjectSemantics.NET/Extensions/ExtractedObjPropertyExtensions.cs b/ObjectSemantics.NET/Extensions/ExtractedObjPropertyExtensions.cs index 9c44e0a..653ffa1 100644 --- a/ObjectSemantics.NET/Extensions/ExtractedObjPropertyExtensions.cs +++ b/ObjectSemantics.NET/Extensions/ExtractedObjPropertyExtensions.cs @@ -5,6 +5,31 @@ namespace ObjectSemantics.NET { public static class ExtractedObjPropertyExtensions { + public static string GetValueFromPropertyFormatted(this ExtractedObjProperty p, string customFormattingValue) + { + if (string.IsNullOrWhiteSpace(customFormattingValue)) + return p.StringFormatted; + if (p.Type.Equals(typeof(int))) + return int.Parse(p.StringFormatted).ToString(customFormattingValue); + else if (p.Type.Equals(typeof(double))) + return double.Parse(p.StringFormatted).ToString(customFormattingValue); + else if (p.Type.Equals(typeof(long))) + return long.Parse(p.StringFormatted).ToString(customFormattingValue); + else if (p.Type.Equals(typeof(float))) + return float.Parse(p.StringFormatted).ToString(customFormattingValue); + else if (p.Type.Equals(typeof(decimal))) + return decimal.Parse(p.StringFormatted).ToString(customFormattingValue); + else if (p.Type.Equals(typeof(DateTime))) + return DateTime.Parse(p.StringFormatted).ToString(customFormattingValue); + //Custom Formats + else if (customFormattingValue.ToLower().Equals("uppercase")) + return p.StringFormatted?.ToUpper(); + else if (customFormattingValue.ToLower().Equals("lowercase")) + return p.StringFormatted?.ToLower(); + else + return p.StringFormatted?.ToUpper(); + } + private static T GetConvertibleValue(string value) where T : IConvertible { return (string.IsNullOrEmpty(value) || value?.ToLower()?.Trim() == "null") ? default : (T)Convert.ChangeType(value, typeof(T)); diff --git a/ObjectSemantics.NET/Extensions/StringExtensions.cs b/ObjectSemantics.NET/Extensions/StringExtensions.cs index 78acaeb..96c21b1 100644 --- a/ObjectSemantics.NET/Extensions/StringExtensions.cs +++ b/ObjectSemantics.NET/Extensions/StringExtensions.cs @@ -4,6 +4,13 @@ namespace ObjectSemantics.NET { public static class StringExtensions { + public static string ReplaceFirstOccurrence(this string text, string search, string replace) + { + int pos = text.IndexOf(search); + if (pos < 0) + return text; + return string.Format("{0}{1}{2}", text.Substring(0, pos), replace, text.Substring(pos + search.Length)); + } public static string RemoveLastInstanceOfString(this string value, string removeString) { int index = value.LastIndexOf(removeString, StringComparison.Ordinal);