public static SchemaMemberSelection CreateSelectionTree(object SourceObject, MemberAccesor SourceAccesor = null, IEnumerable <object> PreExclusion = null,
                                                                Func <object, Tuple <bool,                                // is-selectable
                                                                                     bool,                                // is-selected
                                                                                     bool,                                // can-show-is-selected
                                                                                     IRecognizableElement>                // action-info
                                                                      > MemberMergeSelectionDeterminer            = null,
                                                                Func <object, MemberAccesor, bool> ChildrenFilter = null, // Determines whether a child should be included for selection (e.g. "obj is Concept || obj.CompositeIdeas.Count >0")
                                                                SchemaMemberSelection DirectParent = null)
        {
            if (SourceAccesor == null)
            {
                SourceAccesor = GetAccesor(SourceObject);
            }

            if (SourceAccesor == null)
            {
                return(null);
            }

            var Selection = (MemberMergeSelectionDeterminer == null
                             ? Tuple.Create(false, false, false, (IRecognizableElement)null)
                             : MemberMergeSelectionDeterminer(SourceObject));

            var Result = new SchemaMemberSelection(SourceObject, SourceAccesor)
            {
                RefMember    = SourceObject,
                IsSelectable = Selection.Item1,
                IsSelected   = (Selection.Item2 &&
                                (PreExclusion == null || !PreExclusion.Contains(SourceObject))),
                CanShowIsSelected = Selection.Item3,
                ActionInfo        = Selection.Item4,
                Parent            = DirectParent
            };

            var SourceChildren = Result.MemberChildren;

            if (!SourceChildren.IsEmpty())
            {
                Result.Children = new List <SchemaMemberSelection>();
                foreach (var Child in SourceChildren)
                {
                    var ChildAccesor = GetAccesor(Child);
                    if (ChildrenFilter == null || (ChildAccesor != null && ChildrenFilter(Child, ChildAccesor)))
                    {
                        var SelItem = CreateSelectionTree(Child, ChildAccesor, PreExclusion,
                                                          MemberMergeSelectionDeterminer, ChildrenFilter, Result);
                        if (SelItem != null)
                        {
                            Result.Children.Add(SelItem);
                        }
                    }
                }
            }

            return(Result);
        }
        public SchemaMemberSelection FindEquivalentCounterpartAtSameLevel(SchemaMemberSelection CounterpartRoot, Func <object, object, bool> MatchEvaluator)
        {
            var LocalHierarchy       = this.GetContainmentHierarchy(true, false); // Notice that the root is ignored
            var CounterpartSelection = CounterpartRoot;

            foreach (var Selection in LocalHierarchy)
            {
                if (!CounterpartSelection.HasChildren)
                {
                    return(null);
                }

                CounterpartSelection = CounterpartSelection.Children.FirstOrDefault(chl => MatchEvaluator(chl.RefMember, Selection.RefMember));
                if (CounterpartSelection == null)
                {
                    break;
                }
            }

            return(CounterpartSelection);
        }
        private void GetCompleteTree(Dictionary <SchemaMemberSelection, SchemaMemberSelection> Result, SchemaMemberSelection Parent = null)
        {
            Result.AddNew(this, Parent);

            if (this.Children != null && this.Children.Count > 0)
            {
                foreach (var Child in Children)
                {
                    Child.GetCompleteTree(Result, this);
                }
            }
        }