This commit is contained in:
Mike Phares 2024-09-13 14:14:22 -07:00
parent 45502a30a9
commit 513e8ae4fc
7 changed files with 234 additions and 8 deletions

View File

@ -19,6 +19,7 @@ public class FileRead : Shared.FileRead, IFileRead
{
private readonly Timer _Timer;
private readonly ReadOnlyCollection<string> _WorkItemTypes;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
@ -32,6 +33,9 @@ public class FileRead : Shared.FileRead, IFileRead
throw new Exception(cellInstanceConnectionName);
if (_IsDuplicator)
throw new Exception(cellInstanceConnectionName);
string cellInstanceNamed = string.Concat("CellInstance.", _EquipmentType);
string workItemTypes = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, $"{cellInstanceNamed}.WorkItemTypes");
_WorkItemTypes = new(workItemTypes.Split('|'));
if (!Debugger.IsAttached && fileConnectorConfiguration.PreProcessingMode != FileConnectorConfiguration.PreProcessingModeEnum.Process)
_Timer = new Timer(Callback, null, (int)(fileConnectorConfiguration.FileScanningIntervalInSeconds * 1000), Timeout.Infinite);
else
@ -119,6 +123,8 @@ public class FileRead : Shared.FileRead, IFileRead
if (alternateTargetFolder == fileConnectorConfiguration.TargetFileLocation)
continue;
pathRoot = Path.GetPathRoot(alternateTargetFolder);
if (string.IsNullOrEmpty(pathRoot))
continue;
try
{
if (!Directory.Exists(pathRoot))
@ -194,7 +200,157 @@ public class FileRead : Shared.FileRead, IFileRead
return new(results);
}
private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, string[] alternateTargetFolders)
private static ReadOnlyDictionary<int, WorkItem> GetWorkItems(ReadOnlyCollection<WorkItem> workItems)
{
Dictionary<int, WorkItem> results = new();
foreach (WorkItem workItem in workItems)
results.Add(workItem.Id, workItem);
return new(results);
}
private static int? GetIdFromUrlIfChild(Relation relation)
{
int? result;
string[] segments = relation.Attributes.Name != "Child" ? Array.Empty<string>() : relation.URL.Split('/');
if (segments.Length < 2)
result = null;
else
{
if (!int.TryParse(segments[segments.Length - 1], out int id))
result = null;
else
result = id;
}
return result;
}
private static Dictionary<int, Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> workItems, WorkItem workItem)
{
Dictionary<int, Record> results = new();
int? childId;
WorkItem? childWorkItem;
List<WorkItem> collection = new();
Dictionary<int, Record> keyValuePairs;
if (workItem.Relations is not null && workItem.Relations.Length > 0)
{
collection.Clear();
foreach (Relation relation in workItem.Relations)
{
childId = GetIdFromUrlIfChild(relation);
if (childId is null || !workItems.TryGetValue(childId.Value, out childWorkItem))
continue;
collection.Add(childWorkItem);
}
collection = (from l in collection orderby l.State != "Closed", l.Id select l).ToList();
foreach (WorkItem item in collection)
{
keyValuePairs = GetKeyValuePairs(workItems, item);
results.Add(item.Id, new(item, new(keyValuePairs)));
}
}
return results;
}
private static ReadOnlyDictionary<int, Record> GetWorkItemAndChildren(ReadOnlyDictionary<int, WorkItem> workItems)
{
Dictionary<int, Record> results = new();
Dictionary<int, Record> keyValuePairs;
foreach (KeyValuePair<int, WorkItem> keyValuePair in workItems)
{
// if (keyValuePair.Key != 119185)
// continue;
keyValuePairs = GetKeyValuePairs(workItems, keyValuePair.Value);
results.Add(keyValuePair.Key, new(keyValuePair.Value, new(keyValuePairs)));
}
return new(results);
}
private static string GetClosed(WorkItem workItem)
{
string result = workItem.State != "Closed" ? "[ ]" : "[x]";
return result;
}
private static string GetLine(List<char> spaces, WorkItem workItem, KeyValuePair<int, Record> keyValuePair, bool condensed) =>
!condensed ? $"{new string(spaces.Skip(1).ToArray())}- {GetClosed(workItem)} {keyValuePair.Key} - {workItem.Title}" :
$"{new string(spaces.Skip(1).ToArray())}- {GetClosed(workItem)} {keyValuePair.Key} - {workItem.Title} ~~~ {workItem.AssignedTo} - {workItem.IterationPath.Replace('\\', '-')} - {workItem.CreatedDate} --- {workItem.ClosedDate}";
private static void AppendLines(List<char> spaces, List<string> lines, Record record, bool condensed)
{
spaces.Add('\t');
WorkItem workItem;
foreach (KeyValuePair<int, Record> keyValuePair in record.Children)
{
workItem = keyValuePair.Value.WorkItem;
lines.Add(GetLine(spaces, workItem, keyValuePair, condensed));
AppendLines(spaces, lines, keyValuePair.Value, condensed);
}
spaces.RemoveAt(0);
}
private static void AppendLines(List<char> spaces, List<string> lines, ReadOnlyDictionary<int, Record> workItemAndChildren, string workItemType)
{
WorkItem workItem;
foreach (KeyValuePair<int, Record> keyValuePair in workItemAndChildren)
{
workItem = keyValuePair.Value.WorkItem;
if (workItem.WorkItemType != workItemType)
continue;
lines.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}");
lines.Add(string.Empty);
lines.Add($"- [{workItem.Id}](https://tfs.intra.infineon.com/tfs/FactoryIntegration/ART%20SPS/_workitems/edit/{workItem.Id})");
lines.Add(string.Empty);
if (keyValuePair.Value.Children.Count > 0)
{
AppendLines(spaces, lines, keyValuePair.Value, condensed: true);
lines.Add(string.Empty);
lines.Add($"## Extended - {workItem.Id} - {workItem.Title}");
lines.Add(string.Empty);
AppendLines(spaces, lines, keyValuePair.Value, condensed: false);
lines.Add(string.Empty);
}
}
}
private static void WriteMarkdownFile(FileConnectorConfiguration fileConnectorConfiguration, string[] alternateTargetFolders, ReadOnlyCollection<WorkItem> workItems, ReadOnlyCollection<string> workItemTypes)
{
string json;
string? pathRoot;
List<char> spaces = new();
List<string> lines = new();
lines.Add("# WorkItems");
ReadOnlyDictionary<int, WorkItem> keyValuePairs = GetWorkItems(workItems);
ReadOnlyDictionary<int, Record> workItemAndChildren = GetWorkItemAndChildren(keyValuePairs);
foreach (string alternateTargetFolder in alternateTargetFolders)
{
if (alternateTargetFolder == fileConnectorConfiguration.TargetFileLocation)
continue;
pathRoot = Path.GetPathRoot(alternateTargetFolder);
if (string.IsNullOrEmpty(pathRoot))
continue;
try
{
if (!Directory.Exists(pathRoot))
continue;
}
catch (Exception)
{ continue; }
if (!Directory.Exists(alternateTargetFolder))
_ = Directory.CreateDirectory(alternateTargetFolder);
if (workItemAndChildren.Count == -1)
{
json = JsonSerializer.Serialize(workItemAndChildren, new JsonSerializerOptions() { WriteIndented = true });
File.WriteAllText(Path.Combine(alternateTargetFolder, ".json"), json);
}
foreach (string workItemType in workItemTypes)
{
AppendLines(spaces, lines, workItemAndChildren, workItemType);
File.WriteAllText(Path.Combine(alternateTargetFolder, $"{workItemType}.md"), string.Join(Environment.NewLine, lines));
}
}
}
private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, string[] alternateTargetFolders, ReadOnlyCollection<string> workItemTypes)
{
if (!Directory.Exists(fileConnectorConfiguration.TargetFileLocation))
_ = Directory.CreateDirectory(fileConnectorConfiguration.TargetFileLocation);
@ -202,14 +358,17 @@ public class FileRead : Shared.FileRead, IFileRead
ReadOnlyCollection<Value> collection = GetWorkItems(files);
ReadOnlyCollection<WorkItem> workItems = GetWorkItems(collection);
if (workItems.Count > 0)
{
ParseWorkItemsAsync(fileConnectorConfiguration, alternateTargetFolders, workItems);
WriteMarkdownFile(fileConnectorConfiguration, alternateTargetFolders, workItems, workItemTypes);
}
}
private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration)
private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, ReadOnlyCollection<string> workItemTypes)
{
string[] alternateTargetFolders = fileConnectorConfiguration.AlternateTargetFolder.Split('|');
if (alternateTargetFolders.Length > 0)
ParseWorkItemsAsync(fileConnectorConfiguration, alternateTargetFolders);
ParseWorkItemsAsync(fileConnectorConfiguration, alternateTargetFolders, workItemTypes);
}
private void Callback(object state)
@ -217,7 +376,7 @@ public class FileRead : Shared.FileRead, IFileRead
try
{
if (_IsEAFHosted)
ParseWorkItemsAsync(_FileConnectorConfiguration);
ParseWorkItemsAsync(_FileConnectorConfiguration, _WorkItemTypes);
}
catch (Exception exception)
{

View File

@ -0,0 +1,21 @@
using System.Text.Json.Serialization;
namespace Adaptation.FileHandlers.json.WorkItems;
public class Attribute
{
#nullable enable
[JsonConstructor]
public Attribute(bool isLocked,
string name)
{
IsLocked = isLocked;
Name = name;
}
public bool IsLocked { get; set; } // { init; get; }
public string Name { get; set; } // { init; get; }
}

View File

@ -0,0 +1,19 @@
using System.Collections.ObjectModel;
namespace Adaptation.FileHandlers.json.WorkItems;
public class Record
{
#nullable enable
public Record(WorkItem workItem, ReadOnlyDictionary<int, Record> children)
{
WorkItem = workItem;
Children = children;
}
public WorkItem WorkItem { get; set; }
public ReadOnlyDictionary<int, Record> Children { get; set; }
}

View File

@ -0,0 +1,24 @@
using System.Text.Json.Serialization;
namespace Adaptation.FileHandlers.json.WorkItems;
public class Relation
{
#nullable enable
[JsonConstructor]
public Relation(string rel,
string url,
Attribute attributes)
{
Rel = rel;
URL = url;
Attributes = attributes;
}
public string Rel { get; set; } // { init; get; }
public string URL { get; set; } // { init; get; }
public Attribute Attributes { get; set; } // { init; get; }
}

View File

@ -9,7 +9,7 @@ public class Value
int id,
int rev,
Fields fields,
object[] relations,
Relation[] relations,
CommentVersionRef commentVersionRef,
string url
)
@ -32,7 +32,7 @@ public class Value
public Fields Fields { get; }
[JsonPropertyName("relations")]
public object[] Relations { get; }
public Relation[] Relations { get; }
[JsonPropertyName("commentVersionRef")]
public CommentVersionRef CommentVersionRef { get; }

