// effects: Given a set of values in domain // Returns all possible values that are present in domain. static CellConstantSet DeterminePossibleValues(IEnumerable <Constant> domain) { // E.g., if we have 1, 2, NOT(1) --> Result = 1, 2 // 1, NOT(1, 2) --> Result = 1, 2 // 1, 2, NOT(NULL) --> Result = 1, 2, NULL // 1, 2, NOT(2), NOT(3, 4) --> Result = 1, 2, 3, 4 CellConstantSet result = new CellConstantSet(Constant.EqualityComparer); foreach (Constant constant in domain) { NegatedConstant negated = constant as NegatedConstant; if (negated != null) { // Go through all the constants in negated and add them to domain // We add them to possible values also even if (say) Null is not allowed because we want the complete // partitioning of the space, e.g., if the values specified by the caller are 1, NotNull -> we want 1, Null foreach (Constant constElement in negated.Elements) { Debug.Assert(constElement as NegatedConstant == null, "Negated cell constant inside NegatedCellConstant"); result.Add(constElement); } } else { result.Add(constant); } } return(result); }
private void ExpandDomainsIfNeeded(Dictionary <MemberPath, CellConstantSet> domainMapForMembers) { // For the S-side, we always says that NOT(...) is // present. For example, if we are told "C", "P", we assume // that NOT(C, P) is possibly present in that column foreach (MemberPath path in domainMapForMembers.Keys) { CellConstantSet possibleValues = domainMapForMembers[path]; if (path.IsScalarType() && possibleValues.Any(c => c is NegatedConstant) == false) { if (MetadataHelper.HasDiscreteDomain(path.EdmType)) { // for a discrete domain, add all values that are not currently represented // in the domain Set <Constant> completeDomain = Domain.DeriveDomainFromMemberPath(path, m_edmItemCollection, true /* leaveDomainUnbounded */); possibleValues.Unite(completeDomain); } else { // for a non-discrete domain, add NOT("C", "P") NegatedConstant negatedConstant = new NegatedConstant(possibleValues); possibleValues.Add(negatedConstant); } } } }
// effects: Given a set of values in domain, "normalizes" it, i.e., // all positive constants are seperated out and any negative constant // is changed s.t. it is the negative of all positive values // extraValues indicates more constants that domain could take, e.g., // domain could be "1, 2, NOT(1, 2)", extraValues could be "3". In // this case, we return "1, 2, 3, NOT(1, 2, 3)" internal static CellConstantSet ExpandNegationsInDomain(IEnumerable <Constant> domain, IEnumerable <Constant> otherPossibleValues) { //Finds all constants referenced in (domain UNION extraValues) e.g: 1, NOT(2) => 1, 2 CellConstantSet possibleValues = DeterminePossibleValues(domain, otherPossibleValues); // For NOT --> Add all constants into d that are present in p but // not in the NOT // v = 1, NOT(1, 2); p = 1, 2, 3 => d = 1, NOT(1, 2, 3), 3 // v = 1, 2, NOT(1); p = 1, 2, 4 => d = 1, 2, 4, NOT(1, 2, 4) // v = 1, 2, NOT(1, 2, 4), NOT(1, 2, 4, 5); p = 1, 2, 4, 5, 6 => d = 1, 2, 5, 6, NOT(1, 2, 4, 5, 6) // NotNull works naturally now. If possibleValues has (1, 2, NULL) // and values has NOT(NULL), add 1, 2 to m_domain CellConstantSet result = new Set <Constant>(Constant.EqualityComparer); foreach (Constant constant in domain) { NegatedConstant negated = constant as NegatedConstant; if (negated != null) { result.Add(new NegatedConstant(possibleValues)); // Compute all elements in possibleValues that are not present in negated. E.g., if // negated is NOT(1, 2, 3) and possibleValues is 1, 2, 3, // 4, we need to add 4 to result CellConstantSet remainingElements = possibleValues.Difference(negated.Elements); result.AddRange(remainingElements); } else { result.Add(constant); } } return(result); }
protected override bool IsEqualTo(Constant right) { NegatedConstant rightNegatedConstant = right as NegatedConstant; if (rightNegatedConstant == null) { return(false); } return(m_negatedDomain.SetEquals(rightNegatedConstant.m_negatedDomain)); }
// effects: Checks the invariants in "this" internal void AssertInvariant() { // Make sure m_domain has at most one negatedCellConstant // m_possibleValues has none NegatedConstant negated = GetNegatedConstant(m_domain); // Can be null or not-null negated = GetNegatedConstant(m_possibleValues); Debug.Assert(negated == null, "m_possibleValues cannot contain negated constant"); Debug.Assert(m_domain.IsSubsetOf(AllPossibleValuesInternal), "All domain values must be contained in possibleValues"); }
// requires: constants has at most one NegatedCellConstant // effects: Returns the NegatedCellConstant in this if any. Else // returns null private static NegatedConstant GetNegatedConstant(IEnumerable <Constant> constants) { NegatedConstant result = null; foreach (Constant constant in constants) { NegatedConstant negated = constant as NegatedConstant; if (negated != null) { Debug.Assert(result == null, "Multiple negated cell constants?"); result = negated; } } return(result); }
// requires: this is complete // effects: Returns true iff this contains NOT(NULL OR ....) internal bool ContainsNotNull() { NegatedConstant negated = GetNegatedConstant(m_domain); return(negated != null && negated.Contains(Constant.Null)); }
private void ExpandDomainsIfNeeded(Dictionary<MemberPath, CellConstantSet> domainMapForMembers) { // For the S-side, we always says that NOT(...) is // present. For example, if we are told "C", "P", we assume // that NOT(C, P) is possibly present in that column foreach (MemberPath path in domainMapForMembers.Keys) { CellConstantSet possibleValues = domainMapForMembers[path]; if (path.IsScalarType() && possibleValues.Any(c => c is NegatedConstant) == false) { if (MetadataHelper.HasDiscreteDomain(path.EdmType)) { // for a discrete domain, add all values that are not currently represented // in the domain Set<Constant> completeDomain = Domain.DeriveDomainFromMemberPath(path, m_edmItemCollection, true /* leaveDomainUnbounded */); possibleValues.Unite(completeDomain); } else { // for a non-discrete domain, add NOT("C", "P") NegatedConstant negatedConstant = new NegatedConstant(possibleValues); possibleValues.Add(negatedConstant); } } } }
private void AsCql( Action <NegatedConstant, IEnumerable <Constant> > negatedConstantAsCql, Action <Set <Constant> > varInDomain, Action varIsNotNull, Action varIsNull, bool skipIsNotNull) { Debug.Assert(this.RestrictedMemberSlot.MemberPath.IsScalarType(), "Expected scalar."); // If domain values contain a negated constant, delegate Cql generation into that constant. Debug.Assert(this.Domain.Values.Count(c => c is NegatedConstant) <= 1, "Multiple negated constants?"); NegatedConstant negated = (NegatedConstant)this.Domain.Values.FirstOrDefault(c => c is NegatedConstant); if (negated != null) { negatedConstantAsCql(negated, this.Domain.Values); } else // We have only positive constants. { // 1. Generate "var in domain" // 2. If var is not nullable, append "... and var is not null". // This is needed for boolean _from variables that must never evaluate to null because view generation assumes 2-valued boolean logic. // 3. If domain contains null, prepend "var is null or ...". // // A complete generation pattern: // (var is null or ( var in domain and var is not null)) // ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ // generated by #3 generated by #1 generated by #2 // Copy the domain values for simplification changes. Set <Constant> domainValues = new Set <Constant>(this.Domain.Values, Constant.EqualityComparer); bool includeNull = false; if (domainValues.Contains(Constant.Null)) { includeNull = true; domainValues.Remove(Constant.Null); } // Constraint counter-example could contain undefined cellconstant. E.g for booleans (for int its optimized out due to negated constants) // we want to treat undefined as nulls. if (domainValues.Contains(Constant.Undefined)) { includeNull = true; domainValues.Remove(Constant.Undefined); } bool excludeNull = !skipIsNotNull && this.RestrictedMemberSlot.MemberPath.IsNullable; Debug.Assert(!includeNull || !excludeNull, "includeNull and excludeNull can't be true at the same time."); // #1: Generate "var in domain" if (domainValues.Count > 0) { varInDomain(domainValues); } // #2: Append "... and var is not null". if (excludeNull) { varIsNotNull(); } // #3: Prepend "var is null or ...". if (includeNull) { varIsNull(); } } }
internal void ToUserString(bool invertOutput, StringBuilder builder, MetadataWorkspace workspace) { // If there is a negated cell constant, get the inversion of the domain NegatedConstant negatedConstant = null; foreach (Constant constant in Domain.Values) { negatedConstant = constant as NegatedConstant; if (negatedConstant != null) { break; } } Set <Constant> constants; if (negatedConstant != null) { // Invert the domain and invert "invertOutput" invertOutput = !invertOutput; // Add all the values to negatedConstant's values to get the // final set of constants constants = new Set <Constant>(negatedConstant.Elements, Constant.EqualityComparer); foreach (Constant constant in Domain.Values) { if (!(constant is NegatedConstant)) { Debug.Assert(constants.Contains(constant), "Domain of negated constant does not have positive constant"); constants.Remove(constant); } } } else { constants = new Set <Constant>(Domain.Values, Constant.EqualityComparer); } // Determine the resource to use Debug.Assert(constants.Count > 0, "one of const is false?"); bool isNull = constants.Count == 1 && constants.Single().IsNull(); bool isTypeConstant = this is TypeRestriction; Func <object, string> resourceName0 = null; Func <object, object, string> resourceName1 = null; if (invertOutput) { if (isNull) { resourceName0 = isTypeConstant ? (Func <object, string>)Strings.ViewGen_OneOfConst_IsNonNullable : (Func <object, string>)Strings.ViewGen_OneOfConst_MustBeNonNullable; } else if (constants.Count == 1) { resourceName1 = isTypeConstant ? (Func <object, object, string>)Strings.ViewGen_OneOfConst_IsNotEqualTo : (Func <object, object, string>)Strings.ViewGen_OneOfConst_MustNotBeEqualTo; } else { resourceName1 = isTypeConstant ? (Func <object, object, string>)Strings.ViewGen_OneOfConst_IsNotOneOf : (Func <object, object, string>)Strings.ViewGen_OneOfConst_MustNotBeOneOf; } } else { if (isNull) { resourceName0 = isTypeConstant ? (Func <object, string>)Strings.ViewGen_OneOfConst_MustBeNull : (Func <object, string>)Strings.ViewGen_OneOfConst_MustBeNull; } else if (constants.Count == 1) { resourceName1 = isTypeConstant ? (Func <object, object, string>)Strings.ViewGen_OneOfConst_IsEqualTo : (Func <object, object, string>)Strings.ViewGen_OneOfConst_MustBeEqualTo; } else { resourceName1 = isTypeConstant ? (Func <object, object, string>)Strings.ViewGen_OneOfConst_IsOneOf : (Func <object, object, string>)Strings.ViewGen_OneOfConst_MustBeOneOf; } } // Get the constants StringBuilder constantBuilder = new StringBuilder(); Constant.ConstantsToUserString(constantBuilder, constants); Debug.Assert((resourceName0 == null) != (resourceName1 == null), "Both resources must not have been set or be null"); string variableName = m_restrictedMemberSlot.MemberPath.PathToString(false); if (isTypeConstant) { variableName = "TypeOf(" + variableName + ")"; } if (resourceName0 != null) { builder.Append(resourceName0(variableName)); } else { builder.Append(resourceName1(variableName, constantBuilder.ToString())); } if (invertOutput && isTypeConstant) { InvertOutputStringForTypeConstant(builder, constants, workspace); } }