Skip to content

Commit

Permalink
Add reference ids
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-m-knight-gs committed Jan 31, 2025
1 parent f9e3796 commit 341ebbe
Showing 1 changed file with 71 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.finos.legend.pure.m3.serialization.compiler.reference.v1;

import org.eclipse.collections.api.block.procedure.Procedure2;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.factory.Sets;
Expand Down Expand Up @@ -187,7 +188,7 @@ private MapIterable<CoreInstance, GraphPath> generateIdGraphPaths()
private void advanceFromSearchNode(SearchNode searchNode)
{
CoreInstance instance = searchNode.pathNodes.getLast();
this.typeCache.getSimplePropertyInfo(searchNode.finalNodeClassifier).forEachKeyValue((propertyName, propertyInfo) ->
this.typeCache.getClassInfo(searchNode.finalNodeClassifier).forEachPropertyInfo((propertyName, propertyInfo) ->
{
if (propertyInfo.shouldSkip())
{
Expand Down Expand Up @@ -265,27 +266,26 @@ private boolean isInternal(CoreInstance instance)
private PropertyIndex tryIndex(PropertyInfo propertyInfo, ListIterable<? extends CoreInstance> values)
{
// Figure out which key to index by (if any)
String keyProp = propertyInfo.getIndexKey();
if (keyProp == null)
for (String keyProp : this.typeCache.getClassInfo(propertyInfo.getRawType()).getIndexKeys())
{
return null;
}

// Check that the key is present, to-one, and has type of String
PropertyInfo keyPropInfo = this.typeCache.getSimplePropertyInfo(propertyInfo.getRawType()).get(keyProp);
if ((keyPropInfo == null) || !keyPropInfo.isToOne() || !this.typeCache.isStringType(keyPropInfo.getRawType()))
{
return null;
PropertyIndex index = tryIndex(keyProp, values);
if (index != null)
{
return index;
}
}
return null;
}

// Try to build an index
private PropertyIndex tryIndex(String keyProp, ListIterable<? extends CoreInstance> values)
{
// Try to build an index with the given key property
MutableMap<String, CoreInstance> index = Maps.mutable.ofInitialCapacity(values.size());
for (CoreInstance value : values)
{
String key = PrimitiveUtilities.getStringValue(value.getValueForMetaPropertyToOne(keyProp), null);
if ((key == null) || (index.put(key, value) != null))
{
// Either no key exists for the value or there is a clash: cannot build an index
return null;
}
}
Expand Down Expand Up @@ -398,7 +398,7 @@ private static class TypeCache
private final CoreInstance qualifiedPropertyClass;
private final CoreInstance stereotypeClass;
private final CoreInstance tagClass;
private final ConcurrentMutableMap<CoreInstance, MapIterable<String, PropertyInfo>> propertyInfoByClassByName = ConcurrentHashMap.newMap();
private final ConcurrentMutableMap<CoreInstance, ClassInfo> classInfos = ConcurrentHashMap.newMap();

private TypeCache(ProcessorSupport processorSupport)
{
Expand Down Expand Up @@ -432,32 +432,34 @@ boolean isStringType(CoreInstance instance)
return this.stringType == instance;
}

MapIterable<String, PropertyInfo> getSimplePropertyInfo(CoreInstance classifier)
private ClassInfo getClassInfo(CoreInstance classifier)
{
return this.propertyInfoByClassByName.getIfAbsentPutWithKey(classifier, this::computeSimplePropertyInfo);
return (classifier == null) ?
new ClassInfo(Maps.immutable.empty(), Lists.immutable.empty()) :
this.classInfos.getIfAbsentPutWithKey(classifier, this::computeClassInfo);
}

private MapIterable<String, PropertyInfo> computeSimplePropertyInfo(CoreInstance classifier)
private ClassInfo computeClassInfo(CoreInstance classifier)
{
MapIterable<String, CoreInstance> properties = this.processorSupport.class_getSimplePropertiesByName(classifier);
if (properties.isEmpty())
{
return Maps.immutable.empty();
return new ClassInfo(Maps.immutable.empty(), Lists.immutable.empty());
}

CoreInstance classGenericType = Type.wrapGenericType(classifier, classifier.getSourceInformation(), this.processorSupport);
MutableMap<String, PropertyInfo> map = Maps.mutable.empty();
MutableMap<String, PropertyInfo> map = Maps.mutable.ofInitialCapacity(properties.size());
properties.forEachKeyValue((name, prop) -> map.put(name, computePropertyInfo(classGenericType, name, prop)));
if (classifier == this.enumerationClass)
{
// Special handling for Enumeration: the type of values is T, but we know that T will always be a subclass of Enum
PropertyInfo propInfo = map.get(M3Properties.values);
if ((propInfo != null) && (propInfo.getRawType() == null))
{
map.put(M3Properties.values, new ToManyPropertyInfoDefaultIndexKey(this.processorSupport.package_getByUserPath(M3Paths.Enum)));
map.put(M3Properties.values, new ToManyPropertyInfo(this.processorSupport.package_getByUserPath(M3Paths.Enum)));
}
}
return map.isEmpty() ? Maps.immutable.empty() : map;
return new ClassInfo(map.toImmutable(), getIndexKeys(classifier, map));
}

private PropertyInfo computePropertyInfo(CoreInstance classGenericType, String propertyName, CoreInstance property)
Expand All @@ -471,18 +473,9 @@ private PropertyInfo computePropertyInfo(CoreInstance classGenericType, String p
return shouldSkipProperty(propertyName, property) ? new ToOneSkipPropertyInfo(rawType) : new ToOnePropertyInfo(rawType);
}

if (rawType == null)
{
return new ToManyPropertyInfoNoIndexKey(null);
}

if (isPrimitiveType(rawType) || shouldSkipProperty(propertyName, property))
{
return new ToManySkipPropertyInfo(rawType);
}

String indexKey = getSpecialIndexKey(rawType);
return (indexKey == null) ? new ToManyPropertyInfoDefaultIndexKey(rawType) : new ToManyPropertyInfoSpecialIndexKey(rawType, indexKey);
return ((rawType != null) && (isPrimitiveType(rawType) || shouldSkipProperty(propertyName, property))) ?
new ToManySkipPropertyInfo(rawType) :
new ToManyPropertyInfo(rawType);
}

private boolean shouldSkipProperty(String propertyName, CoreInstance property)
Expand All @@ -491,17 +484,32 @@ private boolean shouldSkipProperty(String propertyName, CoreInstance property)
return (realKeyToSkip != null) && realKeyToSkip.equals(Property.calculatePropertyPath(property, this.processorSupport));
}

private String getSpecialIndexKey(CoreInstance rawType)
private ImmutableList<String> getIndexKeys(CoreInstance classifier, MapIterable<String, PropertyInfo> propertyInfos)
{
if (this.qualifiedPropertyClass == rawType)
if (this.qualifiedPropertyClass == classifier)
{
return M3Properties.id;
return Lists.immutable.with(M3Properties.id);
}
if ((this.stereotypeClass == rawType) || (this.tagClass == rawType))
if ((this.stereotypeClass == classifier) || (this.tagClass == classifier))
{
return M3Properties.value;
return Lists.immutable.with(M3Properties.value);
}
return null;
if (isPossibleIndexKey(propertyInfos.get(M3Properties.name)))
{
return isPossibleIndexKey(propertyInfos.get(M3Properties.id)) ?
Lists.immutable.with(M3Properties.name, M3Properties.id) :
Lists.immutable.with(M3Properties.name);
}
if (isPossibleIndexKey(propertyInfos.get(M3Properties.id)))
{
return Lists.immutable.with(M3Properties.id);
}
return Lists.immutable.empty();
}

private boolean isPossibleIndexKey(PropertyInfo propertyInfo)
{
return (propertyInfo != null) && propertyInfo.isToOne() && isStringType(propertyInfo.getRawType());
}
}

Expand All @@ -519,6 +527,28 @@ private SearchNode(GraphPath path, ImmutableList<CoreInstance> pathNodes, CoreIn
}
}

private static class ClassInfo
{
private final MapIterable<String, PropertyInfo> propertyInfos;
private final ImmutableList<String> indexKeys;

private ClassInfo(MapIterable<String, PropertyInfo> propertyInfos, ImmutableList<String> indexKeys)
{
this.propertyInfos = propertyInfos;
this.indexKeys = indexKeys;
}

ImmutableList<String> getIndexKeys()
{
return this.indexKeys;
}

void forEachPropertyInfo(Procedure2<? super String, ? super PropertyInfo> procedure)
{
this.propertyInfos.forEachKeyValue(procedure);
}
}

private abstract static class PropertyInfo
{
private final CoreInstance rawType;
Expand All @@ -539,11 +569,6 @@ boolean shouldSkip()
}

abstract boolean isToOne();

String getIndexKey()
{
return null;
}
}

private static class ToOnePropertyInfo extends PropertyInfo
Expand Down Expand Up @@ -574,7 +599,7 @@ public boolean shouldSkip()
}
}

