Exemple #1
0
        private static IEnumerable <IAdapterCreator> GetAdapterCreators(DomNode node, Type type)
        {
            DomNodeType nodeType = node.Type;

            if (nodeType.m_adapterCreatorCache == null)
            {
                nodeType.m_adapterCreatorCache = new Dictionary <Type, IEnumerable <IAdapterCreator> >();
            }

            IEnumerable <IAdapterCreator> adapterCreators;

            if (!nodeType.m_adapterCreatorCache.TryGetValue(type, out adapterCreators))
            {
                // build an array of adapter creators that can adapt the node
                List <IAdapterCreator> creators = new List <IAdapterCreator>();
                while (nodeType != null)
                {
                    if (nodeType.m_adapterCreators != null)
                    {
                        foreach (IAdapterCreator creator in nodeType.m_adapterCreators)
                        {
                            if (creator.CanAdapt(node, type))
                            {
                                creators.Add(creator);
                            }
                        }
                    }

                    nodeType = nodeType.BaseType;
                }

                // for empty arrays, use global instance
                adapterCreators = (creators.Count > 0) ? creators.ToArray() : EmptyEnumerable <IAdapterCreator> .Instance;

                // cache the result for subsequent searches
                node.Type.m_adapterCreatorCache.Add(type, adapterCreators);
            }

            return(adapterCreators);
        }
Exemple #2
0
        // try to obtain enumeration values from xml annotations
        // Legacy ATF 2.8 example:
        //  <xs:simpleType name="EmotionType">
        //    <xs:annotation>
        //        <xs:appinfo>
        //            <scea.dom.editors.enumeration name="Adequate" displayName="Adequate, good enough"/>
        //            <scea.dom.editors.enumeration name="Capable" displayName="Capable, you betcha!"/>
        //            <scea.dom.editors.enumeration name="Enthusiastic" />
        //        </xs:appinfo>
        //    </xs:annotation>
        //    <xs:restriction base="xs:string">
        //        <xs:enumeration value="Adequate"/>
        //        <xs:enumeration value="Capable"/>
        //        <xs:enumeration value="Enthusiastic"/>
        //     </xs:restriction>
        //  </xs:simpleType>
        private static string[] TryGetEnumeration(DomNodeType domNodeType, XmlNode annotation)
        {
            string[]     enumeration        = null;
            XmlAttribute targetDomAttribute = annotation.Attributes[AnnotationsNameAttribute];

            if (targetDomAttribute != null)
            {
                var domObjectAttribute = domNodeType.GetAttributeInfo(targetDomAttribute.Value);
                if (domObjectAttribute != null)
                {
                    var attributeType = domObjectAttribute.Type;
                    var xmlAnnotation = attributeType.GetTag <IEnumerable <XmlNode> >();
                    if (xmlAnnotation != null)
                    {
                        List <string> enumerationList = new List <string>();
                        foreach (XmlNode enumAnnotation in xmlAnnotation)
                        {
                            if (enumAnnotation.Name == AnnotationsLegacyEnumeration)
                            {
                                string  name        = enumAnnotation.Attributes[AnnotationsNameAttribute].Value;
                                XmlNode displayNode =
                                    enumAnnotation.Attributes.GetNamedItem(AnnotationsDisplayNameAttribute);
                                if (displayNode != null)
                                {
                                    enumerationList.Add(name + "==" + displayNode.Value);
                                }
                                else
                                {
                                    enumerationList.Add(name);
                                }
                            }
                            enumeration = enumerationList.ToArray();
                        }
                    }
                }
            }

            return(enumeration);
        }
