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) }}
[\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 =>
{
- 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,
@@ -117,79 +117,73 @@ internal static TemplatedContent GenerateTemplateFromFileContents(string fileCon
});
// Return Replacement
return _replaceCode;
- });
+ }, RegexOptions.IgnoreCase);
}
#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
+ {
+ 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))
{
- //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 });
+ 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;
}
- 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();
@@ -235,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/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/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 c0c583c..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);
@@ -15,19 +22,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));
- }
}
}
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) }}
- Invoice No: {{ RefNo }} of {{ Narration }} amount {{ Amount:N0 }}
- {{ for-each-end:invoices }}
+ {{ #endforeach }}
"
};