private abstract static class ToManyPropertyInfo extends PropertyInfo
private static class ToManyPropertyInfo extends PropertyInfo
{
private ToManyPropertyInfo(CoreInstance rawType)
{
Expand All @@ -588,15 +613,7 @@ public boolean isToOne()
}
}

private static class ToManyPropertyInfoNoIndexKey extends ToManyPropertyInfo
{
private ToManyPropertyInfoNoIndexKey(CoreInstance rawType)
{
super(rawType);
}
}

private static class ToManySkipPropertyInfo extends ToManyPropertyInfoNoIndexKey
private static class ToManySkipPropertyInfo extends ToManyPropertyInfo
{
private ToManySkipPropertyInfo(CoreInstance rawType)
{
Expand All @@ -610,37 +627,6 @@ boolean shouldSkip()
}
}

private static class ToManyPropertyInfoDefaultIndexKey extends ToManyPropertyInfo
{
private ToManyPropertyInfoDefaultIndexKey(CoreInstance rawType)
{
super(rawType);
}

@Override
String getIndexKey()
{
return M3Properties.name;
}
}

private static class ToManyPropertyInfoSpecialIndexKey extends ToManyPropertyInfo
{
private final String indexKey;

private ToManyPropertyInfoSpecialIndexKey(CoreInstance rawType, String indexKey)
{
super(rawType);
this.indexKey = indexKey;
}

@Override
String getIndexKey()
{
return this.indexKey;
}
}

private static class PropertyIndex
{
private final String property;
Expand Down

0 comments on commit 341ebbe

Please sign in to comment.