in tools/Elastic.CommonSchema.Generator/Projection/TypeProjector.cs [174:248]
private Dictionary<string, EntityClass> CreateEntityTypes()
{
// Create concrete entity instances of base field sets to reference
var nestedEntityClasses = new Dictionary<string, EntityClass>();
foreach (var (name, fieldSetBaseClass) in FieldSetsBaseClasses)
{
var fieldSet = fieldSetBaseClass.FieldSet;
var entityClass = EntityClasses[name];
var parentPath = name;
if (fieldSet.ReusedHere == null) continue;
foreach (var reuse in fieldSet.ReusedHere)
{
var fieldTokens = reuse.Full.Split('.').ToArray();
var isArray = reuse.Normalize != null && reuse.Normalize.Contains("array");
// most common case a reference to a different schema
if (fieldTokens.Length <= 2 && reuse.SchemaName != name)
{
entityClass.EntityReferences[reuse.Full] =
new EntityPropertyReference(parentPath, reuse.Full, EntityClasses[reuse.SchemaName], reuse.Short, isArray);
}
else
{
// We can't assume the direct parent is an ECS field e.g
// email.attachments.file.hash -> file.hash is a property on email.attachments
var basePaths = fieldTokens.Select((_, i) => string.Join('.', fieldTokens.Take(i + 1))).Reverse().ToArray();
var inlineObjectPath = basePaths.FirstOrDefault(p => InlineObjects.ContainsKey(p));
var entityObjectPath = basePaths.FirstOrDefault(p => EntityClasses.ContainsKey(p));
// check if this deeply nested reference refers to an inline object
if (!string.IsNullOrEmpty(inlineObjectPath))
{
InlineObjects[inlineObjectPath].EntityReferences[reuse.Full] =
new EntityPropertyReference(inlineObjectPath, reuse.Full, EntityClasses[reuse.SchemaName], reuse.Short, isArray);
}
else if (!string.IsNullOrWhiteSpace(entityObjectPath) && reuse.SchemaName != name)
{
EntityClasses[entityObjectPath].EntityReferences[reuse.Full] =
new EntityPropertyReference(entityObjectPath, reuse.Full, EntityClasses[reuse.SchemaName], reuse.Short, isArray);
}
// created new nested usage of this entity
else if (!string.IsNullOrWhiteSpace(entityObjectPath))
{
var nestedEntityClass = new SelfReferentialReusedEntityClass(reuse.Full, EntityClasses[reuse.SchemaName].BaseFieldSet, reuse.Short, isArray);
nestedEntityClasses[reuse.Full] = nestedEntityClass;
}
else Warnings.Add($"Unable to project reuse of: ${reuse.Full}");
}
}
}
foreach (var (fullName, entity) in nestedEntityClasses)
{
var fieldTokens = fullName.Split('.').ToArray();
var parentPaths = fieldTokens.Select((_, i) => string.Join('.', fieldTokens.Take(i + 1))).Reverse().Skip(1).ToArray();
var nestedPath = parentPaths.FirstOrDefault(p => nestedEntityClasses.ContainsKey(p));
var entityPath = parentPaths.FirstOrDefault(p => EntityClasses.ContainsKey(p));
var description = entity is SelfReferentialReusedEntityClass s ? s.ReuseDescription : entity.BaseFieldSet.FieldSet.Description;
var isArray = entity is SelfReferentialReusedEntityClass { IsArray: true };
if (!string.IsNullOrEmpty(nestedPath))
{
var nestedEntityClassRef = new EntityPropertyReference(nestedPath, fullName, entity, description, isArray);
nestedEntityClasses[nestedPath].EntityReferences[fullName] = nestedEntityClassRef;
}
else if (!string.IsNullOrEmpty(entityPath))
{
var nestedEntityClassRef = new EntityPropertyReference(entityPath, fullName, entity, description, isArray);
EntityClasses[entityPath].EntityReferences[fullName] = nestedEntityClassRef;
}
else
Warnings.Add($"Unable find host to hold the entity reference ${fullName}");
}
return nestedEntityClasses;
}