200 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Collections.ObjectModel;
 | |
| using System.Linq;
 | |
| using System.Text.Json;
 | |
| using System.Text.Json.Serialization;
 | |
| 
 | |
| namespace Adaptation.FileHandlers.json.WorkItems;
 | |
| 
 | |
| internal class Record
 | |
| {
 | |
| 
 | |
| #nullable enable
 | |
| 
 | |
|     [JsonConstructor]
 | |
|     public Record(WorkItem workItem, WorkItem? parent, Record[]? children, Record[]? related, Record[]? successors, Dictionary<string, string>? tag)
 | |
|     {
 | |
|         WorkItem = workItem;
 | |
|         Parent = parent;
 | |
|         Children = children;
 | |
|         Related = related;
 | |
|         Successors = successors;
 | |
|         Tag = tag;
 | |
|     }
 | |
| 
 | |
|     [JsonPropertyName("WorkItem")] public WorkItem WorkItem { get; set; }
 | |
|     [JsonPropertyName("Parent")] public WorkItem? Parent { get; set; }
 | |
|     [JsonPropertyName("Children")] public Record[]? Children { get; set; }
 | |
|     [JsonPropertyName("Related")] public Record[]? Related { get; set; }
 | |
|     [JsonPropertyName("Successors")] public Record[]? Successors { get; set; }
 | |
|     [JsonPropertyName("Tag")] public Dictionary<string, string>? Tag { get; set; }
 | |
| 
 | |
|     internal static Record GetWithoutNesting(Record record, string? violation)
 | |
|     {
 | |
|         Record result;
 | |
|         WorkItem workItem = new(activatedDate: record.WorkItem.ActivatedDate,
 | |
|                                 areaPath: record.WorkItem.AreaPath,
 | |
|                                 assignedTo: record.WorkItem.AssignedTo,
 | |
|                                 businessValue: record.WorkItem.BusinessValue,
 | |
|                                 changedDate: record.WorkItem.ChangedDate,
 | |
|                                 closedDate: record.WorkItem.ClosedDate,
 | |
|                                 commentCount: record.WorkItem.CommentCount,
 | |
|                                 createdDate: record.WorkItem.CreatedDate,
 | |
|                                 description: record.WorkItem.Description,
 | |
|                                 effort: record.WorkItem.Effort,
 | |
|                                 id: record.WorkItem.Id,
 | |
|                                 iterationPath: record.WorkItem.IterationPath,
 | |
|                                 parent: record.WorkItem.Parent,
 | |
|                                 priority: record.WorkItem.Priority,
 | |
|                                 relations: record.WorkItem.Relations,
 | |
|                                 remainingWork: record.WorkItem.RemainingWork,
 | |
|                                 requester: record.WorkItem.Requester,
 | |
|                                 resolvedDate: record.WorkItem.ResolvedDate,
 | |
|                                 revision: record.WorkItem.Revision,
 | |
|                                 riskReductionMinusOpportunityEnablement: record.WorkItem.RiskReductionMinusOpportunityEnablement,
 | |
|                                 startDate: record.WorkItem.StartDate,
 | |
|                                 state: record.WorkItem.State,
 | |
|                                 storyPoints: record.WorkItem.StoryPoints,
 | |
|                                 tags: record.WorkItem.Tags,
 | |
|                                 targetDate: record.WorkItem.TargetDate,
 | |
|                                 timeCriticality: record.WorkItem.TimeCriticality,
 | |
|                                 title: record.WorkItem.Title,
 | |
|                                 violation: record.WorkItem.Violation is null ? violation : record.WorkItem.Violation,
 | |
|                                 weightedShortestJobFirst: record.WorkItem.WeightedShortestJobFirst,
 | |
|                                 workItemType: record.WorkItem.WorkItemType);
 | |
|         result = new(workItem, record.Parent, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>(), record.Tag);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     private static Record Get(Record record, bool keepRelations)
 | |
|     {
 | |
|         Record result;
 | |
|         Record[]? childRecords;
 | |
|         Record[]? relatedRecords;
 | |
|         Record[]? successorRecords;
 | |
|         List<Record> relationRecords;
 | |
|         WorkItem? parentWorkItem = keepRelations ? record.Parent : WorkItem.GetWithOutRelations(record.Parent);
 | |
|         WorkItem? workItem = keepRelations ? record.WorkItem : WorkItem.GetWithOutRelations(record.WorkItem) ?? throw new Exception();
 | |
|         if (record.Children is null)
 | |
|             childRecords = null;
 | |
|         else
 | |
|         {
 | |
|             relationRecords = new();
 | |
|             foreach (Record r in record.Children)
 | |
|                 relationRecords.Add(Get(r, keepRelations));
 | |
|             childRecords = relationRecords.ToArray();
 | |
|         }
 | |
|         if (record.Related is null)
 | |
|             relatedRecords = null;
 | |
|         else
 | |
|         {
 | |
|             relationRecords = new();
 | |
|             foreach (Record r in record.Related)
 | |
|                 relationRecords.Add(Get(r, keepRelations));
 | |
|             relatedRecords = relationRecords.ToArray();
 | |
|         }
 | |
|         if (record.Successors is null)
 | |
|             successorRecords = null;
 | |
|         else
 | |
|         {
 | |
|             relationRecords = new();
 | |
|             foreach (Record r in record.Successors)
 | |
|                 relationRecords.Add(Get(r, keepRelations));
 | |
|             successorRecords = relationRecords.ToArray();
 | |
|         }
 | |
|         result = new(workItem, parentWorkItem, childRecords, relatedRecords, successorRecords, record.Tag);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal static Dictionary<string, string>? GetTag(ReadOnlyCollection<Record>? records)
 | |
|     {
 | |
|         Dictionary<string, string>? result;
 | |
|         if (records is null)
 | |
|             result = null;
 | |
|         else
 | |
|         {
 | |
|             List<long> collection = new();
 | |
|             foreach (Record record in records)
 | |
|             {
 | |
|                 if (record.WorkItem.State is "Closed" or "Resolved" || record.WorkItem.StoryPoints is null)
 | |
|                     continue;
 | |
|                 collection.Add(record.WorkItem.StoryPoints.Value);
 | |
|             }
 | |
|             if (collection.Count == 0)
 | |
|                 result = null;
 | |
|             else
 | |
|             {
 | |
|                 string json = JsonSerializer.Serialize(collection);
 | |
|                 result = new Dictionary<string, string> { { "StoryPoints", json } };
 | |
|             }
 | |
|         }
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal static Record Get(WorkItem workItem, WorkItem? parent, ReadOnlyCollection<Record>? children, ReadOnlyCollection<Record>? related, ReadOnlyCollection<Record>? successors, bool keepRelations)
 | |
|     {
 | |
|         Record result;
 | |
|         Dictionary<string, string>? tag = GetTag(children);
 | |
|         Record record = new(workItem, parent, children?.ToArray(), related?.ToArray(), successors?.ToArray(), tag);
 | |
|         result = Get(record, keepRelations);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal static ReadOnlyCollection<Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> keyValuePairs, WorkItem workItem, string relationName, List<bool> nests, bool keepRelations)
 | |
|     {
 | |
|         List<Record> results = new();
 | |
|         Record record;
 | |
|         nests.Add(true);
 | |
|         WorkItem? parentWorkItem;
 | |
|         WorkItem? relationWorkItem;
 | |
|         List<WorkItem> collection = new();
 | |
|         ReadOnlyCollection<Record>? childRecords;
 | |
|         ReadOnlyCollection<Record>? relatedRecords;
 | |
|         ReadOnlyCollection<Record>? successorRecords;
 | |
|         if (workItem.Relations is not null && workItem.Relations.Length > 0)
 | |
|         {
 | |
|             collection.Clear();
 | |
|             foreach (Relation relation in workItem.Relations)
 | |
|             {
 | |
|                 if (relation.Attributes.Name != relationName)
 | |
|                     continue;
 | |
|                 if (workItem.Parent is not null && relation.Id == workItem.Parent.Value)
 | |
|                     continue;
 | |
|                 if (!keyValuePairs.TryGetValue(relation.Id, out relationWorkItem))
 | |
|                     continue;
 | |
|                 collection.Add(relationWorkItem);
 | |
|             }
 | |
|             collection = (from l in collection orderby l.State != "Closed", l.Id select l).ToList();
 | |
|             foreach (WorkItem w in collection)
 | |
|             {
 | |
|                 if (nests.Count > 500)
 | |
|                     break;
 | |
|                 if (w.Parent is null)
 | |
|                     parentWorkItem = null;
 | |
|                 else
 | |
|                     _ = keyValuePairs.TryGetValue(w.Parent.Value, out parentWorkItem);
 | |
|                 childRecords = GetKeyValuePairs(keyValuePairs, w, "Child", nests, keepRelations); // Forward
 | |
|                 relatedRecords = null; // GetKeyValuePairs(keyValuePairs, w, "Related", nests, keepRelations); // Related
 | |
|                 successorRecords = null; // GetKeyValuePairs(keyValuePairs, w, "Successor", nests, keepRelations); // Forward
 | |
|                 // predecessorRecords = GetKeyValuePairs(keyValuePairs, w, "Predecessor", nests, keepRelations); // Reverse
 | |
|                 record = Get(w, parentWorkItem, childRecords, relatedRecords, successorRecords, keepRelations);
 | |
|                 results.Add(record);
 | |
|             }
 | |
|         }
 | |
|         return new(results);
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| [JsonSourceGenerationOptions(WriteIndented = true)]
 | |
| [JsonSerializable(typeof(Record))]
 | |
| internal partial class RecordSourceGenerationContext : JsonSerializerContext
 | |
| {
 | |
| }
 | |
| 
 | |
| [JsonSourceGenerationOptions(WriteIndented = true)]
 | |
| [JsonSerializable(typeof(Record[]))]
 | |
| internal partial class RecordCollectionSourceGenerationContext : JsonSerializerContext
 | |
| {
 | |
| } |