Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…piler into develop
  • Loading branch information
tbm0115 committed Mar 16, 2023
2 parents 2a90fe0 + c906fb1 commit e37d278
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Consoul" Version="1.6.1" />
<PackageReference Include="Consoul" Version="1.6.3" />
</ItemGroup>

<ItemGroup>
Expand Down
61 changes: 61 additions & 0 deletions MtconnectTranspiler.Console/Views/MainView.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,74 @@
using ConsoulLibrary;
using ConsoulLibrary.Views;
using Microsoft.Extensions.Logging;
using MtconnectTranspiler.Contracts;
using MtconnectTranspiler.Model;
using System.Threading;

namespace MtconnectTranspiler.Console.Views
{
internal class MainView : StaticView
{
private ILogger<TranspilerDispatcher> _logger;

public MainView()
{
Title = (new BannerEntry($"MTConnect Transpiler")).Message;

// Uses Microsoft.Extensions.Logging for the LoggerFactory and ILogger
// Uses the Consoul library for color formatting
_logger = LoggerFactory.Create((o) => o.AddConsoulLogger()).CreateLogger<TranspilerDispatcher>();
}

[ViewOption("Transpile From GitHub Latest")]
public void TranspileFromGitHub()
{
var options = new FromGitHubOptions() { GitHubRelease = "latest" };
if (!Consoul.Ask("Would you like to use the latest GitHub Release of mtconnect_sysml_model?"))
{
string release = Consoul.Input("Please specify which Release you would prefer to use");
options.GitHubRelease = release;
}

Deserialize(options);
}

[ViewOption("Transpile From File")]
public void TranspileFromFile()
{
var options = new FromFileOptions();
options.Filepath = Consoul.PromptForFilepath("Please provide the filepath to the copy of the mtconnect_sysml_model XMI", true);

Deserialize(options);
}

private async void Deserialize(TranspilerDispatcherOptions options)
{
using (var cancellationSource = new CancellationTokenSource())
{
var deserializer = options.GetDeserializer();

var task = Task.Run(() => Deserialize(deserializer, cancellationSource.Token)).ContinueWith((t) => cancellationSource.Cancel());

// We'll leverage Consoul to help make this pretty. The ContinueWith above helps make sure the Consoul.Wait goes away when the task is done.
Consoul.Wait(cancellationToken: cancellationSource.Token);

if (task.IsCompletedSuccessfully)
{
Consoul.Write("Success!", ConsoleColor.Green);
}
else
{
Consoul.Write("Aborted!", ConsoleColor.Red);
}
}
}
private async void Deserialize(XmiDeserializer deserializer, CancellationToken cancellationToken)
{
Consoul.Write("Deserializing...");
MTConnectModel? model = deserializer.Deserialize<MTConnectModel>("//uml:Model[@name='MTConnect']", cancellationToken);

Consoul.Write("Finished deserializing");
}
}
}
88 changes: 55 additions & 33 deletions MtconnectTranspiler/Contracts/XmiDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,54 +98,76 @@ public XmiDeserializer(XmlDocument xmlDocument, ILogger<XmiDeserializer>? logger
System.Reflection.PropertyInfo[]? properties = targetType
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);

Type attrXPath = typeof(XPathAttribute);
foreach (var property in properties)
{
XPathAttribute[] xpathAttributes = ((XPathAttribute[])property.GetCustomAttributes(attrXPath, true));
foreach (var xpathAttribute in xpathAttributes)
ParseXPathAttribute(xNode, targetType, result, property, cancellationToken);
ParseXmlAttributeAttribute(xNode, targetType, result, property, cancellationToken);
}

return result;
}

