public CswNbtNode GetNode(string NodeId, string NodeKey, CswDateTime Date = null)
        {
            CswNbtNode Node = null;

            if (!string.IsNullOrEmpty(NodeKey))
            {
                //CswNbtNodeKey RealNodeKey = new CswNbtNodeKey( CswNbtResources, FromSafeJavaScriptParam( NodeKey ) );
                CswNbtNodeKey RealNodeKey = new CswNbtNodeKey(NodeKey);
                Node = _CswNbtResources.getNode(RealNodeKey, Date);
            }
            else if (!string.IsNullOrEmpty(NodeId))
            {
                CswPrimaryKey RealNodeId = new CswPrimaryKey();
                if (CswTools.IsInteger(NodeId))
                {
                    RealNodeId.TableName  = "nodes";
                    RealNodeId.PrimaryKey = CswConvert.ToInt32(NodeId);
                }
                else
                {
                    RealNodeId.FromString(NodeId);
                }
                Node = _CswNbtResources.getNode(RealNodeId, Date);
            }
            return(Node);
        } // getNode()
Example #2
0
        /// <summary>
        ///     Returns the NodeKey for the currently indexed node
        /// </summary>
        public CswNbtNodeKey getNodeKeyForCurrentPosition()
        {
            CswNbtNodeKey ReturnVal = getKeyForCurrentNode();

            //ReturnVal.TreeKey = Key;
            return(ReturnVal);
        }
Example #3
0
        private Collection <CswNbtNodeKey> _loadNodeAsChildFromRow(CswNbtNodeKey ParentNodeKey, DataRow DataRowToAdd,
                                                                   bool UseGrouping, string GroupName,
                                                                   CswNbtViewRelationship Relationship, bool Selectable,
                                                                   bool ShowInTree,
                                                                   CswEnumNbtViewAddChildrenSetting AddChildren, Int32 RowCount,
                                                                   bool Included = true, bool Favorited = false)
        {
            CswNbtMetaDataNodeType NodeType = _CswNbtResources.MetaData.getNodeType(CswConvert.ToInt32(DataRowToAdd[_CswNbtColumnNames.NodeTypeId.ToLower()].ToString()));

            //string TableName = NodeType.TableName;
            //string PkColumnName = _CswNbtResources.getPrimeKeyColName( TableName );

            return(_loadNodeAsChild(ParentNodeKey, UseGrouping, GroupName, Relationship, Selectable, ShowInTree,
                                    AddChildren, RowCount, Included,
                                    DataRowToAdd[_CswNbtColumnNames.IconFileName.ToLower()].ToString(),
                                    DataRowToAdd[_CswNbtColumnNames.NameTemplate.ToLower()].ToString(),
                                    new CswPrimaryKey("nodes", CswConvert.ToInt32(DataRowToAdd["nodeid"])),
                                    new CswPrimaryKey(CswConvert.ToString(DataRowToAdd["relationaltable"]), CswConvert.ToInt32(DataRowToAdd["relationalid"])),
                                    DataRowToAdd[_CswNbtColumnNames.NodeName.ToLower()].ToString(),
                                    CswConvert.ToInt32(DataRowToAdd[_CswNbtColumnNames.NodeTypeId.ToLower()].ToString()),
                                    DataRowToAdd[_CswNbtColumnNames.NodeTypeName.ToLower()].ToString(),
                                    CswConvert.ToInt32(DataRowToAdd[_CswNbtColumnNames.ObjectClassId.ToLower()].ToString()),
                                    DataRowToAdd[_CswNbtColumnNames.ObjectClassName.ToLower()].ToString(),
                                    CswConvert.ToBoolean(DataRowToAdd[_CswNbtColumnNames.Locked.ToLower()]),
                                    Favorited
                                    ));
        }
