Пример #1
0
        private static ChildInfo[] GetPath(DomNodeType type, string[] segments, int length)
        {
            ChildInfo[] result = new ChildInfo[length];
            for (int i = 0; i < length; i++)
            {
                ChildInfo metaElement = type.GetChildInfo(segments[i]);
                if (metaElement == null)
                {
                    throw new AnnotationException("Invalid path");
                }

                result[i] = metaElement;

                type = metaElement.Type;
            }

            return(result);
        }
Пример #2
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);
        }
Пример #3
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);
        }
Пример #4
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   = 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);
        }
Пример #5
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);
        }