private Set <EntityType> FindReachableTypes( DomainConstraintConversionContext <string, ValueCondition> converter, Vertex[] mappingConditions) { Vertex[] vertexArray = new Vertex[this.MappedEntityTypes.Count]; for (int index1 = 0; index1 < vertexArray.Length; ++index1) { Vertex left = Vertex.One; for (int index2 = 0; index2 < this.NormalizedEntityTypeMappings.Count; ++index2) { left = !this.NormalizedEntityTypeMappings[index2].ImpliedEntityTypes[index1] ? converter.Solver.And(left, converter.Solver.Not(mappingConditions[index2])) : converter.Solver.And(left, mappingConditions[index2]); } vertexArray[index1] = left; } Set <EntityType> set = new Set <EntityType>(); for (int i = 0; i < vertexArray.Length; ++i) { if (!converter.Solver.And(((IEnumerable <Vertex>)vertexArray).Select <Vertex, Vertex>((Func <Vertex, int, Vertex>)((typeCondition, ordinal) => { if (ordinal != i) { return(converter.Solver.Not(typeCondition)); } return(typeCondition); }))).IsZero()) { set.Add(this.MappedEntityTypes[i]); } } return(set); }
/// <summary> /// Determines which types are produced by this mapping. /// </summary> private Set <EntityType> FindUnambiguouslyReachableTypes( DomainConstraintConversionContext <string, ValueCondition> converter, Vertex[] mappingConditions) { // For each entity type, create a candidate function that evaluates to true given // discriminator assignments iff. all of that type's conditions evaluate to true. var candidateFunctions = new Vertex[MappedEntityTypes.Count]; for (var i = 0; i < candidateFunctions.Length; i++) { // Seed the candidate function conjunction with 'true'. var candidateFunction = Vertex.One; for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++) { var entityTypeMapping = NormalizedEntityTypeMappings[j]; // Determine if this mapping is a positive or negative case for the current type. if (entityTypeMapping.ImpliedEntityTypes[i]) { candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]); } } candidateFunctions[i] = candidateFunction; } // Make sure that for each type with satisfiable candidateFunction all assignments for the type resolve to only that type. var unambigouslyReachableMap = new BitArray(candidateFunctions.Length, true); for (var i = 0; i < candidateFunctions.Length; ++i) { if (candidateFunctions[i].IsZero()) { // The i-th type is unreachable regardless of other types. unambigouslyReachableMap[i] = false; } else { for (var j = i + 1; j < candidateFunctions.Length; ++j) { if (!converter.Solver.And(candidateFunctions[i], candidateFunctions[j]).IsZero()) { // The i-th and j-th types have common assignments, hence they aren't unambiguously reachable. unambigouslyReachableMap[i] = false; unambigouslyReachableMap[j] = false; } } } } var reachableTypes = new Set <EntityType>(); for (var i = 0; i < candidateFunctions.Length; ++i) { if (unambigouslyReachableMap[i]) { reachableTypes.Add(MappedEntityTypes[i]); } } return(reachableTypes); }
private void GetUnreachableTypes( bool validateAmbiguity, out KeyToListMap <EntityType, LineInfo> unreachableEntityTypes, out KeyToListMap <EntityType, LineInfo> unreachableIsTypeOfs) { DomainVariable <string, ValueCondition>[] variables = this.ConstructDomainVariables(); DomainConstraintConversionContext <string, ValueCondition> converter = new DomainConstraintConversionContext <string, ValueCondition>(); Vertex[] vertices = this.ConvertMappingConditionsToVertices((ConversionContext <DomainConstraint <string, ValueCondition> >)converter, variables); this.CollectUnreachableTypes(validateAmbiguity ? this.FindUnambiguouslyReachableTypes(converter, vertices) : this.FindReachableTypes(converter, vertices), out unreachableEntityTypes, out unreachableIsTypeOfs); }
/// <summary> /// Determines which types are produced by this mapping. /// </summary> private Set <EntityType> FindReachableTypes( DomainConstraintConversionContext <string, ValueCondition> converter, Vertex[] mappingConditions) { // For each entity type, create a candidate function that evaluates to true given // discriminator assignments iff. all of that type's conditions evaluate to true // and its negative conditions evaluate to false. var candidateFunctions = new Vertex[MappedEntityTypes.Count]; for (var i = 0; i < candidateFunctions.Length; i++) { // Seed the candidate function conjunction with 'true'. var candidateFunction = Vertex.One; for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++) { var entityTypeMapping = NormalizedEntityTypeMappings[j]; // Determine if this mapping is a positive or negative case for the current type. if (entityTypeMapping.ImpliedEntityTypes[i]) { candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]); } else { candidateFunction = converter.Solver.And(candidateFunction, converter.Solver.Not(mappingConditions[j])); } } candidateFunctions[i] = candidateFunction; } // Make sure that for each type there is an assignment that resolves to only that type. var reachableTypes = new Set <EntityType>(); for (var i = 0; i < candidateFunctions.Length; i++) { // Create a function that evaluates to true iff. the current candidate function is true // and every other candidate function is false. var isExactlyThisTypeCondition = converter.Solver.And( candidateFunctions.Select( (typeCondition, ordinal) => ordinal == i ? typeCondition : converter.Solver.Not(typeCondition))); // If the above conjunction is satisfiable, it means some row configuration exists producing the type. if (!isExactlyThisTypeCondition.IsZero()) { reachableTypes.Add(MappedEntityTypes[i]); } } return(reachableTypes); }
private Set <EntityType> FindUnambiguouslyReachableTypes( DomainConstraintConversionContext <string, ValueCondition> converter, Vertex[] mappingConditions) { Vertex[] vertexArray = new Vertex[this.MappedEntityTypes.Count]; for (int index1 = 0; index1 < vertexArray.Length; ++index1) { Vertex left = Vertex.One; for (int index2 = 0; index2 < this.NormalizedEntityTypeMappings.Count; ++index2) { if (this.NormalizedEntityTypeMappings[index2].ImpliedEntityTypes[index1]) { left = converter.Solver.And(left, mappingConditions[index2]); } } vertexArray[index1] = left; } BitArray bitArray = new BitArray(vertexArray.Length, true); for (int index1 = 0; index1 < vertexArray.Length; ++index1) { if (vertexArray[index1].IsZero()) { bitArray[index1] = false; } else { for (int index2 = index1 + 1; index2 < vertexArray.Length; ++index2) { if (!converter.Solver.And(vertexArray[index1], vertexArray[index2]).IsZero()) { bitArray[index1] = false; bitArray[index2] = false; } } } } Set <EntityType> set = new Set <EntityType>(); for (int index = 0; index < vertexArray.Length; ++index) { if (bitArray[index]) { set.Add(this.MappedEntityTypes[index]); } } return(set); }
/// <summary> /// Determines which explicitly mapped types in the function import mapping cannot be generated. /// For IsTypeOf declarations, reports if no type in hierarchy can be produced. /// Works by: /// - Converting type mapping conditions into vertices /// - Checking that some assignment satisfies /// </summary> private void GetUnreachableTypes( bool validateAmbiguity, out KeyToListMap <EntityType, LineInfo> unreachableEntityTypes, out KeyToListMap <EntityType, LineInfo> unreachableIsTypeOfs) { // Contains, for each DiscriminatorColumn, a domain variable where the domain values are // integers representing the ordinal within discriminatorDomains. var variables = ConstructDomainVariables(); // Convert type mapping conditions to decision diagram vertices. var converter = new DomainConstraintConversionContext <string, ValueCondition>(); var mappingConditions = ConvertMappingConditionsToVertices(converter, variables); // Find reachable types. var reachableTypes = validateAmbiguity ? FindUnambiguouslyReachableTypes(converter, mappingConditions) : FindReachableTypes(converter, mappingConditions); CollectUnreachableTypes(reachableTypes, out unreachableEntityTypes, out unreachableIsTypeOfs); }
/// <summary> /// Determines which types are produced by this mapping. /// </summary> private Set<EntityType> FindUnambiguouslyReachableTypes( DomainConstraintConversionContext<string, ValueCondition> converter, Vertex[] mappingConditions) { // For each entity type, create a candidate function that evaluates to true given // discriminator assignments iff. all of that type's conditions evaluate to true. var candidateFunctions = new Vertex[MappedEntityTypes.Count]; for (var i = 0; i < candidateFunctions.Length; i++) { // Seed the candidate function conjunction with 'true'. var candidateFunction = Vertex.One; for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++) { var entityTypeMapping = NormalizedEntityTypeMappings[j]; // Determine if this mapping is a positive or negative case for the current type. if (entityTypeMapping.ImpliedEntityTypes[i]) { candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]); } } candidateFunctions[i] = candidateFunction; } // Make sure that for each type with satisfiable candidateFunction all assignments for the type resolve to only that type. var unambigouslyReachableMap = new BitArray(candidateFunctions.Length, true); for (var i = 0; i < candidateFunctions.Length; ++i) { if (candidateFunctions[i].IsZero()) { // The i-th type is unreachable regardless of other types. unambigouslyReachableMap[i] = false; } else { for (var j = i + 1; j < candidateFunctions.Length; ++j) { if (!converter.Solver.And(candidateFunctions[i], candidateFunctions[j]).IsZero()) { // The i-th and j-th types have common assignments, hence they aren't unambiguously reachable. unambigouslyReachableMap[i] = false; unambigouslyReachableMap[j] = false; } } } } var reachableTypes = new Set<EntityType>(); for (var i = 0; i < candidateFunctions.Length; ++i) { if (unambigouslyReachableMap[i]) { reachableTypes.Add(MappedEntityTypes[i]); } } return reachableTypes; }
/// <summary> /// Determines which types are produced by this mapping. /// </summary> private Set<EntityType> FindReachableTypes( DomainConstraintConversionContext<string, ValueCondition> converter, Vertex[] mappingConditions) { // For each entity type, create a candidate function that evaluates to true given // discriminator assignments iff. all of that type's conditions evaluate to true // and its negative conditions evaluate to false. var candidateFunctions = new Vertex[MappedEntityTypes.Count]; for (var i = 0; i < candidateFunctions.Length; i++) { // Seed the candidate function conjunction with 'true'. var candidateFunction = Vertex.One; for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++) { var entityTypeMapping = NormalizedEntityTypeMappings[j]; // Determine if this mapping is a positive or negative case for the current type. if (entityTypeMapping.ImpliedEntityTypes[i]) { candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]); } else { candidateFunction = converter.Solver.And(candidateFunction, converter.Solver.Not(mappingConditions[j])); } } candidateFunctions[i] = candidateFunction; } // Make sure that for each type there is an assignment that resolves to only that type. var reachableTypes = new Set<EntityType>(); for (var i = 0; i < candidateFunctions.Length; i++) { // Create a function that evaluates to true iff. the current candidate function is true // and every other candidate function is false. var isExactlyThisTypeCondition = converter.Solver.And( candidateFunctions.Select( (typeCondition, ordinal) => ordinal == i ? typeCondition : converter.Solver.Not(typeCondition))); // If the above conjunction is satisfiable, it means some row configuration exists producing the type. if (!isExactlyThisTypeCondition.IsZero()) { reachableTypes.Add(MappedEntityTypes[i]); } } return reachableTypes; }
/// <summary> /// Determines which explicitly mapped types in the function import mapping cannot be generated. /// For IsTypeOf declarations, reports if no type in hierarchy can be produced. /// Works by: /// - Converting type mapping conditions into vertices /// - Checking that some assignment satisfies /// </summary> private void GetUnreachableTypes( bool validateAmbiguity, out KeyToListMap<EntityType, LineInfo> unreachableEntityTypes, out KeyToListMap<EntityType, LineInfo> unreachableIsTypeOfs) { // Contains, for each DiscriminatorColumn, a domain variable where the domain values are // integers representing the ordinal within discriminatorDomains. var variables = ConstructDomainVariables(); // Convert type mapping conditions to decision diagram vertices. var converter = new DomainConstraintConversionContext<string, ValueCondition>(); var mappingConditions = ConvertMappingConditionsToVertices(converter, variables); // Find reachable types. var reachableTypes = validateAmbiguity ? FindUnambiguouslyReachableTypes(converter, mappingConditions) : FindReachableTypes(converter, mappingConditions); CollectUnreachableTypes(reachableTypes, out unreachableEntityTypes, out unreachableIsTypeOfs); }