Skip to content

Commit d189408

Browse files
committed
S-58164 WIP for FluentQuery formal support! #15
1 parent 4636e0d commit d189408

19 files changed

+331
-929
lines changed

APIClient/Connector/V1Connector.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,11 @@ ICanGetConnector ICanSetEndpointOrGetConnector.UseEndpoint(string endpoint)
513513

514514
return this;
515515
}
516+
517+
public FluentQuery Query(string assetTypeName)
518+
{
519+
return new Services(this.Build()).Query(assetTypeName);
520+
}
516521
}
517522

518523
#endregion
@@ -587,6 +592,7 @@ public interface ICanSetProxyOrEndpointOrGetConnector : ICanSetEndpoint, ICanGet
587592
/// <param name="proxyProvider">The ProxyProvider containing the proxy URI, username, and password.</param>
588593
/// <returns>ICanSetEndpointOrGetConnector</returns>
589594
ICanSetEndpointOrGetConnector WithProxy(ProxyProvider proxyProvider);
595+
FluentQuery Query(string assetTypeName);
590596
}
591597

592598
public interface ICanSetEndpointOrGetConnector : ICanGetConnector

APIClient/Model/Asset/Asset.cs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Dynamic;
34
using System.Linq;
45

56
namespace VersionOne.SDK.APIClient
67
{
7-
public class Asset
8+
public class Asset : DynamicObject
89
{
910
private Oid oid = Oid.Null;
1011
private readonly IDictionary<string, Attribute> attributes = new Dictionary<string, Attribute>();
1112
private readonly IAssetType assetType;
1213
private readonly AssetList children = new AssetList();
14+
protected string AssetBasePrefix { get; set; }
15+
private IMetaModel metaModel;
16+
private IServices services;
1317

1418
public IAssetType AssetType
1519
{
@@ -56,6 +60,20 @@ public Asset(IAssetType assetType)
5660
this.assetType = assetType;
5761
}
5862

63+
public Asset(string basePrefix, IMetaModel metaModel, IServices services)
64+
{
65+
Configure(basePrefix, metaModel, services);
66+
}
67+
68+
public void Configure(string basePrefix, IMetaModel metaModel, IServices services)
69+
{
70+
this.AssetBasePrefix = basePrefix;
71+
this.metaModel = metaModel;
72+
this.services = services;
73+
}
74+
75+
public object this[string name] => GetValueByName(name);
76+
5977
public void SetAttributeValue(IAttributeDefinition attribdef, object value)
6078
{
6179
EnsureAttribute(attribdef).SetValue(value);
@@ -153,5 +171,49 @@ public Attribute EnsureAttribute(IAttributeDefinition attribdef)
153171

154172
return attrib;
155173
}
174+
175+
#region DynamicObject members
176+
177+
public override bool TryGetMember(GetMemberBinder binder,
178+
out object result)
179+
{
180+
var attribute = GetAttributeByName(binder.Name);
181+
result = GetAttribute(attribute).Value;
182+
return result != null;
183+
}
184+
185+
public override bool TrySetMember(SetMemberBinder binder, object value)
186+
{
187+
var attribute = GetAttributeByName(binder.Name);
188+
if (attribute != null)
189+
{
190+
SetAttributeValue(attribute, value);
191+
return true;
192+
}
193+
return false;
194+
}
195+
196+
#endregion
197+
198+
public IAttributeDefinition GetAttributeByName(object fieldName)
199+
{
200+
return metaModel.GetAttributeDefinition(AssetBasePrefix + "." + fieldName);
201+
}
202+
203+
public object GetValueByName(string fieldName)
204+
{
205+
var attribute = GetAttributeByName(fieldName);
206+
return GetAttribute(attribute).Value;
207+
}
208+
209+
public void SaveChanges()
210+
{
211+
services.Save(this);
212+
}
213+
214+
public void SaveChanges(string comment)
215+
{
216+
services.Save(this, comment);
217+
}
156218
}
157219
}

