Skip to content

Commit

Permalink
Add concrete element serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-m-knight-gs committed Feb 3, 2025
1 parent 667dc25 commit af68770
Show file tree
Hide file tree
Showing 21 changed files with 3,239 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
import org.finos.legend.pure.m4.ModelRepository;
import org.finos.legend.pure.m4.coreinstance.CoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.BooleanCoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.ByteCoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.DateCoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.DecimalCoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.FloatCoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.IntegerCoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.StrictTimeCoreInstance;
import org.finos.legend.pure.m4.coreinstance.primitive.date.DateFunctions;
import org.finos.legend.pure.m4.coreinstance.primitive.date.PureDate;
import org.finos.legend.pure.m4.coreinstance.primitive.strictTime.PureStrictTime;
import org.finos.legend.pure.m4.coreinstance.primitive.strictTime.StrictTimeFunctions;

import java.math.BigDecimal;
import java.math.BigInteger;
Expand All @@ -52,6 +56,16 @@ public static boolean getBooleanValue(CoreInstance instance, boolean defaultIfNu
return (instance == null) ? defaultIfNull : getBooleanValue(instance);
}

public static byte getByteValue(CoreInstance instance)
{
return (instance instanceof ByteCoreInstance) ? ((ByteCoreInstance) instance).getValue() : Byte.parseByte(instance.getName());
}

public static byte getByteValue(CoreInstance instance, byte defaultIfNull)
{
return (instance == null) ? defaultIfNull : getByteValue(instance);
}

