Skip to content

Commit

Permalink
Add service registration command
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-m-knight-gs committed Dec 15, 2023
1 parent 8da64eb commit ffac34e
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,11 @@
import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.core.StreamWriteFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.function.Consumer;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.impl.block.function.checked.ThrowingFunction;
import org.eclipse.collections.impl.utility.Iterate;
import org.eclipse.collections.impl.utility.ListIterate;
import org.finos.legend.engine.ide.lsp.extension.declaration.LegendDeclaration;
Expand Down Expand Up @@ -76,6 +68,19 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.function.Consumer;

abstract class AbstractLSPGrammarExtension implements LegendLSPGrammarExtension
{
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractLSPGrammarExtension.class);
Expand Down Expand Up @@ -478,6 +483,11 @@ protected CompileResult tryCompile(GlobalState globalState, DocumentState docume
}

protected PureModelContextData buildPureModelContextData(GlobalState globalState)
{
return pureModelContextDataBuilder(globalState).build();
}

protected PureModelContextData.Builder pureModelContextDataBuilder(GlobalState globalState)
{
PureModelContextData.Builder builder = PureModelContextData.newBuilder();
globalState.forEachDocumentState(docState -> docState.forEachSectionState(secState ->
Expand All @@ -492,7 +502,7 @@ protected PureModelContextData buildPureModelContextData(GlobalState globalState
builder.addElements(parseResult.getElements());
}
}));
return builder.build();
return builder;
}

protected PureModelContextData deserializePMCD(String json)
Expand Down Expand Up @@ -527,7 +537,22 @@ protected boolean isEngineServerConfigured()
return this.engineServerClient.isServerConfigured();
}

protected String postEngineServer(String path, Object payload)
{
return postEngineServer(path, payload, stream ->
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
stream.transferTo(bytes);
return bytes.toString(StandardCharsets.UTF_8);
});
}

protected <T> T postEngineServer(String path, Object payload, Class<T> responseType)
{
return postEngineServer(path, payload, stream -> getProtocolMapper().readValue(stream, responseType));
}