APIClient/Query/FluentQuery.cs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace VersionOne.SDK.APIClient
6+
{
7+
public class FluentQuery
8+
{
9+
private IMetaModel metaModel;
10+
private IServices services;
11+
public Query RawQuery { get; set; }
12+
public string AssetTypeName { get; set; }
13+
public List<Tuple<string, object, FilterTerm.Operator>> WhereCriteria { get; set; }
14+
public List<object> SelectFields { get; set; }
15+
public Action<IEnumerable<Asset>> OnSuccess { get; set; }
16+
public Action OnEmptyResults { get; set; }
17+
public Action<Exception> OnError { get; set; }
18+
19+
public FluentQuery(
20+
string assetTypeName, IMetaModel metaModel, IServices services)
21+
{
22+
this.metaModel = metaModel;
23+
this.services = services;
24+
AssetTypeName = assetTypeName;
25+
26+
WhereCriteria = new List<Tuple<string, object, FilterTerm.Operator>>();
27+
SelectFields = new List<object>();
28+
}
29+
30+
public FluentQuery Where(params Tuple<string, object, FilterTerm.Operator>[] criteria)
31+
{
32+
WhereCriteria.AddRange(criteria);
33+
34+
return this;
35+
}
36+
37+
public FluentQuery Select(params object[] fields)
38+
{
39+
SelectFields.AddRange(fields);
40+
41+
return this;
42+
}
43+
44+
public FluentQuery Success(Action<IEnumerable<Asset>> callback)
45+
{
46+
OnSuccess = callback;
47+
48+
return this;
49+
}
50+
51+
public FluentQuery WhenEmpty(Action callback)
52+
{
53+
OnEmptyResults = callback;
54+
55+
return this;
56+
}
57+
58+
public FluentQuery Error(Action<Exception> callback)
59+
{
60+
OnError = callback;
61+
62+
return this;
63+
}
64+
65+
public FluentQuery Execute(Action<IEnumerable<Asset>> successCallback = null)
66+
{
67+
if (OnSuccess == null && successCallback == null)
68+
{
69+
throw new NullReferenceException("Must specify the OnSuccess callback before calling Execute or pass it directly to Execute as a parameter");
70+
}
71+
72+
try
73+
{
74+
QueryResult result = RetrieveQueryResult();
75+
76+
if (result.Assets.Count == 0)
77+
{
78+
OnSuccess?.Invoke(result.Assets);
79+
}
80+
81+
result.Assets.ForEach(a => a.Configure(AssetTypeName, metaModel, services));
82+
83+
if (result.Assets.Count == 0)
84+
{
85+
OnEmptyResults?.Invoke();
86+
}
87+
88+
if (successCallback != null)
89+
{
90+
successCallback(result.Assets);
91+
}
92+
else
93+
{
94+
OnSuccess(result.Assets);
95+
}
96+
}
97+
catch (Exception exception)
98+
{
99+
if (OnError != null)
100+
{
101+
OnError(exception);
102+
}
103+
else
104+
{
105+
throw;
106+
}
107+
}
108+
109+
return this;
110+
}
111+
112+
private QueryResult RetrieveQueryResult()
113+
{
114+
RawQuery = new Query(metaModel.GetAssetType(AssetTypeName));
115+
116+
var attributes = new List<IAttributeDefinition>();
117+
118+
if (SelectFields.Count > 0)
119+
{
120+
attributes.AddRange(
121+
SelectFields.Select(
122+
m => metaModel.GetAttributeDefinition(AssetTypeName
123+
+ "." + m.ToString())));
124+
}
125+
RawQuery.Selection.AddRange(attributes);
126+
127+
if (WhereCriteria.Count > 0)
128+
{
129+
var andTerms = new List<FilterTerm>();
130+
131+
foreach (var tuple in WhereCriteria)
132+
{
133+
var attribute = metaModel.GetAttributeDefinition(AssetTypeName
134+
+ "." + tuple.Item1);
135+
var item = tuple.Item2;
136+
var term = new FilterTerm(attribute);
137+
term.Operate(tuple.Item3, item);
138+
andTerms.Add(term);
139+
}
140+
141+
var andTerm = new AndFilterTerm(andTerms.ToArray());
142+
RawQuery.Filter = andTerm;
143+
}
144+
145+
var result = services.Retrieve(RawQuery);
146+
return result;
147+
}
148+
149+
public QueryResult Retrieve()
150+
{
151+
QueryResult result = null;
152+
try
153+
{
154+
result = RetrieveQueryResult();
155+
}
156+
catch (Exception exception)
157+
{
158+
if (OnError != null)
159+
{
160+
OnError(exception);
161+
}
162+
else
163+
{
164+
throw;
165+
}
166+
}
167+
return result;
168+
}
169+
}
170+
}

APIClient/Services/IServices.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public interface IServices
1818
string Localization(string key);
1919
string Localization(IAttributeDefinition attribute);
2020
Dictionary<string, string> Localization(params IAttributeDefinition[] attributes);
21+
FluentQuery Query(string assetTypeName);
2122

2223
/// <summary>
2324
/// Executes a query using the Query API (query.v1 endpoint).

APIClient/Services/Services.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,5 +720,10 @@ private static void ParseAttributeNode(Asset asset, IAttributeDefinition attribd
720720
}
721721
}
722722
}
723+
724+
public FluentQuery Query(string assetTypeName)
725+
{
726+
return new FluentQuery(assetTypeName, this.Meta, this);
727+
}
723728
}
724729
}

APIClient/VersionOne.SDK.APIClient.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
</Compile>
151151
<Compile Include="Connector\V1Connector.cs" />
152152
<Compile Include="Query\Builders\HierarchicalPartBuilder.cs" />
153+
<Compile Include="Query\FluentQuery.cs" />
153154
<Compile Include="Services\Services.cs" />
154155
<Compile Include="Query\Builders\QueryURLBuilder.cs" />
155156
<Compile Include="Obsolete\V1CredsAPIConnector.cs" />

Example/GettingStarted/src/ApiVNext/AssetClassBase.cs

Lines changed: 0 additions & 69 deletions
This file was deleted.

0 commit comments

Comments
 (0)