Example #4
0
        // _getTreeNodeFromId()

        private CswNbtNode _getNbtNodeObjFromTreeNode(CswNbtTreeNode TreeNode)
        {
            if (TreeNode.ElementName != Elements.Node)
            {
                throw (new CswDniException("The current node is a " + TreeNode.ElementName + ", not an NbtNode"));
            }

            CswNbtNodeKey NodeKey   = _getKey(TreeNode);
            CswNbtNode    ReturnVal = _CswNbtNodeCollection[TreeNode.CswNodeId];

            if (CswEnumNbtNodeSpecies.Plain == NodeKey.NodeSpecies)
            {
                string IconName            = default(string);
                string PotentialIconSuffix = TreeNode.IconFileName;
                if (false == string.IsNullOrEmpty(PotentialIconSuffix))
                {
                    IconName = CswNbtMetaDataObjectClass.IconPrefix16 + PotentialIconSuffix;
                }
                ReturnVal.IconFileName = IconName;
                ReturnVal.NodeName     = TreeNode.NodeName;
                ReturnVal.NodeTypeId   = TreeNode.NodeTypeId;
            }
            ReturnVal.Selectable = TreeNode.Selectable;
            ReturnVal.ShowInTree = TreeNode.ShowInTree;

            return(ReturnVal);
        }
Example #5
0
 public Collection <CswNbtNodeKey> loadNodeAsChildFromRow(CswNbtNodeKey ParentNodeKey, DataRow DataRowToAdd,
                                                          bool UseGrouping, string GroupName, bool Selectable,
                                                          bool ShowInTree, CswEnumNbtViewAddChildrenSetting AddChildren,
                                                          Int32 RowCount, bool Included = true, bool Favorited = false)
 {
     return(_loadNodeAsChildFromRow(ParentNodeKey, DataRowToAdd, UseGrouping, GroupName, null, Selectable,
                                    ShowInTree, AddChildren, RowCount, Included, Favorited));
 }
Example #6
0
        private void _collectNodesOfClass(object VisitedNodeKey, NodeVisitEventArgs NodeVisitEventArgs)
        {
            CswNbtNodeKey CswNbtNodeKey = (CswNbtNodeKey)VisitedNodeKey;

            if (CswNbtNodeKey.ObjectClassId == NodeVisitEventArgs.ObjectClassIdToFilter)
            {
                _NodesOfClass.Add(CswNbtNodeKey.NodeId);
            } //
        }
Example #7
0
        private void _collectNodesOfNodeType(object VisitedNodeKey, NodeVisitEventArgs NodeVisitEventArgs)
        {
            CswNbtNodeKey CswNbtNodeKey = (CswNbtNodeKey)VisitedNodeKey;

            if (CswNbtNodeKey.NodeTypeId == NodeVisitEventArgs.NodeTypeIdToFilter)
            {
                _NodesOfNodeType.Add(CswNbtNodeKey.NodeId);
            } //
        }
Example #8
0
        //_iterateChildren()

        #endregion Navigation And Interrogation

        #region Modification Methods

        public Collection <CswNbtNodeKey> loadNodeAsChildFromRow(CswNbtNodeKey ParentNodeKey, DataRow DataRowToAdd,
                                                                 bool UseGrouping, string GroupName,
                                                                 CswNbtViewRelationship Relationship, Int32 RowCount,
                                                                 bool Included = true, bool Favorited = false)
        {
            return(_loadNodeAsChildFromRow(ParentNodeKey, DataRowToAdd, UseGrouping, GroupName, Relationship,
                                           Relationship.Selectable, Relationship.ShowInTree, Relationship.AddChildren,
                                           RowCount, Included, Favorited));
        }
Example #9
0
        /// <summary>
        ///     Return a node key for the first matching node in the tree
        /// </summary>
        /// <remarks>
        ///     Candidate to refactor to CswNbtNodes
        /// </remarks>
        /// <param name="NodeId">Primary key of node</param>
        public CswNbtNodeKey getNodeKeyByNodeId(CswPrimaryKey NodeId)
        {
            CswNbtNodeKey ReturnVal            = null;
            Collection <CswNbtNodeKey> KeyList = getKeysForNodeId(NodeId);

            if (null != KeyList && KeyList.Count > 0)
            {
                ReturnVal = KeyList[0];
            }
            return(ReturnVal);
        }
Example #10
0
        // _getTreeNodeFromKey()

        private CswNbtTreeNode _getTreeNodeFromId(CswPrimaryKey NodeId)
        {
            CswNbtTreeNode ret = null;

            if (NodesById.Keys.Contains(NodeId) && NodesById[NodeId].Count > 0)
            {
                CswNbtNodeKey ThisNodeKey = NodesById[NodeId].First();
                ret = _getTreeNodeFromKey(ThisNodeKey);
            }
            return(ret);
        }
