Skip to content

Commit 15c2444

Browse files
committed
Added Code Generation Methods
1 parent 13134db commit 15c2444

File tree

7 files changed

+302
-11
lines changed

7 files changed

+302
-11
lines changed

AValue.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public JToken ToJson()
106106

107107
try
108108
{
109-
return (JToken)Newtonsoft.Json.JsonConvert.SerializeObject(this.Value);
109+
return (JToken) new JObject(this.Value);
110110
} catch
111111
{
112112
return new JObject();

AValue.tt

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ namespace Aerospike.Database.LINQPadDriver.Extensions
7575

7676
try
7777
{
78-
return (JToken)Newtonsoft.Json.JsonConvert.SerializeObject(this.Value);
78+
return (JToken) new JObject(this.Value);
7979
} catch
8080
{
8181
return new JObject();

AValueHelper.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ public static AValue ToAValue<T>(this Nullable<T> value, string bin = null, stri
2323
}
2424

2525
public static AValue ToAValue(this object value, string bin = null, string fld = null)
26-
=> new AValue(value, bin ?? "Object", fld ??"Value");
26+
=> value is AValue aValue
27+
? aValue
28+
: new AValue(value, bin ?? "Object", fld ??"Value");
2729

2830
/// <summary>
2931
/// Converts a collection of <see cref="AValue"/>s into a dictionary where the key is the AValue&apos;s Bin Name and the value is the AValue.

AValuePart.cs

+15-3
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,15 @@ AValue NewAValue(object value, int currIdx)
713713
return new AValue(lsto.Select(v => NewAValue(v, idx++)),
714714
binName,
715715
fldName);
716-
}
717-
case JsonDocument jDoc:
716+
}
717+
case byte[] digest:
718+
{
719+
int idx = 0;
720+
return new AValue(digest.Select(v => NewAValue(v, idx++)).ToArray(),
721+
binName,
722+
fldName);
723+
}
724+
case JsonDocument jDoc:
718725
{
719726
int idx = 0;
720727
return new AValue(jDoc.ToDictionary()
@@ -783,7 +790,12 @@ AValue NewAValue(object value, int currIdx)
783790
int idx = 0;
784791
return lstJProp.Select(v => NewAValue(v, idx++));
785792
}
786-
case JProperty jProp:
793+
case byte[] digest:
794+
{
795+
int idx = 0;
796+
return digest.Select(v => NewAValue(v, idx++)).ToArray();
797+
}
798+
case JProperty jProp:
787799
{
788800
int idx = 0;
789801
return CDTConverter.ConvertToDictionary(jProp)

TestProjects/Aerospike.Database.LINQPadDriverTests/ARecordTests.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ namespace Aerospike.Database.LINQPadDriver.Extensions.Tests
55
[TestClass()]
66
public class ARecordTests
77
{
8-
[TestMethod()]
9-
public void FromJsonTest()
10-
{
11-
var json = @"
8+
public static readonly string jsonRecords = @"
129
{
1310
""_id"": {""$oid"":""0080a245fabe57999707dc41ced60edc4ac7ac40""},
1411
""account_id"": 794875,
@@ -68,7 +65,12 @@ public void FromJsonTest()
6865
]
6966
}
7067
";
71-
var aRecord = ARecord.FromJson("tns", "tset", json);
68+
69+
[TestMethod()]
70+
public void FromJsonTest()
71+
{
72+
var json = jsonRecords;
73+
var aRecord = ARecord.FromJson("tns", "tset", json);
7274

7375
Assert.AreEqual(5, aRecord.Aerospike.Count);
7476
Assert.IsFalse(aRecord.Aerospike.HasKeyValue);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using Aerospike.Database.LINQPadDriver.Extensions;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace Aerospike.Database.LINQPadDriver.Extensions.Tests
10+
{
11+
[TestClass()]
12+
public class ToCodeAPITests
13+
{
14+
[TestMethod()]
15+
public void ToAPICodeTest()
16+
{
17+
var aRecord = ARecord.FromJson("tns", "tset", ARecordTests.jsonRecords);
18+
19+
var records = new ARecord[] { aRecord };
20+
21+
var codeBlocks = records.ToAPICode().ToList();
22+
23+
Assert.AreEqual(2, codeBlocks.Count);
24+
25+
var codeBlock1 = @"tns.tset.Get(new Byte[] { (byte) 0,(byte) 128,(byte) 162,(byte) 69,(byte) 250,(byte) 190,(byte) 87,(byte) 153,(byte) 151,(byte) 7,(byte) 220,(byte) 65,(byte) 206,(byte) 214,(byte) 14,(byte) 220,(byte) 74,(byte) 199,(byte) 172,(byte) 64 })";
26+
var codeBlock2 = @"tns.tset.Put(new Byte[] { (byte) 0,(byte) 128,(byte) 162,(byte) 69,(byte) 250,(byte) 190,(byte) 87,(byte) 153,(byte) 151,(byte) 7,(byte) 220,(byte) 65,(byte) 206,(byte) 214,(byte) 14,(byte) 220,(byte) 74,(byte) 199,(byte) 172,(byte) 64 },
27+
new Dictionary<string,object>() {{""account_id"", 794875L},
28+
{""transaction_count"", 6L},
29+
{""bucket_start_date"", DateTime.Parse(""2018-12-27T05:00:00.0000"")},
30+
{""bucket_end_date"", DateTime.Parse(""2016-09-06T00:00:00.0000"")},
31+
{""transactions"", new List<Object>() { new Dictionary<Object,Object>() { {""date"",DateTime.Parse(""2011-12-28T00:00:00.0000"")},{""amount"",1197L},{""transaction_code"",""buy""},{""symbol"",""nvda""},{""price"",12.733002429934103361119923647M},{""total"",15241.403908631122D} },new Dictionary<Object,Object>() { {""date"",DateTime.Parse(""2016-06-13T00:00:00.0000"")},{""amount"",8797L},{""transaction_code"",""buy""},{""symbol"",""nvda""},{""price"",46.538731724063914896305504953M},{""total"",409401.2229765903D} },new Dictionary<Object,Object>() { {""date"",DateTime.Parse(""2016-08-31T00:00:00.0000"")},{""amount"",6146L},{""transaction_code"",""sell""},{""symbol"",""ebay""},{""price"",""32.11600884852845894101847079582512378692626953125""},{""total"",""197384.9903830559086514995215""} },new Dictionary<Object,Object>() { {""date"",DateTime.Parse(""2004-11-22T00:00:00.0000"")},{""amount"",253L},{""transaction_code"",""buy""},{""symbol"",""amzn""},{""price"",""37.77441226157566944721111212857067584991455078125""},{""total"",""9556.926302178644370144411369""} },new Dictionary<Object,Object>() { {""date"",DateTime.Parse(""2002-05-23T00:00:00.0000"")},{""amount"",4521L},{""transaction_code"",""buy""},{""symbol"",""nvda""},{""price"",""10.763069758141103449133879621513187885284423828125""},{""total"",""48659.83837655592869353426977""} },new Dictionary<Object,Object>() { {""date"",DateTime.Parse(""1999-09-01T00:00:00.0000"")},{""amount"",955L},{""transaction_code"",""buy""},{""symbol"",""csco""},{""price"",""27.992136535152877030441231909207999706268310546875""},{""total"",""26732.49039107099756407137647""} } }}})";
32+
33+
Assert.AreEqual(codeBlock1, codeBlocks[0]);
34+
Assert.AreEqual(codeBlock2, codeBlocks[1]);
35+
36+
codeBlocks = records.ToAPICode(useAerospikeAPI: true).ToList();
37+
38+
Assert.AreEqual(2, codeBlocks.Count);
39+
40+
codeBlock1 = @"ASClient.Get(null,
41+
new Key(""tns"",""tset"",new Byte[] { (byte) 0,(byte) 128,(byte) 162,(byte) 69,(byte) 250,(byte) 190,(byte) 87,(byte) 153,(byte) 151,(byte) 7,(byte) 220,(byte) 65,(byte) 206,(byte) 214,(byte) 14,(byte) 220,(byte) 74,(byte) 199,(byte) 172,(byte) 64 }))";
42+
codeBlock2 = @"ASClient.Put(null,
43+
new Key(""tns"",""tset"",new Byte[] { (byte) 0,(byte) 128,(byte) 162,(byte) 69,(byte) 250,(byte) 190,(byte) 87,(byte) 153,(byte) 151,(byte) 7,(byte) 220,(byte) 65,(byte) 206,(byte) 214,(byte) 14,(byte) 220,(byte) 74,(byte) 199,(byte) 172,(byte) 64 }),
44+
new Bin(""account_id"", Value.Get(794875L)),
45+
new Bin(""transaction_count"", Value.Get(6L)),
46+
new Bin(""bucket_start_date"", Value.Get(""2018-12-27T05:00:00.0000"")),
47+
new Bin(""bucket_end_date"", Value.Get(""2016-09-06T00:00:00.0000"")),
48+
new Bin(""transactions"", Value.Get(new List<Object>() { new Dictionary<Object,Object>() { {""date"",""2011-12-28T00:00:00.0000""},{""amount"",1197L},{""transaction_code"",""buy""},{""symbol"",""nvda""},{""price"",12.733002429934103D},{""total"",15241.403908631122D} },new Dictionary<Object,Object>() { {""date"",""2016-06-13T00:00:00.0000""},{""amount"",8797L},{""transaction_code"",""buy""},{""symbol"",""nvda""},{""price"",46.538731724063915D},{""total"",409401.2229765903D} },new Dictionary<Object,Object>() { {""date"",""2016-08-31T00:00:00.0000""},{""amount"",6146L},{""transaction_code"",""sell""},{""symbol"",""ebay""},{""price"",""32.11600884852845894101847079582512378692626953125""},{""total"",""197384.9903830559086514995215""} },new Dictionary<Object,Object>() { {""date"",""2004-11-22T00:00:00.0000""},{""amount"",253L},{""transaction_code"",""buy""},{""symbol"",""amzn""},{""price"",""37.77441226157566944721111212857067584991455078125""},{""total"",""9556.926302178644370144411369""} },new Dictionary<Object,Object>() { {""date"",""2002-05-23T00:00:00.0000""},{""amount"",4521L},{""transaction_code"",""buy""},{""symbol"",""nvda""},{""price"",""10.763069758141103449133879621513187885284423828125""},{""total"",""48659.83837655592869353426977""} },new Dictionary<Object,Object>() { {""date"",""1999-09-01T00:00:00.0000""},{""amount"",955L},{""transaction_code"",""buy""},{""symbol"",""csco""},{""price"",""27.992136535152877030441231909207999706268310546875""},{""total"",""26732.49039107099756407137647""} } })))";
49+
50+
Assert.AreEqual(codeBlock1, codeBlocks[0]);
51+
Assert.AreEqual(codeBlock2, codeBlocks[1]);
52+
}
53+
}
54+
}

ToCodeAPI.cs

+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
using Aerospike.Client;
2+
using Newtonsoft.Json.Linq;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace Aerospike.Database.LINQPadDriver.Extensions
10+
{
11+
/// <summary>
12+
/// Helpers that will translate an <see cref="ARecord"/> into Aerospike API Code template
13+
/// </summary>
14+
public static class ToCodeAPI
15+
{
16+
[Flags]
17+
public enum Options
18+
{
19+
None = 0,
20+
GetCode = 0x0001,
21+
PutCode = 0x0010,
22+
GetPutCode = GetCode | PutCode
23+
}
24+
25+
static string GenerateCode(ARecord record, Options optCode, bool useAerospikeAPI)
26+
{
27+
string ConvertValue(AValue aValue, bool useAerospikeAPI = false)
28+
{
29+
string strValue = null;
30+
31+
if(useAerospikeAPI)
32+
{
33+
var cvtValue = Helpers.ConvertToAerospikeType(aValue);
34+
if(cvtValue is null || cvtValue is Value.NullValue)
35+
return "Value.AsNull";
36+
37+
if(cvtValue is Value cValue)
38+
{
39+
var dtStr = Helpers.GetRealTypeName(cvtValue.GetType());
40+
strValue = ConvertValue(cValue.Object.ToAValue());
41+
return $"new {dtStr}({strValue})";
42+
}
43+
strValue = ConvertValue(cvtValue.ToAValue());
44+
return $"Value.Get({strValue})";
45+
}
46+
47+
if(aValue is null)
48+
return "null";
49+
if(aValue.IsString)
50+
strValue = Helpers.ToLiteral(aValue.Convert<string>());
51+
else if(aValue.IsBool)
52+
strValue = aValue.Value.ToString();
53+
else if(aValue.IsNumeric)
54+
{
55+
switch(aValue.Value)
56+
{
57+
case long lValue:
58+
strValue = $"{lValue}L";
59+
break;
60+
case float fValue:
61+
strValue = $"{fValue}F";
62+
break;
63+
case double dValue:
64+
strValue = $"{dValue}D";
65+
break;
66+
case decimal dValue:
67+
strValue = $"{dValue}M";
68+
break;
69+
case sbyte sbValue:
70+
strValue = $"(sbyte) {sbValue}";
71+
break;
72+
case byte bValue:
73+
strValue = $"(byte) {bValue}";
74+
break;
75+
default:
76+
strValue = aValue.ToString();
77+
break;
78+
}
79+
}
80+
else if(aValue.IsJson || aValue.IsGeoJson)
81+
{
82+
strValue = aValue.ToJson().ToString(Newtonsoft.Json.Formatting.None);
83+
strValue = $"new JObject(\"{strValue}\")";
84+
}
85+
else if(aValue.IsCDT)
86+
{
87+
var lstValue = aValue.AsEnumerable();
88+
strValue = String.Join(",", lstValue.Select(i => ConvertValue(i)));
89+
var dtStr = Helpers.GetRealTypeName(aValue.UnderlyingType);
90+
var dtParam = "()";
91+
92+
if(dtStr[^2..] == "[]")
93+
dtParam = string.Empty;
94+
95+
if(string.IsNullOrEmpty(dtStr))
96+
strValue = $"new {dtStr}{dtParam}";
97+
else
98+
strValue = $"new {dtStr}{dtParam} {{ {strValue} }}";
99+
}
100+
else if(aValue.IsKeyValuePair)
101+
{
102+
dynamic kvp = aValue.Value;
103+
104+
var kValue = ConvertValue(((object)kvp.Key).ToAValue());
105+
var vValue = ConvertValue(((object)kvp.Value).ToAValue());
106+
107+
var dtStr = Helpers.GetRealTypeName(aValue.UnderlyingType);
108+
strValue = $"{{{kValue},{vValue}}}";
109+
}
110+
else if(aValue.IsDateTime)
111+
{
112+
strValue = $"DateTime.Parse({Helpers.ToLiteral(aValue.ToString(Helpers.DateTimeFormat))})";
113+
}
114+
else if(aValue.IsDateTimeOffset)
115+
{
116+
strValue = $"DateTimeOffset.Parse({Helpers.ToLiteral(aValue.ToString(Helpers.DateTimeOffsetFormat))})";
117+
}
118+
else if(aValue.IsTimeSpan)
119+
{
120+
strValue = $"TimeSpan.Parse({Helpers.ToLiteral(aValue.ToString(Helpers.TimeSpanFormat))})";
121+
}
122+
else
123+
{
124+
var dtStr = Helpers.GetRealTypeName(aValue.UnderlyingType);
125+
strValue = $"new {dtStr}({Helpers.ToLiteral(aValue.ToString())})";
126+
}
127+
return strValue.Replace("AValue", "Object");
128+
}
129+
130+
var strCode = new StringBuilder();
131+
132+
switch(optCode)
133+
{
134+
case Options.None:
135+
return string.Empty;
136+
case Options.GetCode:
137+
if(useAerospikeAPI)
138+
strCode.Append($@"ASClient.Get(null,
139+
new Key(""{record.Aerospike.Namespace}"",{Helpers.ToLiteral(record.Aerospike.SetName)},");
140+
else
141+
{
142+
var safeNSName = Helpers.CheckName(record.Aerospike.Namespace, "Namespace");
143+
var safeSetName = Helpers.CheckName(record.Aerospike.SetName, "Set");
144+
145+
strCode.Append($"{safeNSName}.{safeSetName}.Get(");
146+
}
147+
strCode.Append(ConvertValue(record.GetPK(), false));
148+
if(useAerospikeAPI)
149+
strCode.Append(')');
150+
break;
151+
case Options.PutCode:
152+
if(useAerospikeAPI)
153+
strCode.Append($@"ASClient.Put(null,
154+
new Key(""{record.Aerospike.Namespace}"",{Helpers.ToLiteral(record.Aerospike.SetName)},");
155+
else
156+
{
157+
var safeNSName = Helpers.CheckName(record.Aerospike.Namespace, "Namespace");
158+
var safeSetName = Helpers.CheckName(record.Aerospike.SetName, "Set");
159+
160+
strCode.Append($"{safeNSName}.{safeSetName}.Put(");
161+
}
162+
163+
strCode.Append(ConvertValue(record.GetPK(), false));
164+
if(useAerospikeAPI)
165+
{
166+
strCode.Append(')');
167+
}
168+
strCode.AppendLine(", ");
169+
if(!useAerospikeAPI)
170+
{
171+
strCode.Append("new Dictionary<string,object>() {");
172+
}
173+
var binCode = new List<string>();
174+
foreach(var kvp in record.ToDictionary())
175+
{
176+
if(useAerospikeAPI)
177+
{
178+
binCode.Add($"new Bin({Helpers.ToLiteral(kvp.Key)}, {ConvertValue(kvp.Value?.ToAValue(), true)})");
179+
}
180+
else
181+
{
182+
binCode.Add($"{{{Helpers.ToLiteral(kvp.Key)}, {ConvertValue(kvp.Value?.ToAValue(), false)}}}");
183+
}
184+
}
185+
strCode.AppendJoin(",\r\n", binCode);
186+
if(!useAerospikeAPI)
187+
{
188+
strCode.Append('}');
189+
}
190+
break;
191+
case Options.GetPutCode:
192+
default:
193+
throw new ArgumentException($"Invalid Code Option of {optCode}. must be Put or Get...");
194+
}
195+
196+
strCode.Append(')');
197+
return strCode.ToString();
198+
}
199+
200+
public static IEnumerable<string> ToAPICode(this IEnumerable<ARecord> records,
201+
Options codeOptions = Options.GetPutCode,
202+
bool useAerospikeAPI = false)
203+
{
204+
if(Options.None == codeOptions) yield break;
205+
206+
207+
foreach(var record in records)
208+
{
209+
if(codeOptions.HasFlag(Options.GetCode))
210+
{
211+
yield return GenerateCode(record, Options.GetCode, useAerospikeAPI);
212+
}
213+
214+
if(codeOptions.HasFlag(Options.PutCode))
215+
{
216+
yield return GenerateCode(record, Options.PutCode, useAerospikeAPI);
217+
}
218+
}
219+
}
220+
}
221+
}

0 commit comments

Comments
 (0)