/// <summary>
        /// Initializes a new instance of the EnumDefinition class
        /// Populates this object with information extracted from the XML
        /// </summary>
        /// <param name="theNode">XML node describing the Enum object</param>
        /// <param name="manager">The data dictionary manager constructing this type.</param>
        public EnumDefinition(XElement theNode, DictionaryManager manager)
            : base(theNode, TypeId.EnumType)
        {
            // ByteSize may be set either directly as an integer or by inference from the Type field.
            // If no Type field is present then the type is assumed to be 'int'
            if (theNode.Element("ByteSize") != null)
            {
                SetByteSize(theNode.Element("ByteSize").Value);
            }
            else
            {
                string baseTypeName = theNode.Element("Type") != null ? theNode.Element("Type").Value : "int";

                BaseType = manager.GetElementType(baseTypeName);
                BaseType = DictionaryManager.DereferenceTypeDef(BaseType);

                FixedSizeBytes = BaseType.FixedSizeBytes.Value;
            }

            // Common properties are parsed by the base class.
            // Remaining properties are the Name/Value Literal elements
            List<LiteralDefinition> theLiterals = new List<LiteralDefinition>();
            foreach (var literalNode in theNode.Elements("Literal"))
            {
                theLiterals.Add(new LiteralDefinition(literalNode));
            }

            m_Literals = new ReadOnlyCollection<LiteralDefinition>(theLiterals);

            // Check the name. If it's null then make one up
            if (theNode.Element("Name") == null)
            {
                Name = String.Format("Enum_{0}", Ref);
            }
        }
 /// <summary>
 /// Finishes construction of the object by populating properties of the object from
 /// the XML node
 /// </summary>
 /// <param name="theNode"></param>
 /// <param name="theManager"></param>
 public override void FinishConstruction(XElement theNode, DictionaryManager theManager)
 {
     // Type of the attribute is identified by a number that is the Ref field of a type somewhere
     // or the name of the aliased type
     m_AliasedType = theManager.GetElementType(theNode.Element("Type").Value);
     FixedSizeBytes = m_AliasedType.FixedSizeBytes;
 }
        /// <summary>
        /// Finishes construction of the object by populating properties of the object from
        /// the XML node
        /// </summary>
        /// <param name="theNode"></param>
        /// <param name="theManager"></param>
        public override void FinishConstruction(XElement theNode, DictionaryManager theManager)
        {
            // Parse each of the attribute nodes in turn - this may well get recursive
            List<AttributeDefinition> attributes = new List<AttributeDefinition>();
            foreach (var attributeNode in theNode.Elements("Attribute"))
            {
                attributes.Add(new AttributeDefinition(attributeNode, theManager, this));
            }

            m_AttributeDefinitions = new ReadOnlyCollection<AttributeDefinition>(attributes);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SwitchCaseDefinition"/> class.
        /// </summary>
        /// <param name="theCaseNode">The XML element defining this switch case</param>
        /// <param name="caseValue">The case value.</param>
        /// <param name="theManager">The data dictionary manager.</param>
        public SwitchCaseDefinition(XElement theCaseNode, string caseValue, DictionaryManager theManager)
        {
            Value = caseValue;
            Name = (theCaseNode.Element("Name") != null) ? theCaseNode.Element("Name").Value : string.Empty;

            if (theCaseNode.Element("Type") != null)
            {
                TypeDefinition caseType = theManager.GetElementType(theCaseNode.Element("Type").Value);
                TypeName = caseType.Name;
                Type = DictionaryManager.DereferenceTypeDef (caseType);
            }
            else
            {
                Type = theManager.GetNestedTypeDefinition(theCaseNode);
            }
        }
        /// <summary>
        /// Finishes construction of the object by populating properties of the object from
        /// the XML node
        /// </summary>
        /// <param name="theNode"></param>
        /// <param name="theManager">The manager.</param>
        public override void FinishConstruction(XElement theNode, DictionaryManager theManager)
        {
            XElement useNode = theNode.Element("Use");
            Use = theManager.GetElementType(useNode.Value) as EnumDefinition;
            if (Use == null)
            {
                throw new DataDictionaryException("SwitchDefinition: {0} is not an enum type", useNode.Value);
            }

            m_SwitchCaseCollection = new SwitchCaseCollection(Use);

            // Note that each case node may have more than one value associated with it
            // Also a case node may have a nested type definition rather than a reference to a type
            var caseDefinitions = from caseNode in theNode.Elements("Case")
                                  from valueNode in caseNode.Elements("Value")
                                  select new SwitchCaseDefinition(caseNode, valueNode.Value, theManager);

            m_SwitchCaseCollection.AddRange(caseDefinitions);
            Name = theNode.Element("Name") != null ? theNode.Element("Name").Value : string.Format("switch_{0}", theManager.GetUniqueId());
        }
        /// <summary>
        /// Finishes construction of the object by populating properties of the object from
        /// the XML node
        /// </summary>
        /// <param name="theNode"></param>
        /// <param name="theManager"></param>
        public override void FinishConstruction(XElement theNode, DictionaryManager theManager)
        {
            try
            {
                if (theNode.Element("ByteSize") != null)
                {
                    SetByteSize(theNode.Element("ByteSize").Value);
                }

                IsTlvStructure = false;

                // Parse each of the attribute nodes in turn - this may well get recursive
                m_AttributeDefinitions = new AttributeDefinitionCollection(Name);
                foreach (var attributeNode in theNode.Elements("Attribute"))
                {
                    AttributeDefinition theAttribute = new AttributeDefinition(attributeNode, theManager, this);
                    m_AttributeDefinitions.Add(theAttribute);
                    if (theAttribute.HasDiscriminator && theAttribute.HasLengthIndicator)
                    {
                        IsTlvStructure = true;
                        m_TlvControlAttribute = theAttribute;
                    }
                }

                // Check the name. If it's null then make one up
                if (theNode.Element("Name") == null)
                {
                    Name = String.Format("XXStruct_{0}", Ref);
                }
            }
            catch (DataDictionaryException ex)
            {
                throw new DataDictionaryException("Error constructing definition for Struct. XML:\n{0}\nException: {1}", theNode, ex.Message);
            }
            catch (XmlException ex)
            {
                throw new DataDictionaryException("Error constructing definition for Struct. XML:\n{0}\nException: {1}", theNode, ex.Message);
            }
        }
        /// <summary>
        /// Finishes construction of the object by populating properties of the object from
        /// the XML node
        /// </summary>
        /// <param name="theNode"></param>
        /// <param name="theManager"></param>
        public override void FinishConstruction(XElement theNode, DictionaryManager theManager)
        {
            // Find out what this points to and use this to form the name of the type
            // Type of the attribute is identified by a number that is the Ref field of a type somewhere
            // or a string that is the name of a type somewhere
            TypeDefinition theType = theManager.GetElementType(theNode.Element("Type").Value);
            if (theType == null)
            {
                throw new DataDictionaryException("{0} : cannot find the type for the pointer", theNode.ToString());    
            }

            TypeName = theType.Name;

            // Follow aliases of typedefs so that the underlying type is stored
            while (theType is TypedefDefinition)
            {
                theType = ((TypedefDefinition)theType).AliasedType;
            }

            Type = theType;

            // Finally set the name for the type
            Name = String.Format("*{0}", TypeName);
        }
        /// <summary>
        /// Factory pattern to create a new derived object from the supplied XML node
        /// </summary>
        /// <param name="theManager"></param>
        /// <param name="theNode"></param>
        /// <returns>New type definition</returns>
        public static TypeDefinition Create(DictionaryManager theManager, XElement theNode)
        {
            string typeName = theNode.Name.ToString();
            if (!m_FactoryMap.ContainsKey(typeName))
            {
                throw new DataDictionaryException("Unknown DD type {0}", typeName);
            }

            return m_FactoryMap[typeName](theNode, theManager);
        }
 /// <summary>
 /// Finishes construction of the object by populating properties of the object from
 /// the XML node
 /// </summary>
 /// <param name="theNode"></param>
 /// <param name="theManager"></param>
 public virtual void FinishConstruction(XElement theNode, DictionaryManager theManager)
 {
     // No further action required for this class
 }
 /// <summary>
 /// Finishes construction of the object by populating properties of the object from
 /// the XML node
 /// </summary>
 /// <param name="theNode"></param>
 /// <param name="theManager"></param>
 public override void FinishConstruction(XElement theNode, DictionaryManager theManager)
 {
 }
        /// <summary>
        /// Finishes construction of the object by populating properties of the object from
        /// the XML node
        /// </summary>
        /// <param name="theNode"></param>
        /// <param name="theManager"></param>
        public override void FinishConstruction(XElement theNode, DictionaryManager theManager)
        {
            try
            {
                // Find out what type this holds and use this to form the name of the type
                TypeDefinition theType = theManager.GetElementType(theNode.Element("Type").Value);

                // Set the type name before following any typedefs
                ElementTypeName = theType.Name;

                // Follow aliases of typedefs so that the underlying type is stored
                while (theType is TypedefDefinition)
                {
                    theType = ((TypedefDefinition)theType).AliasedType;
                }

                ElementType = theType;

                if (theNode.Element("UpperBound") != null && !string.IsNullOrEmpty(theNode.Element("UpperBound").Value))
                {
                    // Read the size of the array
                    int thisUpperBound = 0;
                    if (Sepura.Utilities.Formatting.TryGetInt(theNode.Element("UpperBound").Value, out thisUpperBound))
                    {
                        // Handle nested (multi-dimensional) arrays
                        if (theType.GetType() == typeof(ArrayTypeDefinition))
                        {
                            ArrayTypeDefinition nestedArray = theType as ArrayTypeDefinition;

                            // Propagate the name of the underlying type (determined before following typedefs)
                            ElementTypeName = nestedArray.ElementTypeName;
                            ElementType = nestedArray.ElementType;

                            UpperBound = new int[nestedArray.UpperBound.Length + 1];
                            for (int i = 0; i < nestedArray.UpperBound.Length; i++)
                            {
                                UpperBound[i + 1] = nestedArray.UpperBound[i];
                            }

                            UpperBound[0] = thisUpperBound;
                        }
                        else
                        {
                            UpperBound = new int[1];
                            UpperBound[0] = thisUpperBound;
                        }

                        // Finally set the name for the type
                        StringBuilder sb = new StringBuilder();
                        sb.AppendFormat("{0} ", ElementTypeName);
                        for (int i = 0; i < UpperBound.Length; i++)
                        {
                            sb.AppendFormat("[{0}]", UpperBound[i]);
                        }

                        Name = sb.ToString();
                    }
                    else
                    {
                        UpperBoundVariable = theNode.Element("UpperBound").Value;

                        // Length of the array is defined at run-time
                        UpperBound = new int[0];
                        Name = string.Format("{0} []", ElementTypeName);
                    }
                }
                else
                {
                    // Length of the array is undefined - this gets treated as a list whose length is determined at run-time
                    UpperBound = new int[0];
                    Name = string.Format("{0} []", ElementTypeName);
                }
            }
            catch (DataDictionaryException ex)
            {
                throw new DataDictionaryException("Error constructing definition for Array. XML:\n{0}\nException: {1}", theNode, ex.Message);
            }
            catch (XmlException ex)
            {
                throw new DataDictionaryException("Error constructing definition for Array. XML:\n{0}\nException: {1}", theNode, ex.Message);
            }
        }
        /// <summary>
        /// Initializes a new instance of the AttributeDefinition class
        /// Constructor. Create a new object by reading contents from the XML node.
        /// </summary>
        /// <param name="attributeNode">The attribute node.</param>
        /// <param name="theManager">The manager.</param>
        /// <param name="parentType">The parent structure.</param>
        public AttributeDefinition(XElement attributeNode, DictionaryManager theManager, TypeDefinition parentType)
        {
            Name = attributeNode.Element("Name").Value;

            if (attributeNode.Element("Discriminator") == null)
            {
                Discriminator = string.Empty;
                HasDiscriminator = false;
            }
            else
            {
                Discriminator = attributeNode.Element("Discriminator").Value;
                HasDiscriminator = true;
            }

            if (attributeNode.Element("ByteOffset") != null)
            {
                int byteOffset;

                if (!int.TryParse(attributeNode.Element("ByteOffset").Value, out byteOffset))
                {
                    throw new DataDictionaryException("{0} : failed to parse ByteOffset as an integer", attributeNode.ToString());
                }

                ByteOffset = byteOffset;
            }

            HasLengthIndicator = false;
            if (attributeNode.Element("ByteSize") != null)
            {
                LengthIndicator = attributeNode.Element("ByteSize").Value;
                HasLengthIndicator = true;
            }

            // Type of the attribute may identified by a number that is the Ref field of a type somewhere
            // or by the name of the type 
            // or by the XML element nested within the attribute definition
            if (attributeNode.Element("Type") != null)
            {
                Type = theManager.GetElementType(attributeNode.Element("Type").Value);
            }
            else
            {
                // Nested type
                Type = theManager.GetNestedTypeDefinition(attributeNode);
            }

            // Follow aliases of typedefs so that the underlying type is stored
            TypeDefinition theType = Type;
            while (theType is TypedefDefinition)
            {
                theType = ((TypedefDefinition)theType).AliasedType;
            }

            // Finally, if we've just created a Switch type set the discriminator
            if (theType != null && theType.TypeId == TypeId.SwitchType)
            {
                SwitchDefinition theSwitchDefinition = Type as SwitchDefinition;

                if (string.IsNullOrEmpty(Discriminator))
                {
                    throw new DataDictionaryException("Attribute {0}: no discriminator supplied for Switch {1}", Name, Type.Name);
                }

                StructureDefinition structureDefinition = (StructureDefinition)parentType;
                theSwitchDefinition.Discriminator = structureDefinition.AttributeDefinitions[Discriminator];
                theSwitchDefinition.Discriminator.DiscriminatorFor = this;
            }
        }