302 lines
7.2 KiB
C#
302 lines
7.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
|
|
namespace ServerCore;
|
|
|
|
//=============================================================================================
|
|
// 계층적으로 노드를 관리할 수 있는 기능을 제공하는 제네릭 클래스 이다.
|
|
//
|
|
// author : kangms
|
|
//
|
|
//=============================================================================================
|
|
|
|
public interface IHeirerchy<T>
|
|
{
|
|
// 찾으려고 하는 값의 IHeirerchy<T> 를 찾는다.
|
|
IHeirerchy<T>? findHeirerchy(T toFind);
|
|
|
|
// DepthNo 0 일경우 Root 이고 자식 계층이 추가될 경우 1 증가 된다.
|
|
Int32 getDepthNo();
|
|
|
|
// 부모 계층을 수동으로 설정 한다.
|
|
void setParent(IHeirerchy<T> parent);
|
|
IHeirerchy<T>? getParent();
|
|
|
|
// 현재의 계층에 자식 노드을 추가 한다.
|
|
IHeirerchy<T> addChildNode(IHeirerchy<T> child);
|
|
// 현재의 계층에 자식 노드 목록을 반환 한다.
|
|
List<IHeirerchy<T>> 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<T> successedNodes, ref List<IHeirerchy<T>> failedNodes);
|
|
// 하위 노드 목록을 채워준다.
|
|
void fillupLowers(ref List<T> lowers);
|
|
}
|
|
|
|
public class HeirerchyNode<T> : IHeirerchy<T>
|
|
{
|
|
private T m_value;
|
|
private IHeirerchy<T>? m_parent;
|
|
private List<IHeirerchy<T>> m_childs = new();
|
|
private Int32 m_depth_no = 0;
|
|
|
|
public HeirerchyNode(T value)
|
|
{
|
|
m_value = value;
|
|
}
|
|
|
|
public HeirerchyNode(T value, IHeirerchy<T> parent)
|
|
{
|
|
m_value = value;
|
|
|
|
setParent(parent);
|
|
}
|
|
|
|
public virtual bool onCheckValue(ref HashSet<T> successedNodes
|
|
, ref List<IHeirerchy<T>> 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<T>? findByTraveral(IHeirerchy<T> 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<T>? 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<T> newAndAddChildNode<THeirerchy>(T childValue) where THeirerchy : IHeirerchy<T>, new()
|
|
{
|
|
if (m_childs == null)
|
|
{
|
|
m_childs = new List<IHeirerchy<T>>();
|
|
}
|
|
|
|
var to_add_child_node = new THeirerchy();
|
|
to_add_child_node.setValue(childValue);
|
|
|
|
return addChildNode(to_add_child_node);
|
|
}
|
|
|
|
public IHeirerchy<T> addChildNode(IHeirerchy<T> childNode)
|
|
{
|
|
if (m_childs == null)
|
|
{
|
|
m_childs = new List<IHeirerchy<T>>();
|
|
}
|
|
|
|
m_childs.Add(childNode);
|
|
childNode.setParent(this);
|
|
|
|
return childNode;
|
|
}
|
|
|
|
public static IHeirerchy<T>? newAndAddChildNodeOfParent<THeirerchy>(IHeirerchy<T> root, T parentValue, T toAddChildValue) where THeirerchy : IHeirerchy<T>, new()
|
|
{
|
|
var found_parent_heirerchy = findByTraveral(root, parentValue);
|
|
if (null == found_parent_heirerchy)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var found_node = found_parent_heirerchy as HeirerchyNode<T>;
|
|
if (null == found_node)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return found_node.newAndAddChildNode<THeirerchy>(toAddChildValue);
|
|
}
|
|
|
|
public List<IHeirerchy<T>> getChilds()
|
|
{
|
|
return m_childs == null ? (new List<IHeirerchy<T>>()) : m_childs;
|
|
}
|
|
|
|
public IHeirerchy<T> getFirstChildNode()
|
|
{
|
|
return m_childs.First();
|
|
}
|
|
|
|
public IHeirerchy<T> getLastChildNode()
|
|
{
|
|
return m_childs.Last();
|
|
}
|
|
|
|
public IHeirerchy<T>? 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<T> 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<T> parent)
|
|
{
|
|
m_parent = parent;
|
|
|
|
var depth_no = parent.getDepthNo() + 1;
|
|
setDepthNo(depth_no);
|
|
}
|
|
|
|
public IHeirerchy<T>? getParent()
|
|
{
|
|
return m_parent;
|
|
}
|
|
} |