/// <summary>
        /// Determines if a device has any connections on its ports
        /// </summary>
        /// <param name="deviceWrapper">Device to check</param>
        /// <returns>True if any port is connected</returns>
        public static bool HasAnyConnections(DeviceWrapper deviceWrapper)
        {
            //            int? inputPortCount = GdbUtils.GetDomainedIntName(deviceWrapper.Feature, ConfigUtil.InputPortsFieldName);
            //            int? outputPortCount = GdbUtils.GetDomainedIntName(deviceWrapper.Feature, ConfigUtil.OutputPortsFieldName);

            int? inputPortCount = deviceWrapper.inputPorts;
            int? outputPortCount = deviceWrapper.outputPorts;

            List<Range> ranges = null;

            bool isInputClear = true;
            if (null != inputPortCount && 0 < inputPortCount)
            {
                ranges = GetAvailableRanges(deviceWrapper, PortType.Input);
                isInputClear = AreRangesWholeUnitCount(ranges, (int)inputPortCount);
            }

            bool isOutputClear = true;
            if (null != outputPortCount && 0 < outputPortCount)
            {
                ranges = GetAvailableRanges(deviceWrapper, PortType.Output);
                isOutputClear = AreRangesWholeUnitCount(ranges, (int)outputPortCount);
            }

            // If either port type is not clear, there are connections
            return (!isInputClear || !isOutputClear);
        }
        /// <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>
        /// 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;
        }
        /// <summary>
        /// Finds ranges of ports that are not yet connected
        /// </summary>
        /// <param name="device">Device to check for</param>
        /// <param name="portType">Check input ports or output ports?</param>
        /// <returns>List of Range</returns>
        public static List<Range> GetAvailableRanges(DeviceWrapper device, PortType portType)
        {
            if (null == device)
            {
                throw new ArgumentNullException("device");
            }

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

            openPorts.AddRange(GetOpenPorts(device, portType));
            openPorts.Sort();

            List<Range> openRanges = MergeRanges(openPorts);
            return openRanges;
        }
        /// <summary>
        /// Creates given connections between cable and device
        /// </summary>
        /// <param name="cable">Cable</param>
        /// <param name="device">Device</param>
        /// <param name="units">Units to connect</param>
        /// <param name="isFromEnd">Is it the cable's from end?</param>
        /// <param name="portType">Input or Output?</param>
        /// <param name="isExistingOperation">Flag to control whether we need to wrap this in a new edit operation</param>
        /// <returns>Success</returns>
        public bool MakeConnections(FiberCableWrapper cable, DeviceWrapper device, Dictionary<int, int> units, bool isFromEnd, PortType portType, bool isExistingOperation)
        {
            bool success = false;
            bool isOperationOpen = false;

            #region Validation
            if (null == cable)
            {
                throw new ArgumentNullException("cable");
            }

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

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

            if (ESRI.ArcGIS.Editor.esriEditState.esriStateNotEditing == _editor.EditState)
            {
                throw new InvalidOperationException("You must be editing to perform this operation");
            }
            #endregion

            if (!isExistingOperation)
            {
                _editor.StartOperation();
                isOperationOpen = true;
            }

            try
            {
                ESRI.ArcGIS.Geodatabase.IFeatureClass deviceFtClass = device.Feature.Class as ESRI.ArcGIS.Geodatabase.IFeatureClass;
                ESRI.ArcGIS.Geodatabase.IRelationshipClass deviceHasPorts = ConfigUtil.GetPortRelationship(deviceFtClass);
                if (null == deviceHasPorts)
                {
                    throw new Exception("Unable to get port relationship class.");
                }

                ESRI.ArcGIS.Geodatabase.ITable portTable = deviceHasPorts.DestinationClass as ESRI.ArcGIS.Geodatabase.ITable;
                if (null == portTable)
                {
                    throw new Exception("Invalid destination on port relationship class.");
                }

                int portIdIdx = portTable.FindField(ConfigUtil.PortIdFieldName);
                int fiberNumberIdx = portTable.FindField(ConfigUtil.ConnectedFiberFieldName);
                int cableIdIdx = portTable.FindField(ConfigUtil.ConnectedCableFieldName);
                int isFromEndIdx = portTable.FindField(ConfigUtil.ConnectedEndFieldName);
                string isFromEndValue = isFromEnd ? "T" : "F";

                Dictionary<int, int> portsAsKeys = units;
                if (PortType.Input == portType)
                {
                    portsAsKeys = new Dictionary<int, int>();
                    foreach (KeyValuePair<int, int> pair in units)
                    {
                        portsAsKeys[pair.Value] = pair.Key;
                    }
                }

                using (ESRI.ArcGIS.ADF.ComReleaser releaser = new ESRI.ArcGIS.ADF.ComReleaser())
                {
                    ESRI.ArcGIS.Geodatabase.IQueryFilter filter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
                    releaser.ManageLifetime(filter);

                    string format = "{0}='{1}' AND {2}='{3}'";
                    filter.WhereClause = string.Format(format,
                        deviceHasPorts.OriginForeignKey,
                        device.Feature.get_Value(deviceFtClass.FindField(deviceHasPorts.OriginPrimaryKey)),
                        ConfigUtil.PortTypeFieldName,
                        (PortType.Input == portType ? "1" : "2"));

                    // Non recylcing cursor since we are doing updates.
                    ESRI.ArcGIS.Geodatabase.ICursor portCursor = portTable.Update(filter, false);
                    releaser.ManageLifetime(portCursor);

                    ESRI.ArcGIS.Geodatabase.IRow portRow = portCursor.NextRow();
                    while (null != portRow)
                    {
                        object portIdObj = portRow.get_Value(portIdIdx);
                        if (DBNull.Value != portIdObj)
                        {
                            int portId = System.Convert.ToInt32(portIdObj);
                            if (portsAsKeys.ContainsKey(portId))
                            {
                                portRow.set_Value(cableIdIdx, cable.IPID);
                                portRow.set_Value(isFromEndIdx, isFromEndValue);
                                portRow.set_Value(fiberNumberIdx, portsAsKeys[portId]);
                                portRow.Store();
                            }
                        }

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

                    if (isOperationOpen)
                    {
                        _editor.StopOperation("Create Connections");
                        isOperationOpen = false;
                    }

                    success = true;
                }
            }
            catch(Exception ex)
            {
                if (isOperationOpen)
                {
                    _editor.AbortOperation();
                }

                success = false;

                throw new Exception("Save operation failed.");
            }

            return success;
        }
        /// <summary>
        /// Determines if all given ranges are available (neither spliced nor connected)
        /// </summary>
        /// <param name="units">Units to check</param>
        /// <param name="cableWrapper">Device to check</param>
        /// <param name="isFromEnd">Flag of which port type we are checking</param>
        /// <returns>True if they are all available</returns>
        public static bool AreRangesAvailable(ICollection<int> units, DeviceWrapper deviceWrapper, PortType portType)
        {
            bool result = true;

            List<int> openPorts = GetOpenPorts(deviceWrapper, portType);

            foreach(int unit in units)
            {
                if (!openPorts.Contains(unit))
                {
                    result = false;
                    break;
                }
            }

            return result;
        }
        /// <summary>
        /// Returns a list of connections between the cable and the device, at the cable's given end, to the device's given port type
        /// </summary>
        /// <param name="cable">Cable to check</param>
        /// <param name="device">Device to check</param>
        /// <param name="isFromEnd">Digitized end of cable</param>
        /// <param name="portType">Input or output</param>
        /// <returns>List of Connection</returns>
        public List<Connection> GetConnections(FiberCableWrapper cable, DeviceWrapper device, bool isFromEnd, PortType portType)
        {
            if (null == cable)
            {
                throw new ArgumentNullException("cable");
            }

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

            List<Connection> result = new List<Connection>();
            List<int> ports = new List<int>();
            List<int> strands = 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)
                {
                    throw new Exception("Unable to find port relationship class.");
                }

                ESRI.ArcGIS.Geodatabase.ITable portTable = deviceHasPorts.DestinationClass as ESRI.ArcGIS.Geodatabase.ITable;
                if (null == portTable)
                {
                    throw new Exception("Invalid destination on port relationship class.");
                }

                ESRI.ArcGIS.Geodatabase.IQueryFilter filter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
                releaser.ManageLifetime(filter);
                filter.WhereClause = string.Format("{0}='{1}' AND {2}='{3}' AND {4}='{5}' AND {6}='{7}' AND {8} IS NOT NULL AND {9} IS NOT NULL",
                    deviceHasPorts.OriginForeignKey,
                    device.Feature.get_Value(deviceFtClass.FindField(deviceHasPorts.OriginPrimaryKey)),
                    ConfigUtil.ConnectedCableFieldName,
                    cable.IPID,
                    ConfigUtil.PortTypeFieldName,
                    (PortType.Input == portType ? "1" : "2"),
                    ConfigUtil.ConnectedEndFieldName,
                    (isFromEnd ? "T" : "F"),
                    ConfigUtil.ConnectedFiberFieldName,
                    ConfigUtil.PortIdFieldName);

                // ORDER BY does not work outside of SDE.
                // Removing for now, should not be important.
                string orderFormat = "ORDER BY {0}";
                if (PortType.Input == portType)
                {
            //                    ((ESRI.ArcGIS.Geodatabase.IQueryFilterDefinition2)filter).PostfixClause = string.Format(orderFormat, ConfigUtil.ConnectedFiberFieldName);
                }
                else
                {
            //                    ((ESRI.ArcGIS.Geodatabase.IQueryFilterDefinition2)filter).PostfixClause = string.Format(orderFormat, ConfigUtil.PortIdFieldName);
                }

                ESRI.ArcGIS.Geodatabase.ICursor portCursor = portTable.Search(filter, true);
                ESRI.ArcGIS.Geodatabase.IRow portRow = portCursor.NextRow();

                int portIdIdx = portTable.FindField(ConfigUtil.PortIdFieldName);
                int fiberNumberIdx = portTable.FindField(ConfigUtil.ConnectedFiberFieldName);

                while (null != portRow)
                {
                    ports.Add((int)portRow.get_Value(portIdIdx));
                    strands.Add((int)portRow.get_Value(fiberNumberIdx));

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

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

            List<Range> portRanges = SpliceAndConnectionUtils.MergeRanges(ports);
            List<Range> strandRanges = SpliceAndConnectionUtils.MergeRanges(strands);

            if (PortType.Input == portType)
            {
                result = SpliceAndConnectionUtils.MatchUp(strandRanges, portRanges);
            }
            else
            {
                result = SpliceAndConnectionUtils.MatchUp(portRanges, strandRanges);
            }

            return result;
        }
        //public static FiberDeviceConnectionHelper Instance(HookHelperExt hookHelper, ESRI.ArcGIS.Editor.IEditor editor)
        //{
        //    if(_instance != null)
        //    {
        //        return _instance;
        //    }
        //    else
        //    {
        //        _instance = new FiberDeviceConnectionHelper(hookHelper, editor);
        //        return _instance;
        //    }
        //}
        /// <summary>
        /// Returns cables which have an endpoint coincident with the device point
        /// </summary>
        /// <param name="deviceWrapper">Device to check</param>
        /// <returns>List of ConnectableCableWrapper</returns>
        public List<ConnectableCableWrapper> GetCoincidentCables(DeviceWrapper deviceWrapper)
        {
            List<ConnectableCableWrapper> result = new List<ConnectableCableWrapper>();

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

            ESRI.ArcGIS.Geometry.IPoint devicePoint = deviceWrapper.Feature.Shape as ESRI.ArcGIS.Geometry.IPoint;

            ESRI.ArcGIS.Carto.IFeatureLayer cableLayer = _hookHelper.FindFeatureLayer(ConfigUtil.FiberCableFtClassName);
            ESRI.ArcGIS.Geodatabase.IFeatureClass cableFtClass = cableLayer.FeatureClass;
            int displayIdx = cableFtClass.FindField(cableLayer.DisplayField);

            double buffer = _hookHelper.ConvertPixelsToMapUnits(1);
            List<ESRI.ArcGIS.Geodatabase.IFeature> coincidentCables = GdbUtils.GetLinearsWithCoincidentEndpoints(devicePoint, cableFtClass, buffer);

            for (int i = 0; i < coincidentCables.Count; i++)
            {
                ESRI.ArcGIS.Geodatabase.IFeature ft = coincidentCables[i];
                ESRI.ArcGIS.Geometry.IPolyline line = ft.Shape as ESRI.ArcGIS.Geometry.IPolyline;
                ESRI.ArcGIS.Geometry.IRelationalOperator lineToPoint = line.ToPoint as ESRI.ArcGIS.Geometry.IRelationalOperator;

                bool isFromEnd = true;
                if (lineToPoint.Equals(devicePoint))
                {
                    isFromEnd = false;
                }

                result.Add(new ConnectableCableWrapper(ft, isFromEnd, displayIdx));
            }

            return result;
        }
        /// <summary>
        /// Deletes given connections between cable to device
        /// </summary>
        /// <param name="cable">Cable</param>
        /// <param name="device">Device</param>
        /// <param name="units">Units to connect</param>
        /// <param name="portType">Input or Output?</param>
        /// <param name="isExistingOperation">Flag to control whether we need to wrap this in an edit operation</param>
        /// <returns>Success</returns>
        public bool BreakConnections(FiberCableWrapper cable, DeviceWrapper device, Dictionary<int, int> units, PortType portType, bool isExistingOperation)
        {
            bool success = false;
            bool isOperationOpen = false;

            #region Validation
            if (null == cable)
            {
                throw new ArgumentNullException("cable");
            }

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

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

            if (ESRI.ArcGIS.Editor.esriEditState.esriStateNotEditing == _editor.EditState)
            {
                throw new InvalidOperationException("You must be editing to perform this operation");
            }
            #endregion

            if (0 < units.Count)
            {
                if (!isExistingOperation)
                {
                    _editor.StartOperation();
                    isOperationOpen = true;
                }

                try
                {
                    ESRI.ArcGIS.Geodatabase.IFeatureClass deviceFtClass = device.Feature.Class as ESRI.ArcGIS.Geodatabase.IFeatureClass;
                    ESRI.ArcGIS.Geodatabase.IRelationshipClass deviceHasPorts = ConfigUtil.GetPortRelationship(deviceFtClass);
                    if (null == deviceFtClass)
                    {
                        throw new Exception("Unable to find port relationship class.");
                    }

                    ESRI.ArcGIS.Geodatabase.ITable portTable = deviceHasPorts.DestinationClass as ESRI.ArcGIS.Geodatabase.ITable;
                    if (null == portTable)
                    {
                        throw new Exception("Invalid destination on port relationship class.");
                    }

                    using (ESRI.ArcGIS.ADF.ComReleaser releaser = new ESRI.ArcGIS.ADF.ComReleaser())
                    {
                        ESRI.ArcGIS.Geodatabase.IQueryFilter filter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
                        releaser.ManageLifetime(filter);

                        StringBuilder inList = new StringBuilder(1024);
                        foreach (KeyValuePair<int, int> pair in units)
                        {
                            string appendFormat = "{0},";
                            if (PortType.Input == portType)
                            {
                                inList.AppendFormat(appendFormat, pair.Key);
                            }
                            else
                            {
                                inList.AppendFormat(appendFormat, pair.Value);
                            }
                        }
                        inList.Remove(inList.Length - 1, 1);

                        string format = "{0}='{1}' AND {2}='{3}' AND {4}='{5}' AND {6} IN ({7})";
                        filter.WhereClause = string.Format(format,
                            deviceHasPorts.OriginForeignKey,
                            device.Feature.get_Value(deviceFtClass.FindField(deviceHasPorts.OriginPrimaryKey)),
                            ConfigUtil.ConnectedCableFieldName,
                            cable.IPID,
                            ConfigUtil.PortTypeFieldName,
                            (PortType.Input == portType ? "1" : "2"),
                            ConfigUtil.ConnectedFiberFieldName,
                            inList.ToString());

                        filter.SubFields = string.Format("{0},{1},{2}", ConfigUtil.ConnectedEndFieldName, ConfigUtil.ConnectedFiberFieldName, ConfigUtil.ConnectedCableFieldName);

                        ESRI.ArcGIS.Geodatabase.IRowBuffer buffer = portTable.CreateRowBuffer();
                        releaser.ManageLifetime(buffer);
                        // We want to set them to null, so we can just send the empty buffer
                        portTable.UpdateSearchedRows(filter, buffer);

                        if (isOperationOpen)
                        {
                            _editor.StopOperation("Break Connections");
                            isOperationOpen = false;
                        }

                        success = true;
                    }
                }
                catch
                {
                    if (isOperationOpen)
                    {
                        _editor.AbortOperation();
                    }

                    success = false;
                }
            }

            return success;
        }
        private FiberCableWrapper GetConnectedFiber(DeviceWrapper device, int portId, PortType portType, out int fiberNumber)
        {
            FiberCableWrapper result = null;
            fiberNumber = -1;

            ESRI.ArcGIS.Geodatabase.IFeatureClass deviceFtClass = (ESRI.ArcGIS.Geodatabase.IFeatureClass)device.Feature.Class;
            ESRI.ArcGIS.Geodatabase.IRelationshipClass deviceHasPorts = ConfigUtil.GetPortRelationship(deviceFtClass);
            if (null == deviceHasPorts)
            {
                throw new Exception("Device to port relationship is missing or cannot be opened.");
            }

            ESRI.ArcGIS.Geodatabase.ITable portTable = deviceHasPorts.DestinationClass as ESRI.ArcGIS.Geodatabase.ITable;
            if (null == portTable)
            {
                throw new Exception("Port table is missing or cannot be opened.");
            }

            using (ESRI.ArcGIS.ADF.ComReleaser releaser = new ESRI.ArcGIS.ADF.ComReleaser())
            {
                ESRI.ArcGIS.Geodatabase.IQueryFilter filter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
                releaser.ManageLifetime(filter);
                filter.WhereClause = string.Format("{0}='{1}' AND {2}={3} AND {4}='{5}'",
                    deviceHasPorts.OriginForeignKey,
                    device.Feature.get_Value(deviceFtClass.FindField(deviceHasPorts.OriginPrimaryKey)),
                    ConfigUtil.PortIdFieldName,
                    portId,
                    ConfigUtil.PortTypeFieldName,
                    PortType.Input == portType ? 1 : 2);

                ESRI.ArcGIS.Geodatabase.ICursor cursor = portTable.Search(filter, false);
                releaser.ManageLifetime(cursor);
                ESRI.ArcGIS.Geodatabase.IRow portRow = cursor.NextRow();

                if (null != portRow)
                {
                    //releaser.ManageLifetime(portRow);

                    object cableIdValue = portRow.get_Value(portTable.FindField(ConfigUtil.ConnectedCableFieldName));
                    if (DBNull.Value != cableIdValue)
                    {
                        ESRI.ArcGIS.Geodatabase.IFeatureClass cableFtClass = _wkspHelper.FindFeatureClass(ConfigUtil.FiberCableFtClassName);
                        filter.WhereClause = string.Format("{0}='{1}'", ConfigUtil.IpidFieldName, cableIdValue);
                        ESRI.ArcGIS.Geodatabase.IFeatureCursor cableCursor = cableFtClass.Search(filter, false);
                        releaser.ManageLifetime(cableCursor);

                        ESRI.ArcGIS.Geodatabase.IFeature cable = cableCursor.NextFeature();
                        if (null != cable)
                        {
                            result = new FiberCableWrapper(cable);
                            object fiberNumberValue = portRow.get_Value(portTable.FindField(ConfigUtil.ConnectedFiberFieldName));
                            if (DBNull.Value != fiberNumberValue)
                            {
                                int.TryParse(fiberNumberValue.ToString(), out fiberNumber);
                            }
                        }
                    }
                }
            }

            return result;
        }
        /// <summary>
        /// Update the dropdowns of features on the UI
        /// </summary>
        /// <param name="helper">Helper class</param>
        private void PopulateDropDowns(FiberDeviceConnectionHelper helper)
        {
            // Clear the existing choices
            cboFrom.Items.Clear();
            cboTo.Items.Clear();
            lblAvailableFrom.Text = "";
            lblAvailableTo.Text = "";

            // Get the features and the display index for use when creating the wrapper
            ESRI.ArcGIS.Carto.IFeatureLayer ftLayer = _hookHelper.FindFeatureLayer(ConfigUtil.FiberCableFtClassName);
            int displayIdx = ftLayer.FeatureClass.FindField(ftLayer.DisplayField);

            // Get the selected features
            List<ESRI.ArcGIS.Geodatabase.IFeature> selectedFts = _hookHelper.GetSelectedFeatures(ftLayer);

            // Add each of the fiber features to the drop down
            for (int ftIdx = 0; ftIdx < selectedFts.Count; ftIdx++)
            {
                FiberCableWrapper w = new FiberCableWrapper(selectedFts[ftIdx], displayIdx);
                cboFrom.Items.Add(w);
            }

            // Now do that same thing for each of the device feature classes
            string[] deviceClassNames = ConfigUtil.DeviceFeatureClassNames;
            for (int deviceClassIdx = 0; deviceClassIdx < deviceClassNames.Length; deviceClassIdx++)
            {
                string ftClassName = deviceClassNames[deviceClassIdx];

                // Get the features and the display index for use when creating the wrapper
                ftLayer = _hookHelper.FindFeatureLayer(ftClassName);
                if (ftLayer != null) // what if layer removed from map
                {
                    selectedFts = _hookHelper.GetSelectedFeatures(ftLayer);

                    displayIdx = ftLayer.FeatureClass.FindField(ftLayer.DisplayField);

                    for (int ftIdx = 0; ftIdx < selectedFts.Count; ftIdx++)
                    {
                        DeviceWrapper w = new DeviceWrapper(selectedFts[ftIdx], displayIdx);
                        cboFrom.Items.Add(w);
                    }
                }
            }

            // Preselect the first choice
            if (0 < cboFrom.Items.Count)
            {
                cboFrom.SelectedItem = cboFrom.Items[0];
            }
        }