Ejemplo n.º 1
0
        /// <summary>
        /// Parses the specified XML content and returns all prototypes which could be parsed.
        /// </summary>
        /// <param name="xmlContent">The xml content to use for parsing-</param>
        /// <param name="parameters">The parameters for the parser.</param>
        /// <param name="extend">The result to extend when parsing. Setting this will give the parser the ability to let data to be loaded now inherited from data loaded in extend.</param>
        /// <returns></returns>
        public void Parse(string xmlContent, string filename, PrototypeParseParameters parameters)
        {
            PrototypeCaches.LazyInit();

            // Pre-parse data
            var data = new List <SerializedData>();

            _PreParse(xmlContent, filename, ref parameters, data);
            _Parse(data, ref parameters);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Same as <see cref="Parse(string, string)"/>, but can parse many xmls with relationships / dependencies in them together.
        /// This will make it possible to have a prototype in one file which is inherited from in another file.
        ///
        /// The prototypes will be loaded in order and able to resolve references across multiple files!
        /// </summary>
        public void Parse(string[] xmlContents, string[] filenames, PrototypeParseParameters parameters)
        {
            PrototypeCaches.LazyInit();
            List <SerializedData> data = new List <SerializedData>();

            if (xmlContents.Length != filenames.Length)
            {
                throw new ArgumentException("Xml content string count must match filename count in Prototypes.Parse()!");
            }

            for (int i = 0; i < xmlContents.Length; i++)
            {
                _PreParse(xmlContents[i], filenames[i], ref parameters, data);
            }

            _Parse(data, ref parameters);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Actually loads the data from the previous parse <see cref="ParseFields(List{ParsingError})"/>.
        /// It will for every field with string data deserialize this data using <see cref="IPrototypeDataSerializer"/>.
        ///
        /// For every sub-data field (<seealso cref="ParseFields(List{ParsingError})"/>) a <see cref="SerializedData"/> object is being written to <see cref="fields"/>.
        /// The sub-data object will have <see cref="PrepareParse(SerializableTypeCache, XElement, string)"/>, <see cref="ParseFields(List{ParsingError})"/> and <see cref="LoadFields(List{ParsingError}, PrototypeParserState)"/> called.
        /// </summary>
        public void LoadFields(List <ParsingError> errors, PrototypeParserState state)
        {
            foreach (var xNode in xElement.Nodes())
            {
                if (!ParsingValidation.NodeIsElement(xNode, this.filename, errors))                 // Malformed XML
                {
                    continue;
                }

                var xElement    = xNode as XElement;
                var elementName = xElement.Name.LocalName;

                // Field unknown?
                if (!ParsingValidation.FieldKnown(xElement, targetType, elementName, filename, errors))
                {
                    continue;
                }

                debug.Add(elementName, xElement);
                var  fieldData    = targetType.GetFieldData(elementName);
                var  fieldType    = fieldData.serializableTypeCache;
                bool isCollection = SerializedCollectionData.IsCollection(fieldData.fieldInfo.FieldType);
                IPrototypeDataSerializer serializer = PrototypeCaches.GetBestSerializerFor(fieldData.fieldInfo.FieldType);

                if (!ReferenceEquals(serializer, null))
                {
                    try
                    {
                        if (!ParsingValidation.SerializerWasFound(xElement, serializer, elementName, targetType == null ? null : targetType.type, fieldType == null ? null : fieldType.type, filename, errors))
                        {
                            continue;
                        }

                        fields.Add(elementName, serializer.Deserialize(fieldData.fieldInfo.FieldType, xElement, state));
                    }
                    catch (Exception ex)
                    {
                        errors.Add(new ParsingError(ParsingErrorSeverity.ERROR, filename, -1, "Serializer threw exception on field " + elementName + " on type " + targetType.type + ":\n\n" + ex.ToString() + "\n\nSkipping field!"));
                    }
                }
                else if (isCollection)
                {
                    var col = new SerializedCollectionData(fieldData.fieldInfo.FieldType, xElement, this.filename);
                    col.ParseAndLoadData(errors, state);
                    fields.Add(elementName, col);

                    // Collection override action?
                    var collectionOverrideAttrib = xElement.Attribute(PrototypeParser.PrototypeAttributeCollectionOverrideAction);
                    if (!ReferenceEquals(collectionOverrideAttrib, null))
                    {
                        collectionOverrideActions.Set(elementName, (CollectionOverrideAction)Enum.Parse(typeof(CollectionOverrideAction), collectionOverrideAttrib.Value));
                    }
                }
                else
                {
                    // A known serializable

                    // Prototype reference?
                    if (fieldData.isPrototype)
                    {
                        fields.Add(elementName, new SerializedPrototypeReference()
                        {
                            identifier = xElement.Value as string
                        });
                    }
                    else
                    {
                        // Determine which type to serialize
                        var    targetType = fieldData.serializableTypeCache;
                        string typeName   = fieldData.fieldInfo.Name;

                        // Check if element explicitly overwrites the type to support polymorphism
                        // The field type might be some base class type and the xml overwrites this type with a class extending from the base
                        var classAttrib = xElement.Attribute(PrototypeParser.PrototypeAttributeType);
                        if (!ReferenceEquals(classAttrib, null))
                        {
                            targetType = PrototypeCaches.GetSerializableTypeCacheFor(classAttrib.Value, state.parameters.standardNamespace);
                            typeName   = classAttrib.Value;
                        }

                        // Field not serializable?
                        if (!ParsingValidation.DataFieldSerializerValid(xElement, targetType, typeName, elementName, filename, errors))
                        {
                            continue;
                        }

                        // Resolve field name type
                        var d = new SerializedData(targetType, xElement as XElement, this.filename);
                        d.LoadFields(errors, state);
                        fields.Add(elementName, d);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// <see cref="SerializedData.LoadFields(List{ParsingError}, PrototypeParserState)"/>
        /// </summary>
        /// <param name="errors"></param>
        /// <param name="state"></param>
        public void ParseAndLoadData(List <ParsingError> errors, PrototypeParserState state)
        {
            var elementNodes = xElement.Nodes().ToList();
            var collection   = GetCollectionInstance(this.collectionType, elementNodes.Count);

            Type   elementType      = GetElementType(this.collectionType);
            var    elementTypeCache = PrototypeCaches.GetSerializableTypeCacheFor(elementType);
            string elementTypeName  = elementType.Name;

            foreach (var node in elementNodes)
            {
                var xElementNode = node as XElement;
                if (ReferenceEquals(xElementNode, null))                 // Malformed XML
                {
                    errors.Add(new ParsingError(ParsingErrorSeverity.ERROR, filename, (node as IXmlLineInfo).LineNumber, "Unable to cast node to element for " + node + "! Skipping element!"));
                    continue;
                }

                if (typeof(IPrototype).IsAssignableFrom(elementType))
                {
                    // Prototype ref
                    this.elements.Add(new SerializedPrototypeReference()
                    {
                        identifier = xElementNode.Value
                    });
                }
                else
                {
                    // Determine type
                    var    serializableTypeCache = elementTypeCache;
                    string typeName = elementTypeName;

                    // Try to read class attrib
                    var classAttrib = xElementNode.Attribute(PrototypeParser.PrototypeAttributeType);
                    if (!ReferenceEquals(classAttrib, null))
                    {
                        serializableTypeCache = PrototypeCaches.GetSerializableTypeCacheFor(classAttrib.Value, state.parameters.standardNamespace);
                        typeName = classAttrib.Value;
                    }

                    // Validity checks
                    // Field not serializable?
                    if (ReferenceEquals(serializableTypeCache, null))
                    {
                        // TODO: Line number, better reporting as to why this type is unserializable!
                        errors.Add(new ParsingError(ParsingErrorSeverity.ERROR, filename, -1, "Collection element with unknown type " + typeName + " unserializable! Skipping field!"));
                        continue;
                    }

                    // Add element
                    this.elements.Add(new SerializedData(serializableTypeCache, xElementNode, this.filename));
                }
            }

            foreach (var element in this.elements)
            {
                var sElement = element as SerializedData;
                if (!ReferenceEquals(sElement, null))
                {
                    sElement.LoadFields(errors, state);
                }
            }
        }
Ejemplo n.º 5
0
 private static SerializableTypeCache GetSerializableTypeCacheFor(string name, ref PrototypeParseParameters parameters)
 {
     return(PrototypeCaches.GetSerializableTypeCacheFor(name, parameters.standardNamespace));
 }
Ejemplo n.º 6
0
 private static SerializableTypeCache LookupSerializableTypeCache(string name, ref PrototypeParseParameters parameters)
 {
     return(PrototypeCaches.LookupSerializableTypeCache(name, parameters.standardNamespace));
 }