View File

@ -22,7 +22,7 @@ public class WorkItem
string iterationPath,
int? parent,
int? priority,
object[]? relations,
Relation[]? relations,
string? requester,
DateTime? resolvedDate,
int revision,
@ -77,7 +77,7 @@ public class WorkItem
public string IterationPath { get; set; } // { init; get; }
public int? Parent { get; set; } // { init; get; }
public int? Priority { get; set; } // { init; get; }
public object[]? Relations { get; set; } // { init; get; }
public Relation[]? Relations { get; set; } // { init; get; }
public string? Requester { get; set; } // { init; get; }
public DateTime? ResolvedDate { get; set; } // { init; get; }
public int Revision { get; set; } // { init; get; }

View File

@ -122,12 +122,15 @@
<Compile Include="Adaptation\FileHandlers\json\WIQL\Root.cs" />
<Compile Include="Adaptation\FileHandlers\json\WIQL\SortColumn.cs" />
<Compile Include="Adaptation\FileHandlers\json\WIQL\WorkItem.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\Attribute.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\Avatar.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\CommentVersionRef.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\CustomRequester.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\Fields.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\Html.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\Links.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\Record.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\Relation.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\SystemAssignedTo.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\SystemChangedBy.cs" />
<Compile Include="Adaptation\FileHandlers\json\WorkItems\SystemCreatedBy.cs" />