Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E1.37-5 JSON Metadata Defines / Schema for Manufacturer PIDs #35

Draft
wants to merge 56 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
2740476
WIP
patrick-dmxc Sep 13, 2024
684480d
Start implementing JSON-Parser
patrick-dmxc Sep 16, 2024
069f5ef
CleanUp
patrick-dmxc Sep 16, 2024
8ef0200
Work on OneOfTypes
patrick-dmxc Sep 16, 2024
d8c767c
Minor
patrick-dmxc Sep 16, 2024
3489e58
Minor
patrick-dmxc Sep 16, 2024
56471b0
Add missing Types
patrick-dmxc Sep 17, 2024
a5ffb11
Minor
patrick-dmxc Sep 17, 2024
22bce8b
Wrote Test for JSON-Deserielizer
patrick-dmxc Sep 17, 2024
0696394
Remove Not working and not defined Parameters
patrick-dmxc Sep 17, 2024
50c8917
Add more Tests and improve code while adding Tests
patrick-dmxc Sep 17, 2024
081c376
More optimizations
patrick-dmxc Sep 17, 2024
ed6d313
More tests and optimizations
patrick-dmxc Sep 18, 2024
3ab8529
MInor
patrick-dmxc Sep 18, 2024
402368f
Implement PDL-Calculation
patrick-dmxc Sep 19, 2024
5a0bbe9
More Tests
patrick-dmxc Sep 19, 2024
c9202aa
Add more Tests, achieve 100% Code Coverage on Metadata for now
patrick-dmxc Sep 20, 2024
ff47503
Start Implement Type Parsing
patrick-dmxc Sep 21, 2024
c13e5b6
Fix Build
patrick-dmxc Sep 24, 2024
d8eb6f1
WIP
patrick-dmxc Sep 24, 2024
c0516ca
WIP
patrick-dmxc Sep 24, 2024
551e5d4
MInor Fix
patrick-dmxc Sep 24, 2024
978f3e7
Minor
patrick-dmxc Sep 24, 2024
769bd80
WIP
patrick-dmxc Sep 24, 2024
f95c1ec
Minor
patrick-dmxc Sep 25, 2024
67240aa
WIP
patrick-dmxc Sep 25, 2024
4e9782d
Fix BitFieldType-Parser and wrote tests for it
patrick-dmxc Sep 25, 2024
f2cee92
Minor
patrick-dmxc Sep 25, 2024
40311a6
MOOOOOOR TESTS
patrick-dmxc Sep 25, 2024
ea070df
Moooore Tests
patrick-dmxc Sep 25, 2024
87c4171
Implement Parser for ByteType and wrote Tests
patrick-dmxc Sep 25, 2024
5094b6a
minor
patrick-dmxc Sep 25, 2024
1aabd78
Wip Parse StringType
patrick-dmxc Oct 2, 2024
5ecf37a
Minor
patrick-dmxc Oct 2, 2024
1a791d4
Implement Array Format for BytesType
patrick-dmxc Oct 3, 2024
0239ca3
Test CompoundType Parser Stuff
patrick-dmxc Oct 3, 2024
ba00e59
Minor
patrick-dmxc Oct 3, 2024
e3522d2
Add Tests for ListType Parser
patrick-dmxc Oct 3, 2024
9d084b4
More Tests
patrick-dmxc Oct 3, 2024
52314a5
More Tests and Coverage
patrick-dmxc Oct 3, 2024
f89fd52
Add Test for debugFailing Linux Tests
patrick-dmxc Oct 3, 2024
514a573
try fix Tests
patrick-dmxc Oct 3, 2024
aaeba4a
try fix tests
patrick-dmxc Oct 3, 2024
87d9186
MInor
patrick-dmxc Oct 3, 2024
7c8c941
Wrote Parse Tests for ReferenceType
patrick-dmxc Oct 3, 2024
7523afe
Add more Tests
patrick-dmxc Oct 15, 2024
d2d3030
Grrr
patrick-dmxc Oct 15, 2024
6520c47
More Tests
patrick-dmxc Oct 22, 2024
35f941f
Work on PeerToPeerProcess and Tests
patrick-dmxc Oct 22, 2024
e636b05
More Tests
patrick-dmxc Oct 25, 2024
820675a
Work on Parse DataTree to known Objects
patrick-dmxc Nov 1, 2024
d2de40c
Add more DataTreeObject-Attributes to some Enums
patrick-dmxc Nov 22, 2024
b98df92
Update Nuget-Packages
patrick-dmxc Nov 23, 2024
2f08e96
Add DataTreeObjectAttributes to all nesicery Objects
patrick-dmxc Jan 6, 2025
e73ea3c
Some refactoring
patrick-dmxc Jan 7, 2025
a6664d3
Start refactoring of actual Querying
patrick-dmxc Jan 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
98 changes: 98 additions & 0 deletions RDMSharp/Metadata/DataTree.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace RDMSharp.Metadata
{
public readonly struct DataTree : IEquatable<DataTree>
{
public readonly string Name;
public readonly uint Index;
public readonly object? Value;
public readonly string? Unit;
public readonly DataTreeValueLabel[]? Labels;
public readonly DataTree[]? Children;
public readonly DataTreeIssue[]? Issues;

private DataTree(string name, uint index, DataTreeIssue[]? issues = null)
{
Name = name;
Index = index;
Issues = issues;
}
public DataTree(DataTree dataTree, uint index) : this(dataTree.Name, index, dataTree.Issues)
{
Value = dataTree.Value;
Unit = dataTree.Unit;
Labels = dataTree.Labels;
Children = dataTree.Children;
}
public DataTree(string name, uint index, object value, DataTreeIssue[]? issues = null, string unit = null, DataTreeValueLabel[] labels = null) : this(name, index, issues)
{
if (value is IEnumerable<DataTree> || value is DataTree[] children)
throw new ArgumentException($"Use other Constructor if you use {nameof(Children)}");

Value = value;
Unit = unit;
Labels = labels;
}

public DataTree(string name, uint index, DataTree[] children, DataTreeIssue[]? issues = null) : this(name, index, issues)
{
Children = children;
}

public override string ToString()
{
return $"[{Index}] {Name}: {Value}";
}

public override bool Equals(object obj)
{
return obj is DataTree tree && Equals(tree);
}

public bool Equals(DataTree other)
{
return Name == other.Name &&
Index == other.Index &&
EqualityComparer<object>.Default.Equals(Value, other.Value) &&
compairArrays(this, other);

bool compairArrays(DataTree _this, DataTree other)
{
if (_this.Children != null)
{
if (!_this.Children.SequenceEqual(other.Children))
return false;
}
else if (other.Children != null)
return false;
if (_this.Issues != null)
{
if (!_this.Issues.SequenceEqual(other.Issues))
return false;
}
else if (other.Issues != null)
return false;

return true;
}
}

public override int GetHashCode()
{
return HashCode.Combine(Name, Index, Value, Children, Issues);
}

public static bool operator ==(DataTree left, DataTree right)
{
return left.Equals(right);
}

public static bool operator !=(DataTree left, DataTree right)
{
return !(left == right);
}
}
}
282 changes: 282 additions & 0 deletions RDMSharp/Metadata/DataTreeBranch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
using RDMSharp.Metadata.JSON;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;