Example #11
0
 public void makeNodeCurrent(CswNbtNodeKey NodeKey)
 {
     if (NodeKey.TreeKey == this._CswNbtTreeKey)
     {
         _CurrentNode = _getTreeNodeFromKey(NodeKey);
     }
     else
     {
         _CurrentNode = null;
     }
 }
 /// <summary>
 /// Index of nodes by NodeKey.  The NodeId, NodeTypeId and NodeSpecies in the Key are used.  See <see cref="GetNode(CswPrimaryKey, int, CswEnumNbtNodeSpecies, CswDateTime)"/>
 /// </summary>
 /// <param name="NodeKey">NodeKey for Node</param>
 public CswNbtNode this[CswNbtNodeKey NodeKey]
 {
     get
     {
         if (NodeKey == null)
         {
             throw new CswDniException(CswEnumErrorType.Error, "Invalid Node", "CswNbtNodeCollection received a null NodeKey");
         }
         if (NodeKey.NodeSpecies != CswEnumNbtNodeSpecies.Plain)
         {
             throw new CswDniException(CswEnumErrorType.Error, "Invalid Node", "CswNbtNodeCollection cannot fetch Node of species " + NodeKey.NodeSpecies.ToString());
         }
         return(GetNode(NodeKey.NodeId, NodeKey.NodeTypeId, NodeKey.NodeSpecies, null));
     }
 }
Example #13
0
        //getNodeKeysOfNodeType()


        /// <summary>
        ///     Calls the OnIterateNode event on every node in the tree
        /// </summary>
        public void iterateTree()
        {
            if (null == OnIterateNode)
            {
                throw (new CswDniException("OnIterateNode must be set before calling iterateTree()"));
            }

            //cache current position
            CswNbtNodeKey CurrentPosition = getNodeKeyForCurrentPosition();

            goToRoot();
            _iterateNodes();

            //restore current position
            makeNodeCurrent(CurrentPosition);
        }
Example #14
0
        public CswNbtNode getParentNodeOf(CswNbtNodeKey NodeKey)
        {
            CswNbtNode ReturnVal = null;

            CswNbtTreeNode CurrentNodeSave = _CurrentNode;

            makeNodeCurrent(NodeKey);

            if (false == isCurrentPositionRoot())
            {
                ReturnVal = _getNbtNodeObjFromTreeNode(_getTreeNodeFromKey(getNodeKeyForParentOfCurrentPosition()));
            }

            _CurrentNode = CurrentNodeSave;

            return(ReturnVal);
        }
Example #15
0
        private CswNbtTreeNode _getTreeNodeFromKey(CswNbtNodeKey NodeKey)
        {
            CswNbtTreeNode ThisNode = _TreeNode;

            foreach (Int32 ThisCount in NodeKey.NodeCountPath.ToIntCollection())
            {
                if (ThisNode != null)
                {
                    if (ThisNode.ChildNodes.Count >= ThisCount)
                    {
                        ThisNode = ThisNode.ChildNodes[ThisCount - 1];
                    }
                    else
                    {
                        ThisNode = null;
                    }
                } // if( ThisNode == null )
            }
            return(ThisNode);
        }
Example #16
0
 public CswNbtNodeKey getParentKey(CswNbtNodeKey ChildKey)
 {
     return(NodesAndParents[ChildKey]);
 }