private Type XPathAttributeType = typeof(XPathAttribute);
private void ParseXPathAttribute(XmlNode xNode, Type targetType, object? result, PropertyInfo property, CancellationToken cancellationToken)
{
XPathAttribute[] xpathAttributes = ((XPathAttribute[])property.GetCustomAttributes(XPathAttributeType, true));
foreach (var xpathAttribute in xpathAttributes)
{
if (property.PropertyType.IsArray)
{
if (property.PropertyType.IsArray)
_logger?.LogTrace("Deserializing array property '{PropertyName}' in '{TargetType}'", property.Name, targetType.FullName);
XmlNodeList? xPropertyNodes = xNode.SelectNodes(xpathAttribute.Path, nsmgr);
if (xPropertyNodes != null)
{
_logger?.LogTrace("Deserializing array property '{PropertyName}' in '{TargetType}'", property.Name, targetType.FullName);
XmlNodeList? xPropertyNodes = xNode.SelectNodes(xpathAttribute.Path, nsmgr);
if (xPropertyNodes != null)
Type? elementType = property.PropertyType.GetElementType();
Type? resultType = xpathAttribute.Type ?? elementType;
List<object> collection = new List<object>();
foreach (XmlNode xChild in xPropertyNodes)
{
Type? elementType = property.PropertyType.GetElementType();
Type? resultType = xpathAttribute.Type ?? elementType;
List<object> collection = new List<object>();
foreach (XmlNode xChild in xPropertyNodes)
{
var childObject = unwrapObject(xChild, resultType, cancellationToken);
if (childObject != null)
{
collection.Add(childObject);
}
}
object[]? existingArray = property.GetValue(result) as object[];
if (existingArray?.Length > 0)
var childObject = unwrapObject(xChild, resultType, cancellationToken);
if (childObject != null)
{
collection.InsertRange(0, existingArray);
collection.Add(childObject);
}
Array typedArray = Array.CreateInstance(elementType, collection.Count);
Array.Copy(collection.ToArray(), typedArray, collection.Count);
property.SetValue(result, typedArray);
}
}
else
{
_logger?.LogTrace("Deserializing property '{PropertyName}' in '{TargetType}'", property.Name, targetType.FullName);
XmlNode? xPropertyNode = xNode.SelectSingleNode(xpathAttribute.Path, nsmgr);
if (xPropertyNode != null)
object[]? existingArray = property.GetValue(result) as object[];
if (existingArray?.Length > 0)
{
property.SetValue(result, unwrapObject(xPropertyNode, xpathAttribute.Type ?? property.PropertyType, cancellationToken));
collection.InsertRange(0, existingArray);
}
Array typedArray = Array.CreateInstance(elementType, collection.Count);
Array.Copy(collection.ToArray(), typedArray, collection.Count);
property.SetValue(result, typedArray);
}
}
else
{
_logger?.LogTrace("Deserializing property '{PropertyName}' in '{TargetType}'", property.Name, targetType.FullName);
XmlNode? xPropertyNode = xNode.SelectSingleNode(xpathAttribute.Path, nsmgr);
if (xPropertyNode != null)
{
property.SetValue(result, unwrapObject(xPropertyNode, xpathAttribute.Type ?? property.PropertyType, cancellationToken));
}
}
}
}

return result;
private Type XmlAttributeType = typeof(XmlAttributeAttribute);
private void ParseXmlAttributeAttribute(XmlNode xNode, Type targetType, object? result, PropertyInfo property, CancellationToken cancellationToken)
{
XmlAttributeAttribute[] xAttributes = ((XmlAttributeAttribute[])property.GetCustomAttributes(XmlAttributeType, true));
foreach (var xAttribute in xAttributes)
{
_logger?.LogTrace("Deserializing property '{PropertyName}' in '{TargetType}'", property.Name, targetType.FullName);
XmlAttribute? xProperty = xNode.Attributes[xAttribute.AttributeName, xAttribute.Namespace];

if (xProperty != null)
{
property.SetValue(result, xProperty.Value);
}
}
}

/// <summary>
/// Creates a <see cref="XmiDeserializer"/> from a reference to the filepath of a XMI document.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion MtconnectTranspiler/FromFileOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class FromFileOptions : TranspilerDispatcherOptions

/// <inheritdoc />
/// <exception cref="FileNotFoundException"></exception>
internal override XmiDeserializer GetDeserializer()
public override XmiDeserializer GetDeserializer()
{
if (!File.Exists(Filepath)) throw new FileNotFoundException("Could not find specified XMI file", Filepath);

Expand Down
2 changes: 1 addition & 1 deletion MtconnectTranspiler/FromGitHubOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class FromGitHubOptions : TranspilerDispatcherOptions
public string GitHubRelease { get; set; } = "latest";

/// <inheritdoc />
internal override XmiDeserializer GetDeserializer()
public override XmiDeserializer GetDeserializer()
{
if (string.IsNullOrEmpty(GitHubRelease)) throw new ArgumentNullException();

Expand Down
2 changes: 1 addition & 1 deletion MtconnectTranspiler/TranspilerDispatcherOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public abstract class TranspilerDispatcherOptions
/// Returns an instance of <see cref="XmiDeserializer"/> that has a copy of the SysML model in memory.
/// </summary>
/// <returns>Instance of <see cref="XmiDeserializer"/></returns>
internal abstract XmiDeserializer GetDeserializer();
public abstract XmiDeserializer GetDeserializer();
}
}

0 comments on commit e37d278

Please sign in to comment.