Exemple #3
0
        /// <summary>
        /// Checks all property descriptors of adapter type and when an ObservableDomPropertyAttribute
        /// is present on the descriptor, finds the AttributeInfo with matching name on the DomNodeType,
        /// and sets PropertyChangedEventArgs tags to match</summary>
        /// <param name="adapterType">Type of adapter</param>
        /// <param name="nodeType">DomNode type</param>
        private static void AddAttributeTags(Type adapterType, DomNodeType nodeType)
        {
            foreach (var property in adapterType.GetProperties())
            {
                object[] attributes = property.GetCustomAttributes(typeof(ObservableDomPropertyAttribute), true);
                if (attributes != null && attributes.Length > 0)
                {
                    var eventArgs = new PropertyChangedEventArgs(property.Name);

                    foreach (var attribute in attributes)
                    {
                        var attributeName = ((ObservableDomPropertyAttribute)attribute).AttributeName;
                        var currentType   = nodeType;
                        var attributeInfo = currentType.GetAttributeInfo(attributeName);

                        Requires.NotNull(attributeInfo, "Unrecognized attribute name in ObservableDomPropertyAttribute");

                        // Each base type may have duplicate attributeInfo if it is an inherited attribute
                        // We need to set the tag on each base attributeInfo so that the PropertyChanged event
                        // will be raised even if the attribute is set on a base type
                        while (currentType != DomNodeType.BaseOfAllTypes && attributeInfo != null)
                        {
                            var args = attributeInfo.GetTagLocal <PropertyChangedEventArgsCollection>();
                            if (args == null)
                            {
                                args = new PropertyChangedEventArgsCollection();
                                attributeInfo.SetTag(args);
                            }

                            args.Add(eventArgs);

                            currentType   = currentType.BaseType;
                            attributeInfo = currentType.GetAttributeInfo(attributeName);
                        }
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Constructor</summary>
        /// <param name="name">Name of node type</param>
        /// <param name="baseType">Base node type. 'null' equates to DomNodeType.BaseOfAllTypes</param>
        /// <param name="attributes">Attributes for node type, or null</param>
        /// <param name="children">Children for node type, or null</param>
        /// <param name="extensions">Extensions for node type, or null</param>
        public DomNodeType(
            string name,
            DomNodeType baseType,
            IEnumerable <AttributeInfo> attributes,
            IEnumerable <ChildInfo> children,
            IEnumerable <ExtensionInfo> extensions)
            : base(name)
        {
            SetBaseType(baseType);

            if (attributes != null)
            {
                m_definitions.Attributes.AddRange(attributes);
            }
            if (children != null)
            {
                m_definitions.Children.AddRange(children);
            }
            if (extensions != null)
            {
                m_definitions.Extensions.AddRange(extensions);
            }
        }
Exemple #5
0
 /// <summary>
 /// Constructor</summary>
 /// <param name="name">Name of node type</param>
 /// <param name="baseType">Base node type. 'null' equates to DomNodeType.BaseOfAllTypes</param>
 /// <param name="metadata">Zero or more AttributeInfo, ChildInfo, or ExtensionInfo objects</param>
 public DomNodeType(
     string name,
     DomNodeType baseType,
     params FieldMetadata[] metadata)
     : base(name)
 {
     SetBaseType(baseType);
     foreach (FieldMetadata info in metadata)
     {
         if (info is AttributeInfo)
         {
             m_definitions.Attributes.Add((AttributeInfo)info);
         }
         else if (info is ChildInfo)
         {
             m_definitions.Children.Add((ChildInfo)info);
         }
         else if (info is ExtensionInfo)
         {
             m_definitions.Extensions.Add((ExtensionInfo)info);
         }
     }
 }
Exemple #6
0
        /// <summary>
        /// Gets the descendant metadata corresponding to the given path</summary>
        /// <param name="path">Path to descendant, with ':' as separator</param>
        /// <returns>Descendant metadata corresponding to the given path</returns>
        public ChildInfo GetDescendantInfo(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            ChildInfo   result = null;
            DomNodeType type   = this;

            string[] segments = path.Split(':');
            foreach (string segment in segments)
            {
                result = type.GetChildInfo(segment);
                if (result == null)
                {
                    break;
                }
                type = result.Type;
            }

            return(result);
        }
 /// <summary>
 /// Adds a node type to the ones defined by the schema</summary>
 /// <remarks>If the node type is already defined, it is overwritten</remarks>
 /// <param name="name">Name of node type</param>
 /// <param name="type">New node type</param>
 public void AddNodeType(string name, DomNodeType type)
 {
     m_nodeTypeCollection.AddNodeType(name, type);
 }
 /// <summary>
 /// Gets all node types derived from base type</summary>
 /// <param name="baseType">Base type</param>
 /// <remarks>Base type is not returned in the array.</remarks>
 /// <returns>Enumeration of all node types derived from baseType</returns>
 public IEnumerable <DomNodeType> GetNodeTypes(DomNodeType baseType)
 {
     return(m_nodeTypeCollection.GetNodeTypes(baseType));
 }
Exemple #9
0
        private static PropertyDescriptor GetDescriptor(
            DomNodeType type,
            XmlNode annotation,
            string name,
            string[] segments)
        {
            PropertyDescriptor desc = null;
            // Get mandatory display name
            XmlAttribute displayNameAttr = annotation.Attributes["displayName"];

            if (displayNameAttr != null)
            {
                if (string.IsNullOrEmpty(name))
                {
                    throw new AnnotationException(string.Format(
                                                      "Required name attribute is null or empty.\r\nType: {0}\r\nElement: {1}",
                                                      type.Name, annotation.Name));
                }

                string displayName = displayNameAttr.Value;
                if (string.IsNullOrEmpty(displayName))
                {
                    displayName = name;
                }

                // Get optional annotations
                string        category      = GetAnnotation(annotation, "category");
                string        description   = GetAnnotation(annotation, "description");
                bool          readOnly      = GetAnnotation(annotation, "readOnly") == "true";
                object        editor        = CreateObject <object>(type, annotation, "editor");
                TypeConverter typeConverter = CreateObject <TypeConverter>(type, annotation, "converter");

                if (annotation.Name == "scea.dom.editors.attribute")
                {
                    // Attribute annotation
                    if (segments == null)
                    {
                        throw new AnnotationException("Unnamed attribute");
                    }

                    if (segments.Length == 1) // local attribute
                    {
                        AttributeInfo metaAttr = type.GetAttributeInfo(name);
                        if (metaAttr == null)
                        {
                            throw new AnnotationException("Type doesn't have this attribute");
                        }

                        desc = new AttributePropertyDescriptor(
                            displayName, metaAttr,
                            category, description, readOnly, editor, typeConverter);
                    }
                    else // descendant attribute
                    {
                        ChildInfo[]   metaElements = GetPath(type, segments, segments.Length - 1);
                        DomNodeType   childType    = metaElements[segments.Length - 2].Type;
                        AttributeInfo metaAttr     = childType.GetAttributeInfo(segments[segments.Length - 1]);
                        if (metaAttr == null)
                        {
                            throw new AnnotationException("Descendant type doesn't have this attribute");
                        }

                        desc = new ChildAttributePropertyDescriptor(
                            displayName, metaAttr, metaElements,
                            category, description, readOnly, editor, typeConverter);
                    }
                }
                else if (annotation.Name == "scea.dom.editors.child")
                {
                    // Child value annotation
                    ChildInfo element = type.GetChildInfo(name);
                    if (element == null)
                    {
                        throw new AnnotationException("Type doesn't have this element");
                    }

                    desc = new ChildPropertyDescriptor(
                        displayName, element,
                        category, description, readOnly, editor, typeConverter);
                }
            }

            return(desc);
        }
Exemple #10
0
        private void WalkParticle(XmlSchemaParticle particle, DomNodeType nodeType)
        {
            XmlSchemaElement element = particle as XmlSchemaElement;

            if (element != null)
            {
                XmlSchemaSimpleType simpleType = element.ElementSchemaType as XmlSchemaSimpleType;
                if (simpleType != null &&
                    element.MaxOccurs == 1)
                {
                    XmlAttributeType attributeType = GetAttributeType(simpleType);
                    string           fieldName     = GetFieldName(element.QualifiedName);
                    XmlAttributeInfo attributeInfo = new XmlAttributeInfo(fieldName, attributeType);

                    nodeType.Define(attributeInfo);
                    m_annotations.Add(attributeInfo, GetAnnotation(element));

                    attributeInfo.IsElement = true;

                    if (element.DefaultValue != null)
                    {
                        if (element.FixedValue != null)
                        {
                            throw new InvalidOperationException(string.Format("Schema element {0} cannot have both a default value and a fixed value", element.QualifiedName));
                        }
                        attributeInfo.DefaultValue = attributeType.Convert(element.DefaultValue);
                    }
                    else if (element.FixedValue != null)
                    {
                        attributeInfo.DefaultValue = attributeType.Convert(element.FixedValue);
                    }
                }
                else
                {
                    DomNodeType childNodeType = null;
                    if (simpleType != null)
                    {
                        bool firstTime;
                        childNodeType = WrapSimpleType(simpleType, out firstTime);

                        // The collada.xsd's ListOfUInts element breaks the generated Schema.cs file otherwise.
                        if (firstTime)
                        {
                            // Add the value attribute
                            XmlAttributeType valueAttributeType = GetAttributeType(simpleType);
                            var valueAttributeInfo = new XmlAttributeInfo(string.Empty, valueAttributeType);
                            childNodeType.Define(valueAttributeInfo);
                        }
                    }
                    else
                    {
                        XmlSchemaComplexType complexType = element.ElementSchemaType as XmlSchemaComplexType;
                        if (complexType != null)
                        {
                            childNodeType = GetNodeType(complexType, element);
                        }
                    }

                    if (childNodeType != null)
                    {
                        int minOccurs = (int)Math.Min(element.MinOccurs, Int32.MaxValue);
                        int maxOccurs = (int)Math.Min(element.MaxOccurs, Int32.MaxValue);

                        if (particle.Parent is XmlSchemaChoice)
                        {
                            var parent = (XmlSchemaChoice)particle.Parent;
                            if (parent.MinOccurs != 1)
                            {
                                minOccurs = (int)Math.Min(Math.Max(element.MinOccurs, parent.MinOccurs), Int32.MaxValue);
                            }
                            if (parent.MaxOccurs != 1)
                            {
                                maxOccurs = (int)Math.Min(Math.Max(element.MaxOccurs, parent.MaxOccurs), Int32.MaxValue);
                            }
                        }
                        else if (particle.Parent is XmlSchemaSequence)
                        {
                            var parent = (XmlSchemaSequence)particle.Parent;
                            if (parent.MinOccurs != 1)
                            {
                                minOccurs = (int)Math.Min(Math.Max(element.MinOccurs, parent.MinOccurs), Int32.MaxValue);
                            }
                            if (parent.MaxOccurs != 1)
                            {
                                maxOccurs = (int)Math.Min(Math.Max(element.MaxOccurs, parent.MaxOccurs), Int32.MaxValue);
                            }
                        }

                        ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), childNodeType, maxOccurs > 1);

                        if ((minOccurs > 0 || maxOccurs < Int32.MaxValue) &&
                            minOccurs <= maxOccurs)
                        {
                            childInfo.AddRule(new ChildCountRule(minOccurs, maxOccurs));
                        }

                        // Check for substitution groups
                        if (!element.RefName.IsEmpty)
                        {
                            m_refElements.Add(childInfo, element.RefName);
                        }

                        nodeType.Define(childInfo);
                        m_annotations.Add(childInfo, GetAnnotation(element));
                    }
                }
            }
            else
            {
                XmlSchemaGroupBase grp = particle as XmlSchemaSequence;
                if (grp == null)
                {
                    grp = particle as XmlSchemaChoice;
                }
                if (grp == null)
                {
                    grp = particle as XmlSchemaAll;
                }

                if (grp != null)
                {
                    foreach (XmlSchemaParticle subParticle in grp.Items)
                    {
                        WalkParticle(subParticle, nodeType);
                    }
                }
            }
        }
Exemple #11
0
        /// <summary>
        /// Converts schemas to NodeTypes, AttributeTypes, and root elements</summary>
        /// <param name="schemaSet">Schemas to register</param>
        public void Load(XmlSchemaSet schemaSet)
        {
            if (!schemaSet.IsCompiled)
            {
                schemaSet.Compile();
            }

            System.Collections.ICollection schemas = schemaSet.Schemas();
            foreach (XmlSchema schema in schemas)
            {
                string targetNamespace = schema.TargetNamespace;
                if (string.IsNullOrEmpty(targetNamespace))
                {
                    throw new InvalidOperationException("Schema has no target namespace");
                }

                // only register the schema once; targetNamespaces must be globally unique
                if (!m_typeCollections.ContainsKey(targetNamespace))
                {
                    XmlQualifiedName[]      nameSpaces     = schema.Namespaces.ToArray();
                    XmlSchemaTypeCollection typeCollection = new XmlSchemaTypeCollection(nameSpaces, targetNamespace, this);
                    m_typeCollections.Add(targetNamespace, typeCollection);
                }
            }

            try
            {
                m_annotations     = new Dictionary <NamedMetadata, IList <XmlNode> >();
                m_typeNameSet     = new HashSet <string>();
                m_localElementSet = new Dictionary <XmlSchemaElement, XmlQualifiedName>();
                // collect global element & type names so we do not generate local type names that collides with those
                foreach (XmlSchemaElement element in schemaSet.GlobalElements.Values)
                {
                    m_typeNameSet.Add(element.QualifiedName.Name);
                }

                foreach (XmlSchemaType type in schemaSet.GlobalTypes.Values)
                {
                    if (type is XmlSchemaComplexType)
                    {
                        m_typeNameSet.Add(type.Name);
                    }
                }

                var substitutionGroups = new Multimap <XmlQualifiedName, ChildInfo>();

                // Get types reachable from global elements
                foreach (XmlSchemaElement element in schemaSet.GlobalElements.Values)
                {
                    XmlSchemaType type      = element.ElementSchemaType;
                    DomNodeType   nodeType  = GetNodeType(type, element);
                    ChildInfo     childInfo = new ChildInfo(GetFieldName(element.QualifiedName), nodeType);
                    m_annotations.Add(childInfo, GetAnnotation(element));

                    // Keep list of substitution groups
                    if (!element.SubstitutionGroup.IsEmpty)
                    {
                        substitutionGroups.Add(element.SubstitutionGroup, childInfo);
                    }

                    // only add root elements once; root element names must be globally unique
                    string name = element.QualifiedName.ToString();
                    if (!m_rootElements.ContainsKey(name))
                    {
                        m_rootElements[name] = childInfo;
                    }
                }

                // Get global complex type definitions
                foreach (XmlSchemaType type in schemaSet.GlobalTypes.Values)
                {
                    if (type is XmlSchemaComplexType)
                    {
                        GetNodeType(type, null);
                    }
                }

                // Parse substitution groups
                foreach (var kvp in m_refElements)
                {
                    XmlQualifiedName refName   = kvp.Value;
                    ChildInfo        childInfo = kvp.Key;

                    var substitutions = CreateSubstitutions(substitutionGroups, refName).ToArray();
                    if (substitutions.Length > 0)
                    {
                        childInfo.AddRule(new SubstitutionGroupChildRule(substitutions));
                    }
                }

                // Preserve annotation from any types that were redefined
                foreach (XmlSchema schema in schemas)
                {
                    foreach (XmlSchemaObject schemaInclude in schema.Includes)
                    {
                        XmlSchemaRedefine schemaRedefine = schemaInclude as XmlSchemaRedefine;
                        if (schemaRedefine != null)
                        {
                            MergeRedefinedTypeAnnotations(schemaRedefine);
                        }
                    }
                }

                // Sort DomNodeTypes, so that base types are always before derived types
                // Bucket sort by depth in the inheritance tree
                // Time: O(n * d) with n = number of DomNodeTypes, d = depth of inheritance tree
                var sortedTypes = new List <List <DomNodeType> >();
                foreach (DomNodeType type in GetNodeTypes())
                {
                    // Get inheritance depth of current type
                    int         depth   = 0;
                    DomNodeType curType = type;
                    while (curType != null && curType != DomNodeType.BaseOfAllTypes)
                    {
                        depth++;
                        curType = curType.BaseType;
                    }

                    // We don't need to merge annotations for BaseAllTypes (level 0)
                    // and its immediate child types (level 1)
                    int idx = depth - 2;
                    if (idx >= 0)
                    {
                        while (sortedTypes.Count <= idx)
                        {
                            sortedTypes.Add(new List <DomNodeType>());
                        }
                        sortedTypes[idx].Add(type);
                    }
                }

                // Merge type annotations with base type annotations
                foreach (var list in sortedTypes)
                {
                    foreach (DomNodeType type in list)
                    {
                        if (type.BaseType != null && type.BaseType != DomNodeType.BaseOfAllTypes)
                        {
                            IList <XmlNode> baseAnnotations;
                            IList <XmlNode> annotations;
                            if (m_annotations.TryGetValue(type.BaseType, out baseAnnotations) &&
                                m_annotations.TryGetValue(type, out annotations))
                            {
                                // Call protected virtual merge method - allowing clients to define if & how annotations are being merged
                                IEnumerable <XmlNode> mergedAnnotations = MergeInheritedTypeAnnotations(baseAnnotations, annotations);
                                m_annotations[type] = mergedAnnotations as IList <XmlNode> ?? mergedAnnotations.ToList();
                            }
                        }
                    }
                }

                // Call before the DomNodeTypes are frozen. Note that iterating through Attributes or
                //  calling 'SetIdAttribute' freezes the attributes on DomNodeType.
                OnSchemaSetLoaded(schemaSet);

                // Set up ID attributes where xs:ID has been specified
                foreach (DomNodeType nodeType in GetNodeTypes())
                {
                    foreach (var attribute in nodeType.Attributes.OfType <XmlAttributeInfo>())
                    {
                        if (((XmlAttributeType)attribute.Type).XmlTypeCode == XmlTypeCode.Id)
                        {
                            nodeType.SetIdAttribute(attribute.Name);
                        }
                    }
                }

                // Attach annotation as metadata to the associated type so that other classes can find it
                foreach (var keyValuePair in m_annotations)
                {
                    if (keyValuePair.Value.Count > 0)
                    {
                        keyValuePair.Key.SetTag <IEnumerable <XmlNode> >(keyValuePair.Value);
                    }
                }
                ParseAnnotations(schemaSet, m_annotations);

                // Call this after the ID attributes have been set and after the DomNodeTypes are frozen.
                OnDomNodeTypesFrozen(schemaSet);
            }
            finally
            {
                m_annotations     = null;
                m_typeNameSet     = null;
                m_localElementSet = null;
            }
        }
        /// <summary>
        /// Reads the node specified by the child metadata</summary>
        /// <param name="nodeInfo">Child metadata for node</param>
        /// <param name="reader">XML reader</param>
        /// <returns>DomNode specified by the child metadata</returns>
        protected virtual DomNode ReadElement(ChildInfo nodeInfo, XmlReader reader)
        {
            // handle polymorphism, if necessary
            DomNodeType type   = GetChildType(nodeInfo.Type, reader);
            int         index  = type.Name.LastIndexOf(':');
            string      typeNS = type.Name.Substring(0, index);

            DomNode node = new DomNode(type, nodeInfo);

            // read attributes
            while (reader.MoveToNextAttribute())
            {
                if (reader.Prefix == string.Empty ||
                    reader.LookupNamespace(reader.Prefix) == typeNS)
                {
                    AttributeInfo attributeInfo = type.GetAttributeInfo(reader.LocalName);
                    if (attributeInfo != null)
                    {
                        string valueString = reader.Value;
                        if (attributeInfo.Type.Type == AttributeTypes.Reference)
                        {
                            // save reference so it can be resolved after all nodes have been read
                            m_nodeReferences.Add(new XmlNodeReference(node, attributeInfo, valueString));
                        }
                        else
                        {
                            object value = attributeInfo.Type.Convert(valueString);
                            node.SetAttribute(attributeInfo, value);
                        }
                    }
                }
            }

            // add node to map if it has an id
            if (node.Type.IdAttribute != null)
            {
                string id = node.GetId();
                if (!string.IsNullOrEmpty(id))
                {
                    m_nodeDictionary[id] = node; // don't Add, in case there are multiple DomNodes with the same id
                }
            }

            reader.MoveToElement();

            if (!reader.IsEmptyElement)
            {
                // read child elements
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        // look up metadata for this element
                        ChildInfo childInfo = type.GetChildInfo(reader.LocalName);
                        if (childInfo != null)
                        {
                            DomNode childObject = ReadElement(childInfo, reader);
                            // at this point, child is a fully populated sub-tree

                            if (childInfo.IsList)
                            {
                                node.GetChildList(childInfo).Add(childObject);
                            }
                            else
                            {
                                node.SetChild(childInfo, childObject);
                            }
                        }
                        else
                        {
                            // try reading as an attribute
                            AttributeInfo attributeInfo = type.GetAttributeInfo(reader.LocalName);
                            if (attributeInfo != null)
                            {
                                reader.MoveToElement();

                                if (!reader.IsEmptyElement)
                                {
                                    // read element text
                                    while (reader.Read())
                                    {
                                        if (reader.NodeType == XmlNodeType.Text)
                                        {
                                            object value = attributeInfo.Type.Convert(reader.Value);
                                            node.SetAttribute(attributeInfo, value);
                                            // skip child elements, as this is an attribute value
                                            reader.Skip();
                                            break;
                                        }
                                        if (reader.NodeType == XmlNodeType.EndElement)
                                        {
                                            break;
                                        }
                                    }

                                    reader.MoveToContent();
                                }
                            }
                            else
                            {
                                // skip unrecognized element
                                reader.Skip();
                                // if that takes us to the end of the enclosing element, break
                                if (reader.NodeType == XmlNodeType.EndElement)
                                {
                                    break;
                                }
                            }
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.Text)
                    {
                        AttributeInfo attributeInfo = type.GetAttributeInfo(string.Empty);
                        if (attributeInfo != null)
                        {
                            object value = attributeInfo.Type.Convert(reader.Value);
                            node.SetAttribute(attributeInfo, value);
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        break;
                    }
                }
            }

            reader.MoveToContent();

            return(node);
        }
 /// <summary>
 /// Constructor</summary>
 /// <param name="name">Field name</param>
 /// <param name="type">Field type</param>
 public ChildInfo(
     string name,
     DomNodeType type)
     : this(name, type, false)
 {
 }
Exemple #14
0
 /// <summary>
 /// Gets a derived node type, given a base type, namespace, and type name</summary>
 /// <param name="baseType">Base node type</param>
 /// <param name="ns">Type namespace</param>
 /// <param name="typeName">Type name</param>
 /// <returns>Derived node type</returns>
 protected virtual DomNodeType GetDerivedType(DomNodeType baseType, string ns, string typeName)
 {
     return(m_typeLoader.GetNodeType(ns + ":" + typeName));
 }
Exemple #15
0
        /// <summary>
        /// Reads the node specified by the child metadata</summary>
        /// <param name="nodeInfo">Child metadata for node</param>
        /// <param name="reader">XML reader</param>
        /// <returns>DomNode specified by the child metadata</returns>
        protected virtual DomNode ReadElement(ChildInfo nodeInfo, XmlReader reader)
        {
            // handle polymorphism, if necessary
            DomNodeType type = null;
            var         substitutionGroupRule = nodeInfo.Rules.OfType <SubstitutionGroupChildRule>().FirstOrDefault();

            if (substitutionGroupRule != null)
            {
                foreach (var sub in substitutionGroupRule.Substitutions)
                {
                    if (sub.Name == reader.LocalName)
                    {
                        type = sub.Type;
                        break;
                    }
                }

                if (type == null)
                {
                    throw new InvalidOperationException("Could not match substitution group for child " + nodeInfo.Name);
                }
            }
            else
            {
                type = GetChildType(nodeInfo.Type, reader);
            }

            int    index  = type.Name.LastIndexOf(':');
            string typeNS = type.Name.Substring(0, index);

            DomNode node = new DomNode(type, nodeInfo);

            // read attributes
            while (reader.MoveToNextAttribute())
            {
                if (reader.Prefix == string.Empty ||
                    reader.LookupNamespace(reader.Prefix) == typeNS)
                {
                    AttributeInfo attributeInfo = type.GetAttributeInfo(reader.LocalName);
                    if (attributeInfo != null)
                    {
                        ReadAttribute(node, attributeInfo, reader.Value);
                    }
                }
            }

            // add node to map if it has an id
            if (node.Type.IdAttribute != null)
            {
                string id = node.GetId();
                if (!string.IsNullOrEmpty(id))
                {
                    m_nodeDictionary[id] = node; // don't Add, in case there are multiple DomNodes with the same id
                }
            }

            reader.MoveToElement();

            if (!reader.IsEmptyElement)
            {
                // read child elements
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        // look up metadata for this element
                        ChildInfo childInfo = type.GetChildInfo(reader.LocalName);
                        if (childInfo == null)
                        {
                            // Try and get substitution group
                            childInfo = GetSubsitutionGroup(type, reader.LocalName);
                        }

                        if (childInfo != null)
                        {
                            DomNode childNode = ReadElement(childInfo, reader);
                            if (childNode != null)
                            {
                                // childNode is fully populated sub-tree
                                if (childInfo.IsList)
                                {
                                    node.GetChildList(childInfo).Add(childNode);
                                }
                                else
                                {
                                    node.SetChild(childInfo, childNode);
                                }
                            }
                        }
                        else
                        {
                            // try reading as an attribute
                            AttributeInfo attributeInfo = type.GetAttributeInfo(reader.LocalName);
                            if (attributeInfo != null)
                            {
                                reader.MoveToElement();

                                if (!reader.IsEmptyElement)
                                {
                                    // read element text
                                    while (reader.Read())
                                    {
                                        if (reader.NodeType == XmlNodeType.Text)
                                        {
                                            ReadAttribute(node, attributeInfo, reader.Value);
                                            // skip child elements, as this is an attribute value
                                            reader.Skip();
                                            break;
                                        }
                                        if (reader.NodeType == XmlNodeType.EndElement)
                                        {
                                            break;
                                        }
                                    }

                                    reader.MoveToContent();
                                }
                            }
                            else
                            {
                                // skip unrecognized element
                                reader.Skip();
                                // if that takes us to the end of the enclosing element, break
                                if (reader.NodeType == XmlNodeType.EndElement)
                                {
                                    break;
                                }
                            }
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.Text)
                    {
                        AttributeInfo attributeInfo = type.GetAttributeInfo(string.Empty);
                        if (attributeInfo != null)
                        {
                            ReadAttribute(node, attributeInfo, reader.Value);
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        break;
                    }
                }
            }

            reader.MoveToContent();

            return(node);
        }
Exemple #16
0
        /// <summary>
        /// Writes the attributes corresponding to the node</summary>
        /// <param name="node">DomNode to write</param>
        /// <param name="writer">The XML writer. See <see cref="T:System.Xml.XmlWriter"/></param>
        protected virtual void WriteAttributes(DomNode node, XmlWriter writer)
        {
            // write type name if this is a polymorphic type
            // if this node is substitution group element then ignore type name
            // unless it is a root node (for root node, substitution groups are ignored)
            DomNodeType type = node.Type;

            if (node.ChildInfo.Type != type &&
                (IsRootNode(node) || node.ChildInfo.Rules.OfType <SubstitutionGroupChildRule>().FirstOrDefault() == null))
            {
                string name  = type.Name;
                int    index = name.LastIndexOf(':');
                if (index >= 0)
                {
                    string typeName   = name.Substring(index + 1, type.Name.Length - index - 1);
                    string typeNS     = name.Substring(0, index);
                    string typePrefix = writer.LookupPrefix(typeNS);
                    if (typePrefix == null)
                    {
                        typePrefix = GeneratePrefix(typeNS);
                        writer.WriteAttributeString("xmlns", typePrefix, null, typeNS);
                    }

                    name = typeName;
                    if (typePrefix != string.Empty)
                    {
                        name = typePrefix + ":" + typeName;
                    }
                }

                writer.WriteAttributeString("xsi", "type", XmlSchema.InstanceNamespace, name);
            }

            // write attributes
            AttributeInfo valueAttribute       = null;
            var           attributesAsElements = new List <AttributeInfo>();

            foreach (AttributeInfo attributeInfo in type.Attributes)
            {
                // if attribute is not the default, write it
                if (ShouldWriteAttribute(node, attributeInfo))
                {
                    if (attributeInfo.Name == string.Empty)
                    {
                        valueAttribute = attributeInfo;
                    }
                    else
                    {
                        if (PreserveSimpleElements)
                        {
                            var xmlAttributeInfo = attributeInfo as XmlAttributeInfo;
                            if (xmlAttributeInfo != null &&
                                xmlAttributeInfo.IsElement)
                            {
                                attributesAsElements.Add(xmlAttributeInfo);
                                continue;
                            }
                        }

                        WriteXmlAttribute(node, attributeInfo, writer);
                    }
                }
            }

            // write value if not the default
            if (valueAttribute != null)
            {
                string valueString = Convert(node, valueAttribute);
                writer.WriteString(valueString);
            }

            // write DOM attributes that were originally XML elements of a simple type
            foreach (AttributeInfo info in attributesAsElements)
            {
                writer.WriteStartElement(m_elementPrefix, info.Name, m_elementNS);
                string valueString = Convert(node, info);
                writer.WriteString(valueString);
                writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Writes the element corresponding to the DomNode</summary>
        /// <param name="node">DomNode to write</param>
        protected virtual void WriteElement(DomNode node, XmlWriter writer)
        {
            string elementNS = m_typeCollection.TargetNamespace;
            int    index     = node.ChildInfo.Name.LastIndexOf(':');

            if (index >= 0)
            {
                elementNS = node.ChildInfo.Name.Substring(0, index);
            }

            string elementPrefix = string.Empty;

            // is this the root DomNode?
            if (node.Parent == null)
            {
                elementPrefix = m_typeCollection.GetPrefix(elementNS);
                if (elementPrefix == null)
                {
                    elementPrefix = GeneratePrefix(elementNS);
                }

                writer.WriteStartElement(elementPrefix, node.ChildInfo.Name, elementNS);

                // define the xsi namespace
                writer.WriteAttributeString("xmlns", "xsi", null, XmlSchema.InstanceNamespace);

                // define schema namespaces
                foreach (XmlQualifiedName name in m_typeCollection.Namespaces)
                {
                    if (name.Name != elementPrefix) // don't redefine the element namespace
                    {
                        writer.WriteAttributeString("xmlns", name.Name, null, name.Namespace);
                    }
                }
            }
            else
            {
                // not the root, so all schema namespaces have been defined
                elementPrefix = writer.LookupPrefix(elementNS);
                if (elementPrefix == null)
                {
                    elementPrefix = GeneratePrefix(elementNS);
                }

                writer.WriteStartElement(elementPrefix, node.ChildInfo.Name, elementNS);
            }

            // write type name if this is a polymorphic type
            DomNodeType type = node.Type;

            if (node.ChildInfo.Type != type)
            {
                string name = type.Name;
                index = name.LastIndexOf(':');
                if (index >= 0)
                {
                    string typeName   = name.Substring(index + 1, type.Name.Length - index - 1);
                    string typeNS     = name.Substring(0, index);
                    string typePrefix = writer.LookupPrefix(typeNS);
                    if (typePrefix == null)
                    {
                        typePrefix = GeneratePrefix(typeNS);
                        writer.WriteAttributeString("xmlns", typePrefix, null, typeNS);
                    }

                    name = typeName;
                    if (typePrefix != string.Empty)
                    {
                        name = typePrefix + ":" + typeName;
                    }
                }

                writer.WriteAttributeString("xsi", "type", XmlSchema.InstanceNamespace, name);
            }

            // write attributes
            AttributeInfo valueAttribute = null;

            foreach (AttributeInfo attributeInfo in type.Attributes)
            {
                // if attribute is required, or not the default, write it
                if (/*attributeInfo.Required ||*/ !node.IsAttributeDefault(attributeInfo))
                {
                    if (attributeInfo.Name == string.Empty)
                    {
                        valueAttribute = attributeInfo;
                    }
                    else
                    {
                        object value       = node.GetAttribute(attributeInfo);
                        string valueString = null;
                        if (attributeInfo.Type.Type == AttributeTypes.Reference)
                        {
                            // if reference is a valid node, convert to string
                            DomNode refNode = value as DomNode;
                            if (refNode != null)
                            {
                                valueString = GetNodeReferenceString(refNode, m_root, m_uri);
                            }
                        }
                        if (valueString == null)
                        {
                            valueString = attributeInfo.Type.Convert(value);
                        }

                        writer.WriteAttributeString(attributeInfo.Name, valueString);
                    }
                }
            }

            // write value if not the default
            if (valueAttribute != null)
            {
                object value = node.GetAttribute(valueAttribute);
                writer.WriteString(valueAttribute.Type.Convert(value));
            }

            // write child elements
            foreach (ChildInfo childInfo in type.Children)
            {
                if (childInfo.IsList)
                {
                    foreach (DomNode child in node.GetChildList(childInfo))
                    {
                        WriteElement(child, writer);
                    }
                }
                else
                {
                    DomNode child = node.GetChild(childInfo);
                    if (child != null)
                    {
                        WriteElement(child, writer);
                    }
                }
            }

            writer.WriteEndElement();
        }
Exemple #18
0
        private DomNodeType GetNodeType(XmlSchemaComplexType complexType, XmlSchemaElement element)
        {
            // get type name
            XmlQualifiedName name = complexType.QualifiedName;

            if (name.IsEmpty) // local type
            {
                name = GetLocalTypeName(element);
            }

            string      typeName = name.ToString();
            DomNodeType nodeType;

            if (!m_nodeTypes.TryGetValue(typeName, out nodeType))
            {
                // build a new complex type and add it to the dictionary
                nodeType = new DomNodeType(typeName);
                m_nodeTypes.Add(typeName, nodeType);

                m_annotations.Add(nodeType, GetAnnotation(complexType));

                DomNodeType      baseType  = null;
                XmlAttributeType valueType = null;

                XmlSchemaComplexType complexBaseType = GetBaseType(complexType);
                if (complexBaseType != null)
                {
                    baseType = GetNodeType(complexBaseType, null);
                }

                XmlSchemaSimpleType simpleBase = complexType.BaseXmlSchemaType as XmlSchemaSimpleType;
                if (simpleBase != null)
                {
                    valueType = GetAttributeType(simpleBase);
                }
                else if (complexType.IsMixed)
                {
                    valueType = s_mixedTextFieldSimpleType;
                }

                WalkParticle(complexType.ContentTypeParticle, nodeType);

                if (valueType != null)
                {
                    XmlAttributeInfo attributeInfo = new XmlAttributeInfo(string.Empty, valueType);
                    nodeType.Define(attributeInfo);
                }

                // get XML attributes
                System.Collections.ICollection attributeUses = complexType.AttributeUses.Values;
                foreach (XmlSchemaAttribute attribute in attributeUses)
                {
                    XmlAttributeType attributeType = GetAttributeType(attribute.AttributeSchemaType);
                    string           fieldName     = GetFieldName(attribute.QualifiedName);
                    XmlAttributeInfo attributeInfo = new XmlAttributeInfo(fieldName, attributeType);

                    if (attribute.DefaultValue != null)
                    {
                        attributeInfo.DefaultValue = attributeType.Convert(attribute.DefaultValue);
                    }

                    m_annotations.Add(attributeInfo, GetAnnotation(attribute));

                    nodeType.Define(attributeInfo);
                }

                if (baseType != null)
                {
                    nodeType.BaseType = baseType;
                }

                nodeType.IsAbstract = complexType.IsAbstract;
            }

            return(nodeType);
        }
 /// <summary>
 /// Gets a derived node type given a base type, namespace, and type name</summary>
 /// <param name="baseType">Base node type</param>
 /// <param name="ns">Type namespace</param>
 /// <param name="typeName">Type name</param>
 /// <returns>Derived DomNodeType</returns>
 protected virtual DomNodeType GetDerivedType(DomNodeType baseType, string ns, string typeName)
 {
     return(m_typeCollection.GetNodeType(typeName));
 }
Exemple #20
0
 /// <summary>Adds a node type to the ones defined by the schema</summary>
 /// <remarks>If the node type is already defined, it is overwritten</remarks>
 /// <param name="name">Name of node type</param>
 /// <param name="type">New node type</param>
 public void AddNodeType(string name, DomNodeType type)
 {
     m_nodeTypes[name] = type;
 }
Exemple #21
0
        private void WalkParticle(XmlSchemaParticle particle, DomNodeType nodeType)
        {
            XmlSchemaElement element = particle as XmlSchemaElement;

            if (element != null)
            {
                XmlSchemaSimpleType simpleType = element.ElementSchemaType as XmlSchemaSimpleType;
                if (simpleType != null &&
                    element.MaxOccurs == 1)
                {
                    XmlAttributeType attributeType = GetAttributeType(simpleType);
                    string           fieldName     = GetFieldName(element.QualifiedName);
                    XmlAttributeInfo attributeInfo = new XmlAttributeInfo(fieldName, attributeType);

                    nodeType.Define(attributeInfo);
                    m_annotations.Add(attributeInfo, GetAnnotation(element));

                    attributeInfo.IsElement = true;

                    if (element.DefaultValue != null)
                    {
                        if (element.FixedValue != null)
                        {
                            throw new InvalidOperationException(string.Format("Schema element {0} cannot have both a default value and a fixed value", element.QualifiedName));
                        }
                        attributeInfo.DefaultValue = attributeType.Convert(element.DefaultValue);
                    }
                    else if (element.FixedValue != null)
                    {
                        attributeInfo.DefaultValue = attributeType.Convert(element.FixedValue);
                    }
                }
                else
                {
                    DomNodeType childNodeType = null;
                    if (simpleType != null)
                    {
                        childNodeType = WrapSimpleType(simpleType);

                        // Add the value attribute
                        XmlAttributeType valueAttributeType = GetAttributeType(simpleType);
                        var valueAttributeInfo = new XmlAttributeInfo(string.Empty, valueAttributeType);
                        childNodeType.Define(valueAttributeInfo);
                    }
                    else
                    {
                        XmlSchemaComplexType complexType = element.ElementSchemaType as XmlSchemaComplexType;
                        if (complexType != null)
                        {
                            childNodeType = GetNodeType(complexType, element);
                        }
                    }

                    if (childNodeType != null)
                    {
                        int minOccurs = (int)Math.Min(element.MinOccurs, Int32.MaxValue);
                        int maxOccurs = (int)Math.Min(element.MaxOccurs, Int32.MaxValue);

                        // If <xs:choice> is within a <xs:sequence>, choose the most relaxed constraints.
                        if (particle.Parent is XmlSchemaChoice &&
                            particle.Parent.Parent is XmlSchemaSequence)
                        {
                            XmlSchemaChoice parent          = (XmlSchemaChoice)particle.Parent;
                            int             parentMinOccurs = (int)Math.Min(parent.MinOccurs, Int32.MaxValue);
                            int             parentMaxOccurs = (int)Math.Min(parent.MaxOccurs, Int32.MaxValue);
                            minOccurs = Math.Min(parentMinOccurs, minOccurs);
                            maxOccurs = Math.Max(parentMaxOccurs, maxOccurs);
                        }

                        ChildInfo childInfo = new ChildInfo(GetFieldName(element.QualifiedName), childNodeType, maxOccurs > 1);

                        if (minOccurs > 0 || maxOccurs < Int32.MaxValue)
                        {
                            childInfo.AddRule(new ChildCountRule(minOccurs, maxOccurs));
                        }

                        // Check for substitution groups
                        if (!element.RefName.IsEmpty)
                        {
                            m_refElements.Add(childInfo, element.RefName);
                        }

                        nodeType.Define(childInfo);
                        m_annotations.Add(childInfo, GetAnnotation(element));
                    }
                }
            }
            else
            {
                // if sequence, continue collecting elements
                XmlSchemaSequence sequence = particle as XmlSchemaSequence;
                if (sequence != null)
                {
                    foreach (XmlSchemaParticle subParticle in sequence.Items)
                    {
                        WalkParticle(subParticle, nodeType);
                    }
                }
                else
                {
                    XmlSchemaChoice choice = particle as XmlSchemaChoice;
                    if (choice != null)
                    {
                        // for now, treat choice as if it were a sequence
                        foreach (XmlSchemaParticle subParticle in choice.Items)
                        {
                            WalkParticle(subParticle, nodeType);
                        }
                    }
                }
            }
        }