namespace RDMSharp.Metadata
{
public readonly struct DataTreeBranch : IEquatable<DataTreeBranch>
{
public static readonly DataTreeBranch Empty = new DataTreeBranch();
public static readonly DataTreeBranch Unset = new DataTreeBranch(true);

public readonly DataTree[] Children;
public readonly bool IsEmpty;
public readonly bool IsUnset;

public readonly object ParsedObject;
public DataTreeBranch()
{
IsEmpty = true;
}
private DataTreeBranch(bool isUnset)
{
IsUnset = true;
}
public DataTreeBranch(params DataTree[] children)
{
if (children.Length == 0)
IsEmpty = true;

Children = children;
if (Children.Count(c => c.Index == 0) > 1)
for (uint i = 0; i < Children.Length; i++)
Children[i] = new DataTree(Children[i], i);
}
private DataTreeBranch(object parsedObject, params DataTree[] children): this(children)
{
ParsedObject = parsedObject;
}
public DataTreeBranch(MetadataJSONObjectDefine define, Command.ECommandDublicte commandType, params DataTree[] children): this(children)
{
if (define == null)
throw new ArgumentNullException();

ParsedObject = this.getParsedObject(define, commandType);
}

private object getParsedObject(MetadataJSONObjectDefine define, Command.ECommandDublicte commandType)
{
ushort pid = define.PID;
var definedDataTreeObjectType = MetadataFactory.GetDefinedDataTreeObjectType(define, commandType);
return getParsedObject(pid, definedDataTreeObjectType, commandType);
}
private object getParsedObject(ushort pid, Type definedDataTreeObjectType, Command.ECommandDublicte commandType)
{
if (IsEmpty || IsUnset)
return null;
try
{
if (definedDataTreeObjectType != null)
{
if (definedDataTreeObjectType.IsEnum)
{
var enumAttribute = definedDataTreeObjectType.GetCustomAttributes<DataTreeEnumAttribute>().FirstOrDefault(a => (ushort)a.Parameter == pid && a.Command == commandType);

var eChildren = getChildrenUsingPath(enumAttribute, Children);
if (enumAttribute.IsArray)
{
var array = Array.CreateInstance(definedDataTreeObjectType, eChildren.Length);
var aa = eChildren.Select(eC => Enum.ToObject(definedDataTreeObjectType, eC.Value)).ToArray();
Array.Copy(aa, array, eChildren.Length);
return array;
}
else
return Enum.ToObject(definedDataTreeObjectType, eChildren.Single().Value);
}

ConstructorInfo[] constructors = definedDataTreeObjectType.GetConstructors();
var objectAttribute = definedDataTreeObjectType.GetCustomAttributes<DataTreeObjectAttribute>().FirstOrDefault(a => (ushort)a.Parameter == pid && a.Command == commandType);


var children = getChildrenUsingPath(objectAttribute, Children);
DataTree[] getChildrenUsingPath(DataTreeObjectAttribute objectAttribute, DataTree[] children)
{
if (!string.IsNullOrWhiteSpace(objectAttribute.Path))
{
string[] path = objectAttribute.Path.Split('/');
while (path.Length >= 1)
{
children = children.FirstOrDefault(c => string.Equals(c.Name, path[0])).Children;
path = path.Skip(1).ToArray();
}
}
return children;
}


foreach (var constructor in constructors)
{
if (constructor.GetCustomAttribute<DataTreeObjectConstructorAttribute>() is DataTreeObjectConstructorAttribute cAttribute)
{
var parameters = new List<object>();
foreach (var param in constructor.GetParameters())
if (param.GetCustomAttribute<DataTreeObjectParameterAttribute>() is DataTreeObjectParameterAttribute pAttribute)
{
var children2 = children;
string name = pAttribute.Name;
string[] path = name.Split('/');
while (path.Length > 1)
{
children2 = children2.FirstOrDefault(c => string.Equals(c.Name, path[0])).Children;
path = path.Skip(1).ToArray();
if (path.Length == 1)
name = path[0];
}
if (!pAttribute.IsArray && children2.FirstOrDefault(c => string.Equals(c.Name, name)) is DataTree child)
parameters.Add(child.Value);
else if (pAttribute.IsArray && children2.Where(c => string.Equals(c.Name, pAttribute.Name)).OfType<DataTree>() is IEnumerable<DataTree> childenum)
{
Type targetType = children2.First().Value.GetType();
var array = Array.CreateInstance(targetType, children2.Length);
Array.Copy(children2.Select(c => c.Value).ToArray(), array, children2.Length);
parameters.Add(array);
}
else
throw new ArgumentException($"No matching Value found for '{pAttribute.Name}'");
}

var instance = constructor.Invoke(parameters.ToArray());
return instance;
}
}
}

if (Children.Length == 1)
{
DataTree dataTree = Children[0];

if (dataTree.Value != null)
return dataTree.Value;

if (dataTree.Children.GroupBy(c => c.Name).Count() == 1)
{
var list = dataTree.Children.Select(c => c.Value).ToList();
Type targetType = list.First().GetType();
var array = Array.CreateInstance(targetType, list.Count);
Array.Copy(list.ToArray(), array, list.Count);
//for (int i = 0; i < list.Count; i++)
// array.SetValue(Convert.ChangeType(list[i], targetType), i);

return array;
}
}
}
catch (Exception e)
{
throw e;
}

throw new NotImplementedException();
}

public static DataTreeBranch FromObject(object obj, ERDM_Command command, ERDM_Parameter parameter)
{

Type type = obj.GetType();
bool isArray = type.IsArray;

if (isArray)
type = type.GetElementType();

if (type.GetCustomAttributes<DataTreeObjectAttribute>().FirstOrDefault(a => a.Parameter == parameter && a.Command == Tools.ConvertCommandDublicteToCommand(command) && a.IsArray == isArray) is not DataTreeObjectAttribute dataTreeObjectAttribute)
return DataTreeBranch.Unset;

List<DataTree> children = new List<DataTree>();
if (!type.IsEnum)
{
var properties = type.GetProperties().Where(p => p.GetCustomAttributes<DataTreeObjectPropertyAttribute>().Count() != 0).ToArray();

if (isArray)
{
Array array = (Array)obj;
for (uint i = 0; i < array.Length; i++)
children.Add(new DataTree(string.Empty, i, convertToDataTree(array.GetValue(i), properties, parameter)));
}
else
children.AddRange(convertToDataTree(obj, properties, parameter));
}
else
{
DataTreeEnumAttribute enumAttribute = dataTreeObjectAttribute as DataTreeEnumAttribute;
if (isArray)
{
Array array = (Array)obj;
for (uint i = 0; i < array.Length; i++)
children.Add(new DataTree(enumAttribute.Name, i, getUnderlyingValue(array.GetValue(i))));
}
else
children.Add(new DataTree(enumAttribute.Name, 0, getUnderlyingValue(obj)));
}

if (!string.IsNullOrWhiteSpace(dataTreeObjectAttribute.Path))
{
string[] path = dataTreeObjectAttribute.Path.Split('/');
DataTree? route = null;
for (int i = path.Length; i != 0; i--)
{
if (route.HasValue)
route = new DataTree(path[i - 1], 0, route);
else
route = new DataTree(path[i - 1], 0, children.ToArray());
}

return new DataTreeBranch(obj, route.Value);
}

return new DataTreeBranch(obj, children.ToArray());

static DataTree[] convertToDataTree(object value, PropertyInfo[] properties, ERDM_Parameter parameter)
{
List<DataTree> innetChildren = new List<DataTree>();
foreach (var property in properties)
{
var attributes = property.GetCustomAttributes<DataTreeObjectPropertyAttribute>();
DataTreeObjectPropertyAttribute attribute = attributes.FirstOrDefault();
if (attributes.Count() != 1)
attribute = attributes.FirstOrDefault(a => a.Parameter == parameter);

if (attribute != null)
innetChildren.Add(new DataTree(attribute.Name, attribute.Index, property.GetValue(value)));
}
return innetChildren.ToArray();
}
static object getUnderlyingValue(object enumValue)
{
// Ermitteln des zugrunde liegenden Typs
Type underlyingType = Enum.GetUnderlyingType(enumValue.GetType());

// Konvertierung des Enum-Werts in den zugrunde liegenden Typ
return Convert.ChangeType(enumValue, underlyingType);
}
}

public override bool Equals(object obj)
{
return obj is DataTreeBranch branch && Equals(branch);
}

public bool Equals(DataTreeBranch other)
{
for (int i = 0; i < Children.Length; i++)
{
DataTree me = Children[i];
if ((other.Children?.Length ?? 0) <= i)
return false;
DataTree ot = other.Children[i];
if (!me.Equals(ot))
return false;
}
return true;
// return EqualityComparer<DataTree[]>.Default.Equals(Children, other.Children); // is not dooing its job
}

public override int GetHashCode()
{
return HashCode.Combine(Children);
}

public static bool operator ==(DataTreeBranch left, DataTreeBranch right)
{
return left.Equals(right);
}

public static bool operator !=(DataTreeBranch left, DataTreeBranch right)
{
return !(left == right);
}
}
}
Loading