in libraries/Microsoft.Bot.Builder.Dialogs.Adaptive/AdaptiveDialog.cs [1312:1454]
private bool MatchesAssignment(EntityInfo entity, EntityAssignment assignment)
=> (entity.Operation == null || entity.Operation == assignment.Operation)
&& (entity.Property == null || entity.Property == assignment.Property);
// Generate candidate assignments including property and operation
private IEnumerable<EntityAssignment> Candidates(Dictionary<string, List<EntityInfo>> entities, string[] expected, string lastEvent, EntityAssignment nextAssignment, JObject askDefault, JObject dialogDefault)
{
var globalExpectedOnly = dialogSchema.Schema[ExpectedOnlyKey]?.ToObject<List<string>>() ?? new List<string>();
var requiresValue = dialogSchema.Schema[RequiresValueKey]?.ToObject<List<string>>() ?? new List<string>();
var assignments = new List<EntityAssignment>();
// Add entities with a recognized property
foreach (var alternatives in entities.Values)
{
foreach (var alternative in alternatives)
{
if (alternative.Property != null && (alternative.Value != null || !requiresValue.Contains(alternative.Operation)))
{
assignments.Add(new EntityAssignment
{
Value = alternative,
Property = alternative.Property,
Operation = alternative.Operation,
IsExpected = expected.Contains(alternative.Property)
});
}
}
}
// Find possible mappings for entities without a property or where property entities are expected
foreach (var propSchema in dialogSchema.Property.Children)
{
var isExpected = expected.Contains(propSchema.Name);
var expectedOnly = propSchema.ExpectedOnly ?? globalExpectedOnly;
foreach (var propEntity in propSchema.Entities)
{
var entityName = StripProperty(propEntity);
if (entities.TryGetValue(entityName, out var matches) && (isExpected || !expectedOnly.Contains(entityName)))
{
foreach (var entity in matches)
{
if (entity.Property == null)
{
assignments.Add(new EntityAssignment
{
Value = entity,
Property = propSchema.Name,
Operation = entity.Operation,
IsExpected = isExpected
});
}
else if (entity.Property == entityName && entity.Value == null && entity.Operation == null && isExpected)
{
// Recast property with no value as match for property entities
assignments.Add(new EntityAssignment
{
Value = entity,
Property = propSchema.Name,
Operation = null,
IsExpected = isExpected,
});
}
}
}
}
}
// Add default operations
foreach (var assignment in assignments)
{
if (assignment.Operation == null)
{
// Assign missing operation
if (lastEvent == AdaptiveEvents.ChooseEntity
&& assignment.Value.Property == nextAssignment.Property)
{
// Property and value match ambiguous entity
assignment.Operation = AdaptiveEvents.ChooseEntity;
assignment.IsExpected = true;
}
else
{
// Assign default operator
assignment.Operation = DefaultOperation(assignment, askDefault, dialogDefault);
}
}
}
// Add choose property matches
if (lastEvent == AdaptiveEvents.ChooseProperty)
{
foreach (var alternatives in entities.Values)
{
foreach (var alternative in alternatives)
{
if (alternative.Value == null)
{
// If alternative matches one alternative it answers chooseProperty
var matches = nextAssignment.Alternatives.Where(a => MatchesAssignment(alternative, a));
if (matches.Count() == 1)
{
assignments.Add(new EntityAssignment
{
Value = alternative,
Operation = AdaptiveEvents.ChooseProperty,
IsExpected = true
});
}
}
}
}
}
// Add pure operations
foreach (var alternatives in entities.Values)
{
foreach (var alternative in alternatives)
{
if (alternative.Operation != null && alternative.Property == null && alternative.Value == null)
{
var assignment = new EntityAssignment
{
Value = alternative,
Property = null,
Operation = alternative.Operation,
IsExpected = false
};
assignments.Add(assignment);
}
}
}
// Preserve expectedProperties if there is no property
foreach (var assignment in assignments)
{
if (assignment.Property == null)
{
assignment.ExpectedProperties = expected.ToList();
}
}
return assignments;
}