master
Harald Wolff 2019-06-11 11:26:13 +02:00
parent a4b2b1d9c3
commit 32c0967cce
4 changed files with 109 additions and 59 deletions

View File

@ -0,0 +1,68 @@
using System;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Reflection;
using ln.types.json;
namespace ln.http.resources.collections
{
public class EntityMapper<TENTITY>
{
public JSONConvert JSONConvert { get; set; }
Dictionary<string, FieldInfo> publicFields = new Dictionary<string, FieldInfo>();
Dictionary<string, PropertyInfo> publicProperties = new Dictionary<string, PropertyInfo>();
public EntityMapper()
{
foreach (PropertyInfo propertyInfo in typeof(TENTITY).GetProperties())
{
publicProperties.Add(propertyInfo.Name, propertyInfo);
}
foreach (FieldInfo fieldInfo in typeof(TENTITY).GetFields())
{
publicFields.Add(fieldInfo.Name, fieldInfo);
}
}
public EntityMapper(JSONConvert jsonConvert)
:this()
{
JSONConvert = jsonConvert;
}
public JObject MapEntity(TENTITY entity)
{
JObject jObject = new JObject();
foreach (FieldInfo fieldInfo in publicFields.Values)
{
JToken jToken = null;
if (JSONConvert.Value2JSON(
fieldInfo.GetValue(entity),
ref jToken
))
{
jObject.Add(fieldInfo.Name, jToken);
}
}
foreach (PropertyInfo propertyInfo in publicProperties.Values)
{
JToken jToken = null;
if (JSONConvert.Value2JSON(
propertyInfo.GetValue(entity),
ref jToken
))
{
jObject.Add(propertyInfo.Name, jToken);
}
}
return jObject;
}
public bool PopulateEntity(JObject json)
{
return false;
}
}
}

View File

