private ModelInfo CreateModel(xml.model model)
        {
            NamingConventions conventions = new NamingConventions();

            ModelInfo result = new ModelInfo();

            if (!string.IsNullOrWhiteSpace(model.projectNamespace))
            {
                GlobalConfig.ProjectNamespace = model.projectNamespace;
            }

            foreach (var modelItem in model.Items)
            {
                if (modelItem is config)
                {
                    var config = (config)modelItem;
                    if (config.serialization != null && !string.IsNullOrWhiteSpace(config.serialization.@namespace))
                    {
                        GlobalConfig.SerializationNamespace = [email protected]();
                    }
                }
                else if (modelItem is type)
                {
                    var type = (type)modelItem;

                    var ti = new TypeInfo(type.name, model.@namespace, type.immutable, type.cloneable,
                                          type.serializable, type.equals);

                    if (type.deepCopySpecified)
                    {
                        ti.DeepCopy = type.deepCopy;
                    }

                    if (!string.IsNullOrWhiteSpace(type.doc))
                    {
                        ti.Documentation = type.doc;
                    }

                    if (!string.IsNullOrWhiteSpace(type.implements))
                    {
                        var impls = type.implements.Split(',');
                        foreach (var impl in impls)
                        {
                            var tmp = impl.Trim();
                            if (!string.IsNullOrWhiteSpace(tmp))
                            {
                                ti.Implements.Add(tmp);
                            }
                        }
                    }

                    if (type.extends != null && type.extends.Trim() != "")
                    {
                        ti.Extends = type.extends.Trim();
                    }

                    if (type.baseClass != null)
                    {
                        var bc = type.baseClass;

                        if (bc.hasChildPropertyChangedSpecified)
                        {
                            ti.BaseClass.HasChildPropertyChanged = bc.hasChildPropertyChanged;
                        }
                        if (bc.hasPropertyChangedSpecified)
                        {
                            ti.BaseClass.HasPropertyChanged = bc.hasPropertyChanged;
                        }
                        if (bc.hasChildPropertyChangingSpecified)
                        {
                            ti.BaseClass.HasChildPropertyChanging = bc.hasChildPropertyChanging;
                        }
                        if (bc.hasPropertyChangingSpecified)
                        {
                            ti.BaseClass.HasPropertyChanging = bc.hasPropertyChanging;
                        }
                        if (bc.hasCopyFromSpecified)
                        {
                            ti.BaseClass.HasCopyFrom = bc.hasCopyFrom;
                        }
                        if (bc.hasPropertiesSpecified)
                        {
                            ti.BaseClass.HasProperties = bc.hasProperties;
                        }
                    }

                    foreach (var item in type.Items)
                    {
                        if (item is property)
                        {
                            var property = (property)item;

                            var prop = new PropertyInfo(conventions, ti, property.name, property.type, property.required,
                                                        false);

                            if (property.deepCopySpecified)
                            {
                                prop.DeepCopy = property.deepCopy;
                            }

                            if (!string.IsNullOrWhiteSpace(property.doc))
                            {
                                prop.Documentation = property.doc;
                            }

                            if (!string.IsNullOrWhiteSpace(property.@default))
                            {
                                prop.DefaultValue = property.@default;
                            }

                            if (!string.IsNullOrWhiteSpace(property.getter) &&
                                ValidateVisibility(property.getter, "getter"))
                            {
                                prop.GetterVisibility = property.getter;
                            }
                            if (!string.IsNullOrWhiteSpace(property.setter) &&
                                ValidateVisibility(property.setter, "setter"))
                            {
                                prop.SetterVisibility = property.setter;
                            }

                            if (property.receiveInConstructorSpecified && property.receiveInConstructor)
                            {
                                prop.ReceiveInConstructor = property.receiveInConstructor;
                            }

                            if (property.precisionSpecified)
                            {
                                prop.Precision = (double)property.precision;
                            }

                            if (prop.Required && !prop.IsPrimitive)
                            {
                                prop.Validations.Add(new ValidationInfo("value == null",
                                                                        property.requiredException
                                                                        ?? "new ArgumentNullException(property)",
                                                                        "#pragma warning disable 472\n// ReSharper disable ConditionIsAlwaysTrueOrFalse",
                                                                        "// ReSharper restore ConditionIsAlwaysTrueOrFalse\n#pragma warning restore 472"));
                            }

                            prop.AddValidationAttrib(property.validationAttrib, property.validationException);
                            prop.AddValidation(property.validation1, property.validationException);

                            if (property.validation != null)
                            {
                                foreach (var validation in property.validation)
                                {
                                    prop.AddValidationAttrib(validation.attrib, validation.exception);
                                    prop.AddValidation(validation.test, validation.exception);
                                }
                            }

                            ti.Properties.Add(prop);
                        }
                        else if (item is component)
                        {
                            var component = (component)item;

                            var comp = new ComponentInfo(conventions, ti, component.name, component.type, component.lazy);

                            if (!string.IsNullOrWhiteSpace(component.doc))
                            {
                                comp.Documentation = component.doc;
                            }

                            if (!string.IsNullOrWhiteSpace(component.@default))
                            {
                                comp.DefaultValue = component.@default;
                            }

                            if (component.receiveInConstructorSpecified && component.receiveInConstructor)
                            {
                                comp.ReceiveInConstructor = component.receiveInConstructor;
                            }

                            comp.AddValidationAttrib(component.validationAttrib, component.validationException);
                            comp.AddValidation(component.validation1, component.validationException);

                            if (component.validation != null)
                            {
                                foreach (var validation in component.validation)
                                {
                                    comp.AddValidationAttrib(validation.attrib, validation.exception);
                                    comp.AddValidation(validation.test, validation.exception);
                                }
                            }

                            ti.Properties.Add(comp);
                        }
                        else if (item is collection)
                        {
                            var collection = (collection)item;

                            var col = new CollectionInfo(conventions, ti, collection.name, collection.type,
                                                         collection.lazy, collection.readOnly);

                            if (collection.deepCopySpecified)
                            {
                                col.DeepCopy = collection.deepCopy;
                            }

                            if (!string.IsNullOrWhiteSpace(collection.doc))
                            {
                                col.Documentation = collection.doc;
                            }

                            if (!string.IsNullOrWhiteSpace(collection.@default))
                            {
                                col.DefaultValue = collection.@default;
                            }

                            ti.Properties.Add(col);
                        }
                        else if (item is computedproperty)
                        {
                            var computed = (computedproperty)item;

                            var deps = (from d in computed.dependsOn.Split(',')
                                        where d.Trim() != ""
                                        select StringUtils.FirstUpper(d.Trim()));

                            var prop = new ComputedPropertyInfo(conventions, ti, computed.name, computed.type,
                                                                computed.cached, deps, computed.formula);

                            if (!string.IsNullOrWhiteSpace(computed.getter) &&
                                ValidateVisibility(computed.getter, "getter"))
                            {
                                prop.GetterVisibility = computed.getter;
                            }

                            if (!string.IsNullOrWhiteSpace(computed.doc))
                            {
                                prop.Documentation = computed.doc;
                            }

                            ti.Properties.Add(prop);
                        }
                        else if (item is @using)
                        {
                            var us = item as @using;
                            ti.Using.Add(us.@namespace);
                        }
                    }

                    result.AddType(ti);
                }
                else if (modelItem is @using)
                {
                    var us = modelItem as @using;
                    result.Using.Add(us.@namespace);
                }
            }

            return(result);
        }