// 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); }
/// <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); }
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); }
/// <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); }