public static PureDate getDateValue(CoreInstance instance)
{
return (instance instanceof DateCoreInstance) ? ((DateCoreInstance) instance).getValue() : DateFunctions.parsePureDate(instance.getName());
Expand Down Expand Up @@ -122,6 +136,16 @@ public static Number getIntegerValue(CoreInstance instance, BigInteger defaultIf
return (instance == null) ? defaultIfNull : getIntegerValue(instance);
}

public static PureStrictTime getStrictTimeValue(CoreInstance instance)
{
return (instance instanceof StrictTimeCoreInstance) ? ((StrictTimeCoreInstance) instance).getValue() : StrictTimeFunctions.parsePureStrictTime(instance.getName());
}

public static PureStrictTime getStrictTimeValue(CoreInstance instance, PureStrictTime defaultIfNull)
{
return (instance == null) ? defaultIfNull : getStrictTimeValue(instance);
}

public static String getStringValue(CoreInstance instance)
{
return instance.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,19 @@ public static String getPropertyName(CoreInstance property)
return PrimitiveUtilities.getStringValue(property.getValueForMetaPropertyToOne(M3Properties.name));
}

public static CoreInstance getPropertySourceType(CoreInstance property, ProcessorSupport processorSupport)
{
CoreInstance classifierGenericType = property.getValueForMetaPropertyToOne(M3Properties.classifierGenericType);
ListIterable<? extends CoreInstance> typeArguments = classifierGenericType.getValueForMetaPropertyToMany(M3Properties.typeArguments);
return Instance.getValueForMetaPropertyToOneResolved(typeArguments.get(0), M3Properties.rawType, processorSupport);
}

public static ListIterable<String> calculatePropertyPath(CoreInstance property, ProcessorSupport processorSupport)
{
// Example: [Root, children, core, children, Any, properties, classifierGenericType]
String propertyName = getPropertyName(property);

CoreInstance sourceType = Instance.getValueForMetaPropertyToOneResolved(Instance.getValueForMetaPropertyToManyResolved(Instance.getValueForMetaPropertyToOneResolved(property, M3Properties.classifierGenericType, processorSupport), M3Properties.typeArguments, processorSupport).get(0), M3Properties.rawType, processorSupport);
CoreInstance sourceType = getPropertySourceType(property, processorSupport);

String propertiesProperty = getPropertiesProperty(sourceType, property);
if (propertiesProperty == null)
Expand Down Expand Up @@ -153,8 +160,8 @@ public static CoreInstance resolvePropertyReturnMultiplicity(CoreInstance source
return multiplicity;
}

CoreInstance propertyOwnerRawType = Instance.getValueForMetaPropertyToOneResolved(Instance.getValueForMetaPropertyToManyResolved(Instance.getValueForMetaPropertyToOneResolved(property, M3Properties.classifierGenericType, processorSupport), M3Properties.typeArguments, processorSupport).get(0), M3Properties.rawType, processorSupport);
GenericTypeWithXArguments p = GenericType.resolveClassMultiplicityParameterUsingInheritance(sourceGenericType, propertyOwnerRawType, processorSupport);
CoreInstance propertySourceType = getPropertySourceType(property, processorSupport);
GenericTypeWithXArguments p = GenericType.resolveClassMultiplicityParameterUsingInheritance(sourceGenericType, propertySourceType, processorSupport);
return p.getArgumentsByParameterName().get(Multiplicity.getMultiplicityParameter(multiplicity));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2024 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.finos.legend.pure.m3.serialization.compiler.element;

import org.finos.legend.pure.m3.navigation.ProcessorSupport;
import org.finos.legend.pure.m3.serialization.compiler.ExtensibleSerializer;
import org.finos.legend.pure.m3.serialization.compiler.reference.ReferenceIdProvider;
import org.finos.legend.pure.m3.serialization.compiler.reference.ReferenceIds;
import org.finos.legend.pure.m3.serialization.compiler.strings.StringIndexer;
import org.finos.legend.pure.m4.coreinstance.CoreInstance;
import org.finos.legend.pure.m4.serialization.Reader;
import org.finos.legend.pure.m4.serialization.Writer;

import java.util.Arrays;
import java.util.Objects;

public class ConcreteElementSerializer extends ExtensibleSerializer<ConcreteElementSerializerExtension>
{
private static final long LEGEND_ENTITY_SIGNATURE = Long.parseLong("LegendEntity", 36);

private final ReferenceIds referenceIds;
private final StringIndexer stringIndexer;
private final ProcessorSupport processorSupport;

private ConcreteElementSerializer(Iterable<? extends ConcreteElementSerializerExtension> extensions, int defaultVersion, StringIndexer stringIndexer, ReferenceIds referenceIds, ProcessorSupport processorSupport)
{
super(extensions, defaultVersion);
this.stringIndexer = stringIndexer;
this.referenceIds = referenceIds;
this.processorSupport = processorSupport;
}

public void serialize(Writer writer, CoreInstance element)
{
serialize(writer, element, getDefaultExtension(), this.referenceIds.provider());
}

public void serialize(Writer writer, CoreInstance element, int serializerVersion, int referenceIdVersion)
{
ConcreteElementSerializerExtension serializerExtension = getExtension(serializerVersion);
ReferenceIdProvider referenceIdProvider = this.referenceIds.provider(referenceIdVersion);
serialize(writer, element, serializerExtension, referenceIdProvider);
}

private void serialize(Writer writer, CoreInstance element, ConcreteElementSerializerExtension serializerExtension, ReferenceIdProvider referenceIdProvider)
{
writer.writeLong(LEGEND_ENTITY_SIGNATURE);
writer.writeInt(serializerExtension.version());
writer.writeInt(referenceIdProvider.version());
serializerExtension.serialize(writer, element, new SerializationContext(this.stringIndexer, referenceIdProvider, this.processorSupport));
}

public DeserializedConcreteElement deserialize(Reader reader)
{
long signature = reader.readLong();
if (signature != LEGEND_ENTITY_SIGNATURE)
{
throw new IllegalArgumentException("Invalid file format: not a Legend concrete element file");
}
int version = reader.readInt();
ConcreteElementSerializerExtension extension = getExtension(version);
int referenceIdVersion = reader.readInt();
return extension.deserialize(reader, new SerializationContext(this.stringIndexer, this.referenceIds.provider(referenceIdVersion), this.processorSupport));
}

public static Builder builder(ProcessorSupport processorSupport)
{
return new Builder(processorSupport);
}

public static class Builder extends AbstractBuilder<ConcreteElementSerializerExtension, ConcreteElementSerializer>
{
private StringIndexer stringIndexer;
private ReferenceIds referenceIds;
private final ProcessorSupport processorSupport;

private Builder(ProcessorSupport processorSupport)
{
this.processorSupport = Objects.requireNonNull(processorSupport);
}

public Builder withExtension(ConcreteElementSerializerExtension extension)
{
addExtension(extension);
return this;
}

public Builder withExtensions(Iterable<? extends ConcreteElementSerializerExtension> extensions)
{
addExtensions(extensions);
return this;
}

public Builder withExtensions(ConcreteElementSerializerExtension... extensions)
{
return withExtensions(Arrays.asList(extensions));
}

public Builder withLoadedExtensions(ClassLoader classLoader)
{
loadExtensions(classLoader);
return this;
}

public Builder withLoadedExtensions()
{
loadExtensions();
return this;
}

public Builder withDefaultVersion(int defaultVersion)
{
setDefaultVersion(defaultVersion);
return this;
}

public Builder withStringIndexer(StringIndexer stringIndexer)
{
this.stringIndexer = stringIndexer;
return this;
}

public Builder withReferenceIds(ReferenceIds referenceIds)
{
this.referenceIds = referenceIds;
return this;
}

@Override
protected ConcreteElementSerializer build(Iterable<ConcreteElementSerializerExtension> extensions, int defaultVersion)
{
return new ConcreteElementSerializer(extensions, defaultVersion, resolveStringIndexer(), resolveReferenceIds(), this.processorSupport);
}

private ReferenceIds resolveReferenceIds()
{
// If reference ids has not been specified, create one
return (this.referenceIds == null) ?
ReferenceIds.builder(this.processorSupport).withAvailableExtensions().build() :
this.referenceIds;
}

private StringIndexer resolveStringIndexer()
{
// if string indexer has not been specified, use the default
return (this.stringIndexer == null) ? StringIndexer.defaultStringIndexer() : this.stringIndexer;
}

@Override
protected Class<ConcreteElementSerializerExtension> getExtensionClass()
{
return ConcreteElementSerializerExtension.class;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2024 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.finos.legend.pure.m3.serialization.compiler.element;

import org.finos.legend.pure.m3.serialization.compiler.SerializerExtension;
import org.finos.legend.pure.m4.coreinstance.CoreInstance;
import org.finos.legend.pure.m4.serialization.Reader;
import org.finos.legend.pure.m4.serialization.Writer;

public interface ConcreteElementSerializerExtension extends SerializerExtension
{
void serialize(Writer writer, CoreInstance element, SerializationContext serializationContext);

DeserializedConcreteElement deserialize(Reader reader, SerializationContext serializationContext);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2024 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.finos.legend.pure.m3.serialization.compiler.element;

public interface DeserializedConcreteElement extends DeserializedElement
{
String getPath();

DeserializedElement getInternalElement(int id);

int getReferenceIdVersion();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2024 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.finos.legend.pure.m3.serialization.compiler.element;

import org.finos.legend.pure.m4.coreinstance.SourceInformation;

public interface DeserializedElement
{
String getName();

String getClassifierReferenceId();

SourceInformation getSourceInformation();

Iterable<? extends PropertyValues> getPropertyValues();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2024 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.finos.legend.pure.m3.serialization.compiler.element;

import org.eclipse.collections.api.list.ListIterable;

public interface PropertyValues
{
String getPropertyName();

ListIterable<String> getRealKey();

ListIterable<ValueOrReference> getValues();
}
Loading

0 comments on commit af68770

Please sign in to comment.