Example #17
0
        private void _makeNbtTreeNode(CswNbtTreeNode ParentNode,
                                      string ElemName,
                                      CswPrimaryKey NodeId,
                                      string NodeName,
                                      Int32 NodeTypeId,
                                      Int32 ObjectClassId,
                                      string Icon,
                                      bool Selectable,
                                      CswNbtViewNode ViewNode,
                                      CswEnumNbtNodeSpecies Species,
                                      bool ShowInTree,
                                      bool Locked,
                                      bool Included,
                                      bool Favorited,
                                      CswPrimaryKey RelationalId,
                                      out CswNbtTreeNode NewNode,
                                      out CswNbtNodeKey NewNodeKey)
        {
            // Make the object
            NewNode = new CswNbtTreeNode(NodeId, NodeName, NodeTypeId, ObjectClassId, RelationalId)
            {
                ElementName  = ElemName,
                IconFileName = Icon,
                Selectable   = Selectable,
                ShowInTree   = ShowInTree,
                Locked       = Locked,
                Included     = Included,
                Favorited    = Favorited,
                ChildNodes   = new Collection <CswNbtTreeNode>(),
                ChildProps   = new Collection <CswNbtTreeNodeProp>()
            };

            CswNbtNodeKey      ParentNodeKey = null;
            CswDelimitedString NodeCountPath = new CswDelimitedString(CswNbtNodeKey.NodeCountDelimiter);

            if (ParentNode != null)
            {
                ParentNodeKey = _getKey(ParentNode);
                string ParentNodeCountPath = ParentNodeKey.NodeCountPath.ToString();
                NodeCountPath.FromString(ParentNodeCountPath);
                NodeCountPath.Add(((ParentNode.ChildNodes.Count()) + 1).ToString());
                ParentNode.ChildNodes.Add(NewNode);
                NewNode.ParentNode = ParentNode;
            }

            // Make the key
            NewNodeKey               = new CswNbtNodeKey();
            NewNodeKey.TreeKey       = _CswNbtTreeKey;
            NewNodeKey.NodeSpecies   = Species;
            NewNodeKey.NodeCountPath = NodeCountPath;
            if (NewNode.ElementName == Elements.Node)
            {
                NewNodeKey.NodeId        = NodeId;
                NewNodeKey.NodeTypeId    = NodeTypeId;
                NewNodeKey.ObjectClassId = ObjectClassId;
                if (ViewNode != null)
                {
                    NewNodeKey.ViewNodeUniqueId = ViewNode.UniqueId;
                }
            }
            else if (NewNode.ElementName == Elements.Tree || NewNode.ElementName == Elements.Group)
            {
                // Nothing
            }
            else if (NewNode.ElementName == Elements.Prop)
            {
                throw (new CswDniException("_makeNbtTreeNode called on an NbtNodeProp element"));
            }
            else
            {
                throw (new CswDniException("Unknown element: " + NewNode.ElementName));
            }

            // Dictionaries
            if (NodeId != null)
            {
                if (false == NodesById.ContainsKey(NodeId))
                {
                    NodesById.Add(NodeId, new Collection <CswNbtNodeKey>());
                }
                NodesById[NodeId].Add(NewNodeKey);
            }
            if (ParentNodeKey != null && !NodesAndParents.ContainsKey(NewNodeKey))
            {
                NodesAndParents.Add(NewNodeKey, ParentNodeKey);
            }

            NewNode.NodeKey = NewNodeKey;
        }
Example #18
0
        //public JObject getRawJSON()
        //{
        //    return _TreeNode;
        //}

        public CswNbtNode getNode(CswNbtNodeKey NodeKey)
        {
            return(_getNbtNodeObjFromTreeNode(_getTreeNodeFromKey(NodeKey)));
        }
Example #19
0
 public bool isNodeDefined(CswNbtNodeKey NodeKey)
 {
     return(null != _getTreeNodeFromKey(NodeKey));
 }