protected <T> T postEngineServer(String path, Object payload, ThrowingFunction<InputStream, T> consumer)
{
if (!isEngineServerConfigured())
{
Expand All @@ -538,7 +563,7 @@ protected <T> T postEngineServer(String path, Object payload, Class<T> responseT
{
JsonMapper mapper = getProtocolMapper();
String payloadJson = mapper.writeValueAsString(payload);
return this.engineServerClient.post(path, payloadJson, stream -> mapper.readValue(stream, responseType));
return this.engineServerClient.post(path, payloadJson, consumer);
}
catch (IOException e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package org.finos.legend.engine.ide.lsp.extension;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.core.StreamWriteFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.eclipse.collections.api.factory.Lists;
Expand Down Expand Up @@ -87,10 +89,7 @@ public class PureLSPGrammarExtension extends AbstractLegacyParserLSPGrammarExten
private static final String EXEC_FUNCTION_ID = "legend.pure.executeFunction";
private static final String EXEC_FUNCTION_TITLE = "Execute function";

private static final JsonMapper JSON = PureProtocolObjectMapperFactory.withPureProtocolExtensions(JsonMapper.builder()
.enable(SerializationFeature.INDENT_OUTPUT)
.serializationInclusion(JsonInclude.Include.NON_NULL)
.build());
private JsonMapper functionResultMapper;

public PureLSPGrammarExtension()
{
Expand Down Expand Up @@ -121,8 +120,8 @@ protected void collectCommands(SectionState sectionState, PackageableElement ele
public Iterable<? extends LegendExecutionResult> execute(SectionState section, String entityPath, String commandId, Map<String, String> executableArgs)
{
return EXEC_FUNCTION_ID.equals(commandId) ?
executeFunction(section, entityPath) :
super.execute(section, entityPath, commandId, executableArgs);
executeFunction(section, entityPath) :
super.execute(section, entityPath, commandId, executableArgs);
}

@Override
Expand Down Expand Up @@ -296,12 +295,30 @@ private String getConstantValueResult(Object value)
}
try
{
return JSON.writeValueAsString(value);
return getFunctionResultMapper().writeValueAsString(value);
}
catch (Exception e)
{
LOGGER.error("Error converting value to JSON", e);
}
return value.toString();
}

private JsonMapper getFunctionResultMapper()
{
synchronized (this)
{
if (this.functionResultMapper == null)
{
this.functionResultMapper = PureProtocolObjectMapperFactory.withPureProtocolExtensions(JsonMapper.builder()
.disable(StreamWriteFeature.AUTO_CLOSE_TARGET)
.disable(StreamReadFeature.AUTO_CLOSE_SOURCE)
.enable(SerializationFeature.INDENT_OUTPUT)
.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
.serializationInclusion(JsonInclude.Include.NON_NULL)
.build());
}
return this.functionResultMapper;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

package org.finos.legend.engine.ide.lsp.extension;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.core.StreamWriteFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.impl.utility.Iterate;
Expand All @@ -25,6 +31,14 @@
import org.finos.legend.engine.plan.execution.PlanExecutor;
import org.finos.legend.engine.plan.generation.extension.PlanGeneratorExtension;
import org.finos.legend.engine.plan.generation.transformers.PlanTransformer;
import org.finos.legend.engine.protocol.Protocol;
import org.finos.legend.engine.protocol.pure.PureClientVersions;
import org.finos.legend.engine.protocol.pure.v1.PureProtocolObjectMapperFactory;
import org.finos.legend.engine.protocol.pure.v1.model.context.AlloySDLC;
import org.finos.legend.engine.protocol.pure.v1.model.context.PackageableElementPointer;
import org.finos.legend.engine.protocol.pure.v1.model.context.PackageableElementType;
import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData;
import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextPointer;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.Service;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.ServiceTestSuite;
Expand Down Expand Up @@ -52,6 +66,11 @@ public class ServiceLSPGrammarExtension extends AbstractSectionParserLSPGrammarE
private static final String RUN_LEGACY_TESTS_COMMAND_ID = "legend.service.runLegacyTests";
private static final String RUN_LEGACY_TESTS_COMMAND_TITLE = "Run legacy tests";

private static final String REGISTER_SERVICE_COMMAND_ID = "legend.service.registerService";
private static final String REGISTER_SERVICE_COMMAND_TITLE = "Register service";

private JsonMapper resultMapper;

public ServiceLSPGrammarExtension()
{
super(ServiceParserExtension.NAME, new ServiceParserExtension());
Expand Down Expand Up @@ -81,6 +100,10 @@ protected void collectCommands(SectionState sectionState, PackageableElement ele
if (element instanceof Service)
{
Service service = (Service) element;
if (isEngineServerConfigured())
{
consumer.accept(REGISTER_SERVICE_COMMAND_ID, REGISTER_SERVICE_COMMAND_TITLE, service.sourceInformation);
}
if (service.test != null)
{
consumer.accept(RUN_LEGACY_TESTS_COMMAND_ID, RUN_LEGACY_TESTS_COMMAND_TITLE, service.sourceInformation);
Expand All @@ -91,9 +114,21 @@ protected void collectCommands(SectionState sectionState, PackageableElement ele
@Override
public Iterable<? extends LegendExecutionResult> execute(SectionState section, String entityPath, String commandId, Map<String, String> executableArgs)
{
return RUN_LEGACY_TESTS_COMMAND_ID.equals(commandId) ?
runLegacyServiceTest(section, entityPath) :
super.execute(section, entityPath, commandId, executableArgs);
switch (commandId)
{
case RUN_LEGACY_TESTS_COMMAND_ID:
{
return runLegacyServiceTest(section, entityPath);
}
case REGISTER_SERVICE_COMMAND_ID:
{
return registerService(section, entityPath);
}
default:
{
return super.execute(section, entityPath, commandId, executableArgs);
}
}
}

private Iterable<? extends LegendExecutionResult> runLegacyServiceTest(SectionState section, String entityPath)
Expand Down Expand Up @@ -177,4 +212,58 @@ private Type toResultType(TestResult testResult)
}
}
}

private Iterable<? extends LegendExecutionResult> registerService(SectionState section, String entityPath)
{
try
{
Protocol serializer = new Protocol("pure", PureClientVersions.production);
PureModelContextPointer origin = new PureModelContextPointer();
origin.serializer = serializer;
origin.sdlcInfo = new AlloySDLC();
origin.sdlcInfo.baseVersion = "latest";
origin.sdlcInfo.version = "none";
origin.sdlcInfo.packageableElementPointers = Collections.singletonList(new PackageableElementPointer(PackageableElementType.SERVICE, entityPath));
PureModelContextData pmcd = pureModelContextDataBuilder(section.getDocumentState().getGlobalState())
.withSerializer(serializer)
.withOrigin(origin)
.build();
String response = postEngineServer("/service/v1/register_fullInteractive", pmcd);
try
{
// Try to parse it as JSON and then format it prettily
JsonMapper mapper = getResultMapper();
JsonNode node = mapper.readTree(response);
String formatted = mapper.writeValueAsString(node);
return Collections.singletonList(LegendExecutionResult.newResult(entityPath, Type.SUCCESS, formatted));
}
catch (Exception ignore)
{
// Couldn't format as JSON
return Collections.singletonList(LegendExecutionResult.newResult(entityPath, Type.SUCCESS, response));
}
}
catch (Exception e)
{
return Collections.singletonList(errorResult(e, entityPath));
}
}

private JsonMapper getResultMapper()
{
synchronized (this)
{
if (this.resultMapper == null)
{
this.resultMapper = PureProtocolObjectMapperFactory.withPureProtocolExtensions(JsonMapper.builder()
.disable(StreamWriteFeature.AUTO_CLOSE_TARGET)
.disable(StreamReadFeature.AUTO_CLOSE_SOURCE)
.enable(SerializationFeature.INDENT_OUTPUT)
.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
.serializationInclusion(JsonInclude.Include.NON_NULL)
.build());
}
return this.resultMapper;
}
}
}

0 comments on commit ffac34e

Please sign in to comment.