/// <summary>
        /// Second pass parsing and validation.
        /// </summary>
        /// <param name="options">Configuration options</param>
        /// <param name="reportExtractionNode">Node contaiing the entity references.</param>
        /// <param name="reportExtraction">ReportExtraction element to contain the parsed entity references.</param>
        /// <param name="types">List of .Net types defined.</param>
        /// <param name="entities">List of entities defined.</param>
        /// <param name="vd">Validation delegate for error reporting.</param>
        /// <returns>List of entity references parsed.</returns>
        public static ArrayList ParseFromXml(Configuration options, XmlNode reportExtractionNode, ReportExtractionElement reportExtraction, Hashtable types, Hashtable sqltypes, IList entities, ParserValidationDelegate vd)
        {
            ArrayList entityReferences = new ArrayList();

            foreach (XmlNode node in reportExtractionNode.ChildNodes)
            {
                if (node.NodeType == XmlNodeType.Comment)
                {
                    continue;
                }
                EntityReferenceElement entityReference = new EntityReferenceElement(reportExtraction);
                if (entityReference.Name != null)
                {
                    entityReference.Name = node.Attributes[NAME].Value;
                }
                else
                {
                    vd(ParserValidationArgs.NewError("Entity reference specified in report extraction " + reportExtraction.Name + " with no name."));
                }

                if (node.Attributes[ENTITY] != null)
                {
                    EntityElement ee = EntityElement.FindEntityByName(entities, node.Attributes[ENTITY].Value);
                    if (ee != null)
                    {
                        entityReference.Entity = ee;
                        if (entityReference.Entity.SqlEntity.Name == String.Empty)
                        {
                            vd(ParserValidationArgs.NewError("Entity Reference " + entityReference.Name + " refers to entity " + node.Attributes[ENTITY].Value + " which does not have an associated SQL entity."));
                        }
                    }
                    else
                    {
                        vd(ParserValidationArgs.NewError("Entity Reference " + entityReference.Name + " refers to entity " + node.Attributes[ENTITY].Value + " which does not exist."));
                    }
                }
                else
                {
                    vd(ParserValidationArgs.NewError("Entity Reference " + node.Attributes[NAME].Value + " has no entity attribute."));
                }

                if (node.Attributes[ALIAS_PREFIX] != null)
                {
                    entityReference.aliasPrefix = node.Attributes[ALIAS_PREFIX].Value;
                }

                if (node.Attributes[HINTS] != null)
                {
                    entityReference.Hints = node.Attributes[HINTS].Value;
                }

                if (node.Attributes[FILTER] != null)
                {
                    entityReference.Filter = node.Attributes[FILTER].Value;
                }

                if (node.Attributes[JOIN_MODIFIER] != null)
                {
                    entityReference.JoinModifier = node.Attributes[JOIN_MODIFIER].Value;
                    if (entityReference.JoinModifier.ToUpper() != JOIN_LEFT &&
                        entityReference.JoinModifier.ToUpper() != JOIN_RIGHT &&
                        entityReference.JoinModifier.ToUpper() != JOIN_FULL)
                    {
                        vd(ParserValidationArgs.NewError("Entity Reference " + node.Attributes[NAME].Value + " has join modifier other than left, right or full."));
                    }
                }

                entityReference.ReportExtraction = reportExtraction;
                // Note we pass entityReference.Entity because the fields refer to fields in the entity.
                entityReference.propertyReferences = PropertyElement.ParseFromXml(GetChildNodeByName(node, PROPERTY_REFERENCES), entities, entityReference.Entity, sqltypes, types, true, vd);
                entityReference.ProcessAsteriskName(vd);
                entityReference.AdjustSqlAlias();
                entityReferences.Add(entityReference);
            }
            return(entityReferences);
        }