public CommonSchemaTypesProjection CreateProjection()

in tools/Elastic.CommonSchema.Generator/Projection/TypeProjector.cs [102:172]


		public CommonSchemaTypesProjection CreateProjection()
		{
			if (Projection != null) return Projection;

			var nestedEntityTypes = CreateEntityTypes();

			var entities = EntityClasses.Values;
			var assignables = entities
				.Concat(nestedEntityTypes.Values)
				.Where(e => e.EntityReferences.Count > 0)
				.SelectMany(e => e.EntityReferences.Select(r => (EntityClass: e, EntityPropertyReference: r)).ToList())
				.Select(r =>
				{
					var prop = r.EntityPropertyReference;
					var sharedKey = prop.Key.Split('.') switch
					{
						[.. { Length: > 1 } ] a => string.Join('.', a[1..]).PascalCase(),
						_ => prop.Key.PascalCase()
					};
					if (r.EntityPropertyReference.Value.Entity is SelfReferentialReusedEntityClass s)
						sharedKey = s.Name;
					return (Key: sharedKey, r.EntityClass, r.EntityPropertyReference);
				})
				.GroupBy(e => e.Key)
				.SelectMany(g =>
					g.Select(r => r.EntityPropertyReference.Value).DistinctBy(r=>r.ClrType)
						.Select(r => new AssignableEntityInterface(g.Key, r, g.Select(r=>r.EntityClass).ToList()))
					)
				//.DistinctBy(g=>g.Name)
				.ToList();
			foreach (var entity in entities)
				entity.AssignableInterfaces = assignables.Where(a => a.Entities.Contains(entity)).DistinctBy(a=>a.Name).ToList();

			Projection = new CommonSchemaTypesProjection
			{
				Version = Schema.Version,
				GitRef = Schema.GitRef,
				FieldSets = FieldSetsBaseClasses.Values.Where(e=>e.FieldSet.Root != true || e.FieldSet.Name == "base" ).ToList(),
				EntityClasses = EntityClasses.Values.Where(e => e.Name != "EcsDocument" && e.BaseFieldSet.FieldSet.Root != true).ToList(),
				EntitiesWithPropertiesAtRoot = new Dictionary<EntityClass, string[]>
				{
					{ EntityClasses.Values.First(e=>e.Name == "Log"), new []{"level"}},
					{ EntityClasses.Values.First(e=>e.Name == "Ecs"), new []{"version"}},
				},
				Base = EntityClasses.Values.First(e=>e.Name == "EcsDocument"),
				InlineObjects = InlineObjects.Values.ToList(),
				NestedEntityClasses = nestedEntityTypes.Values.ToList(),
				Warnings = Warnings.AsReadOnly(),
				IndexTemplates = Schema.Templates.Select(kv => new IndexTemplate(kv.Key, kv.Value, Schema.Version)).OrderBy(t=>t.Name).ToList(),
				IndexComponents = Schema.Components.Select(kv => new IndexComponent(kv.Key, kv.Value, Schema.Version)).OrderBy(t=>t.Name).ToList(),
				AssignableInterfaces = assignables
			};

			var assignableToEcsDocument = Projection.EntityClasses.Select(e=> assignables.FirstOrDefault(a=>a.Property.Entity == e && a.Property.Name == e.Name)).Where(a => a != null).ToList();
			Projection.Base.AssignableInterfaces = assignableToEcsDocument;

			var allEntities = Projection.EntityClasses.Concat(Projection.NestedEntityClasses).ToDictionary(kv=>kv.Name);
			var assignable = Projection.AssignableInterfaces.ToDictionary(e => e.Name.Substring(1, e.Name.Length - 1));
			var propDispatches = new List<PropDispatch>();
			foreach (var (name, entity) in allEntities)
			{
				var found = assignable.TryGetValue(name, out var a);
				if (found && a.Property.IsArray)
					continue;
				if (entity is SelfReferentialReusedEntityClass)
					continue;
				propDispatches.Add(new PropDispatch(entity, a));
			}
			Projection.AssignablePropDispatches = propDispatches;
			return Projection;
		}