private SchemaTypeEntry GenerateForType(StructuredType structuredType) { string extends = null; var resourceTypeSpec = structuredType as ResourceType; IEnumerable <StructuredProperty> properties = structuredType.Properties; if (resourceTypeSpec == null || !resourceTypeSpec.IsUriBaseType) { if (structuredType.BaseType != null && structuredType.BaseType != typeof(object)) { extends = structuredType.BaseType.Name; var propsOfBaseType = new HashSet <string>(structuredType.BaseType.Properties.Select(x => x.Name)); properties = properties.Where(x => !propsOfBaseType.Contains(x.Name)); } } var typeName = structuredType.Name; var schemaTypeEntry = new SchemaTypeEntry { Extends = extends, Name = typeName, Properties = new SortedDictionary <string, SchemaPropertyEntry>(properties .Select(GenerateForProperty) .ToDictionary(x => x.Name, x => x)), // TODO: Expose IsAbstract on TypeSpec Abstract = structuredType.Type != null && structuredType.Type.IsAbstract, AllowedMethods = structuredType.AllowedMethods }; if (resourceTypeSpec != null) { schemaTypeEntry.Uri = resourceTypeSpec.UrlRelativePath; } return(schemaTypeEntry); }
private static void PropertiesAreBackwardsCompatible(TextWriter errorLog, SchemaTypeEntry oldType, SchemaTypeEntry newType, ref bool isBackwardsCompatible, string typeName) { var propertyNames = oldType.Properties.Select(x => x.Key).Concat(newType.Properties.Select(x => x.Key)).Distinct(); foreach (var propName in propertyNames) { SchemaPropertyEntry oldPropEntry, newPropEntry; oldType.Properties.TryGetValue(propName, out oldPropEntry); newType.Properties.TryGetValue(propName, out newPropEntry); if (oldPropEntry == null && newPropEntry == null) { throw new InvalidOperationException("Should have found a property named " + propName + " on either old or new type. WTF?"); } if (newPropEntry == null) { // Removal of property, not allowed! isBackwardsCompatible = false; errorLog.Write( "Removal of property {0} from type {1} breaks backwards compability.\r\n", propName, typeName); continue; } if (oldPropEntry == null) { if (newPropEntry.Required) { isBackwardsCompatible = false; errorLog.Write( "Introducing a new required property {0} to type {1} breaks backwards compability.\r\n", propName, typeName); } continue; } var lostRights = oldPropEntry.Access ^ (newPropEntry.Access & oldPropEntry.Access); if (lostRights != 0) { isBackwardsCompatible = false; errorLog.Write( "The property access rights {0} has been removed from property, which breaks backwards compatibility.", lostRights); } if (!oldPropEntry.Required && newPropEntry.Required) { isBackwardsCompatible = false; errorLog.Write( "Making previosly optional property {0} of type {1} required breaks compability.\r\n", propName, typeName); } if (newPropEntry.Type != oldPropEntry.Type) { isBackwardsCompatible = false; errorLog.Write( "Changing type of property {0} declared by {1} from type {2} to type {3} breaks compability\r\n", propName, typeName, oldPropEntry.Type, newPropEntry.Type); } } }
private SchemaTypeEntry GenerateForType(TransformedType transformedType) { string extends = null; var resourceTypeSpec = transformedType as ResourceType; IEnumerable<PropertyMapping> properties = transformedType.Properties; if (resourceTypeSpec == null || !resourceTypeSpec.IsUriBaseType) { extends = transformedType.BaseType.Name; var propsOfBaseType = new HashSet<string>(transformedType.BaseType.Properties.Select(x => x.Name)); properties = properties.Where(x => !propsOfBaseType.Contains(x.Name)); } var typeName = transformedType.Name; var schemaTypeEntry = new SchemaTypeEntry { Extends = extends, Name = typeName, Properties = new SortedDictionary<string, SchemaPropertyEntry>(properties .Select(GenerateForProperty) .ToDictionary(x => x.Name, x => x)), // TODO: Expose IsAbstract on TypeSpec Abstract = transformedType.Type != null && transformedType.Type.IsAbstract, AllowedMethods = transformedType.AllowedMethods }; if (resourceTypeSpec != null) { schemaTypeEntry.Uri = resourceTypeSpec.UriRelativePath; } return schemaTypeEntry; }