Example #20
0
        public Collection <CswNbtNodeKey> _loadNodeAsChild(CswNbtNodeKey ParentNodeKey, bool UseGrouping,
                                                           string GroupName, CswNbtViewRelationship Relationship,
                                                           bool Selectable, bool ShowInTree,
                                                           CswEnumNbtViewAddChildrenSetting AddChildren, Int32 RowCount,
                                                           bool Included,
                                                           string IconFileName, string NameTemplate,
                                                           CswPrimaryKey NodeId, CswPrimaryKey RelationalId, string NodeName, Int32 NodeTypeId,
                                                           string NodeTypeName, Int32 ObjectClassId,
                                                           string ObjectClassName, bool Locked, bool Favorited)
        {
            Collection <CswNbtNodeKey> ReturnKeyColl = new Collection <CswNbtNodeKey>();

            CswNbtTreeNode ParentNode = null;

            ParentNode = _CurrentNode ?? _TreeNode;

            Collection <CswNbtTreeNode> ParentNodes = new Collection <CswNbtTreeNode>();

            if (false == UseGrouping)
            {
                ParentNodes.Add(ParentNode);
            }
            else
            {
                // Interpret commas to denote multiple groups
                string GroupNameForLoop = GroupName;
                string ThisGroupName    = GroupName;
                do
                {
                    if (GroupNameForLoop.IndexOf(',') >= 0)
                    {
                        ThisGroupName    = GroupNameForLoop.Substring(0, GroupNameForLoop.IndexOf(',')).Trim();
                        GroupNameForLoop = GroupNameForLoop.Substring(GroupNameForLoop.IndexOf(',') + 1).Trim();
                    }
                    else
                    {
                        ThisGroupName    = GroupNameForLoop.Trim();
                        GroupNameForLoop = string.Empty;
                    }

                    CswNbtTreeNode MatchingGroup = _getMatchingGroup(ParentNode, ThisGroupName);
                    if (MatchingGroup == null)
                    {
                        CswNbtNodeKey MatchingGroupKey = null;
                        _makeNbtTreeNode(ParentNode,
                                         Elements.Group,
                                         null,
                                         ThisGroupName,
                                         Int32.MinValue,
                                         Int32.MinValue,
                                         "group.gif",
                                         false,
                                         Relationship,
                                         CswEnumNbtNodeSpecies.Group,
                                         true,
                                         false,
                                         true,
                                         false,
                                         null,
                                         out MatchingGroup,
                                         out MatchingGroupKey);
                    }

                    if (MatchingGroup != null)
                    {
                        ParentNodes.Add(MatchingGroup);
                    }
                } // do
                while(GroupNameForLoop != string.Empty);
            }     // if-else( !UseGrouping )


            foreach (CswNbtTreeNode ThisParentNode in ParentNodes)
            {
                CswNbtNodeKey  ThisKey  = null;
                CswNbtTreeNode ThisNode = null;
                _makeNbtTreeNode(ThisParentNode,
                                 Elements.Node,
                                 NodeId,
                                 NodeName,
                                 NodeTypeId,
                                 ObjectClassId,
                                 IconFileName,
                                 Selectable,
                                 Relationship,
                                 CswEnumNbtNodeSpecies.Plain,
                                 ShowInTree,
                                 Locked,
                                 Included,
                                 Favorited,
                                 RelationalId,
                                 out ThisNode,
                                 out ThisKey);
                ReturnKeyColl.Add(ThisKey);
            }

            return(ReturnKeyColl);
        }
        } // load()

        private void loadRelationshipRecursive(CswNbtViewRelationship Relationship, bool RequireViewPermissions, bool GroupBySiblings,
                                               IEnumerable <CswPrimaryKey> ParentNodeIds = null, Int32 ResultsLimit = Int32.MinValue)
        {
            CswNbtNodeKey PriorCurrentNodeKey = _CswNbtTree.getNodeKeyForCurrentPosition();

            // Nodes and Properties
            DataTable          NodesTable   = new DataTable();
            CswArbitrarySelect ResultSelect = _makeNodeSql(Relationship, ParentNodeIds);

            Int32 thisResultLimit = _CswNbtResources.TreeViewResultLimit;

            if (ResultsLimit != Int32.MinValue)
            {
                thisResultLimit = ResultsLimit;
            }

            if (Relationship.Properties.Count > 0)
            {
                thisResultLimit = thisResultLimit * Relationship.Properties.Count;
            }

            CswTimer SqlTimer = new CswTimer();

            try
            {
                NodesTable = ResultSelect.getTable(0, thisResultLimit, false);
            }
            catch (Exception ex)
            {
                throw new CswDniException(CswEnumErrorType.Error, "Invalid View", "_getNodes() attempted to run invalid SQL: " + ResultSelect.Sql, ex);
            }
            _CswNbtResources.CswLogger.TreeLoaderSQLTime += SqlTimer.ElapsedDurationInMilliseconds;

            if (SqlTimer.ElapsedDurationInSeconds > 2)
            {
                _CswNbtResources.logMessage("Tree View SQL required longer than 2 seconds to run: " + ResultSelect.Sql);
            }

            Int32 PriorNodeId       = Int32.MinValue;
            Int32 PriorParentNodeId = Int32.MinValue;
            Collection <CswPrimaryKey> KeysThisLevel  = new Collection <CswPrimaryKey>();
            Collection <CswNbtNodeKey> NewNodeKeys    = new Collection <CswNbtNodeKey>();
            Collection <CswNbtNodeKey> ParentNodeKeys = null;

            foreach (DataRow NodesRow in NodesTable.Rows)
            {
                Int32         ThisNodeId       = CswConvert.ToInt32(NodesRow["nodeid"]);
                CswPrimaryKey ThisNodePk       = new CswPrimaryKey("nodes", ThisNodeId);
                Int32         ThisParentNodeId = Int32.MinValue;
                if (NodesTable.Columns.Contains("parentnodeid"))
                {
                    ThisParentNodeId = CswConvert.ToInt32(NodesRow["parentnodeid"]);
                }
                Int32 ThisNodeTypeId    = CswConvert.ToInt32(NodesRow["nodetypeid"]);
                bool  ThisNodeFavorited = false == String.IsNullOrEmpty(NodesRow["userid"].ToString());

                // Verify permissions
                // this could be a performance problem
                CswNbtMetaDataNodeType ThisNodeType = _CswNbtResources.MetaData.getNodeType(ThisNodeTypeId);
                if (false == RequireViewPermissions ||
                    (_CswNbtResources.Permit.canAnyTab(CswEnumNbtNodeTypePermission.View, ThisNodeType, _RunAsUser) &&
                     _CswNbtResources.Permit.isNodeWritable(CswEnumNbtNodeTypePermission.View, ThisNodeType, ThisNodePk, _RunAsUser)))
                {
                    // Handle property multiplexing
                    // This assumes that property rows for the same nodeid are next to one another
                    if (ThisNodeId != PriorNodeId || ThisParentNodeId != PriorParentNodeId)
                    {
                        PriorNodeId       = ThisNodeId;
                        PriorParentNodeId = ThisParentNodeId;
                        NewNodeKeys       = new Collection <CswNbtNodeKey>();
                        Collection <CswNbtNodeKey> ThisNewNodeKeys = new Collection <CswNbtNodeKey>();
                        ParentNodeKeys = new Collection <CswNbtNodeKey>();

                        // Handle ResultMode.Disabled on filters
                        bool Included = true;
                        foreach (DataColumn Column in NodesRow.Table.Columns)
                        {
                            if (Column.ColumnName.StartsWith("INCLUDED"))
                            {
                                string Conjunction = Column.ColumnName.Substring("INCLUDED".Length);
                                if (Conjunction.StartsWith("OR"))
                                {
                                    Included = Included || CswConvert.ToBoolean(NodesRow[Column]);
                                }
                                else
                                {
                                    Included = Included && CswConvert.ToBoolean(NodesRow[Column]);
                                }
                            }
                        }
                        bool   UseGroupBy = Relationship.GroupByPropId != Int32.MinValue;
                        string GroupName  = string.Empty;
                        if (UseGroupBy)
                        {
                            GroupName = CswConvert.ToString(NodesRow["groupname"]);
                            if (GroupName == string.Empty)
                            {
                                GroupName = "[blank]";
                            }
                        }
                        else if (GroupBySiblings)
                        {
                            UseGroupBy = true;
                            GroupName  = CswConvert.ToString(NodesRow["nodetypename"]);
                        }

                        if (NodesTable.Columns.Contains("parentnodeid"))
                        {
                            CswPrimaryKey ParentNodePk = new CswPrimaryKey("nodes", CswConvert.ToInt32(NodesRow["parentnodeid"]));

                            // We can't use getNodeKeyByNodeId, because there may be more instances of this node at different places in the tree
                            //ParentNodeKey = _CswNbtTree.getNodeKeyByNodeId( ParentNodeId );
                            ParentNodeKeys = _CswNbtTree.getNodeKeysByNodeIdAndViewNode(ParentNodePk, Relationship.Parent);

                            if (ParentNodeKeys.Count == 0)
                            {
                                // If the parent isn't in the tree, don't add the child
                                PriorNodeId = Int32.MinValue;   // case 24788
                            }
                            else
                            {
                                foreach (CswNbtNodeKey ParentNodeKey in ParentNodeKeys)
                                {
                                    _CswNbtTree.makeNodeCurrent(ParentNodeKey);
                                    Int32 ChildCount = _CswNbtTree.getChildNodeCount();
                                    ThisNewNodeKeys = _CswNbtTree.loadNodeAsChildFromRow(ParentNodeKey, NodesRow, UseGroupBy, GroupName, Relationship, ChildCount + 1, Included, ThisNodeFavorited);
                                    foreach (CswNbtNodeKey ThisNewNodeKey in ThisNewNodeKeys)
                                    {
                                        NewNodeKeys.Add(ThisNewNodeKey);
                                        KeysThisLevel.Add(ThisNewNodeKey.NodeId);
                                    }
                                } // foreach( CswNbtNodeKey ParentNodeKey in ParentNodeKeys )
                            }
                        }         // if( NodesTable.Columns.Contains( "parentnodeid" ) )
                        else
                        {
                            Int32 ChildCount = _CswNbtTree.getChildNodeCount();
                            ThisNewNodeKeys = _CswNbtTree.loadNodeAsChildFromRow(null, NodesRow, UseGroupBy, GroupName, Relationship, ChildCount + 1, Included, ThisNodeFavorited);
                            foreach (CswNbtNodeKey ThisNewNodeKey in ThisNewNodeKeys)
                            {
                                NewNodeKeys.Add(ThisNewNodeKey);
                                KeysThisLevel.Add(ThisNewNodeKey.NodeId);
                            }
                        } // if( AddChild )
                    }     // if( ThisNodeId != PriorNodeId )

                    // This assumes that property rows for the same nodeid are next to one another
                    // It also assumes that loadNodeAsChildFromRow() made the node current
                    if (NewNodeKeys.Count > 0 && NodesTable.Columns.Contains("jctnodepropid"))
                    {
                        foreach (CswNbtNodeKey NewNodeKey in NewNodeKeys)
                        {
                            _CswNbtTree.makeNodeCurrent(NewNodeKey);
                            _CswNbtTree.addProperty(CswConvert.ToInt32(NodesRow["nodetypepropid"]),
                                                    CswConvert.ToInt32(NodesRow["objectclasspropid"]),
                                                    CswConvert.ToInt32(NodesRow["jctnodepropid"]),
                                                    NodesRow["propname"].ToString(),
                                                    NodesRow["objectclasspropname"].ToString(),
                                                    NodesRow["gestalt"].ToString(),
                                                    CswConvert.ToString(NodesRow["fieldtype"]),
                                                    CswConvert.ToString(NodesRow["field1"]),
                                                    CswConvert.ToString(NodesRow["field2"]),
                                                    CswConvert.ToInt32(NodesRow["field1_fk"]),
                                                    CswConvert.ToDouble(NodesRow["field1_numeric"]),
                                                    CswConvert.ToBoolean(NodesRow["hidden"]),
                                                    CswConvert.ToString(NodesRow["field1_big"]));
                        } // foreach( CswNbtNodeKey NewNodeKey in NewNodeKeys )
                        if (ParentNodeKeys.Count > 0)
                        {
                            _CswNbtTree.makeNodeCurrent(ParentNodeKeys[0]);
                        }
                        else
                        {
                            _CswNbtTree.goToRoot();
                        }
                    } // if( NewNodeKeys != null && NodesTable.Columns.Contains( "jctnodepropid" ) )
                }     // if( false == RequireViewPermissions || _CswNbtResources.Permit.can( CswEnumNbtNodeTypePermission.View, ThisNodeType, true, null, _RunAsUser ) )
            }         // foreach(DataRow NodesRow in NodesTable.Rows)

            if (KeysThisLevel.Count > 0)  // only recurse if there are results
            {
                // Recurse
                foreach (CswNbtViewRelationship ChildRelationship in Relationship.ChildRelationships)
                {
                    bool ContinueGroupingBySibling = (_View.GroupBySiblings && Relationship.ChildRelationships.Count > 1);
                    loadRelationshipRecursive(ChildRelationship, RequireViewPermissions, ContinueGroupingBySibling, KeysThisLevel);
                }

                // case 24678 - Mark truncated results
                if (KeysThisLevel.Count == thisResultLimit)
                {
                    //if( ParentNodeKeys != null && ParentNodeKeys.Count > 0 )
                    //{
                    //    foreach( CswNbtNodeKey ParentNodeKey in ParentNodeKeys )
                    //    {
                    //        // assume truncation on every potential parent
                    //        _CswNbtTree.makeNodeCurrent( ParentNodeKey );
                    //        _CswNbtTree.goToParentNode();
                    //        for( Int32 c = 0; c < _CswNbtTree.getChildNodeCount(); c++ )
                    //        {
                    //            _CswNbtTree.goToNthChild( c );
                    //            _CswNbtTree.setCurrentNodeChildrenTruncated( true );
                    //            _CswNbtTree.goToParentNode();
                    //        }
                    //    }
                    //}
                    //else
                    //{
                    _CswNbtTree.goToRoot();
                    _CswNbtTree.setCurrentNodeChildrenTruncated(true);
                    //}
                } // if( NodesTable.Rows.Count == thisResultLimit )
            }     // if( NodesTable.Rows.Count > 0 )

            _CswNbtTree.makeNodeCurrent(PriorCurrentNodeKey);
        } // loadRelationshipRecursive()