// Copyright © Microsoft Corporation. // This source file is subject to the Microsoft Permissive License. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx. // All other rights reserved. using System; using System.Collections.Generic; using System.Text; using System.Xml; using System.Xml.XPath; namespace BuildComponents { public interface ISimpleReference { string Id { get; } } public abstract partial class Reference { } // Namespace public partial class NamespaceReference : Reference, ISimpleReference { internal NamespaceReference (string id) { this.namespaceId = id; } private string namespaceId; public string Id { get { return (namespaceId); } } } // Type public abstract partial class TypeReference : Reference { } public partial class SimpleTypeReference : TypeReference { internal SimpleTypeReference (string id) { this.typeId = id; } private string typeId; public string Id { get { return (typeId); } } } public partial class ReferenceTypeReference : TypeReference { private TypeReference referedToType; public TypeReference ReferedToType { get { return (referedToType); } } internal ReferenceTypeReference (TypeReference referedToType) { if (referedToType == null) throw new ArgumentNullException("referedToType"); this.referedToType = referedToType; } } public partial class PointerTypeReference : TypeReference { internal PointerTypeReference (TypeReference pointedToType) { if (pointedToType == null) throw new ArgumentNullException("pointedToType"); this.pointedToType = pointedToType; } private TypeReference pointedToType; public TypeReference PointedToType { get { return (pointedToType); } } } public partial class ArrayTypeReference : TypeReference { internal ArrayTypeReference (TypeReference elementType, int rank) { if (elementType == null) throw new ArgumentNullException("elementType"); if (rank <= 0) throw new ArgumentOutOfRangeException("rank"); this.elementType = elementType; this.rank = rank; } private int rank; private TypeReference elementType; public int Rank { get { return (rank); } } public TypeReference ElementType { get { return (elementType); } } } public class TemplateTypeReference : TypeReference { internal TemplateTypeReference (string templateId, int position) { if (template == null) throw new ArgumentNullException("template"); if (position < 0) throw new ArgumentOutOfRangeException("position"); this.template = null; // fix this: create a reference this.position = position; } internal TemplateTypeReference (ISimpleReference template, int position) { if (template == null) throw new ArgumentNullException("template"); if (position < 0) throw new ArgumentOutOfRangeException("position"); this.template = template; this.position = position; } private ISimpleReference template; private int position; } public abstract partial class MemberReference : Reference {} public partial class SimpleMemberReference : MemberReference, ISimpleReference { internal SimpleMemberReference (string id) { if (id == null) throw new ArgumentNullException("id"); this.memberId = id; } private string memberId; public string Id { get { return(memberId); } } } // ***** XML PARSING **** public partial class Reference { public static Reference Create (XmlReader element) { if (element == null) throw new ArgumentNullException("element"); switch (element.LocalName) { case "namespace": return (NamespaceReference.Create(element)); case "member": return (MemberReference.Create(element)); default: return (TypeReference.Create(element)); } } public static Reference Create (XPathNavigator node) { if (node == null) throw new ArgumentNullException("node"); if (node.NodeType == XPathNodeType.Element) { string tag = node.LocalName; if (tag == "namespace") return (NamespaceReference.Create(node)); //if (tag == "member") return (MemberReference.Create(node)); return (TypeReference.Create(node)); } else { return (null); } } protected static XPathExpression referenceApiExpression = XPathExpression.Compile("string(@api)"); } public partial class NamespaceReference { public static new NamespaceReference Create (XmlReader space) { if (space == null) throw new ArgumentNullException("space"); string api = space.GetAttribute("api"); return(new NamespaceReference(api)); } public static new NamespaceReference Create (XPathNavigator space) { if (space == null) throw new ArgumentNullException("space"); string api = (string) space.Evaluate(referenceApiExpression); return(new NamespaceReference(api)); } } public partial class TypeReference { public static new TypeReference Create (XmlReader element) { if (element == null) throw new ArgumentNullException("element"); switch (element.LocalName) { case "type": // also handle specialization! return(SimpleTypeReference.Create(element)); case "referenceTo": return(ReferenceTypeReference.Create(element)); case "pointerTo": return(PointerTypeReference.Create(element)); case "arrayOf": return(ArrayTypeReference.Create(element)); } return (null); } public static new TypeReference Create (XPathNavigator element) { if (element == null) throw new ArgumentNullException("element"); string tag = element.LocalName; if (tag == "type") { bool isSpecialized = (bool)element.Evaluate("boolean(.//specialization)"); if (isSpecialized) { // deal with specialization! // return (CreateSpecializedTypeReference(element)); return (SimpleTypeReference.Create(element)); } else { return (SimpleTypeReference.Create(element)); } } else if (tag == "arrayOf") { string rankValue = element.GetAttribute("rank", String.Empty); XPathNavigator elementNode = element.SelectSingleNode("*[1]"); return (new ArrayTypeReference(TypeReference.Create(elementNode), Convert.ToInt32(rankValue))); } else if (tag == "referenceTo") { XPathNavigator referedToNode = element.SelectSingleNode("*[1]"); return (new ReferenceTypeReference(TypeReference.Create(referedToNode))); } else if (tag == "pointerTo") { XPathNavigator pointedToNode = element.SelectSingleNode("*[1]"); return (new PointerTypeReference(TypeReference.Create(pointedToNode))); } else if (tag == "template") { //string nameValue = element.GetAttribute("name", String.Empty); string indexValue = element.GetAttribute("index", String.Empty); string apiValue = element.GetAttribute("api", String.Empty); if ((!String.IsNullOrEmpty(apiValue)) && (!String.IsNullOrEmpty(indexValue))) { return (new TemplateTypeReference(apiValue, Convert.ToInt32(indexValue))); // return (new IndexedTemplateTypeReference(apiValue, Convert.ToInt32(indexValue))); } else { throw new InvalidOperationException(); // return (new NamedTemplateTypeReference(nameValue)); } } throw new InvalidOperationException(String.Format("INVALID '{0}'", tag)); } } public partial class SimpleTypeReference { public static new SimpleTypeReference Create (XmlReader type) { if (type == null) throw new ArgumentNullException("type"); string api = type.GetAttribute("api"); return (new SimpleTypeReference(api)); } public static new SimpleTypeReference Create (XPathNavigator type) { if (type == null) throw new ArgumentNullException("type"); string api = (string)type.Evaluate(referenceApiExpression); return(new SimpleTypeReference(api)); } } public partial class ReferenceTypeReference { public static new ReferenceTypeReference Create (XmlReader referenceTo) { if (referenceTo == null) throw new ArgumentException("refernceTo"); referenceTo.Read(); TypeReference referedToType = TypeReference.Create(referenceTo); return (new ReferenceTypeReference(referedToType)); } public static new ReferenceTypeReference Create (XPathNavigator referenceTo) { XPathNavigator referedToNode = referenceTo.SelectSingleNode("*[1]"); TypeReference referedToType = TypeReference.Create(referedToNode); return (new ReferenceTypeReference(referedToType)); } } public partial class PointerTypeReference { public static new PointerTypeReference Create (XmlReader pointerTo) { if (pointerTo == null) throw new ArgumentNullException("pointerTo"); pointerTo.Read(); TypeReference pointedToType = TypeReference.Create(pointerTo); return (new PointerTypeReference(pointedToType)); } public static new PointerTypeReference Create (XPathNavigator pointerTo) { XPathNavigator pointedToNode = pointerTo.SelectSingleNode("*[1]"); TypeReference pointedToType = TypeReference.Create(pointedToNode); return (new PointerTypeReference(pointedToType)); } } public partial class ArrayTypeReference { public static new ArrayTypeReference Create (XmlReader arrayOf) { if (arrayOf == null) throw new ArgumentNullException("arrayOf"); int rank = 1; string rankText = arrayOf.GetAttribute("rank"); if (!String.IsNullOrEmpty(rankText)) rank = Convert.ToInt32(rankText); arrayOf.Read(); TypeReference elementType = TypeReference.Create(arrayOf); return (new ArrayTypeReference(elementType, rank)); } } }