/// <summary>
        /// Seeder/Drill data will often report rates on bin device elements.   These device elements are the geometrical equivalent of the parent boom for mapping purposes.
        /// They are modeled as sections in ADAPT so that we can detect individual products/rates from these different device elements (tanks).
        /// Since they fall at the same level in the hierarchy as true implement sections, we need to reorder the section depths so that anything below the boom
        /// that is not a bin is moved down one level.   As such, the bin will not effect the geometric modeling of individual sections from left to right.
        /// </summary>
        /// <param name="h"></param>
        public static void HandleBinDeviceElements(DeviceElementHierarchy h)
        {
            for (int i = 0; i <= h.GetMaxDepth(); i++)
            {
                if (h.GetElementsAtDepth(i).Any(d => d.DeviceElement.DeviceElementType == ISODeviceElementType.Bin) &&
                    h.GetElementsAtDepth(i).Any(d => d.DeviceElement.DeviceElementType != ISODeviceElementType.Bin))
                {
                    //There are both bin and non-bin elements at this depth

                    //Move everything deeper than this level down
                    for (int d = h.GetMaxDepth(); d > i; d--)
                    {
                        h.GetElementsAtDepth(d)
                        .ToList()
                        .ForEach(e => e.Depth++);
                    }

                    //Drop the non-bin elements at this level down to the new gap just created
                    h.GetElementsAtDepth(i)
                    .Where(e => e.DeviceElement.DeviceElementType != ISODeviceElementType.Bin)
                    .ToList()
                    .ForEach(x => x.Depth++);
                }
            }
        }
        public ISODeviceElement GetISODeviceElementFromID(string deviceElementID)
        {
            DeviceElementHierarchy hierarchy = GetRelevantHierarchy(deviceElementID);

            if (hierarchy != null)
            {
                return(hierarchy.DeviceElement);
            }
            return(null);
        }
        public DeviceElementHierarchy GetRootDeviceElementHierarchy()
        {
            DeviceElementHierarchy item = this;

            while (item.Parent != null)
            {
                item = item.Parent;
            }
            return(item);
        }
 public DeviceElementHierarchy GetRelevantHierarchy(string isoDeviceElementId)
 {
     foreach (DeviceElementHierarchy hierarchy in this.Items.Values)
     {
         DeviceElementHierarchy foundModel = hierarchy.FromDeviceElementID(isoDeviceElementId);
         if (foundModel != null)
         {
             return(foundModel);
         }
     }
     return(null);
 }
 public DeviceElementHierarchies(IEnumerable <ISODevice> devices, RepresentationMapper representationMapper)
 {
     Items = new Dictionary <string, DeviceElementHierarchy>();
     foreach (ISODevice device in devices)
     {
         ISODeviceElement rootDeviceElement = device.DeviceElements.SingleOrDefault(det => det.DeviceElementType == ISODeviceElementType.Device);
         if (rootDeviceElement != null)
         {
             DeviceElementHierarchy hierarchy = new DeviceElementHierarchy(rootDeviceElement, 0, representationMapper);
             DeviceElementHierarchy.HandleBinDeviceElements(hierarchy);
             Items.Add(device.DeviceId, hierarchy);
         }
     }
 }
 public DeviceElementHierarchy FromDeviceElementID(string deviceElementID)
 {
     if (DeviceElement.DeviceElementId == deviceElementID)
     {
         return(this);
     }
     else if (Children != null)
     {
         foreach (DeviceElementHierarchy child in Children)
         {
             DeviceElementHierarchy childModel = child.FromDeviceElementID(deviceElementID);
             if (childModel != null)
             {
                 return(childModel);
             }
         }
     }
     return(null);
 }
        public DeviceElementHierarchy(ISODeviceElement deviceElement, int depth, RepresentationMapper representationMapper, HashSet <int> crawledElements = null, DeviceElementHierarchy parent = null)
        {
            RepresentationMapper = representationMapper;
            //This Hashset will track that we don't build infinite hierarchies.
            //The plugin does not support peer control at this time.
            _crawledElements = crawledElements;
            if (_crawledElements == null)
            {
                _crawledElements = new HashSet <int>();
            }

            if (_crawledElements.Add((int)deviceElement.DeviceElementObjectId))
            {
                Type          = deviceElement.DeviceElementType;
                DeviceElement = deviceElement;
                Depth         = depth;
                Order         = (int)deviceElement.DeviceElementNumber; //Using this number as analagous to this purpose.  The ISO spec requires these numbers increment from left to right as in ADAPT.  (See ISO11783-10:2015(E) B.3.2 Element number)

                //DeviceProperty assigned Widths & Offsets
                //DeviceProcessData assigned values will be assigned as the SectionMapper reads timelog data.

                //Width
                ISODeviceProperty widthProperty = deviceElement.DeviceProperties.FirstOrDefault(dpt => dpt.DDI == "0046");
                if (widthProperty != null)
                {
                    Width    = widthProperty.Value;
                    WidthDDI = "0046";
                }
                else
                {
                    widthProperty = deviceElement.DeviceProperties.FirstOrDefault(dpt => dpt.DDI == "0043");
                    if (widthProperty != null)
                    {
                        Width    = widthProperty.Value;
                        WidthDDI = "0043";
                    }
                }

                //Offsets
                ISODeviceProperty xOffsetProperty = deviceElement.DeviceProperties.FirstOrDefault(dpt => dpt.DDI == "0086");
                if (xOffsetProperty != null)
                {
                    XOffset = xOffsetProperty.Value;
                }

                ISODeviceProperty yOffsetProperty = deviceElement.DeviceProperties.FirstOrDefault(dpt => dpt.DDI == "0087");
                if (yOffsetProperty != null)
                {
                    YOffset = yOffsetProperty.Value;
                }

                ISODeviceProperty zOffsetProperty = deviceElement.DeviceProperties.FirstOrDefault(dpt => dpt.DDI == "0088");
                if (zOffsetProperty != null)
                {
                    ZOffset = zOffsetProperty.Value;
                }

                //Children
                IEnumerable <ISODeviceElement> childDeviceElements = deviceElement.Device.DeviceElements.Where(det => det.ParentObjectId == deviceElement.DeviceElementObjectId);// && det.DeviceElementType == ISOEnumerations.ISODeviceElementType.Section);
                if (childDeviceElements.Any())
                {
                    int childDepth = depth + 1;
                    Children = new List <DeviceElementHierarchy>();
                    foreach (ISODeviceElement det in childDeviceElements)
                    {
                        DeviceElementHierarchy child = new DeviceElementHierarchy(det, childDepth, representationMapper, _crawledElements, this);
                        Children.Add(child);
                    }
                }

                //Parent
                Parent = parent;
            }
        }