/// <summary>
        /// Gets a list of all port numbers from a device that are not connected on the given end
        /// </summary>
        /// <param name="device">Device to check</param>
        /// <param name="portType">Check input or output ports</param>
        /// <returns>List of int</returns>
        private static List <int> GetOpenPorts(DeviceWrapper device, PortType portType)
        {
            #region Validation
            if (null == device)
            {
                throw new ArgumentNullException("device");
            }

            if (null == device.Feature)
            {
                throw new ArgumentException("device.Class cannot be null");
            }
            #endregion

            List <int> result = new List <int>();

            using (ESRI.ArcGIS.ADF.ComReleaser releaser = new ESRI.ArcGIS.ADF.ComReleaser())
            {
                ESRI.ArcGIS.Geodatabase.IFeatureClass      deviceFtClass  = device.Feature.Class as ESRI.ArcGIS.Geodatabase.IFeatureClass;
                ESRI.ArcGIS.Geodatabase.IRelationshipClass deviceHasPorts = ConfigUtil.GetPortRelationship(deviceFtClass);
                if (null != deviceHasPorts)
                {
                    ESRI.ArcGIS.Geodatabase.ITable portTable = deviceHasPorts.DestinationClass as ESRI.ArcGIS.Geodatabase.ITable;
                    if (null != portTable)
                    {
                        ESRI.ArcGIS.Geodatabase.IQueryFilter filter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
                        releaser.ManageLifetime(filter);
                        filter.WhereClause = string.Format("{0}='{1}' AND {2} IS NULL AND {3}='{4}'",
                                                           deviceHasPorts.OriginForeignKey,
                                                           device.Feature.get_Value(deviceFtClass.FindField(deviceHasPorts.OriginPrimaryKey)),
                                                           ConfigUtil.ConnectedCableFieldName,
                                                           ConfigUtil.PortTypeFieldName,
                                                           (PortType.Input == portType ? "1" : "2"));

                        ESRI.ArcGIS.Geodatabase.ICursor portCursor = portTable.Search(filter, true);
                        ESRI.ArcGIS.Geodatabase.IRow    portRow    = portCursor.NextRow();
                        int portIdIdx = portTable.FindField(ConfigUtil.PortIdFieldName);

                        while (null != portRow)
                        {
                            result.Add((int)portRow.get_Value(portIdIdx));

                            ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(portRow);
                            portRow = portCursor.NextRow();
                        }

                        ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(portCursor);
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// Gets a list of all strand numbers from a cable that are connected on the given end
        /// </summary>
        /// <param name="cable">Cable to check</param>
        /// <param name="isFromEnd">True to check from end, False to check to end</param>
        /// <returns>List of int</returns>
        private static List <int> GetConnectedStrands(FiberCableWrapper cable, bool isFromEnd)
        {
            #region Validation
            if (null == cable)
            {
                throw new ArgumentNullException("cable");
            }

            #endregion

            List <int> result = new List <int>();

            using (ESRI.ArcGIS.ADF.ComReleaser releaser = new ESRI.ArcGIS.ADF.ComReleaser())
            {
                ESRI.ArcGIS.Geodatabase.IFeatureClass cableFtClass = cable.Feature.Class as ESRI.ArcGIS.Geodatabase.IFeatureClass;

                string[] deviceClassNames = ConfigUtil.DeviceFeatureClassNames;
                for (int i = 0; i < deviceClassNames.Length; i++)
                {
                    string deviceClassName = deviceClassNames[i];
                    ESRI.ArcGIS.Geodatabase.IFeatureClass deviceFtClass = TelecomWorkspaceHelper.Instance().FindFeatureClass(deviceClassName);
//                    ESRI.ArcGIS.Geodatabase.IFeatureClass deviceFtClass = GdbUtils.GetFeatureClass(cableFtClass, deviceClassName);
                    if (null != deviceFtClass)
                    {
                        ESRI.ArcGIS.Geodatabase.IRelationshipClass deviceHasPorts = ConfigUtil.GetPortRelationship(deviceFtClass);
                        if (null != deviceHasPorts)
                        {
                            ESRI.ArcGIS.Geodatabase.ITable portTable = deviceHasPorts.DestinationClass as ESRI.ArcGIS.Geodatabase.ITable;
                            if (null != portTable)
                            {
                                ESRI.ArcGIS.Geodatabase.IQueryFilter filter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
                                releaser.ManageLifetime(filter);

                                filter.WhereClause = string.Format("{0}='{1}' AND {2}='{3}' AND {4} IS NOT NULL",
                                                                   ConfigUtil.ConnectedCableFieldName,
                                                                   cable.IPID,
                                                                   ConfigUtil.ConnectedEndFieldName,
                                                                   (isFromEnd ? "T" : "F"),
                                                                   ConfigUtil.ConnectedFiberFieldName);

                                ESRI.ArcGIS.Geodatabase.ICursor portCursor = portTable.Search(filter, true);
                                ESRI.ArcGIS.Geodatabase.IRow    portRow    = portCursor.NextRow();
                                int fiberIdIdx = portTable.FindField(ConfigUtil.ConnectedFiberFieldName);

                                while (null != portRow)
                                {
                                    result.Add((int)portRow.get_Value(fiberIdIdx));

                                    ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(portRow);
                                    portRow = portCursor.NextRow();
                                }

                                ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(portCursor);
                            }
                        }
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// Determines if all the ranges fall between 1 to port count
        /// </summary>
        /// <param name="ranges">Ranges to check</param>
        /// <param name="device">Device to check on</param>
        /// <param name="portType">Port type</param>
        /// <returns>True if valid ranges</returns>
        public static bool AreRangesWithinPortCount(List <Range> ranges, DeviceWrapper device, PortType portType)
        {
            bool result = false; // Default to false in case we can't even find the port relationship class

            #region Validation

            if (null == ranges)
            {
                throw new ArgumentNullException("ranges");
            }

            if (null == device)
            {
                throw new ArgumentNullException("device");
            }

            #endregion

            ESRI.ArcGIS.Geodatabase.IFeatureClass ftClass = device.Feature.Class as ESRI.ArcGIS.Geodatabase.IFeatureClass;
            if (null != ftClass)
            {
                using (ESRI.ArcGIS.ADF.ComReleaser releaser = new ESRI.ArcGIS.ADF.ComReleaser())
                {
                    ESRI.ArcGIS.Geodatabase.IRelationshipClass deviceHasPorts = ConfigUtil.GetPortRelationship(ftClass);
                    if (null != deviceHasPorts)
                    {
                        ESRI.ArcGIS.Geodatabase.ITable portTable = deviceHasPorts.DestinationClass as ESRI.ArcGIS.Geodatabase.ITable;
                        int portIdIdx = portTable.FindField(ConfigUtil.PortIdFieldName);

                        if (-1 < portIdIdx)
                        {
                            result = true; // Now that we have the ports, assume we're ok until we find a problem

                            ESRI.ArcGIS.Geodatabase.IQueryFilter filter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
                            releaser.ManageLifetime(filter);

                            filter.SubFields   = ConfigUtil.PortIdFieldName;
                            filter.WhereClause = string.Format("{0}='{1}' AND {2}='{3}' AND {4} IS NOT NULL",
                                                               deviceHasPorts.OriginForeignKey,
                                                               device.Feature.get_Value(ftClass.FindField(deviceHasPorts.OriginPrimaryKey)),
                                                               ConfigUtil.PortTypeFieldName,
                                                               PortType.Input == portType ? 1 : 2,
                                                               ConfigUtil.PortIdFieldName);

                            ((ESRI.ArcGIS.Geodatabase.IQueryFilterDefinition)filter).PostfixClause = string.Format("ORDER BY {0}", ConfigUtil.PortIdFieldName);
                            ESRI.ArcGIS.Geodatabase.ICursor cursor = portTable.Search(filter, true);
                            releaser.ManageLifetime(cursor);

                            int minPort = int.MinValue;
                            int maxPort = int.MaxValue;
                            ESRI.ArcGIS.Geodatabase.IRow row = cursor.NextRow();

                            if (null != row)
                            {
                                minPort = (int)row.get_Value(portIdIdx);

                                while (null != row)
                                {
                                    maxPort = (int)row.get_Value(portIdIdx);
                                    ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(row);

                                    row = cursor.NextRow();
                                }
                            }

                            foreach (Range r in ranges)
                            {
                                if (r.High > maxPort ||
                                    minPort > r.Low)
                                {
                                    result = false;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            return(result);
        }