/// <summary> /// Creates a qualifier from a given input qualifier such that the resulting qualifier respects target qualifier space. /// </summary> public bool TryCreateQualifierForQualifierSpace( PathTable pathTable, LoggingContext loggingContext, QualifierId qualifierId, QualifierSpaceId qualifierSpaceId, bool useDefaultsForCoercion, out QualifierId resultingQualifierId, out UnsupportedQualifierValue error) { Contract.RequiresNotNull(pathTable); Contract.RequiresNotNull(loggingContext); #if DEBUG Contract.Requires(IsValidQualifierId(qualifierId)); Contract.Requires(qualifierSpaceId.IsValid); Contract.Requires(IsValidQualifierSpaceId(qualifierSpaceId), "Id " + qualifierSpaceId.Id + " is not valid."); #endif Qualifier qualifier = GetQualifier(qualifierId); QualifierSpace qualifierSpace = GetQualifierSpace(qualifierSpaceId); Qualifier resultingQualifier; bool success = qualifierSpace.TryCreateQualifierForQualifierSpace( StringTable, pathTable, loggingContext, qualifier, out resultingQualifier, out error, useDefaultsForCoercion); resultingQualifierId = success ? GetOrAddQualifier(resultingQualifier) : EmptyQualifierId; return(success); }
/// <summary> /// Creates a qualifier from a given input qualifier such that the resulting qualifier respects this qualifier space. /// </summary> internal bool TryCreateQualifierForQualifierSpace( StringTable stringTable, PathTable pathTable, LoggingContext loggingContext, Qualifier currentQualifier, out Qualifier qualifier, out UnsupportedQualifierValue error, bool useDefaults) { Contract.Requires(stringTable != null); Contract.Requires(pathTable != null); Contract.Requires(loggingContext != null); StringId[] keys; StringId[] values; currentQualifier.GetInternalKeyValueArrays(out keys, out values); var targetKeys = new StringId[m_keys.Length]; var targetValues = new StringId[m_keys.Length]; int qIndex = 0; int sIndex = 0; while (sIndex < m_keys.Length) { var sKey = m_keys[sIndex]; if (qIndex < keys.Length && keys[qIndex] == sKey) { var qValue = values[qIndex]; if (m_valueValues[sIndex].Contains(qValue)) { targetKeys[sIndex] = keys[qIndex]; targetValues[sIndex] = qValue; qIndex++; sIndex++; } else { error = new UnsupportedQualifierValue { QualifierKey = sKey.ToString(stringTable), InvalidValue = qValue.ToString(stringTable), LegalValues = string.Join(", ", m_valueValues[sIndex].Select(id => id.ToString(stringTable))), }; qualifier = Qualifier.Empty; return(false); } } else { // Check if we have any key from the currentQualifier left. If not, we'll 'trick' the compare below be a 'missing' // value we can treat it to insert the default value for the remaining space keys var compare = qIndex < keys.Length ? stringTable.OrdinalComparer.Compare(keys[qIndex], sKey) : 1; Contract.Assume(compare != 0, "expected above equals to handle that case"); if (compare < 0) { // Given that the lists are sorted and the qualifier key is less than the space key, it means that key is not in the target space. // so we can skip it. qIndex++; } else { if (useDefaults == false) { qualifier = Qualifier.Empty; // var lineInfo = location.Value.ToLogLocation(pathTable); // TODO: Consider adding a more specific exception for the no defaults case error = new UnsupportedQualifierValue { // Location = lineInfo, QualifierKey = sKey.ToString(stringTable), InvalidValue = string.Empty, LegalValues = string.Join(", ", m_valueValues[sIndex].Select(id => id.ToString(stringTable))), }; return(false); } // It is larger, so we need to add the default value of the space to the target if enabled. targetKeys[sIndex] = sKey; targetValues[sIndex] = m_defaults[sIndex]; sIndex++; } } } qualifier = new Qualifier(targetKeys, targetValues); error = default(UnsupportedQualifierValue); return(true); }