@ -3,16 +3,16 @@ using System.Collections.Generic;
using System.Collections;
namespace ln.http.resources.collections
{
public interface IEntityCollectionInterface<TVALUE,TIDENT>
public interface IEntityCollectionInterface<TENTITY,TIDENT>
{
IEnumerable<TVALUE> List();
IEnumerable<TENTITY> List();
// ToDo: IEnumerable<TVALUE> Query(/* Filter expressions ?! */);
object GetIdentity(TIDENT entity);
TVALUE CreateEntity();
TENTITY CreateEntity();
TIDENT GetIdentity(TENTITY entity);
bool StoreEntity(TVALUE entity);
bool GetEntity(TIDENT identity);
bool StoreEntity(TENTITY entity);
TENTITY GetEntity(TIDENT identity);
bool RemoveEntity(TIDENT identity);
string GetLastErrorMessage();

View File

@ -25,15 +25,16 @@ namespace ln.http.resources.collections
public class JSONCollectionResource<TENTITY, TIDENT> : Resource where TENTITY : class
{
public JSONConvert JSONConvert { get; set; }
public EntityMapper<TENTITY> EntityMapper { get;}
IEntityCollectionInterface<TENTITY, TIDENT> entityCollectionInterface;
public JSONCollectionResource(Resource container, IEntityCollectionInterface<TENTITY,TIDENT> entityCollectionInterface)
: base(container, typeof(TENTITY).Name)
{
this.entityCollectionInterface = entityCollectionInterface;
JSONConvert = JSONConvert.DefaultInstance;
EntityMapper = new EntityMapper<TENTITY>(JSONConvert);
}
public override bool HandlesDispatching => true;
@ -45,24 +46,22 @@ namespace ln.http.resources.collections
public override HttpResponse GetResponse(HttpRequest httpRequest) => GetResponse(httpRequest, new Queue<string>());
public override HttpResponse GetResponse(HttpRequest httpRequest, Queue<string> pathStack)
{
object responseValue = null;
HttpResponse httpResponse = new HttpResponse(httpRequest);
httpResponse.SetHeader("content-type", "application/json");
CollectionResult collectionResult = null;
if (pathStack.Count == 0)
{
switch (httpRequest.Method)
{
case "GET":
responseValue = Query(httpRequest);
collectionResult = Query(httpRequest);
break;
case "POST":
/*
T ni = PostItem(httpRequest);
object documentID = collection.Mapper.GetDocumentID(ni);
httpResponse.SetHeader("Location", String.Format("/{0}/{1}", String.Join("/", this.Path), documentID.ToString()));
httpResponse.StatusCode = 201;
responseValue = ni;
responseValue = ni;*/
break;
default:
throw new NotSupportedException();
@ -71,81 +70,62 @@ namespace ln.http.resources.collections
else
{
String documentID = pathStack.Dequeue();
Type idType = collection.IDType;
object docID = documentID;
if (!typeof(string).Equals(idType))
{
TypeConverter converter = TypeDescriptor.GetConverter(idType);
docID = converter.ConvertFromString(documentID);
}
T instance = collection[ODBMapper.Default.MapValue(docID)];
TIDENT ident = this.JSONConvert.JSON2Value<TIDENT>(new JValue(documentID));
TENTITY entity = entityCollectionInterface.GetEntity(ident);
switch (httpRequest.Method)
{
case "GET":
responseValue = instance;
collectionResult = new CollectionResult();
collectionResult.Values.Add(entity);
break;
case "PUT":
JsonConvert.PopulateObject(httpRequest.ContentReader.ReadToEnd(), instance);
bool updated = collection.Update(instance);
responseValue = instance;
break;
default:
throw new NotSupportedException();
}
}
httpResponse.ContentWriter.Write(
JsonConvert.SerializeObject(responseValue)
);
HttpResponse httpResponse = ConstructResponse(httpRequest, collectionResult);
return httpResponse;
}
private CollectionResult Query(HttpRequest request)
{
CollectionResult collectionResult = new CollectionResult();
foreach (TENTITY entity in entityCollectionInterface.List())
collectionResult.Values.Add(entity);
return collectionResult;
}
private string ConstructEntityURL(HttpRequest request,TIDENT identity)
{
JToken jId = null;
if (!JSONConvert.Value2JSON(identity, ref jId))
throw new HttpException(500,"Identity can not be serialized");
return string.Format("/{0}/{1}", String.Join("/", Path), jId.ToObject(typeof(string)));
return string.Format("{0}/{1}", String.Join("/", Path), identity.ToString());
}
private HttpResponse ConstructResponse(HttpRequest request,IEnumerable<TIDENT> values,IEnumerable<TIDENT> failed)
private HttpResponse ConstructResponse(HttpRequest request,CollectionResult collectionResult)
{
HttpResponse response = new HttpResponse(request);
JObject surround = new JObject();
JObject jvalues = new JObject();
if (values != null)
foreach (TENTITY entity in collectionResult.Values)
{
foreach (TIDENT id in values)
{
JToken jId = null;
if (this.JSONConvert.Value2JSON(id, ref jId))
{
jvalues.Add(jId.ToObject(typeof(string)).ToString(), ConstructEntityURL(request, id));
}
}
TIDENT identity = entityCollectionInterface.GetIdentity(entity);
jvalues.Add(ConstructEntityURL(request, identity), EntityMapper.MapEntity(entity));
}
surround.Add("values", jvalues);
if (failed!= null)
JObject jfailed = new JObject();
foreach (TIDENT id in collectionResult.Failed.Keys)
{
JObject jfailed = new JObject();
foreach (TIDENT id in failed)
{
JToken jId = null;
if (this.JSONConvert.Value2JSON(id, ref jId))
{
jfailed.Add(jId.ToObject(typeof(string)).ToString(), null);
}
}
jfailed.Add(id.ToString(), collectionResult.Failed[id]);
}
surround.Add("failed", jvalues);
surround.Add("failed", jfailed);
response.SetHeader("content-type", "application/json");
response.ContentWriter.Write(surround.ToString());
@ -155,7 +135,8 @@ namespace ln.http.resources.collections
class CollectionResult
{
public List<TENTITY> Values { get; } = new List<TENTITY>();
public Dictionary<TIDENT, String> Failed { get; } = new Dictionary<TIDENT, string>();
}
}

View File

@ -49,6 +49,7 @@
<Compile Include="ObjectContainerResource.cs" />
<Compile Include="collections\JSONCollectionResource&lt;T&gt;.cs" />
<Compile Include="collections\IEntityCollectionInterface.cs" />
<Compile Include="collections\EntityMapper.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.http\ln.http.csproj">