using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace ServerCore; //============================================================================================= // 계층적으로 노드를 관리할 수 있는 기능을 제공하는 제네릭 클래스 이다. // // author : kangms // //============================================================================================= public interface IHeirerchy { // 찾으려고 하는 값의 IHeirerchy 를 찾는다. IHeirerchy? findHeirerchy(T toFind); // DepthNo 0 일경우 Root 이고 자식 계층이 추가될 경우 1 증가 된다. Int32 getDepthNo(); // 부모 계층을 수동으로 설정 한다. void setParent(IHeirerchy parent); IHeirerchy? getParent(); // 현재의 계층에 자식 노드을 추가 한다. IHeirerchy addChildNode(IHeirerchy child); // 현재의 계층에 자식 노드 목록을 반환 한다. List> getChilds(); // 현재 노드에 값을 설정 한다. void setValue(T value); // 현재 노드의 값을 반환 한다. T getValue(); // 현재 계층 부터 부모의 Root 계층 까지 해당 T 타입인지 체크 한다. bool isUpperHeirerchy(T toCheck); // 현재 계층 부터 자식의 Leaf 계층 까지 해당 T 타입인지 체크 한다. bool isLowerHeirerchy(T toCheck); // 현재 노드가 Root 인가? bool isRoot(); // 현재 노드가 최하위 노드 인가? bool isLeaf(); bool isEqual(T value); // 현재 노드에서 자식 노드 계층의 모든 노드값의 체크해서 성공 & 실패 노드 목록을 반환 한다. bool onCheckValue(ref HashSet successedNodes, ref List> failedNodes); // 하위 노드 목록을 채워준다. void fillupLowers(ref List lowers); } public class HeirerchyNode : IHeirerchy { private T m_value; private IHeirerchy? m_parent; private List> m_childs = new(); private Int32 m_depth_no = 0; public HeirerchyNode(T value) { m_value = value; } public HeirerchyNode(T value, IHeirerchy parent) { m_value = value; setParent(parent); } public virtual bool onCheckValue(ref HashSet successedNodes , ref List> failedNodes) { var is_success = true; foreach (var heirerchy_node in getChilds()) { var value = heirerchy_node.getValue(); if (true == successedNodes.Contains(value)) { failedNodes.Add(heirerchy_node); is_success = false; continue; } successedNodes.Add(value); if (false == heirerchy_node.onCheckValue(ref successedNodes, ref failedNodes)) { failedNodes.Add(heirerchy_node); is_success = false; continue; } } return is_success; } public static IHeirerchy? findByTraveral(IHeirerchy root, T toFind) { if (true == root.isEqual(toFind)) { return root; } foreach (var heirerchy_node in root.getChilds()) { var found_heirerchy = heirerchy_node.findHeirerchy(toFind); if (null != found_heirerchy) { return found_heirerchy; } } return null; } public IHeirerchy? findHeirerchy(T toFind) { if (true == isEqual(toFind)) { return this; } foreach (var heirerchy_node in getChilds()) { var found_heirerchy = heirerchy_node.findHeirerchy(toFind); if (null != found_heirerchy) { return found_heirerchy; } } return null; } public IHeirerchy newAndAddChildNode(T childValue) where THeirerchy : IHeirerchy, new() { if (m_childs == null) { m_childs = new List>(); } var to_add_child_node = new THeirerchy(); to_add_child_node.setValue(childValue); return addChildNode(to_add_child_node); } public IHeirerchy addChildNode(IHeirerchy childNode) { if (m_childs == null) { m_childs = new List>(); } m_childs.Add(childNode); childNode.setParent(this); return childNode; } public static IHeirerchy? newAndAddChildNodeOfParent(IHeirerchy root, T parentValue, T toAddChildValue) where THeirerchy : IHeirerchy, new() { var found_parent_heirerchy = findByTraveral(root, parentValue); if (null == found_parent_heirerchy) { return null; } var found_node = found_parent_heirerchy as HeirerchyNode; if (null == found_node) { return null; } return found_node.newAndAddChildNode(toAddChildValue); } public List> getChilds() { return m_childs == null ? (new List>()) : m_childs; } public IHeirerchy getFirstChildNode() { return m_childs.First(); } public IHeirerchy getLastChildNode() { return m_childs.Last(); } public IHeirerchy? getChildNodeByIndex(Int32 index) { if (m_childs.Count <= index) { return null; } return m_childs[index]; } public virtual bool isUpperHeirerchy(T toCheck) { if (true == isEqual(toCheck)) { return true; } var parent = getParent(); if (null != parent) { if (true == parent.isUpperHeirerchy(toCheck)) { return true; } } return false; } public virtual bool isLowerHeirerchy(T toCheck) { if (true == isEqual(toCheck)) { return true; } foreach (var child_node in getChilds()) { if (true == child_node.isLowerHeirerchy(toCheck)) { return true; } } return false; } // 하위 노드들 얻기 public virtual void fillupLowers(ref List lowers) { foreach (var child_node in getChilds()) { lowers.Add(child_node.getValue()); } } public bool isRoot() { return getParent() == null; } public bool isLeaf() { return getChilds().Count <= 0; } public void setValue(T value) { m_value = value; } public T getValue() { return m_value; } public bool isEqual(T value) { return m_value?.Equals(value) ?? false; } public void setDepthNo(Int32 depthNo) { m_depth_no = depthNo; } public Int32 getDepthNo() { return m_depth_no; } public void setParent(IHeirerchy parent) { m_parent = parent; var depth_no = parent.getDepthNo() + 1; setDepthNo(depth_no); } public IHeirerchy? getParent() { return m_parent; } }