public override void Deserialize(XmlNode parentNode)
        {
            base.Deserialize(parentNode);

            if (parentNode.ChildNodes.Count == 1 && parentNode.FirstChild.Name == "SpeedZone")
            {
                XmlNode child = parentNode.FirstChild;

                if (child.Attributes.Count == 1 && child.Attributes[0].Name == Constants.XsiTypeTCXString &&
                    child.Attributes[0].Value.Equals(Constants.SpeedRangeZoneTCXString[0]))
                {
                    // We have a GTC HR zone
                    ConcreteTarget = new SpeedZoneGTCTarget(this);
                    ConcreteTarget.Deserialize(child);
                }
                else if (child.Attributes.Count == 1 && child.Attributes[0].Name == Constants.XsiTypeTCXString &&
                    child.Attributes[0].Value.Equals(Constants.SpeedRangeZoneTCXString[1]))
                {
                    // We have either a range or a ST HR zone but we can't tell before the
                    //  extension section so create a range and if it ends up being a ST
                    //  zone, replace it
                    ConcreteTarget = new SpeedRangeTarget(this);
                    ConcreteTarget.Deserialize(child); ;
                }
                else
                {
                }
            }
        }
 public new void Deserialize_V0(Stream stream, DataVersion version)
 {
     // In V0, we only have speed range target
     ConcreteTarget = new SpeedRangeTarget(stream, version, this);
 }
        public void Deserialize_V1(Stream stream, DataVersion version)
        {
            Byte[] intBuffer = new Byte[sizeof(UInt32)];
            BaseSpeedTarget.IConcreteSpeedTarget.SpeedTargetType type;

            stream.Read(intBuffer, 0, sizeof(UInt32));
            type = (IConcreteSpeedTarget.SpeedTargetType)BitConverter.ToUInt32(intBuffer, 0);

            switch (type)
            {
                case BaseSpeedTarget.IConcreteSpeedTarget.SpeedTargetType.ZoneGTC:
                    {
                        ConcreteTarget = new SpeedZoneGTCTarget(stream, version, this);
                        break;
                    }
                case BaseSpeedTarget.IConcreteSpeedTarget.SpeedTargetType.ZoneST:
                    {
                        ConcreteTarget = new SpeedZoneSTTarget(stream, version, this);
                        break;
                    }
                case BaseSpeedTarget.IConcreteSpeedTarget.SpeedTargetType.Range:
                    {
                        ConcreteTarget = new SpeedRangeTarget(stream, version, this);
                        break;
                    }
                default:
                    {
                        Debug.Assert(false);
                        break;
                    }
            }
        }
        public static ITarget Create(FITMessage stepMessage, RegularStep parent)
        {
            FITMessageField targetTypeField = stepMessage.GetField((Byte)FITWorkoutStepFieldIds.TargetType);
            FITMessageField targetField = stepMessage.GetField((Byte)FITWorkoutStepFieldIds.TargetValue);
            FITMessageField targetCustomLowField = stepMessage.GetField((Byte)FITWorkoutStepFieldIds.TargetCustomValueLow);
            FITMessageField targetCustomHighField = stepMessage.GetField((Byte)FITWorkoutStepFieldIds.TargetCustomValueHigh);
            ITarget result = new NullTarget(parent);

            if(targetTypeField != null)
            {
                switch((FITWorkoutStepTargetTypes)targetTypeField.GetEnum())
                {
                    case FITWorkoutStepTargetTypes.HeartRate:
                        {
                            if(targetField != null)
                            {
                                BaseHeartRateTarget hrTarget = (BaseHeartRateTarget)Create(ITarget.TargetType.HeartRate, parent);
                                UInt32 hrZone = targetField.GetUInt32();

                                if (hrZone == 0)
                                {
                                    if (targetCustomLowField != null &&
                                        targetCustomHighField != null)
                                    {
                                        HeartRateRangeTarget concreteTarget = new HeartRateRangeTarget(hrTarget);

                                        if (targetCustomLowField.GetUInt32() > 100)
                                        {
                                            concreteTarget.SetValues((Byte)(targetCustomLowField.GetUInt32() - 100),
                                                                     (Byte)(targetCustomHighField.GetUInt32() - 100),
                                                                     false);
                                        }
                                        else
                                        {
                                            concreteTarget.SetValues((Byte)targetCustomLowField.GetUInt32(),
                                                                     (Byte)targetCustomHighField.GetUInt32(),
                                                                     true);
                                        }

                                        hrTarget.ConcreteTarget = concreteTarget;
                                    }
                                    else
                                    {
                                        throw new FITParserException("Missing target custom value field");
                                    }
                                }
                                else
                                {
                                    HeartRateZoneGTCTarget concreteTarget = new HeartRateZoneGTCTarget(hrTarget);

                                    concreteTarget.Zone = (Byte)hrZone;
                                    hrTarget.ConcreteTarget = concreteTarget;
                                }

                                result = hrTarget;
                            }
                            else
                            {
                                throw new FITParserException("Missing target value field");
                            }
                            break;
                        }
                    case FITWorkoutStepTargetTypes.Cadence:
                        {
                            if (targetField != null &&
                                targetCustomLowField != null &&
                                targetCustomHighField != null)
                            {
                                BaseCadenceTarget cadenceTarget = (BaseCadenceTarget)Create(ITarget.TargetType.Cadence, parent);
                                CadenceRangeTarget concreteTarget = new CadenceRangeTarget(cadenceTarget);
                                UInt32 cadenceZone = targetField.GetUInt32();

                                Debug.Assert(cadenceZone == 0);

                                concreteTarget.SetValues((Byte)targetCustomLowField.GetUInt32(),
                                                         (Byte)targetCustomHighField.GetUInt32());
                                cadenceTarget.ConcreteTarget = concreteTarget;

                                result = cadenceTarget;
                            }
                            else
                            {
                                throw new FITParserException("Missing target or custom values field");
                            }

                            break;
                        }
                    case FITWorkoutStepTargetTypes.Speed:
                        {
                            if(targetField != null)
                            {
                                BaseSpeedTarget speedTarget = (BaseSpeedTarget)Create(ITarget.TargetType.Speed, parent);
                                UInt32 speedZone = targetField.GetUInt32();

                                if (speedZone == 0)
                                {
                                    if (targetCustomLowField != null &&
                                        targetCustomHighField != null)
                                    {
                                        SpeedRangeTarget concreteTarget = new SpeedRangeTarget(speedTarget);

                                        concreteTarget.SetRangeInBaseUnitsPerHour(Length.Convert(targetCustomLowField.GetUInt32() * 3.6, Length.Units.Meter, concreteTarget.BaseUnit),
                                                                                  Length.Convert(targetCustomHighField.GetUInt32() * 3.6, Length.Units.Meter, concreteTarget.BaseUnit));
                                        speedTarget.ConcreteTarget = concreteTarget;
                                    }
                                    else
                                    {
                                        throw new FITParserException("Missing target custom value field");
                                    }
                                }
                                else
                                {
                                    SpeedZoneGTCTarget concreteTarget = new SpeedZoneGTCTarget(speedTarget);

                                    concreteTarget.Zone = (Byte)speedZone;
                                    speedTarget.ConcreteTarget = concreteTarget;
                                }

                                result = speedTarget;
                            }
                            else
                            {
                                throw new FITParserException("Missing target value field");
                            }
                            break;
                        }
                    case FITWorkoutStepTargetTypes.Power:
                        {
                            if(targetField != null)
                            {
                                BasePowerTarget powerTarget = (BasePowerTarget)Create(ITarget.TargetType.Power, parent);
                                UInt32 powerZone = targetField.GetUInt32();

                                if (powerZone == 0)
                                {
                                    if (targetCustomLowField != null &&
                                        targetCustomHighField != null)
                                    {
                                        PowerRangeTarget concreteTarget = new PowerRangeTarget(powerTarget);

                                        if (targetCustomLowField.GetUInt32() > 1000)
                                        {
                                            concreteTarget.SetValues((UInt16)(targetCustomLowField.GetUInt32() - 1000),
                                                                     (UInt16)(targetCustomHighField.GetUInt32() - 1000),
                                                                     false);
                                        }
                                        else
                                        {
                                            concreteTarget.SetValues((UInt16)(targetCustomLowField.GetUInt32()),
                                                                     (UInt16)(targetCustomHighField.GetUInt32()),
                                                                     true);
                                        }
                                        powerTarget.ConcreteTarget = concreteTarget;
                                    }
                                    else
                                    {
                                        throw new FITParserException("Missing target custom value field");
                                    }
                                }
                                else
                                {
                                    PowerZoneGTCTarget concreteTarget = new PowerZoneGTCTarget(powerTarget);

                                    concreteTarget.Zone = (Byte)powerZone;
                                    powerTarget.ConcreteTarget = concreteTarget;
                                }

                                result = powerTarget;
                            }
                            else
                            {
                                throw new FITParserException("Missing target value field");
                            }

                            break;
                        }
                }
            }
            else
            {
                throw new FITParserException("Missing target type field");
            }

            return result;
        }