diff --git a/legend-sdlc-server-demo/Dockerfile b/legend-sdlc-server-demo/Dockerfile
new file mode 100644
index 0000000000..c2b98f540c
--- /dev/null
+++ b/legend-sdlc-server-demo/Dockerfile
@@ -0,0 +1,9 @@
+FROM eclipse-temurin:11.0.17_8-jdk-jammy
+COPY target/legend-sdlc-server-demo-*-shaded.jar /app/bin/
+COPY src/main/resources/docker/config /config
+CMD java -cp /app/bin/*.jar \
+-XX:+ExitOnOutOfMemoryError \
+-XX:MaxRAMPercentage=60 \
+-Xss4M \
+-Dfile.encoding=UTF8 \
+org.finos.legend.sdlc.server.demo.LegendSDLCServerForDemo server /config/config.json
diff --git a/legend-sdlc-server-demo/pom.xml b/legend-sdlc-server-demo/pom.xml
new file mode 100644
index 0000000000..b369e5529c
--- /dev/null
+++ b/legend-sdlc-server-demo/pom.xml
@@ -0,0 +1,197 @@
+
+
+
+ legend-sdlc
+ org.finos.legend.sdlc
+ 0.135.2-SNAPSHOT
+
+ 4.0.0
+
+ legend-sdlc-server-demo
+ Legend SDLC Server - Demo
+
+
+ 11
+ 11
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+
+
+
+
+ org.slf4j:jcl-over-slf4j:${slf4j.version}
+ org.slf4j:jul-to-slf4j:${slf4j.version}
+ ch.qos.logback:logback-access
+ ch.qos.logback:logback-classic
+ ch.qos.logback:logback-core
+
+
+
+
+
+
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+ false
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
+ true
+
+
+
+ org.finos.legend.sdlc.server.LegendSDLCServer
+
+
+
+
+
+
+
+
+
+
+
+
+ org.finos.legend.sdlc
+ legend-sdlc-model
+
+
+ org.finos.legend.sdlc
+ legend-sdlc-server-shared
+
+
+ com.zaxxer
+ HikariCP
+
+
+ org.glassfish.hk2.external
+ *
+
+
+
+
+ org.finos.legend.sdlc
+ legend-sdlc-extensions-collection-entity-serializer
+ runtime
+
+
+ org.finos.legend.sdlc
+ legend-sdlc-server
+
+
+ org.gitlab4j
+ *
+
+
+
+
+
+
+
+ org.finos.legend.engine
+ legend-engine-protocol-pure
+
+
+
+
+ org.eclipse.collections
+ eclipse-collections-api
+
+
+ org.eclipse.collections
+ eclipse-collections
+
+
+
+
+ com.google.inject
+ guice
+
+
+ com.google.inject.extensions
+ guice-servlet
+
+
+
+ javax.servlet
+ javax.servlet-api
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+
+ com.hubspot.dropwizard
+ dropwizard-guicier
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ io.dropwizard
+ dropwizard-core
+
+
+
+ io.swagger
+ swagger-annotations
+
+
+
+ javax.inject
+ javax.inject
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+ io.dropwizard
+ dropwizard-testing
+ test
+
+
+
+ junit
+ junit
+ test
+
+
+
+
+
\ No newline at end of file
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/backup/SimpleBackendBackupApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/backup/SimpleBackendBackupApi.java
new file mode 100644
index 0000000000..37f5d71752
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/backup/SimpleBackendBackupApi.java
@@ -0,0 +1,41 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.backup;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.backup.BackupApi;
+
+import javax.inject.Inject;
+
+public class SimpleBackendBackupApi implements BackupApi
+{
+ @Inject
+ public SimpleBackendBackupApi()
+ {
+ }
+
+ @Override
+ public void discardBackupWorkspace(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ UnavailableFeature.exception();
+ }
+
+ @Override
+ public void recoverBackupWorkspace(String projectId, String workspaceId, WorkspaceType workspaceType, boolean forceRecovery)
+ {
+ UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/build/SimpleBackendBuildAccessContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/build/SimpleBackendBuildAccessContext.java
new file mode 100644
index 0000000000..dfaecd7e30
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/build/SimpleBackendBuildAccessContext.java
@@ -0,0 +1,37 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.build;
+
+import org.finos.legend.sdlc.domain.model.build.Build;
+import org.finos.legend.sdlc.domain.model.build.BuildStatus;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.build.BuildAccessContext;
+
+import java.util.List;
+
+public class SimpleBackendBuildAccessContext implements BuildAccessContext
+{
+ @Override
+ public Build getBuild(String buildId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public List getBuilds(Iterable revisionIds, Iterable statuses, Integer limit)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/build/SimpleBackendBuildApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/build/SimpleBackendBuildApi.java
new file mode 100644
index 0000000000..4f50b2ec0c
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/build/SimpleBackendBuildApi.java
@@ -0,0 +1,50 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.build;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.domain.model.version.VersionId;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.build.BuildAccessContext;
+import org.finos.legend.sdlc.server.domain.api.build.BuildApi;
+import org.finos.legend.sdlc.server.project.ProjectFileAccessProvider;
+
+import javax.inject.Inject;
+
+public class SimpleBackendBuildApi implements BuildApi
+{
+ @Inject
+ public SimpleBackendBuildApi()
+ {
+ }
+
+ @Override
+ public BuildAccessContext getProjectBuildAccessContext(String projectId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public BuildAccessContext getWorkspaceBuildAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType, ProjectFileAccessProvider.WorkspaceAccessType workspaceAccessType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public BuildAccessContext getVersionBuildAccessContext(String projectId, VersionId versionId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/comparison/SimpleBackendComparisonApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/comparison/SimpleBackendComparisonApi.java
new file mode 100644
index 0000000000..34b5d62f3a
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/comparison/SimpleBackendComparisonApi.java
@@ -0,0 +1,54 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.comparison;
+
+import org.finos.legend.sdlc.domain.model.comparison.Comparison;
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.comparison.ComparisonApi;
+
+import javax.inject.Inject;
+
+public class SimpleBackendComparisonApi implements ComparisonApi
+{
+ @Inject
+ public SimpleBackendComparisonApi()
+ {
+ }
+
+ @Override
+ public Comparison getWorkspaceCreationComparison(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Comparison getWorkspaceProjectComparison(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Comparison getReviewComparison(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Comparison getReviewWorkspaceCreationComparison(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/conflictresolution/SimpleBackendConflictResolutionApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/conflictresolution/SimpleBackendConflictResolutionApi.java
new file mode 100644
index 0000000000..85a14d9032
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/conflictresolution/SimpleBackendConflictResolutionApi.java
@@ -0,0 +1,48 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.conflictresolution;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.server.application.entity.PerformChangesCommand;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.conflictResolution.ConflictResolutionApi;
+
+import javax.inject.Inject;
+
+public class SimpleBackendConflictResolutionApi implements ConflictResolutionApi
+{
+ @Inject
+ public SimpleBackendConflictResolutionApi()
+ {
+ }
+
+ @Override
+ public void discardConflictResolution(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public void discardChangesConflictResolution(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public void acceptConflictResolution(String projectId, String workspaceId, WorkspaceType workspaceType, PerformChangesCommand command)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/dependency/SimpleBackendDependenciesApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/dependency/SimpleBackendDependenciesApi.java
new file mode 100644
index 0000000000..d73138026e
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/dependency/SimpleBackendDependenciesApi.java
@@ -0,0 +1,50 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.dependency;
+
+import org.finos.legend.sdlc.domain.model.project.configuration.ProjectDependency;
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.server.domain.api.dependency.DependenciesApi;
+import org.finos.legend.sdlc.server.domain.api.dependency.ProjectRevision;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class SimpleBackendDependenciesApi implements DependenciesApi
+{
+ @Override
+ public Set getWorkspaceRevisionUpstreamProjects(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId, boolean transitive)
+ {
+ return Collections.EMPTY_SET;
+ }
+
+ @Override
+ public Set getProjectRevisionUpstreamProjects(String projectId, String revisionId, boolean transitive)
+ {
+ return Collections.EMPTY_SET;
+ }
+
+ @Override
+ public Set getProjectVersionUpstreamProjects(String projectId, String versionId, boolean transitive)
+ {
+ return Collections.EMPTY_SET;
+ }
+
+ @Override
+ public Set getDownstreamProjects(String projectId)
+ {
+ return Collections.EMPTY_SET;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityAccessContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityAccessContext.java
new file mode 100644
index 0000000000..d64e95f729
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityAccessContext.java
@@ -0,0 +1,80 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.entity;
+
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.revision.SimpleBackendRevision;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityAccessContext;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+public class SimpleBackendEntityAccessContext implements EntityAccessContext
+{
+ private final SimpleBackendRevision revision;
+
+ public SimpleBackendEntityAccessContext(SimpleBackendRevision revision)
+ {
+ this.revision = revision;
+ }
+
+ @Override
+ public Entity getEntity(String path)
+ {
+ List matches = this.getEntities((p) -> p.equals(path), null, null);
+ if (matches.size() > 1)
+ {
+ throw new IllegalStateException(String.format("Found %d instead of 1 matches for entity with path %s", matches.size(), path));
+ }
+ if (matches.size() == 0)
+ {
+ throw new IllegalStateException(String.format("Entity with path %s not found", path));
+ }
+ return matches.get(0);
+ }
+
+ @Override
+ public List getEntities(Predicate entityPathPredicate, Predicate classifierPathPredicate, Predicate super Map> entityContentPredicate, boolean excludeInvalid)
+ {
+ Stream stream = StreamSupport.stream(this.revision.getEntities().spliterator(), false);
+ if (entityPathPredicate != null)
+ {
+ stream = stream.filter(entity -> entityPathPredicate.test(entity.getPath()));
+ }
+
+ if (classifierPathPredicate != null)
+ {
+ stream = stream.filter(entity -> classifierPathPredicate.test(entity.getClassifierPath()));
+ }
+
+ if (entityContentPredicate != null)
+ {
+ stream = stream.filter(entity -> entityContentPredicate.test(entity.getContent()));
+ }
+
+ return stream.collect(Collectors.toList());
+ }
+
+ @Override
+ public List getEntityPaths(Predicate entityPathPredicate, Predicate classifierPathPredicate, Predicate super Map> entityContentPredicate)
+ {
+ List entities = this.getEntities(entityPathPredicate, classifierPathPredicate, entityContentPredicate);
+ return entities.stream().map(Entity::getPath).collect(Collectors.toList());
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityApi.java
new file mode 100644
index 0000000000..5c83cb432c
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityApi.java
@@ -0,0 +1,114 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.entity;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.domain.model.version.VersionId;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.backend.simple.state.SimpleBackendState;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityAccessContext;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityApi;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityModificationContext;
+
+import javax.inject.Inject;
+
+public class SimpleBackendEntityApi implements EntityApi
+{
+ private SimpleBackendState simpleBackendState;
+
+ @Inject
+ public SimpleBackendEntityApi(SimpleBackendState simpleBackendState)
+ {
+ this.simpleBackendState = simpleBackendState;
+ }
+
+ @Override
+ public EntityAccessContext getProjectEntityAccessContext(String projectId)
+ {
+ return this.simpleBackendState.getProject(projectId).getEntityAccessContext();
+ }
+
+ @Override
+ public EntityAccessContext getProjectRevisionEntityAccessContext(String projectId, String revisionId)
+ {
+ return this.simpleBackendState.getProject(projectId).getEntityAccessContext();
+ }
+
+ @Override
+ public EntityAccessContext getWorkspaceEntityAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return this.simpleBackendState.getProject(projectId).getWorkspace(workspaceId, workspaceType).getEntityAccessContext();
+ }
+
+ @Override
+ public EntityAccessContext getBackupWorkspaceEntityAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public EntityAccessContext getWorkspaceWithConflictResolutionEntityAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public EntityAccessContext getWorkspaceRevisionEntityAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId)
+ {
+ return this.simpleBackendState.getProject(projectId).getWorkspace(workspaceId, workspaceType).getEntityAccessContext();
+ }
+
+ @Override
+ public EntityAccessContext getBackupWorkspaceRevisionEntityAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public EntityAccessContext getWorkspaceWithConflictResolutionRevisionEntityAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public EntityAccessContext getReviewFromEntityAccessContext(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public EntityAccessContext getReviewToEntityAccessContext(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public EntityAccessContext getVersionEntityAccessContext(String projectId, VersionId versionId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public EntityModificationContext getWorkspaceEntityModificationContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return this.simpleBackendState.getProject(projectId).getWorkspace(workspaceId, workspaceType).getEntityModificationContext();
+ }
+
+ @Override
+ public EntityModificationContext getWorkspaceWithConflictResolutionEntityModificationContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityModificationContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityModificationContext.java
new file mode 100644
index 0000000000..88fa067058
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendEntityModificationContext.java
@@ -0,0 +1,86 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.entity;
+
+import org.eclipse.collections.api.factory.Lists;
+import org.eclipse.collections.api.list.MutableList;
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.domain.model.entity.change.EntityChange;
+import org.finos.legend.sdlc.domain.model.entity.change.EntityChangeType;
+import org.finos.legend.sdlc.domain.model.revision.Revision;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.revision.SimpleBackendRevision;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityModificationContext;
+
+import java.util.List;
+
+public class SimpleBackendEntityModificationContext implements EntityModificationContext
+{
+ private SimpleBackendRevision revision;
+
+ public SimpleBackendEntityModificationContext(SimpleBackendRevision revision)
+ {
+ this.revision = revision;
+ }
+
+ @Override
+ public Revision updateEntities(Iterable extends Entity> entities, boolean replace, String message)
+ {
+ if (!replace)
+ {
+ revision.delete(entities);
+ revision.update(entities);
+ }
+ else
+ {
+ revision.update(entities);
+ }
+ this.revision.logStats();
+ return this.revision;
+ }
+
+ @Override
+ public Revision performChanges(List extends EntityChange> changes, String revisionId, String message)
+ {
+ MutableList toAdd = Lists.mutable.empty();
+ MutableList toDelete = Lists.mutable.empty();
+ MutableList toUpdate = Lists.mutable.empty();
+ for (EntityChange change : changes)
+ {
+ if (change.getType() == EntityChangeType.CREATE)
+ {
+ String entityPath = change.getEntityPath();
+ Entity entity = Entity.newEntity(entityPath, change.getClassifierPath(), change.getContent());
+ toAdd.add(entity);
+ }
+ else if (change.getType() == EntityChangeType.DELETE)
+ {
+ String entityPath = change.getEntityPath();
+ Entity entity = Entity.newEntity(entityPath, change.getClassifierPath(), change.getContent());
+ toDelete.add(entity);
+ }
+ else if (change.getType() == EntityChangeType.MODIFY)
+ {
+ String entityPath = change.getEntityPath();
+ Entity entity = Entity.newEntity(entityPath, change.getClassifierPath(), change.getContent());
+ toUpdate.add(entity);
+ }
+ }
+ revision.delete(toDelete);
+ revision.update(toUpdate);
+ revision.add(toAdd);
+ this.revision.logStats();
+ return revision;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendWorkspaceEntityAccessContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendWorkspaceEntityAccessContext.java
new file mode 100644
index 0000000000..046f30bcc6
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/entity/SimpleBackendWorkspaceEntityAccessContext.java
@@ -0,0 +1,81 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.entity;
+
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.revision.SimpleBackendRevision;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityAccessContext;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+public class SimpleBackendWorkspaceEntityAccessContext implements EntityAccessContext
+{
+ private SimpleBackendRevision revision;
+
+ public SimpleBackendWorkspaceEntityAccessContext(SimpleBackendRevision revision)
+ {
+ this.revision = revision;
+ }
+
+ @Override
+ public Entity getEntity(String path)
+ {
+ List matches = this.getEntities((p) -> p.equals(path), null, null);
+ if (matches.size() > 1)
+ {
+ throw new IllegalStateException(String.format("Found %d instead of 1 matches for entity with path %s", matches.size(), path));
+ }
+ if (matches.size() == 0)
+ {
+ throw new IllegalStateException(String.format("Entity with path %s not found", path));
+ }
+ return matches.get(0);
+ }
+
+ @Override
+ public List getEntities(Predicate entityPathPredicate, Predicate classifierPathPredicate, Predicate super Map> entityContentPredicate, boolean excludeInvalid)
+ {
+ Stream stream = StreamSupport.stream(this.revision.getEntities().spliterator(), false);
+ if (entityPathPredicate != null)
+ {
+ stream = stream.filter(entity -> entityPathPredicate.test(entity.getPath()));
+ }
+
+ if (classifierPathPredicate != null)
+ {
+ stream = stream.filter(entity -> classifierPathPredicate.test(entity.getClassifierPath()));
+ }
+
+ if (entityContentPredicate != null)
+ {
+ stream = stream.filter(entity -> entityContentPredicate.test(entity.getContent()));
+ }
+
+ return stream.collect(Collectors.toList());
+ }
+
+
+ @Override
+ public List getEntityPaths(Predicate entityPathPredicate, Predicate classifierPathPredicate, Predicate super Map> entityContentPredicate)
+ {
+ List entities = this.getEntities(entityPathPredicate, classifierPathPredicate, entityContentPredicate);
+ return entities.stream().map(Entity::getPath).collect(Collectors.toList());
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/issue/SimpleBackendIssueApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/issue/SimpleBackendIssueApi.java
new file mode 100644
index 0000000000..3a0feea993
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/issue/SimpleBackendIssueApi.java
@@ -0,0 +1,55 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.issue;
+
+import org.finos.legend.sdlc.domain.model.issue.Issue;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.issue.IssueApi;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.List;
+
+public class SimpleBackendIssueApi implements IssueApi
+{
+ @Inject
+ public SimpleBackendIssueApi()
+ {
+ }
+
+ @Override
+ public Issue getIssue(String projectId, String issueId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public List getIssues(String projectId)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Issue createIssue(String projectId, String title, String description)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public void deleteIssue(String projectId, String issueId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/project/SimpleBackendProjectApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/project/SimpleBackendProjectApi.java
new file mode 100644
index 0000000000..758a27d417
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/project/SimpleBackendProjectApi.java
@@ -0,0 +1,117 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.project;
+
+import org.finos.legend.sdlc.domain.model.project.Project;
+import org.finos.legend.sdlc.domain.model.project.ProjectType;
+import org.finos.legend.sdlc.domain.model.project.accessRole.AccessRole;
+import org.finos.legend.sdlc.domain.model.project.accessRole.AuthorizableProjectAction;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.backend.simple.state.SimpleBackendState;
+import org.finos.legend.sdlc.server.domain.api.project.ProjectApi;
+
+import javax.inject.Inject;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+public class SimpleBackendProjectApi implements ProjectApi
+{
+ private SimpleBackendState backendState;
+
+ @Inject
+ public SimpleBackendProjectApi(SimpleBackendState backendState)
+ {
+ this.backendState = backendState;
+ }
+
+ @Override
+ public Project getProject(String id)
+ {
+ return this.backendState.getProject(id);
+ }
+
+ @Override
+ public List getProjects(boolean user, String search, Iterable tags, Integer limit)
+ {
+ return this.backendState.getProjects();
+ }
+
+ @Override
+ public Project createProject(String name, String description, ProjectType type, String groupId, String artifactId, Iterable tags)
+ {
+ return this.backendState.createProject(name, description, type, groupId, artifactId, tags);
+ }
+
+ @Override
+ public void deleteProject(String id)
+ {
+ this.backendState.deleteProject(id);
+ }
+
+ @Override
+ public void changeProjectName(String id, String newName)
+ {
+ this.backendState.getProject(id).setName(newName);
+ }
+
+ @Override
+ public void changeProjectDescription(String id, String newDescription)
+ {
+ this.backendState.getProject(id).setDescription(newDescription);
+ }
+
+ @Override
+ public void updateProjectTags(String id, Iterable tagsToRemove, Iterable tagsToAdd)
+ {
+ }
+
+ @Override
+ public void setProjectTags(String id, Iterable tags)
+ {
+
+ }
+
+ @Override
+ public AccessRole getCurrentUserAccessRole(String id)
+ {
+ return new AccessRole()
+ {
+ @Override
+ public String getAccessRole()
+ {
+ return "ALL";
+ }
+ };
+ }
+
+ @Override
+ public Set checkUserAuthorizedActions(String id, Set actions)
+ {
+ return EnumSet.of(AuthorizableProjectAction.CREATE_WORKSPACE);
+ }
+
+ @Override
+ public boolean checkUserAuthorizedAction(String id, AuthorizableProjectAction action)
+ {
+ return action == AuthorizableProjectAction.CREATE_WORKSPACE;
+ }
+
+ @Override
+ public ImportReport importProject(String id, ProjectType type, String groupId, String artifactId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/project/SimpleBackendProjectConfigurationApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/project/SimpleBackendProjectConfigurationApi.java
new file mode 100644
index 0000000000..72bdfdf51a
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/project/SimpleBackendProjectConfigurationApi.java
@@ -0,0 +1,175 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.project;
+
+import org.finos.legend.sdlc.domain.model.project.configuration.ArtifactTypeGenerationConfiguration;
+import org.finos.legend.sdlc.domain.model.project.configuration.ProjectConfiguration;
+import org.finos.legend.sdlc.domain.model.project.configuration.ProjectStructureVersion;
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.domain.model.revision.Revision;
+import org.finos.legend.sdlc.domain.model.version.VersionId;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.backend.simple.state.SimpleBackendState;
+import org.finos.legend.sdlc.server.domain.api.project.ProjectConfigurationApi;
+import org.finos.legend.sdlc.server.domain.api.project.ProjectConfigurationUpdater;
+import org.finos.legend.sdlc.server.project.ProjectConfigurationStatusReport;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.List;
+
+public class SimpleBackendProjectConfigurationApi implements ProjectConfigurationApi
+{
+ private SimpleBackendState simpleBackendState;
+
+ @Inject
+ public SimpleBackendProjectConfigurationApi(SimpleBackendState simpleBackendState)
+ {
+ this.simpleBackendState = simpleBackendState;
+ }
+
+ @Override
+ public ProjectConfiguration getProjectProjectConfiguration(String projectId)
+ {
+ return this.simpleBackendState.getProject(projectId).getProjectConfiguration();
+ }
+
+ @Override
+ public ProjectConfiguration getProjectRevisionProjectConfiguration(String projectId, String revisionId)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getWorkspaceProjectConfiguration(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getBackupWorkspaceProjectConfiguration(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getWorkspaceWithConflictResolutionProjectConfiguration(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getWorkspaceRevisionProjectConfiguration(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getBackupWorkspaceRevisionProjectConfiguration(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getWorkspaceWithConflictResolutionRevisionProjectConfiguration(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getVersionProjectConfiguration(String projectId, VersionId versionId)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getReviewFromProjectConfiguration(String projectId, String reviewId)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public ProjectConfiguration getReviewToProjectConfiguration(String projectId, String reviewId)
+ {
+ return this.getProjectProjectConfiguration(projectId);
+ }
+
+ @Override
+ public Revision updateProjectConfiguration(String projectId, String workspaceId, WorkspaceType workspaceType, String message, ProjectConfigurationUpdater updater)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Revision updateProjectConfigurationForWorkspaceWithConflictResolution(String projectId, String workspaceId, String message, ProjectConfigurationUpdater updater)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public List getProjectAvailableArtifactGenerations(String projectId)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public List getRevisionAvailableArtifactGenerations(String projectId, String revisionId)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public List getWorkspaceRevisionAvailableArtifactGenerations(String projectId, String workspaceId, WorkspaceType workspaceType, String revisionId)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public List getWorkspaceAvailableArtifactGenerations(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public List getVersionAvailableArtifactGenerations(String projectId, String versionId)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public ProjectStructureVersion getLatestProjectStructureVersion()
+ {
+ return ProjectStructureVersion.newProjectStructureVersion(13);
+ }
+
+ @Override
+ public ProjectConfigurationStatusReport getProjectConfigurationStatus(String projectId)
+ {
+ return new ProjectConfigurationStatusReport()
+ {
+ @Override
+ public boolean isProjectConfigured()
+ {
+ return true;
+ }
+
+ @Override
+ public List getReviewIds()
+ {
+ return Collections.emptyList();
+ }
+ };
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/review/SimpleBackendReviewApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/review/SimpleBackendReviewApi.java
new file mode 100644
index 0000000000..9fb3e10d31
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/review/SimpleBackendReviewApi.java
@@ -0,0 +1,120 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.review;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.domain.model.review.Approval;
+import org.finos.legend.sdlc.domain.model.review.Review;
+import org.finos.legend.sdlc.domain.model.review.ReviewState;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.review.ReviewApi;
+
+import javax.inject.Inject;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiPredicate;
+
+public class SimpleBackendReviewApi implements ReviewApi
+{
+ @Inject
+ public SimpleBackendReviewApi()
+ {
+ }
+
+ @Override
+ public Review getReview(String projectId, String reviewId)
+ {
+ return null;
+ }
+
+ @Override
+ public List getReviews(String projectId, ReviewState state, Iterable revisionIds, BiPredicate workspaceIdAndTypePredicate, Instant since, Instant until, Integer limit)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List getReviews(boolean assignedToMe, boolean authoredByMe, List labels, BiPredicate workspaceIdAndTypePredicate, ReviewState state, Instant since, Instant until, Integer limit)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Review createReview(String projectId, String workspaceId, WorkspaceType workspaceType, String title, String description, List labels)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Review closeReview(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Review reopenReview(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Review approveReview(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Review revokeReviewApproval(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Review rejectReview(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Approval getReviewApproval(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Review commitReview(String projectId, String reviewId, String message)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public ReviewUpdateStatus getReviewUpdateStatus(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public ReviewUpdateStatus updateReview(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public Review editReview(String projectId, String reviewId, String title, String description, List labels)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/revision/SimpleBackendRevisionAccessContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/revision/SimpleBackendRevisionAccessContext.java
new file mode 100644
index 0000000000..9a8a44c93c
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/revision/SimpleBackendRevisionAccessContext.java
@@ -0,0 +1,57 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.revision;
+
+import org.finos.legend.sdlc.domain.model.revision.Revision;
+import org.finos.legend.sdlc.server.domain.api.revision.RevisionAccessContext;
+
+import java.time.Instant;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Predicate;
+
+public class SimpleBackendRevisionAccessContext implements RevisionAccessContext
+{
+ private Revision revision;
+
+ public SimpleBackendRevisionAccessContext(Revision revision)
+ {
+ this.revision = revision;
+ }
+
+ @Override
+ public Revision getRevision(String revisionId)
+ {
+ return revision;
+ }
+
+ @Override
+ public Revision getBaseRevision()
+ {
+ return revision;
+ }
+
+ @Override
+ public Revision getCurrentRevision()
+ {
+ return revision;
+ }
+
+ @Override
+ public List getRevisions(Predicate super Revision> predicate, Instant since, Instant until, Integer limit)
+ {
+ return Collections.emptyList();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/revision/SimpleBackendRevisionApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/revision/SimpleBackendRevisionApi.java
new file mode 100644
index 0000000000..552399c918
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/revision/SimpleBackendRevisionApi.java
@@ -0,0 +1,89 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.revision;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.domain.model.revision.RevisionStatus;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.backend.simple.state.SimpleBackendState;
+import org.finos.legend.sdlc.server.domain.api.revision.RevisionAccessContext;
+import org.finos.legend.sdlc.server.domain.api.revision.RevisionApi;
+
+import javax.inject.Inject;
+
+public class SimpleBackendRevisionApi implements RevisionApi
+{
+ private SimpleBackendState simpleBackendState;
+
+ @Inject
+ public SimpleBackendRevisionApi(SimpleBackendState simpleBackendState)
+ {
+ this.simpleBackendState = simpleBackendState;
+ }
+
+ @Override
+ public RevisionAccessContext getProjectRevisionContext(String projectId)
+ {
+ return simpleBackendState.getProject(projectId).getRevisionAccessContext();
+ }
+
+ @Override
+ public RevisionAccessContext getProjectEntityRevisionContext(String projectId, String entityPath)
+ {
+ return simpleBackendState.getProject(projectId).getRevisionAccessContext();
+ }
+
+ @Override
+ public RevisionAccessContext getProjectPackageRevisionContext(String projectId, String packagePath)
+ {
+ return simpleBackendState.getProject(projectId).getRevisionAccessContext();
+ }
+
+ @Override
+ public RevisionAccessContext getWorkspaceRevisionContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return simpleBackendState.getProject(projectId).getWorkspace(workspaceId, workspaceType).getRevisionAccessContext();
+ }
+
+ @Override
+ public RevisionAccessContext getBackupWorkspaceRevisionContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public RevisionAccessContext getWorkspaceWithConflictResolutionRevisionContext(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public RevisionAccessContext getWorkspaceEntityRevisionContext(String projectId, String workspaceId, WorkspaceType workspaceType, String entityPath)
+ {
+ return simpleBackendState.getProject(projectId).getWorkspace(workspaceId, workspaceType).getRevisionAccessContext();
+ }
+
+ @Override
+ public RevisionAccessContext getWorkspacePackageRevisionContext(String projectId, String workspaceId, WorkspaceType workspaceType, String packagePath)
+ {
+ return simpleBackendState.getProject(projectId).getWorkspace(workspaceId, workspaceType).getRevisionAccessContext();
+ }
+
+ @Override
+ public RevisionStatus getRevisionStatus(String projectId, String revisionId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/user/SimpleBackendUserApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/user/SimpleBackendUserApi.java
new file mode 100644
index 0000000000..3fb209473a
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/user/SimpleBackendUserApi.java
@@ -0,0 +1,67 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.user;
+
+import org.eclipse.collections.api.factory.Maps;
+import org.eclipse.collections.api.map.ImmutableMap;
+import org.eclipse.collections.impl.list.mutable.FastList;
+import org.finos.legend.sdlc.domain.model.user.User;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.user.SimpleBackendUser;
+import org.finos.legend.sdlc.server.domain.api.user.UserApi;
+
+import javax.inject.Inject;
+import java.util.List;
+
+public class SimpleBackendUserApi implements UserApi
+{
+ private SimpleBackendUser LOCAL_USER = new SimpleBackendUser("local_user", "local_user");
+ private SimpleBackendUser DEMO_OWNER = new SimpleBackendUser("demo_owner", "demo_owner");
+
+ private ImmutableMap users = Maps.immutable.of(
+ LOCAL_USER.getUserId(), LOCAL_USER,
+ DEMO_OWNER.getUserId(), DEMO_OWNER
+ );
+
+ @Inject
+ public SimpleBackendUserApi()
+ {
+ }
+
+ @Override
+ public List getUsers()
+ {
+ return FastList.newListWith(LOCAL_USER, DEMO_OWNER);
+ }
+
+ @Override
+ public User getUserById(String userId)
+ {
+ return this.users.get(userId);
+ }
+
+ @Override
+ public List findUsers(String searchString)
+ {
+ FastList users = FastList.newList();
+ this.users.forEachValue(user -> users.add(user));
+ return users;
+ }
+
+ @Override
+ public User getCurrentUserInfo()
+ {
+ return LOCAL_USER;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/version/SimpleBackendVersionApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/version/SimpleBackendVersionApi.java
new file mode 100644
index 0000000000..d086e9d682
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/version/SimpleBackendVersionApi.java
@@ -0,0 +1,60 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.version;
+
+import org.eclipse.collections.impl.list.mutable.FastList;
+import org.finos.legend.sdlc.domain.model.version.Version;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.backend.simple.state.SimpleBackendState;
+import org.finos.legend.sdlc.server.domain.api.version.NewVersionType;
+import org.finos.legend.sdlc.server.domain.api.version.VersionApi;
+
+import javax.inject.Inject;
+import java.util.List;
+
+public class SimpleBackendVersionApi implements VersionApi
+{
+ private SimpleBackendState simpleBackendState;
+
+ @Inject
+ public SimpleBackendVersionApi(SimpleBackendState simpleBackendState)
+ {
+ this.simpleBackendState = simpleBackendState;
+ }
+
+ @Override
+ public List getVersions(String projectId, Integer minMajorVersion, Integer maxMajorVersion, Integer minMinorVersion, Integer maxMinorVersion, Integer minPatchVersion, Integer maxPatchVersion)
+ {
+ return FastList.newListWith(this.simpleBackendState.getProject(projectId).getVersion());
+ }
+
+ @Override
+ public Version getLatestVersion(String projectId, Integer minMajorVersion, Integer maxMajorVersion, Integer minMinorVersion, Integer maxMinorVersion, Integer minPatchVersion, Integer maxPatchVersion)
+ {
+ return this.simpleBackendState.getProject(projectId).getVersion();
+ }
+
+ @Override
+ public Version getVersion(String projectId, int majorVersion, int minorVersion, int patchVersion)
+ {
+ return this.simpleBackendState.getProject(projectId).getVersion();
+ }
+
+ @Override
+ public Version newVersion(String projectId, NewVersionType type, String revisionId, String notes)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowAccessContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowAccessContext.java
new file mode 100644
index 0000000000..ab1666ae44
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowAccessContext.java
@@ -0,0 +1,38 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.workflow;
+
+import org.finos.legend.sdlc.domain.model.workflow.Workflow;
+import org.finos.legend.sdlc.domain.model.workflow.WorkflowStatus;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowAccessContext;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SimpleBackendWorkflowAccessContext implements WorkflowAccessContext
+{
+ @Override
+ public Workflow getWorkflow(String workflowId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public List getWorkflows(Iterable revisionIds, Iterable statuses, Integer limit)
+ {
+ return Collections.emptyList();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowApi.java
new file mode 100644
index 0000000000..6bec61158b
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowApi.java
@@ -0,0 +1,56 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.workflow;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.domain.model.version.VersionId;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowAccessContext;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowApi;
+import org.finos.legend.sdlc.server.project.ProjectFileAccessProvider;
+
+import javax.inject.Inject;
+
+public class SimpleBackendWorkflowApi implements WorkflowApi
+{
+ @Inject
+ public SimpleBackendWorkflowApi()
+ {
+ }
+
+ @Override
+ public WorkflowAccessContext getProjectWorkflowAccessContext(String projectId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowAccessContext getWorkspaceWorkflowAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType, ProjectFileAccessProvider.WorkspaceAccessType workspaceAccessType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowAccessContext getVersionWorkflowAccessContext(String projectId, VersionId versionId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowAccessContext getReviewWorkflowAccessContext(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowJobAccessContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowJobAccessContext.java
new file mode 100644
index 0000000000..920e70d0bc
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowJobAccessContext.java
@@ -0,0 +1,62 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.workflow;
+
+import org.finos.legend.sdlc.domain.model.workflow.WorkflowJob;
+import org.finos.legend.sdlc.domain.model.workflow.WorkflowJobStatus;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowJobAccessContext;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SimpleBackendWorkflowJobAccessContext implements WorkflowJobAccessContext
+{
+ @Override
+ public WorkflowJob getWorkflowJob(String workflowId, String workflowJobId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public List getWorkflowJobs(String workflowId, Iterable statuses)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String getWorkflowJobLog(String workflowId, String workflowJobId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowJob runWorkflowJob(String workflowId, String workflowJobId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowJob retryWorkflowJob(String workflowId, String workflowJobId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowJob cancelWorkflowJob(String workflowId, String workflowJobId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowJobApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowJobApi.java
new file mode 100644
index 0000000000..ab6aa6f0db
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workflow/SimpleBackendWorkflowJobApi.java
@@ -0,0 +1,56 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.workflow;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.domain.model.version.VersionId;
+import org.finos.legend.sdlc.server.backend.simple.exception.UnavailableFeature;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowJobAccessContext;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowJobApi;
+import org.finos.legend.sdlc.server.project.ProjectFileAccessProvider;
+
+import javax.inject.Inject;
+
+public class SimpleBackendWorkflowJobApi implements WorkflowJobApi
+{
+ @Inject
+ public SimpleBackendWorkflowJobApi()
+ {
+ }
+
+ @Override
+ public WorkflowJobAccessContext getProjectWorkflowJobAccessContext(String projectId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowJobAccessContext getWorkspaceWorkflowJobAccessContext(String projectId, String workspaceId, WorkspaceType workspaceType, ProjectFileAccessProvider.WorkspaceAccessType workspaceAccessType)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowJobAccessContext getVersionWorkflowJobAccessContext(String projectId, VersionId versionId)
+ {
+ throw UnavailableFeature.exception();
+ }
+
+ @Override
+ public WorkflowJobAccessContext getReviewWorkflowJobAccessContext(String projectId, String reviewId)
+ {
+ throw UnavailableFeature.exception();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workspace/SimpleBackendWorkspaceApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workspace/SimpleBackendWorkspaceApi.java
new file mode 100644
index 0000000000..1ef6d57c34
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/api/workspace/SimpleBackendWorkspaceApi.java
@@ -0,0 +1,120 @@
+// Copyright 2023 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.sdlc.server.backend.simple.api.workspace;
+
+import org.finos.legend.sdlc.domain.model.project.workspace.Workspace;
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.server.backend.simple.state.SimpleBackendState;
+import org.finos.legend.sdlc.server.domain.api.workspace.WorkspaceApi;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public class SimpleBackendWorkspaceApi implements WorkspaceApi
+{
+ private SimpleBackendState simpleBackendState;
+
+ @Inject
+ public SimpleBackendWorkspaceApi(SimpleBackendState simpleBackendState)
+ {
+ this.simpleBackendState = simpleBackendState;
+ }
+
+ @Override
+ public List getWorkspaces(String projectId, Set workspaceTypes)
+ {
+ return this.simpleBackendState.getProject(projectId).getWorkspaces(workspaceTypes);
+ }
+
+ @Override
+ public List getWorkspacesWithConflictResolution(String projectId)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List getBackupWorkspaces(String projectId)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List getAllWorkspaces(String projectId, Set workspaceTypes)
+ {
+ return this.getWorkspaces(projectId, workspaceTypes);
+ }
+
+ @Override
+ public Workspace getWorkspace(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return this.simpleBackendState.getProject(projectId).getWorkspace(workspaceId, workspaceType);
+ }
+
+ @Override
+ public Workspace getWorkspaceWithConflictResolution(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return null;
+ }
+
+ @Override
+ public Workspace getBackupWorkspace(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isWorkspaceOutdated(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isWorkspaceWithConflictResolutionOutdated(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isBackupWorkspaceOutdated(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isWorkspaceInConflictResolutionMode(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return false;
+ }
+
+ @Override
+ public Workspace newWorkspace(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return this.simpleBackendState.getProject(projectId).newWorkspace(workspaceId, workspaceType);
+ }
+
+ @Override
+ public void deleteWorkspace(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ this.simpleBackendState.getProject(projectId).deleteWorkspace(workspaceId, workspaceType);
+ }
+
+ @Override
+ public WorkspaceUpdateReport updateWorkspace(String projectId, String workspaceId, WorkspaceType workspaceType)
+ {
+ return null;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/auth/SimpleBackendUserContext.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/auth/SimpleBackendUserContext.java
new file mode 100644
index 0000000000..ea165331e3
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/auth/SimpleBackendUserContext.java
@@ -0,0 +1,37 @@
+// Copyright 2023 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.sdlc.server.backend.simple.auth;
+
+import com.google.inject.servlet.RequestScoped;
+import org.finos.legend.sdlc.server.guice.UserContext;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@RequestScoped
+public class SimpleBackendUserContext extends UserContext
+{
+ @Inject
+ public SimpleBackendUserContext(HttpServletRequest httpRequest, HttpServletResponse httpResponse)
+ {
+ super(httpRequest, httpResponse);
+ }
+
+ public boolean isUserAuthorized()
+ {
+ return true;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/canned/StaticEntities.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/canned/StaticEntities.java
new file mode 100644
index 0000000000..16a343bf19
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/canned/StaticEntities.java
@@ -0,0 +1,72 @@
+// Copyright 2023 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.sdlc.server.backend.simple.canned;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.eclipse.collections.api.factory.Maps;
+import org.eclipse.collections.api.map.MutableMap;
+import org.finos.legend.engine.protocol.pure.v1.PureProtocolObjectMapperFactory;
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.entity.SimpleBackendEntity;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class StaticEntities
+{
+ public static String load(String resourceName) throws Exception
+ {
+ InputStream resourceAsStream = null;
+ try
+ {
+ String fullName = "/backend/simple/canned/" + resourceName;
+ resourceAsStream = StaticEntities.class.getResourceAsStream(fullName);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(resourceAsStream));
+ String contents = reader.lines().collect(Collectors.joining(System.lineSeparator()));
+ return contents;
+ }
+ finally
+ {
+ if (resourceAsStream != null)
+ {
+ resourceAsStream.close();
+ }
+ }
+ }
+
+ public static MutableMap loadEntities(String resourceName) throws Exception
+ {
+ String rawJSON = StaticEntities.load(resourceName);
+ ObjectMapper newObjectMapper = PureProtocolObjectMapperFactory.getNewObjectMapper();
+ TypeReference> typeReference = new TypeReference>()
+ {
+ };
+ List simpleBackendEntities = newObjectMapper.readValue(rawJSON, typeReference);
+
+ MutableMap simpleBackendEntitiesMap = Maps.mutable.empty();
+ simpleBackendEntities.forEach(entity -> simpleBackendEntitiesMap.put(entity.getPath(), entity));
+
+ return simpleBackendEntitiesMap;
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ StaticEntities.loadEntities("tour.json");
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/depot/SimpleBackendMetadataApi.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/depot/SimpleBackendMetadataApi.java
new file mode 100644
index 0000000000..0ff4652f1a
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/depot/SimpleBackendMetadataApi.java
@@ -0,0 +1,45 @@
+// Copyright 2023 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.sdlc.server.backend.simple.depot;
+
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.server.depot.api.MetadataApi;
+import org.finos.legend.sdlc.server.depot.model.DepotProjectId;
+import org.finos.legend.sdlc.server.depot.model.DepotProjectVersion;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public class SimpleBackendMetadataApi implements MetadataApi
+{
+ @Inject
+ public SimpleBackendMetadataApi()
+ {
+ }
+
+ @Override
+ public List getEntities(DepotProjectId projectId, String versionId)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Set getProjectDependencies(DepotProjectId projectId, String versionId, boolean transitive)
+ {
+ return Collections.emptySet();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/entity/SimpleBackendEntity.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/entity/SimpleBackendEntity.java
new file mode 100644
index 0000000000..d5408ed352
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/entity/SimpleBackendEntity.java
@@ -0,0 +1,98 @@
+// Copyright 2023 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.sdlc.server.backend.simple.domain.model.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.tools.entity.EntityPaths;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SimpleBackendEntity implements Entity
+{
+ private String path;
+ private String classifierPath;
+ private Map content;
+
+ @Inject
+ public SimpleBackendEntity()
+ {
+ }
+
+ public SimpleBackendEntity(String path, String classifierPath, Map content)
+ {
+ this.path = path;
+ this.classifierPath = classifierPath;
+ this.content = content;
+ }
+
+ @Override
+ public String getPath()
+ {
+ return this.path;
+ }
+
+ @Override
+ public String getClassifierPath()
+ {
+ return this.classifierPath;
+ }
+
+ @Override
+ public Map getContent()
+ {
+ return this.content;
+ }
+
+ @JsonIgnore
+ public static Entity newEntity(String name, String pkg)
+ {
+ return newEntity(name, pkg, null, null);
+ }
+
+ @JsonIgnore
+ public static Entity newEntity(String name, String pkg, Map property)
+ {
+ return newEntity(name, pkg, Collections.singletonList(property), null);
+ }
+
+ @JsonIgnore
+ public static Entity newEntity(String name, String pkg, List extends Map> properties)
+ {
+ return newEntity(name, pkg, properties, null);
+ }
+
+ @JsonIgnore
+ public static Entity newEntity(String name, String pkg, List extends Map> properties, List superTypes)
+ {
+ Map content = new HashMap<>(5);
+ content.put("_type", "class");
+ content.put("name", name);
+ content.put("package", pkg);
+ content.put("properties", (properties == null) ? Collections.emptyList() : properties);
+ content.put("superTypes", ((superTypes == null) || superTypes.isEmpty()) ? Collections.singletonList("meta::pure::metamodel::type::Any") : superTypes);
+ return new SimpleBackendEntity(
+ pkg + EntityPaths.PACKAGE_SEPARATOR + name,
+ "meta::pure::metamodel::type::Class",
+ content
+ );
+ }
+}
\ No newline at end of file
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/SimpleBackendProject.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/SimpleBackendProject.java
new file mode 100644
index 0000000000..5767004d11
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/SimpleBackendProject.java
@@ -0,0 +1,246 @@
+// Copyright 2023 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.sdlc.server.backend.simple.domain.model.project;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import org.eclipse.collections.api.factory.Lists;
+import org.eclipse.collections.api.factory.Maps;
+import org.eclipse.collections.api.list.MutableList;
+import org.eclipse.collections.api.map.ImmutableMap;
+import org.eclipse.collections.api.map.MutableMap;
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.domain.model.project.Project;
+import org.finos.legend.sdlc.domain.model.project.ProjectType;
+import org.finos.legend.sdlc.domain.model.project.workspace.Workspace;
+import org.finos.legend.sdlc.domain.model.project.workspace.WorkspaceType;
+import org.finos.legend.sdlc.server.backend.simple.api.entity.SimpleBackendEntityAccessContext;
+import org.finos.legend.sdlc.server.backend.simple.api.revision.SimpleBackendRevisionAccessContext;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.project.configuration.SimpleBackendProjectConfiguration;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.project.workspace.SimpleBackendProjectWorkspace;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.revision.SimpleBackendRevision;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.version.SimpleBackendVersion;
+import org.finos.legend.sdlc.server.domain.api.revision.RevisionAccessContext;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SimpleBackendProject implements Project
+{
+ private SimpleBackendVersion version;
+ private SimpleBackendRevision revision;
+ private String projectId;
+ private String name;
+ private String description;
+ private List tags = Collections.emptyList();
+ private ProjectType projectType;
+ private String webUrl;
+
+ @JsonIgnore
+ private SimpleBackendProjectConfiguration projectConfiguration;
+
+ @JsonIgnore
+ private MutableMap userWorkspaces = Maps.mutable.empty();
+
+ @JsonIgnore
+ private MutableMap groupWorkspaces = Maps.mutable.empty();
+
+ @JsonIgnore
+ private MutableMap entities = Maps.mutable.empty();
+
+ @JsonIgnore
+ private SimpleBackendRevisionAccessContext revisionAccessContext;
+
+ @JsonIgnore
+ private SimpleBackendEntityAccessContext entityAccessContext;
+
+ @Inject
+ public SimpleBackendProject()
+ {
+ }
+
+ public SimpleBackendProject(String projectId, String name, String description, ProjectType projectType, String webUrl)
+ {
+ this.projectId = projectId;
+ this.name = name;
+ this.description = description;
+ this.projectType = projectType;
+ this.webUrl = webUrl;
+
+ this.revision = new SimpleBackendRevision(this.entities, new String[]{"project", projectId});
+ this.version = new SimpleBackendVersion(projectId, revision);
+ this.revisionAccessContext = new SimpleBackendRevisionAccessContext(revision);
+ this.entityAccessContext = new SimpleBackendEntityAccessContext(revision);
+ }
+
+ public SimpleBackendProjectConfiguration getProjectConfiguration()
+ {
+ return projectConfiguration;
+ }
+
+ public void setProjectConfiguration(SimpleBackendProjectConfiguration projectConfiguration)
+ {
+ this.projectConfiguration = projectConfiguration;
+ }
+
+ @Override
+ public String getProjectId()
+ {
+ return projectId;
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return description;
+ }
+
+ @Override
+ public List getTags()
+ {
+ return tags;
+ }
+
+ @Override
+ public ProjectType getProjectType()
+ {
+ return projectType;
+ }
+
+ @Override
+ public String getWebUrl()
+ {
+ return webUrl;
+ }
+
+ public void setProjectId(String projectId)
+ {
+ this.projectId = projectId;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ public void setTags(List tags)
+ {
+ this.tags = tags;
+ }
+
+ public void setProjectType(ProjectType projectType)
+ {
+ this.projectType = projectType;
+ }
+
+ public void setWebUrl(String webUrl)
+ {
+ this.webUrl = webUrl;
+ }
+
+ public SimpleBackendEntityAccessContext getEntityAccessContext()
+ {
+ return entityAccessContext;
+ }
+
+ public void setEntityAccessContext(SimpleBackendEntityAccessContext entityAccessContext)
+ {
+ this.entityAccessContext = entityAccessContext;
+ }
+
+ public SimpleBackendProjectWorkspace getWorkspace(String id, WorkspaceType workspaceType)
+ {
+ if (WorkspaceType.USER == workspaceType)
+ {
+ return this.userWorkspaces.get(id);
+ }
+ return this.groupWorkspaces.get(id);
+ }
+
+ public List getWorkspaces(Set workspaceTypes)
+ {
+ MutableList workspaces = Lists.mutable.empty();
+ for (WorkspaceType workspaceType : workspaceTypes)
+ {
+ if (workspaceType == WorkspaceType.GROUP)
+ {
+ workspaces.addAll(this.groupWorkspaces.values());
+ }
+ if (workspaceType == WorkspaceType.USER)
+ {
+ workspaces.addAll(this.userWorkspaces.values());
+ }
+ }
+ return workspaces;
+ }
+
+ public Workspace newWorkspace(String workspaceId, WorkspaceType workspaceType)
+ {
+ ImmutableMap entities = this.entities.toImmutable();
+ if (workspaceType == WorkspaceType.GROUP)
+ {
+ SimpleBackendProjectWorkspace workspace = new SimpleBackendProjectWorkspace(projectId, workspaceId, entities);
+ this.groupWorkspaces.put(workspaceId, workspace);
+ }
+ else
+ {
+ SimpleBackendProjectWorkspace workspace = new SimpleBackendProjectWorkspace(projectId, workspaceId, "alice", entities);
+ this.userWorkspaces.put(workspaceId, workspace);
+ }
+
+ return this.getWorkspace(workspaceId, workspaceType);
+ }
+
+ public void deleteWorkspace(String workspaceId, WorkspaceType workspaceType)
+ {
+ if (WorkspaceType.USER == workspaceType)
+ {
+ this.userWorkspaces.remove(workspaceId);
+ }
+ else if (WorkspaceType.GROUP == workspaceType)
+ {
+ this.groupWorkspaces.remove(workspaceId);
+ }
+ }
+
+ public RevisionAccessContext getRevisionAccessContext()
+ {
+ return this.revisionAccessContext;
+ }
+
+ public SimpleBackendVersion getVersion()
+ {
+ return this.version;
+ }
+
+ public void addEntities(MutableMap entities)
+ {
+ this.entities.putAll(entities);
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/configuration/SimpleBackendProjectConfiguration.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/configuration/SimpleBackendProjectConfiguration.java
new file mode 100644
index 0000000000..cd03d70c2c
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/configuration/SimpleBackendProjectConfiguration.java
@@ -0,0 +1,78 @@
+// Copyright 2023 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.sdlc.server.backend.simple.domain.model.project.configuration;
+
+import org.finos.legend.sdlc.domain.model.project.configuration.MetamodelDependency;
+import org.finos.legend.sdlc.domain.model.project.configuration.ProjectConfiguration;
+import org.finos.legend.sdlc.domain.model.project.configuration.ProjectDependency;
+import org.finos.legend.sdlc.domain.model.project.configuration.ProjectStructureVersion;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SimpleBackendProjectConfiguration implements ProjectConfiguration
+{
+ private String projectId;
+ private ProjectStructureVersion projectStructureVersion = ProjectStructureVersion.newProjectStructureVersion(13);
+ private String groupId;
+ private String artifactId;
+
+ public SimpleBackendProjectConfiguration()
+ {
+ }
+
+ public SimpleBackendProjectConfiguration(String projectId, String groupId, String artifactId)
+ {
+ this.projectId = projectId;
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ }
+
+ @Override
+ public String getProjectId()
+ {
+ return this.projectId;
+ }
+
+ @Override
+ public ProjectStructureVersion getProjectStructureVersion()
+ {
+ return this.projectStructureVersion;
+ }
+
+ @Override
+ public String getGroupId()
+ {
+ return this.groupId;
+ }
+
+ @Override
+ public String getArtifactId()
+ {
+ return this.artifactId;
+ }
+
+ @Override
+ public List getProjectDependencies()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List getMetamodelDependencies()
+ {
+ return Collections.emptyList();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/workspace/SimpleBackendProjectWorkspace.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/workspace/SimpleBackendProjectWorkspace.java
new file mode 100644
index 0000000000..3760c2b7c3
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/project/workspace/SimpleBackendProjectWorkspace.java
@@ -0,0 +1,105 @@
+// Copyright 2023 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.sdlc.server.backend.simple.domain.model.project.workspace;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import org.eclipse.collections.api.factory.Maps;
+import org.eclipse.collections.api.map.ImmutableMap;
+import org.eclipse.collections.api.map.MutableMap;
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.domain.model.project.workspace.Workspace;
+import org.finos.legend.sdlc.server.backend.simple.api.entity.SimpleBackendEntityAccessContext;
+import org.finos.legend.sdlc.server.backend.simple.api.entity.SimpleBackendEntityModificationContext;
+import org.finos.legend.sdlc.server.backend.simple.api.revision.SimpleBackendRevisionAccessContext;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.revision.SimpleBackendRevision;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityModificationContext;
+import org.finos.legend.sdlc.server.domain.api.revision.RevisionAccessContext;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SimpleBackendProjectWorkspace implements Workspace
+{
+ private final SimpleBackendRevision revision;
+ private String projectId;
+ private String workspaceId;
+ private String userId;
+
+ @JsonIgnore
+ private MutableMap entities = Maps.mutable.empty();
+
+ @JsonIgnore
+ private SimpleBackendEntityModificationContext entityModificationContext;
+
+ @JsonIgnore
+ private RevisionAccessContext revisionAccessContext;
+
+ @JsonIgnore
+ private SimpleBackendEntityAccessContext entityAccessContext;
+
+ public SimpleBackendProjectWorkspace(String projectId, String workspaceId, String userId, ImmutableMap entities)
+ {
+ this.projectId = projectId;
+ this.workspaceId = workspaceId;
+ this.userId = userId;
+ this.entities.putAll(entities.castToMap());
+ this.revision = new SimpleBackendRevision(this.entities, new String[]{"project", projectId, "workspace", workspaceId});
+ this.revisionAccessContext = new SimpleBackendRevisionAccessContext(this.revision);
+ this.entityAccessContext = new SimpleBackendEntityAccessContext(this.revision);
+ this.entityModificationContext = new SimpleBackendEntityModificationContext(this.revision);
+ }
+
+ public SimpleBackendProjectWorkspace(String projectId, String workspaceId, ImmutableMap entities)
+ {
+ this(projectId, workspaceId, null, entities);
+ }
+
+ @Override
+ public String getProjectId()
+ {
+ return projectId;
+ }
+
+ @Override
+ public String getWorkspaceId()
+ {
+ return workspaceId;
+ }
+
+ @Override
+ public String getUserId()
+ {
+ return userId;
+ }
+
+ public SimpleBackendEntityAccessContext getEntityAccessContext()
+ {
+ return entityAccessContext;
+ }
+
+ public void setEntityAccessContext(SimpleBackendEntityAccessContext entityAccessContext)
+ {
+ this.entityAccessContext = entityAccessContext;
+ }
+
+ public RevisionAccessContext getRevisionAccessContext()
+ {
+ return this.revisionAccessContext;
+ }
+
+ public EntityModificationContext getEntityModificationContext()
+ {
+ return this.entityModificationContext;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/revision/SimpleBackendRevision.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/revision/SimpleBackendRevision.java
new file mode 100644
index 0000000000..a5c58c578b
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/revision/SimpleBackendRevision.java
@@ -0,0 +1,157 @@
+// Copyright 2023 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.sdlc.server.backend.simple.domain.model.revision;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.eclipse.collections.api.map.MutableMap;
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.domain.model.revision.Revision;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+public class SimpleBackendRevision implements Revision
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBackendRevision.class);
+
+ private String id;
+ private String authorName;
+ private Instant authoredTimestamp;
+ private String committerName;
+ private Instant committedTimestamp;
+ private String message;
+ private MutableMap entities;
+ private String[] context;
+
+ @JsonIgnore
+ private int revisionCounter = 1;
+
+ public SimpleBackendRevision(MutableMap entities, String[] context)
+ {
+ this.entities = entities;
+ this.context = context;
+ this.revisionCounter = 1;
+ this.id = this.makeId();
+ this.authorName = "alice";
+ this.authoredTimestamp = Instant.now();
+ this.committerName = "alice";
+ this.committedTimestamp = Instant.now();
+ this.message = "message";
+ }
+
+ private String makeId()
+ {
+ return "rev" + this.revisionCounter;
+ }
+
+ @Override
+ public String getId()
+ {
+ return id;
+ }
+
+ @Override
+ public String getAuthorName()
+ {
+ return authorName;
+ }
+
+ @Override
+ public Instant getAuthoredTimestamp()
+ {
+ return authoredTimestamp;
+ }
+
+ @Override
+ public String getCommitterName()
+ {
+ return committerName;
+ }
+
+ @Override
+ public Instant getCommittedTimestamp()
+ {
+ return committedTimestamp;
+ }
+
+ @Override
+ public String getMessage()
+ {
+ return message;
+ }
+
+ @JsonIgnore
+ public MutableMap getEntities()
+ {
+ return entities;
+ }
+
+ public void update(Iterable extends Entity> entities)
+ {
+ this.revisionCounter += 1;
+ this.delete(entities);
+ this.add(entities);
+ this.updateTime();
+ }
+
+ public void add(Iterable extends Entity> entities)
+ {
+ this.revisionCounter += 1;
+ for (Entity entity : entities)
+ {
+ String path = fullPath(entity);
+ this.entities.put(path, entity);
+ }
+ this.updateTime();
+ }
+
+ public void delete(Iterable extends Entity> entities)
+ {
+ this.revisionCounter += 1;
+ for (Entity entity : entities)
+ {
+ String path = fullPath(entity);
+ this.entities.remove(path);
+ }
+ this.updateTime();
+ }
+
+ private String fullPath(Entity entity)
+ {
+ return entity.getPath();
+ }
+
+ private void updateTime()
+ {
+ this.committedTimestamp = Instant.now();
+ }
+
+ public void logStats()
+ {
+ LOGGER.info("Revision stats. Revision=%s. Context=%s. Entities count=%d", this.id, this.contextToString(), this.entities.size());
+ }
+
+ private String contextToString()
+ {
+ if (context == null)
+ {
+ return "";
+ }
+ return Arrays.stream(this.context).collect(Collectors.joining(","));
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/user/SimpleBackendUser.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/user/SimpleBackendUser.java
new file mode 100644
index 0000000000..e2196f574d
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/user/SimpleBackendUser.java
@@ -0,0 +1,55 @@
+// Copyright 2023 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.sdlc.server.backend.simple.domain.model.user;
+
+import org.finos.legend.sdlc.domain.model.user.User;
+
+public class SimpleBackendUser implements User
+{
+ private String userId;
+ private String name;
+
+ public SimpleBackendUser(String userId, String name)
+ {
+ this.userId = userId;
+ this.name = name;
+ }
+
+ public SimpleBackendUser()
+ {
+ }
+
+ @Override
+ public String getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(String userId)
+ {
+ this.userId = userId;
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/version/SimpleBackendVersion.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/version/SimpleBackendVersion.java
new file mode 100644
index 0000000000..a02ee7c78a
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/domain/model/version/SimpleBackendVersion.java
@@ -0,0 +1,83 @@
+// Copyright 2023 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.sdlc.server.backend.simple.domain.model.version;
+
+import org.finos.legend.sdlc.domain.model.version.Version;
+import org.finos.legend.sdlc.domain.model.version.VersionId;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.revision.SimpleBackendRevision;
+
+public class SimpleBackendVersion implements Version
+{
+ private VersionId id;
+ private String projectId;
+ private String revisionId;
+ private String notes;
+
+ public SimpleBackendVersion()
+ {
+ }
+
+ public SimpleBackendVersion(String projectId, SimpleBackendRevision revision)
+ {
+ this.id = VersionId.newVersionId(0, 0,0);
+ this.projectId = projectId;
+ this.revisionId = revision.getId();
+ this.notes = "";
+ }
+
+ @Override
+ public VersionId getId()
+ {
+ return id;
+ }
+
+ public void setId(VersionId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public String getProjectId()
+ {
+ return projectId;
+ }
+
+ public void setProjectId(String projectId)
+ {
+ this.projectId = projectId;
+ }
+
+ @Override
+ public String getRevisionId()
+ {
+ return revisionId;
+ }
+
+ public void setRevisionId(String revisionId)
+ {
+ this.revisionId = revisionId;
+ }
+
+ @Override
+ public String getNotes()
+ {
+ return notes;
+ }
+
+ public void setNotes(String notes)
+ {
+ this.notes = notes;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/exception/UnavailableFeature.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/exception/UnavailableFeature.java
new file mode 100644
index 0000000000..8b0733a688
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/exception/UnavailableFeature.java
@@ -0,0 +1,23 @@
+// Copyright 2023 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.sdlc.server.backend.simple.exception;
+
+public class UnavailableFeature
+{
+ public static UnsupportedOperationException exception()
+ {
+ return new UnsupportedOperationException("Feature unavailable");
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/guice/SimpleBackendMixins.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/guice/SimpleBackendMixins.java
new file mode 100644
index 0000000000..a8163d4084
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/guice/SimpleBackendMixins.java
@@ -0,0 +1,57 @@
+// Copyright 2023 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.sdlc.server.backend.simple.guice;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.project.SimpleBackendProject;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.project.workspace.SimpleBackendProjectWorkspace;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.revision.SimpleBackendRevision;
+
+public class SimpleBackendMixins
+{
+ @JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.PROPERTY,
+ property = "jackson-type")
+ @JsonSubTypes({
+ @JsonSubTypes.Type(value = SimpleBackendProject.class, name = "SimpleBackendProject")})
+ public abstract class Project
+ {
+
+ }
+
+ @JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.PROPERTY,
+ property = "jackson-type")
+ @JsonSubTypes({
+ @JsonSubTypes.Type(value = SimpleBackendProjectWorkspace.class, name = "SimpleBackendProjectWorkspace")})
+ public abstract class Workspace
+ {
+
+ }
+
+ @JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.PROPERTY,
+ property = "jackson-type")
+ @JsonSubTypes({
+ @JsonSubTypes.Type(value = SimpleBackendRevision.class, name = "SimpleBackendRevision")})
+ public abstract class Revision
+ {
+
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/guice/SimpleBackendModule.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/guice/SimpleBackendModule.java
new file mode 100644
index 0000000000..fcd95f3abc
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/guice/SimpleBackendModule.java
@@ -0,0 +1,95 @@
+// Copyright 2023 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.sdlc.server.backend.simple.guice;
+
+import com.google.inject.Binder;
+import com.google.inject.Scopes;
+import org.finos.legend.sdlc.domain.model.project.Project;
+import org.finos.legend.sdlc.server.BaseLegendSDLCServer;
+import org.finos.legend.sdlc.server.backend.simple.api.backup.SimpleBackendBackupApi;
+import org.finos.legend.sdlc.server.backend.simple.api.build.SimpleBackendBuildApi;
+import org.finos.legend.sdlc.server.backend.simple.api.comparison.SimpleBackendComparisonApi;
+import org.finos.legend.sdlc.server.backend.simple.api.conflictresolution.SimpleBackendConflictResolutionApi;
+import org.finos.legend.sdlc.server.backend.simple.api.entity.SimpleBackendEntityApi;
+import org.finos.legend.sdlc.server.backend.simple.api.issue.SimpleBackendIssueApi;
+import org.finos.legend.sdlc.server.backend.simple.api.project.SimpleBackendProjectApi;
+import org.finos.legend.sdlc.server.backend.simple.api.project.SimpleBackendProjectConfigurationApi;
+import org.finos.legend.sdlc.server.backend.simple.api.review.SimpleBackendReviewApi;
+import org.finos.legend.sdlc.server.backend.simple.api.revision.SimpleBackendRevisionApi;
+import org.finos.legend.sdlc.server.backend.simple.api.user.SimpleBackendUserApi;
+import org.finos.legend.sdlc.server.backend.simple.api.version.SimpleBackendVersionApi;
+import org.finos.legend.sdlc.server.backend.simple.api.workflow.SimpleBackendWorkflowApi;
+import org.finos.legend.sdlc.server.backend.simple.api.workflow.SimpleBackendWorkflowJobApi;
+import org.finos.legend.sdlc.server.backend.simple.api.workspace.SimpleBackendWorkspaceApi;
+import org.finos.legend.sdlc.server.backend.simple.depot.SimpleBackendMetadataApi;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.project.SimpleBackendProject;
+import org.finos.legend.sdlc.server.resources.backend.simple.SimpleBackendAuthCheckResource;
+import org.finos.legend.sdlc.server.resources.backend.simple.SimpleBackendAuthResource;
+import org.finos.legend.sdlc.server.backend.simple.state.SimpleBackendState;
+import org.finos.legend.sdlc.server.depot.api.MetadataApi;
+import org.finos.legend.sdlc.server.domain.api.backup.BackupApi;
+import org.finos.legend.sdlc.server.domain.api.build.BuildApi;
+import org.finos.legend.sdlc.server.domain.api.comparison.ComparisonApi;
+import org.finos.legend.sdlc.server.domain.api.conflictResolution.ConflictResolutionApi;
+import org.finos.legend.sdlc.server.domain.api.entity.EntityApi;
+import org.finos.legend.sdlc.server.domain.api.issue.IssueApi;
+import org.finos.legend.sdlc.server.domain.api.project.ProjectApi;
+import org.finos.legend.sdlc.server.domain.api.project.ProjectConfigurationApi;
+import org.finos.legend.sdlc.server.domain.api.review.ReviewApi;
+import org.finos.legend.sdlc.server.domain.api.revision.RevisionApi;
+import org.finos.legend.sdlc.server.domain.api.user.UserApi;
+import org.finos.legend.sdlc.server.domain.api.version.VersionApi;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowApi;
+import org.finos.legend.sdlc.server.domain.api.workflow.WorkflowJobApi;
+import org.finos.legend.sdlc.server.domain.api.workspace.WorkspaceApi;
+import org.finos.legend.sdlc.server.guice.AbstractBaseModule;
+
+public class SimpleBackendModule extends AbstractBaseModule
+{
+ public SimpleBackendModule(BaseLegendSDLCServer> server)
+ {
+ super(server);
+ }
+
+ @Override
+ protected void configureApis(Binder binder)
+ {
+ configureLegendApis(binder);
+ }
+
+ public static void configureLegendApis(Binder binder)
+ {
+ binder.bind(SimpleBackendState.class).in(Scopes.SINGLETON);
+ binder.bind(MetadataApi.class).to(SimpleBackendMetadataApi.class);
+ binder.bind(ProjectApi.class).to(SimpleBackendProjectApi.class);
+ binder.bind(ProjectConfigurationApi.class).to(SimpleBackendProjectConfigurationApi.class);
+ binder.bind(UserApi.class).to(SimpleBackendUserApi.class);
+ binder.bind(IssueApi.class).to(SimpleBackendIssueApi.class);
+ binder.bind(EntityApi.class).to(SimpleBackendEntityApi.class);
+ binder.bind(WorkspaceApi.class).to(SimpleBackendWorkspaceApi.class);
+ binder.bind(RevisionApi.class).to(SimpleBackendRevisionApi.class);
+ binder.bind(ReviewApi.class).to(SimpleBackendReviewApi.class);
+ binder.bind(BuildApi.class).to(SimpleBackendBuildApi.class);
+ binder.bind(VersionApi.class).to(SimpleBackendVersionApi.class);
+ binder.bind(ComparisonApi.class).to(SimpleBackendComparisonApi.class);
+ binder.bind(ConflictResolutionApi.class).to(SimpleBackendConflictResolutionApi.class);
+ binder.bind(BackupApi.class).to(SimpleBackendBackupApi.class);
+ binder.bind(WorkflowApi.class).to(SimpleBackendWorkflowApi.class);
+ binder.bind(WorkflowJobApi.class).to(SimpleBackendWorkflowJobApi.class);
+ binder.bind(SimpleBackendAuthCheckResource.class);
+ binder.bind(SimpleBackendAuthResource.class);
+ binder.bind(Project.class).to(SimpleBackendProject.class);
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/state/SimpleBackendState.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/state/SimpleBackendState.java
new file mode 100644
index 0000000000..a1f6ad561e
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/backend/simple/state/SimpleBackendState.java
@@ -0,0 +1,113 @@
+// Copyright 2023 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.sdlc.server.backend.simple.state;
+
+import org.eclipse.collections.api.factory.Lists;
+import org.eclipse.collections.api.factory.Maps;
+import org.eclipse.collections.api.list.MutableList;
+import org.eclipse.collections.api.map.MutableMap;
+import org.finos.legend.sdlc.domain.model.entity.Entity;
+import org.finos.legend.sdlc.domain.model.project.Project;
+import org.finos.legend.sdlc.domain.model.project.ProjectType;
+import org.finos.legend.sdlc.server.backend.simple.api.revision.SimpleBackendRevisionApi;
+import org.finos.legend.sdlc.server.backend.simple.canned.StaticEntities;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.project.SimpleBackendProject;
+import org.finos.legend.sdlc.server.backend.simple.domain.model.project.configuration.SimpleBackendProjectConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class SimpleBackendState
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBackendState.class);
+
+ private static final AtomicInteger COUNTER = new AtomicInteger();
+
+ private MutableMap projects = Maps.mutable.empty();
+
+ private SimpleBackendRevisionApi revisionApi = new SimpleBackendRevisionApi(this);
+
+ @Inject
+ public SimpleBackendState()
+ {
+ this.initializeWithStaticProjects();
+ }
+
+ public SimpleBackendProject getProject(String projectId)
+ {
+ return this.projects.get(projectId);
+ }
+
+ public SimpleBackendRevisionApi revisionApi()
+ {
+ return this.revisionApi;
+ }
+
+ public List getProjects()
+ {
+ MutableList projects = Lists.mutable.empty();
+ projects.addAll(this.projects.values());
+ return projects.toImmutable().castToList();
+ }
+
+ public String nextProjectId()
+ {
+ return String.valueOf(COUNTER.incrementAndGet());
+ }
+
+ public Project createProject(String name, String description, ProjectType type, String groupId, String artifactId, Iterable tags)
+ {
+ String projectId = this.nextProjectId();
+ SimpleBackendProject simpleBackendProject = new SimpleBackendProject(projectId, name, description, type, null);
+ SimpleBackendProjectConfiguration simpleBackendProjectConfiguration = new SimpleBackendProjectConfiguration(simpleBackendProject.getProjectId(), groupId, artifactId);
+ simpleBackendProject.setProjectConfiguration(simpleBackendProjectConfiguration);
+
+ this.projects.put(projectId, simpleBackendProject);
+
+ return this.projects.get(projectId);
+ }
+
+ public void deleteProject(String id)
+ {
+ this.projects.remove(id);
+ }
+
+ public void initializeWithStaticProjects()
+ {
+ this.initializeWithGuidedTourProject();
+ }
+
+ private void initializeWithGuidedTourProject()
+ {
+ String resourceName = "tour.json";
+ LOGGER.info("Initializing in memory backend with 'Guided Tour' project from '" + resourceName + "' (CLASSPATH) ");
+ try
+ {
+ SimpleBackendProject project = (SimpleBackendProject) this.createProject("Guided Tour", "A guided tour of Legend", ProjectType.PRODUCTION, "demo", "demo", Collections.emptyList());
+ MutableMap simpleBackendEntitiesMap = StaticEntities.loadEntities(resourceName);
+ project.addEntities(simpleBackendEntitiesMap);
+
+ this.projects.put(project.getProjectId(), project);
+ }
+ catch (Exception e)
+ {
+ LOGGER.warn("Failed to initialize guided tour project", e);
+ }
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/demo/LegendSDLCServerForDemo.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/demo/LegendSDLCServerForDemo.java
new file mode 100644
index 0000000000..2f5c22acfb
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/demo/LegendSDLCServerForDemo.java
@@ -0,0 +1,80 @@
+// Copyright 2020 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.sdlc.server.demo;
+
+import com.hubspot.dropwizard.guicier.GuiceBundle;
+import io.dropwizard.setup.Bootstrap;
+import org.finos.legend.sdlc.domain.model.project.Project;
+import org.finos.legend.sdlc.domain.model.project.workspace.Workspace;
+import org.finos.legend.sdlc.domain.model.revision.Revision;
+import org.finos.legend.sdlc.server.BaseLegendSDLCServer;
+import org.finos.legend.sdlc.server.backend.simple.guice.SimpleBackendMixins;
+import org.finos.legend.sdlc.server.backend.simple.guice.SimpleBackendModule;
+import org.finos.legend.sdlc.server.config.LegendSDLCServerConfiguration;
+import org.finos.legend.sdlc.server.guice.AbstractBaseModule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LegendSDLCServerForDemo extends BaseLegendSDLCServer
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(LegendSDLCServerForDemo.class);
+
+ private GuiceBundle guiceBundle;
+
+ public LegendSDLCServerForDemo()
+ {
+ super(null);
+ }
+
+ @Override
+ protected void configureApis(Bootstrap bootstrap)
+ {
+ super.configureApis(bootstrap);
+
+ bootstrap.getObjectMapper().addMixIn(Project.class, SimpleBackendMixins.Project.class);
+ bootstrap.getObjectMapper().addMixIn(Workspace.class, SimpleBackendMixins.Workspace.class);
+ bootstrap.getObjectMapper().addMixIn(Revision.class, SimpleBackendMixins.Revision.class);
+ }
+
+ @Override
+ protected GuiceBundle buildGuiceBundle()
+ {
+ this.guiceBundle = super.buildGuiceBundle();
+ return this.guiceBundle;
+ }
+
+ @Override
+ protected AbstractBaseModule buildBaseModule()
+ {
+ return new SimpleBackendModule(this);
+ }
+
+ public GuiceBundle getGuiceBundle()
+ {
+ return this.guiceBundle;
+ }
+
+ @Override
+ protected ServerPlatformInfo newServerPlatformInfo()
+ {
+ return new ServerPlatformInfo(null, null, null);
+ }
+
+ public static void main(String... args) throws Exception
+ {
+ LOGGER.info("Starting demo SDLC server");
+ new LegendSDLCServerForDemo().run(args);
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/resources/backend/simple/SimpleBackendAuthCheckResource.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/resources/backend/simple/SimpleBackendAuthCheckResource.java
new file mode 100644
index 0000000000..b71023c847
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/resources/backend/simple/SimpleBackendAuthCheckResource.java
@@ -0,0 +1,48 @@
+// Copyright 2023 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.sdlc.server.resources.backend.simple;
+
+import org.finos.legend.sdlc.server.resources.BaseResource;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Path("/auth")
+public class SimpleBackendAuthCheckResource extends BaseResource
+{
+ private final HttpServletRequest httpRequest;
+ private final HttpServletResponse httpResponse;
+
+ @Inject
+ public SimpleBackendAuthCheckResource(HttpServletRequest httpRequest, HttpServletResponse httpResponse)
+ {
+ super();
+ this.httpRequest = httpRequest;
+ this.httpResponse = httpResponse;
+ }
+
+ @GET
+ @Path("authorized")
+ @Produces(MediaType.APPLICATION_JSON)
+ public boolean isAuthorized()
+ {
+ return true;
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/resources/backend/simple/SimpleBackendAuthResource.java b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/resources/backend/simple/SimpleBackendAuthResource.java
new file mode 100644
index 0000000000..43158d9d54
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/java/org/finos/legend/sdlc/server/resources/backend/simple/SimpleBackendAuthResource.java
@@ -0,0 +1,67 @@
+// Copyright 2023 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.sdlc.server.resources.backend.simple;
+
+import io.swagger.annotations.ApiParam;
+import org.finos.legend.sdlc.server.resources.BaseResource;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.util.Collections;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+@Path("/auth")
+public class SimpleBackendAuthResource extends BaseResource
+{
+ private static final Pattern TERMS_OF_SERVICE_MESSAGE_PATTERN = Pattern.compile("terms\\s++of\\s++service", Pattern.CASE_INSENSITIVE);
+
+ @Inject
+ public SimpleBackendAuthResource()
+ {
+ super();
+ }
+
+ @GET
+ @Path("callback")
+ public Object callback(@QueryParam("code") String code, @QueryParam("state") String state)
+ {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @GET
+ @Path("authorize")
+ @Produces(MediaType.TEXT_HTML)
+ public String authorize(@QueryParam("redirect_uri") @ApiParam("URI to redirect to when authorization is complete") String redirectUri)
+ {
+ return executeWithLogging("authorizing", () ->
+ {
+ return "Success
";
+ });
+ }
+
+ @GET
+ @Path("termsOfServiceAcceptance")
+ @Produces(MediaType.APPLICATION_JSON)
+ // NOTE: we have to return a set for backward compatibility reason
+ public Set termsOfServiceAcceptance()
+ {
+ return Collections.emptySet();
+ }
+}
diff --git a/legend-sdlc-server-demo/src/main/resources/backend/simple/canned/tour.json b/legend-sdlc-server-demo/src/main/resources/backend/simple/canned/tour.json
new file mode 100644
index 0000000000..818ea0bcfc
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/resources/backend/simple/canned/tour.json
@@ -0,0 +1,2761 @@
+[
+ {
+ "path": "domain::Firm_Person",
+ "content": {
+ "_type": "association",
+ "name": "Firm_Person",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 5,
+ "endColumn": 1
+ },
+ "properties": [
+ {
+ "name": "firm",
+ "type": "domain::Firm",
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 3,
+ "endLine": 3,
+ "endColumn": 24
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 20
+ }
+ },
+ {
+ "name": "employees",
+ "type": "domain::Person",
+ "multiplicity": {
+ "lowerBound": 0
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 4,
+ "endColumn": 31
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 14,
+ "endLine": 4,
+ "endColumn": 27
+ }
+ }
+ ],
+ "originalMilestonedProperties": [],
+ "qualifiedProperties": [],
+ "stereotypes": [],
+ "taggedValues": [],
+ "package": "domain"
+ },
+ "classifierPath": "meta::pure::metamodel::relationship::Association"
+ },
+ {
+ "path": "generation::MyGenerationSpecification",
+ "content": {
+ "_type": "generationSpecification",
+ "name": "MyGenerationSpecification",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 9,
+ "endColumn": 1
+ },
+ "generationNodes": [],
+ "fileGenerations": [
+ {
+ "type": "FILE_GENERATION",
+ "path": "generation::JSONschemasWithRelatedType",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 5,
+ "startColumn": 5,
+ "endLine": 5,
+ "endColumn": 42
+ }
+ },
+ {
+ "type": "FILE_GENERATION",
+ "path": "generation::OpenAPIDiscriminators",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 6,
+ "startColumn": 5,
+ "endLine": 6,
+ "endColumn": 37
+ }
+ },
+ {
+ "type": "FILE_GENERATION",
+ "path": "generation::JSONWithNoRelatedTypes",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 7,
+ "startColumn": 5,
+ "endLine": 7,
+ "endColumn": 38
+ }
+ }
+ ],
+ "package": "generation"
+ },
+ "classifierPath": "meta::pure::generation::metamodel::GenerationSpecification"
+ },
+ {
+ "path": "generation::JSONWithNoRelatedTypes",
+ "content": {
+ "_type": "fileGeneration",
+ "name": "JSONWithNoRelatedTypes",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 7,
+ "endColumn": 1
+ },
+ "type": "jsonSchema",
+ "scopeElements": [
+ "domain"
+ ],
+ "configurationProperties": [
+ {
+ "name": "includeAllRelatedTypes",
+ "value": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 5,
+ "startColumn": 3,
+ "endLine": 5,
+ "endColumn": 32
+ }
+ },
+ {
+ "name": "generateConstraintFunctionSchemas",
+ "value": true,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 6,
+ "startColumn": 3,
+ "endLine": 6,
+ "endColumn": 42
+ }
+ }
+ ],
+ "typeSourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 2,
+ "endColumn": 10
+ },
+ "package": "generation"
+ },
+ "classifierPath": "meta::pure::generation::metamodel::GenerationConfiguration"
+ },
+ {
+ "path": "mapping::relational::Firm_Person",
+ "content": {
+ "_type": "mapping",
+ "name": "Firm_Person",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 59,
+ "endColumn": 1
+ },
+ "classMappings": [
+ {
+ "_type": "relational",
+ "root": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 13,
+ "endColumn": 3
+ },
+ "classSourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 4,
+ "endColumn": 16
+ },
+ "primaryKey": [
+ {
+ "_type": "column",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 8,
+ "startColumn": 7,
+ "endLine": 8,
+ "endColumn": 29
+ },
+ "table": {
+ "_type": "Table",
+ "table": "PERSON",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 8,
+ "startColumn": 21,
+ "endLine": 8,
+ "endColumn": 26
+ }
+ },
+ "tableAlias": "PERSON",
+ "column": "ID"
+ }
+ ],
+ "propertyMappings": [
+ {
+ "_type": "relationalPropertyMapping",
+ "property": {
+ "property": "firstName",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 11,
+ "startColumn": 5,
+ "endLine": 11,
+ "endColumn": 13
+ },
+ "class": "domain::Person"
+ },
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 11,
+ "startColumn": 14,
+ "endLine": 11,
+ "endColumn": 46
+ },
+ "relationalOperation": {
+ "_type": "column",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 11,
+ "startColumn": 16,
+ "endLine": 11,
+ "endColumn": 46
+ },
+ "table": {
+ "_type": "Table",
+ "table": "PERSON",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 11,
+ "startColumn": 30,
+ "endLine": 11,
+ "endColumn": 35
+ }
+ },
+ "tableAlias": "PERSON",
+ "column": "FIRST_NAME"
+ }
+ },
+ {
+ "_type": "relationalPropertyMapping",
+ "property": {
+ "property": "lastName",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 12,
+ "startColumn": 5,
+ "endLine": 12,
+ "endColumn": 12
+ },
+ "class": "domain::Person"
+ },
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 12,
+ "startColumn": 13,
+ "endLine": 12,
+ "endColumn": 44
+ },
+ "relationalOperation": {
+ "_type": "column",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 12,
+ "startColumn": 15,
+ "endLine": 12,
+ "endColumn": 44
+ },
+ "table": {
+ "_type": "Table",
+ "table": "PERSON",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 12,
+ "startColumn": 29,
+ "endLine": 12,
+ "endColumn": 34
+ }
+ },
+ "tableAlias": "PERSON",
+ "column": "LAST_NAME"
+ }
+ }
+ ],
+ "mainTable": {
+ "_type": "Table",
+ "table": "PERSON",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 10,
+ "startColumn": 30,
+ "endLine": 10,
+ "endColumn": 35
+ }
+ },
+ "distinct": false,
+ "groupBy": [],
+ "class": "domain::Person"
+ },
+ {
+ "_type": "relational",
+ "root": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 14,
+ "startColumn": 3,
+ "endLine": 23,
+ "endColumn": 3
+ },
+ "classSourceInformation": {
+ "sourceId": "",
+ "startLine": 14,
+ "startColumn": 3,
+ "endLine": 14,
+ "endColumn": 14
+ },
+ "primaryKey": [
+ {
+ "_type": "column",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 18,
+ "startColumn": 7,
+ "endLine": 18,
+ "endColumn": 27
+ },
+ "table": {
+ "_type": "Table",
+ "table": "FIRM",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 18,
+ "startColumn": 21,
+ "endLine": 18,
+ "endColumn": 24
+ }
+ },
+ "tableAlias": "FIRM",
+ "column": "ID"
+ }
+ ],
+ "propertyMappings": [
+ {
+ "_type": "relationalPropertyMapping",
+ "property": {
+ "property": "legalName",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 21,
+ "startColumn": 5,
+ "endLine": 21,
+ "endColumn": 13
+ },
+ "class": "domain::Firm"
+ },
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 21,
+ "startColumn": 14,
+ "endLine": 21,
+ "endColumn": 44
+ },
+ "relationalOperation": {
+ "_type": "column",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 21,
+ "startColumn": 16,
+ "endLine": 21,
+ "endColumn": 44
+ },
+ "table": {
+ "_type": "Table",
+ "table": "FIRM",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 21,
+ "startColumn": 30,
+ "endLine": 21,
+ "endColumn": 33
+ }
+ },
+ "tableAlias": "FIRM",
+ "column": "LEGAL_NAME"
+ }
+ },
+ {
+ "_type": "relationalPropertyMapping",
+ "property": {
+ "property": "employees",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 22,
+ "startColumn": 5,
+ "endLine": 22,
+ "endColumn": 13
+ },
+ "class": "domain::Firm"
+ },
+ "target": "domain_Person",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 22,
+ "startColumn": 29,
+ "endLine": 22,
+ "endColumn": 56
+ },
+ "relationalOperation": {
+ "_type": "elemtWithJoins",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 22,
+ "startColumn": 31,
+ "endLine": 22,
+ "endColumn": 56
+ },
+ "joins": [
+ {
+ "db": "database::h2",
+ "name": "Firm_Person",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 22,
+ "startColumn": 45,
+ "endLine": 22,
+ "endColumn": 56
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "mainTable": {
+ "_type": "Table",
+ "table": "FIRM",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 20,
+ "startColumn": 30,
+ "endLine": 20,
+ "endColumn": 33
+ }
+ },
+ "distinct": false,
+ "groupBy": [],
+ "class": "domain::Firm"
+ }
+ ],
+ "includedMappings": [],
+ "associationMappings": [],
+ "enumerationMappings": [],
+ "tests": [
+ {
+ "name": "test_1",
+ "query": {
+ "_type": "lambda",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 29,
+ "startColumn": 14,
+ "endLine": 40,
+ "endColumn": 1
+ },
+ "body": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 29,
+ "startColumn": 35,
+ "endLine": 29,
+ "endColumn": 41
+ },
+ "function": "project",
+ "parameters": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 29,
+ "startColumn": 27,
+ "endLine": 29,
+ "endColumn": 32
+ },
+ "function": "getAll",
+ "parameters": [
+ {
+ "_type": "packageableElementPtr",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 29,
+ "startColumn": 15,
+ "endLine": 29,
+ "endColumn": 26
+ },
+ "fullPath": "domain::Firm"
+ }
+ ]
+ },
+ {
+ "_type": "collection",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 30,
+ "startColumn": 3,
+ "endLine": 34,
+ "endColumn": 3
+ },
+ "values": [
+ {
+ "_type": "lambda",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 31,
+ "startColumn": 6,
+ "endLine": 31,
+ "endColumn": 18
+ },
+ "body": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 31,
+ "startColumn": 10,
+ "endLine": 31,
+ "endColumn": 18
+ },
+ "property": "legalName",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 31,
+ "startColumn": 7,
+ "endLine": 31,
+ "endColumn": 8
+ },
+ "name": "x"
+ }
+ ]
+ }
+ ],
+ "parameters": [
+ {
+ "_type": "var",
+ "name": "x"
+ }
+ ]
+ },
+ {
+ "_type": "lambda",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 32,
+ "startColumn": 6,
+ "endLine": 32,
+ "endColumn": 28
+ },
+ "body": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 32,
+ "startColumn": 20,
+ "endLine": 32,
+ "endColumn": 28
+ },
+ "property": "firstName",
+ "parameters": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 32,
+ "startColumn": 10,
+ "endLine": 32,
+ "endColumn": 18
+ },
+ "property": "employees",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 32,
+ "startColumn": 7,
+ "endLine": 32,
+ "endColumn": 8
+ },
+ "name": "x"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "parameters": [
+ {
+ "_type": "var",
+ "name": "x"
+ }
+ ]
+ },
+ {
+ "_type": "lambda",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 33,
+ "startColumn": 6,
+ "endLine": 33,
+ "endColumn": 27
+ },
+ "body": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 33,
+ "startColumn": 20,
+ "endLine": 33,
+ "endColumn": 27
+ },
+ "property": "lastName",
+ "parameters": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 33,
+ "startColumn": 10,
+ "endLine": 33,
+ "endColumn": 18
+ },
+ "property": "employees",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 33,
+ "startColumn": 7,
+ "endLine": 33,
+ "endColumn": 8
+ },
+ "name": "x"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "parameters": [
+ {
+ "_type": "var",
+ "name": "x"
+ }
+ ]
+ }
+ ],
+ "multiplicity": {
+ "lowerBound": 3,
+ "upperBound": 3
+ }
+ },
+ {
+ "_type": "collection",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 35,
+ "startColumn": 3,
+ "endLine": 39,
+ "endColumn": 3
+ },
+ "values": [
+ {
+ "_type": "string",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 36,
+ "startColumn": 5,
+ "endLine": 36,
+ "endColumn": 16
+ },
+ "values": [
+ "Legal Name"
+ ],
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ }
+ },
+ {
+ "_type": "string",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 37,
+ "startColumn": 5,
+ "endLine": 37,
+ "endColumn": 26
+ },
+ "values": [
+ "Employees/First Name"
+ ],
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ }
+ },
+ {
+ "_type": "string",
+ "sourceInformation": {
+ "sourceId": "mapping::relational::Firm_Person",
+ "startLine": 38,
+ "startColumn": 5,
+ "endLine": 38,
+ "endColumn": 25
+ },
+ "values": [
+ "Employees/Last Name"
+ ],
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ }
+ }
+ ],
+ "multiplicity": {
+ "lowerBound": 3,
+ "upperBound": 3
+ }
+ }
+ ]
+ }
+ ],
+ "parameters": []
+ },
+ "inputData": [
+ {
+ "_type": "relational",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 43,
+ "startColumn": 9,
+ "endLine": 54,
+ "endColumn": 9
+ },
+ "database": "database::h2",
+ "data": "drop table if exists FIRM;\ncreate table FIRM(ID INTEGER, LEGAL_NAME VARCHAR(200));\ninsert into FIRM(ID, LEGAL_NAME) values(100, 'ACME Corp.');\ninsert into FIRM(ID, LEGAL_NAME) values(200, 'Monsters Inc.');\ndrop table if exists PERSON;\ncreate table PERSON(ID INTEGER, FIRMID INTEGER, FIRST_NAME VARCHAR(200), LAST_NAME VARCHAR(200));\ninsert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(1, 100, 'Road', 'Runner');\ninsert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(2, 100, 'Wile', 'Coyote');\ninsert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(3, 200, 'Jake', 'Sullivan');\ninsert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(4, 200, 'Mike', 'Wazwoski');\n",
+ "inputType": "SQL"
+ }
+ ],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 27,
+ "startColumn": 5,
+ "endLine": 57,
+ "endColumn": 5
+ },
+ "assert": {
+ "_type": "expectedOutputMappingTestAssert",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 56,
+ "startColumn": 7,
+ "endLine": 56,
+ "endColumn": 196
+ },
+ "expectedOutput": "[{\"values\":[\"ACME Corp.\",\"Road\",\"Runner\"]},{\"values\":[\"ACME Corp.\",\"Wile\",\"Coyote\"]},{\"values\":[\"Monsters Inc.\",\"Jake\",\"Sullivan\"]},{\"values\":[\"Monsters Inc.\",\"Mike\",\"Wazwoski\"]}]"
+ }
+ }
+ ],
+ "package": "mapping::relational"
+ },
+ "classifierPath": "meta::pure::mapping::Mapping"
+ },
+ {
+ "path": "database::h2",
+ "content": {
+ "_type": "relational",
+ "name": "h2",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 18,
+ "endColumn": 1
+ },
+ "includedStores": [],
+ "schemas": [
+ {
+ "name": "default",
+ "tables": [
+ {
+ "name": "PERSON",
+ "columns": [
+ {
+ "name": "ID",
+ "type": {
+ "_type": "Integer"
+ },
+ "nullable": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 6,
+ "startColumn": 5,
+ "endLine": 6,
+ "endColumn": 26
+ }
+ },
+ {
+ "name": "FIRMID",
+ "type": {
+ "_type": "Integer"
+ },
+ "nullable": true,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 7,
+ "startColumn": 5,
+ "endLine": 7,
+ "endColumn": 18
+ }
+ },
+ {
+ "name": "FIRST_NAME",
+ "type": {
+ "_type": "Varchar",
+ "size": 200
+ },
+ "nullable": true,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 8,
+ "startColumn": 5,
+ "endLine": 8,
+ "endColumn": 27
+ }
+ },
+ {
+ "name": "LAST_NAME",
+ "type": {
+ "_type": "Varchar",
+ "size": 200
+ },
+ "nullable": true,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 9,
+ "startColumn": 5,
+ "endLine": 9,
+ "endColumn": 26
+ }
+ }
+ ],
+ "primaryKey": [
+ "ID"
+ ],
+ "milestoning": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 10,
+ "endColumn": 3
+ }
+ },
+ {
+ "name": "FIRM",
+ "columns": [
+ {
+ "name": "ID",
+ "type": {
+ "_type": "Integer"
+ },
+ "nullable": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 13,
+ "startColumn": 5,
+ "endLine": 13,
+ "endColumn": 26
+ }
+ },
+ {
+ "name": "LEGAL_NAME",
+ "type": {
+ "_type": "Varchar",
+ "size": 200
+ },
+ "nullable": true,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 14,
+ "startColumn": 5,
+ "endLine": 14,
+ "endColumn": 27
+ }
+ }
+ ],
+ "primaryKey": [
+ "ID"
+ ],
+ "milestoning": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 11,
+ "startColumn": 3,
+ "endLine": 15,
+ "endColumn": 3
+ }
+ }
+ ],
+ "views": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 18,
+ "endColumn": 1
+ }
+ }
+ ],
+ "joins": [
+ {
+ "name": "Firm_Person",
+ "operation": {
+ "_type": "dynaFunc",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 17,
+ "startColumn": 34,
+ "endLine": 17,
+ "endColumn": 42
+ },
+ "funcName": "equal",
+ "parameters": [
+ {
+ "_type": "column",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 17,
+ "startColumn": 20,
+ "endLine": 17,
+ "endColumn": 42
+ },
+ "table": {
+ "_type": "Table",
+ "table": "PERSON",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 17,
+ "startColumn": 20,
+ "endLine": 17,
+ "endColumn": 25
+ }
+ },
+ "tableAlias": "PERSON",
+ "column": "FIRMID"
+ },
+ {
+ "_type": "column",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 17,
+ "startColumn": 36,
+ "endLine": 17,
+ "endColumn": 42
+ },
+ "table": {
+ "_type": "Table",
+ "table": "FIRM",
+ "schema": "default",
+ "database": "database::h2",
+ "mainTableDb": "database::h2",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 17,
+ "startColumn": 36,
+ "endLine": 17,
+ "endColumn": 39
+ }
+ },
+ "tableAlias": "FIRM",
+ "column": "ID"
+ }
+ ]
+ },
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 17,
+ "startColumn": 3,
+ "endLine": 17,
+ "endColumn": 43
+ }
+ }
+ ],
+ "filters": [],
+ "package": "database"
+ },
+ "classifierPath": "meta::relational::metamodel::Database"
+ },
+ {
+ "path": "domain::Person",
+ "content": {
+ "_type": "class",
+ "name": "Person",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 5,
+ "endColumn": 1
+ },
+ "superTypes": [],
+ "originalMilestonedProperties": [],
+ "properties": [
+ {
+ "name": "firstName",
+ "type": "String",
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 3,
+ "endLine": 3,
+ "endColumn": 23
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 14,
+ "endLine": 3,
+ "endColumn": 19
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "String",
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 4,
+ "endColumn": 22
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 13,
+ "endLine": 4,
+ "endColumn": 18
+ }
+ }
+ ],
+ "qualifiedProperties": [],
+ "stereotypes": [],
+ "taggedValues": [],
+ "constraints": [],
+ "package": "domain"
+ },
+ "classifierPath": "meta::pure::metamodel::type::Class"
+ },
+ {
+ "path": "domain::Firm",
+ "content": {
+ "_type": "class",
+ "name": "Firm",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 4,
+ "endColumn": 1
+ },
+ "superTypes": [],
+ "originalMilestonedProperties": [],
+ "properties": [
+ {
+ "name": "legalName",
+ "type": "String",
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 3,
+ "endLine": 3,
+ "endColumn": 23
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 14,
+ "endLine": 3,
+ "endColumn": 19
+ }
+ }
+ ],
+ "qualifiedProperties": [],
+ "stereotypes": [],
+ "taggedValues": [],
+ "constraints": [],
+ "package": "domain"
+ },
+ "classifierPath": "meta::pure::metamodel::type::Class"
+ },
+ {
+ "path": "domain::S_Firm",
+ "content": {
+ "_type": "class",
+ "name": "S_Firm",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 4,
+ "endColumn": 1
+ },
+ "superTypes": [],
+ "originalMilestonedProperties": [],
+ "properties": [
+ {
+ "name": "legalName",
+ "type": "String",
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 3,
+ "endLine": 3,
+ "endColumn": 23
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 14,
+ "endLine": 3,
+ "endColumn": 19
+ }
+ }
+ ],
+ "qualifiedProperties": [],
+ "stereotypes": [],
+ "taggedValues": [],
+ "constraints": [],
+ "package": "domain"
+ },
+ "classifierPath": "meta::pure::metamodel::type::Class"
+ },
+ {
+ "path": "generation::OpenAPIDiscriminators",
+ "content": {
+ "_type": "fileGeneration",
+ "name": "OpenAPIDiscriminators",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 7,
+ "endColumn": 1
+ },
+ "type": "jsonSchema",
+ "scopeElements": [
+ "domain"
+ ],
+ "configurationProperties": [
+ {
+ "name": "schemaSpecification",
+ "value": "meta::json::schema::generation::JSONSchemaSpecification.OPEN_API_V3_0_3_YAML",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 5,
+ "startColumn": 3,
+ "endLine": 5,
+ "endColumn": 102
+ }
+ },
+ {
+ "name": "includeAllRelatedTypes",
+ "value": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 6,
+ "startColumn": 3,
+ "endLine": 6,
+ "endColumn": 32
+ }
+ }
+ ],
+ "typeSourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 2,
+ "endColumn": 10
+ },
+ "package": "generation"
+ },
+ "classifierPath": "meta::pure::generation::metamodel::GenerationConfiguration"
+ },
+ {
+ "path": "generation::JSONschemasWithRelatedType",
+ "content": {
+ "_type": "fileGeneration",
+ "name": "JSONschemasWithRelatedType",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 6,
+ "endColumn": 1
+ },
+ "type": "jsonSchema",
+ "scopeElements": [
+ "domain"
+ ],
+ "configurationProperties": [
+ {
+ "name": "generateConstraintFunctionSchemas",
+ "value": true,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 5,
+ "startColumn": 3,
+ "endLine": 5,
+ "endColumn": 42
+ }
+ }
+ ],
+ "typeSourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 2,
+ "endColumn": 10
+ },
+ "package": "generation"
+ },
+ "classifierPath": "meta::pure::generation::metamodel::GenerationConfiguration"
+ },
+ {
+ "path": "domain::S_Person",
+ "content": {
+ "_type": "class",
+ "name": "S_Person",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 4,
+ "endColumn": 1
+ },
+ "superTypes": [],
+ "originalMilestonedProperties": [],
+ "properties": [
+ {
+ "name": "fullName",
+ "type": "String",
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 3,
+ "endLine": 3,
+ "endColumn": 22
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 13,
+ "endLine": 3,
+ "endColumn": 18
+ }
+ }
+ ],
+ "qualifiedProperties": [],
+ "stereotypes": [],
+ "taggedValues": [],
+ "constraints": [],
+ "package": "domain"
+ },
+ "classifierPath": "meta::pure::metamodel::type::Class"
+ },
+ {
+ "path": "service::m2m::service1",
+ "content": {
+ "_type": "service",
+ "name": "service1",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 64,
+ "endColumn": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "pattern": "/5bdac84b-ce97-45e9-87a6-8f8703e52fa8",
+ "owners": [
+ "epsstan"
+ ],
+ "documentation": "",
+ "autoActivateUpdates": true,
+ "execution": {
+ "_type": "pureSingleExecution",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 11,
+ "startColumn": 14,
+ "endLine": 56,
+ "endColumn": 3
+ },
+ "func": {
+ "_type": "lambda",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 13,
+ "startColumn": 12,
+ "endLine": 33,
+ "endColumn": 1
+ },
+ "body": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 23,
+ "startColumn": 4,
+ "endLine": 23,
+ "endColumn": 12
+ },
+ "function": "serialize",
+ "parameters": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 13,
+ "startColumn": 33,
+ "endLine": 13,
+ "endColumn": 49
+ },
+ "function": "graphFetchChecked",
+ "parameters": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 13,
+ "startColumn": 25,
+ "endLine": 13,
+ "endColumn": 30
+ },
+ "function": "getAll",
+ "parameters": [
+ {
+ "_type": "packageableElementPtr",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 13,
+ "startColumn": 13,
+ "endLine": 13,
+ "endColumn": 24
+ },
+ "fullPath": "domain::Firm"
+ }
+ ]
+ },
+ {
+ "_type": "rootGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 15,
+ "startColumn": 5,
+ "endLine": 15,
+ "endColumn": 16
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 16,
+ "startColumn": 7,
+ "endLine": 16,
+ "endColumn": 15
+ },
+ "subTrees": [],
+ "property": "legalName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 17,
+ "startColumn": 7,
+ "endLine": 17,
+ "endColumn": 15
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 18,
+ "startColumn": 9,
+ "endLine": 18,
+ "endColumn": 17
+ },
+ "subTrees": [],
+ "property": "firstName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 19,
+ "startColumn": 9,
+ "endLine": 19,
+ "endColumn": 16
+ },
+ "subTrees": [],
+ "property": "lastName",
+ "parameters": []
+ }
+ ],
+ "property": "employees",
+ "parameters": []
+ }
+ ],
+ "class": "domain::Firm"
+ }
+ ]
+ },
+ {
+ "_type": "rootGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 25,
+ "startColumn": 5,
+ "endLine": 25,
+ "endColumn": 16
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 26,
+ "startColumn": 7,
+ "endLine": 26,
+ "endColumn": 15
+ },
+ "subTrees": [],
+ "property": "legalName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 27,
+ "startColumn": 7,
+ "endLine": 27,
+ "endColumn": 15
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 28,
+ "startColumn": 9,
+ "endLine": 28,
+ "endColumn": 17
+ },
+ "subTrees": [],
+ "property": "firstName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 29,
+ "startColumn": 9,
+ "endLine": 29,
+ "endColumn": 16
+ },
+ "subTrees": [],
+ "property": "lastName",
+ "parameters": []
+ }
+ ],
+ "property": "employees",
+ "parameters": []
+ }
+ ],
+ "class": "domain::Firm"
+ }
+ ]
+ }
+ ],
+ "parameters": []
+ },
+ "mapping": "mapping::m2m::Firm_Person",
+ "runtime": {
+ "_type": "engineRuntime",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 37,
+ "startColumn": 7,
+ "endLine": 54,
+ "endColumn": 8
+ },
+ "mappings": [
+ {
+ "type": "MAPPING",
+ "path": "mapping::m2m::Firm_Person",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 39,
+ "startColumn": 9,
+ "endLine": 39,
+ "endColumn": 33
+ }
+ }
+ ],
+ "connections": [
+ {
+ "store": {
+ "type": "STORE",
+ "path": "ModelStore",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 43,
+ "startColumn": 9,
+ "endLine": 43,
+ "endColumn": 18
+ }
+ },
+ "storeConnections": [
+ {
+ "id": "connection_1",
+ "connection": {
+ "_type": "JsonModelConnection",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 47,
+ "startColumn": 13,
+ "endLine": 51,
+ "endColumn": 13
+ },
+ "url": "data:application/json,[{\"employees\":[{\"fullName\":\"Road Runner\",\"age\":100},{\"fullName\":\"Wile Coyote\",\"age\":100}],\"legalName\":\"ACME Corp.\"},{\"employees\":[{\"fullName\":\"Jake Sullivan\",\"age\":100},{\"fullName\":\"Mike Wazwoski\",\"age\":100}],\"legalName\":\"Monsters Inc.\"}]",
+ "classSourceInformation": {
+ "sourceId": "",
+ "startLine": 49,
+ "startColumn": 22,
+ "endLine": 49,
+ "endColumn": 35
+ },
+ "class": "domain::S_Firm"
+ },
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 45,
+ "startColumn": 11,
+ "endLine": 52,
+ "endColumn": 12
+ }
+ }
+ ],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 43,
+ "startColumn": 9,
+ "endLine": 53,
+ "endColumn": 9
+ }
+ }
+ ]
+ },
+ "mappingSourceInformation": {
+ "sourceId": "",
+ "startLine": 34,
+ "startColumn": 14,
+ "endLine": 34,
+ "endColumn": 38
+ }
+ },
+ "test": {
+ "_type": "singleExecutionTest",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 57,
+ "startColumn": 9,
+ "endLine": 63,
+ "endColumn": 3
+ },
+ "data": "",
+ "asserts": []
+ },
+ "package": "service::m2m"
+ },
+ "classifierPath": "meta::legend::service::metamodel::Service"
+ },
+ {
+ "path": "mapping::m2m::Firm_Person",
+ "content": {
+ "_type": "mapping",
+ "name": "Firm_Person",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 55,
+ "endColumn": 1
+ },
+ "classMappings": [
+ {
+ "_type": "pureInstance",
+ "root": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 15,
+ "endColumn": 3
+ },
+ "classSourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 4,
+ "endColumn": 16
+ },
+ "srcClass": "domain::S_Person",
+ "propertyMappings": [
+ {
+ "_type": "purePropertyMapping",
+ "property": {
+ "property": "firstName",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 7,
+ "startColumn": 5,
+ "endLine": 7,
+ "endColumn": 13
+ },
+ "class": "domain::Person"
+ },
+ "source": "",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 7,
+ "startColumn": 5,
+ "endLine": 10,
+ "endColumn": 1
+ },
+ "transform": {
+ "_type": "lambda",
+ "body": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 7,
+ "startColumn": 31,
+ "endLine": 7,
+ "endColumn": 39
+ },
+ "function": "substring",
+ "parameters": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 7,
+ "startColumn": 21,
+ "endLine": 7,
+ "endColumn": 28
+ },
+ "property": "fullName",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 7,
+ "startColumn": 16,
+ "endLine": 7,
+ "endColumn": 19
+ },
+ "name": "src"
+ }
+ ]
+ },
+ {
+ "_type": "integer",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 8,
+ "startColumn": 3,
+ "endLine": 8,
+ "endColumn": 3
+ },
+ "values": [
+ 0
+ ],
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ }
+ },
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 9,
+ "startColumn": 18,
+ "endLine": 9,
+ "endColumn": 24
+ },
+ "function": "indexOf",
+ "parameters": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 9,
+ "startColumn": 8,
+ "endLine": 9,
+ "endColumn": 15
+ },
+ "property": "fullName",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 9,
+ "startColumn": 3,
+ "endLine": 9,
+ "endColumn": 6
+ },
+ "name": "src"
+ }
+ ]
+ },
+ {
+ "_type": "string",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 9,
+ "startColumn": 26,
+ "endLine": 9,
+ "endColumn": 28
+ },
+ "values": [
+ " "
+ ],
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "parameters": []
+ },
+ "explodeProperty": false
+ },
+ {
+ "_type": "purePropertyMapping",
+ "property": {
+ "property": "lastName",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 11,
+ "startColumn": 5,
+ "endLine": 11,
+ "endColumn": 12
+ },
+ "class": "domain::Person"
+ },
+ "source": "",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 11,
+ "startColumn": 5,
+ "endLine": 14,
+ "endColumn": 1
+ },
+ "transform": {
+ "_type": "lambda",
+ "body": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 11,
+ "startColumn": 30,
+ "endLine": 11,
+ "endColumn": 38
+ },
+ "function": "substring",
+ "parameters": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 11,
+ "startColumn": 20,
+ "endLine": 11,
+ "endColumn": 27
+ },
+ "property": "fullName",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 11,
+ "startColumn": 15,
+ "endLine": 11,
+ "endColumn": 18
+ },
+ "name": "src"
+ }
+ ]
+ },
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 12,
+ "startColumn": 31,
+ "endLine": 12,
+ "endColumn": 33
+ },
+ "function": "plus",
+ "parameters": [
+ {
+ "_type": "collection",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 12,
+ "startColumn": 31,
+ "endLine": 12,
+ "endColumn": 33
+ },
+ "values": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 12,
+ "startColumn": 18,
+ "endLine": 12,
+ "endColumn": 24
+ },
+ "function": "indexOf",
+ "parameters": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 12,
+ "startColumn": 8,
+ "endLine": 12,
+ "endColumn": 15
+ },
+ "property": "fullName",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 12,
+ "startColumn": 3,
+ "endLine": 12,
+ "endColumn": 6
+ },
+ "name": "src"
+ }
+ ]
+ },
+ {
+ "_type": "string",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 12,
+ "startColumn": 26,
+ "endLine": 12,
+ "endColumn": 28
+ },
+ "values": [
+ " "
+ ],
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ }
+ }
+ ]
+ },
+ {
+ "_type": "integer",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 12,
+ "startColumn": 33,
+ "endLine": 12,
+ "endColumn": 33
+ },
+ "values": [
+ 1
+ ],
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ }
+ }
+ ],
+ "multiplicity": {
+ "lowerBound": 2,
+ "upperBound": 2
+ }
+ }
+ ]
+ },
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 13,
+ "startColumn": 18,
+ "endLine": 13,
+ "endColumn": 23
+ },
+ "function": "length",
+ "parameters": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 13,
+ "startColumn": 8,
+ "endLine": 13,
+ "endColumn": 15
+ },
+ "property": "fullName",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 13,
+ "startColumn": 3,
+ "endLine": 13,
+ "endColumn": 6
+ },
+ "name": "src"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "parameters": []
+ },
+ "explodeProperty": false
+ }
+ ],
+ "sourceClassSourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 6,
+ "startColumn": 10,
+ "endLine": 6,
+ "endColumn": 25
+ },
+ "class": "domain::Person"
+ },
+ {
+ "_type": "pureInstance",
+ "root": false,
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 16,
+ "startColumn": 3,
+ "endLine": 21,
+ "endColumn": 3
+ },
+ "classSourceInformation": {
+ "sourceId": "",
+ "startLine": 16,
+ "startColumn": 3,
+ "endLine": 16,
+ "endColumn": 14
+ },
+ "srcClass": "domain::S_Firm",
+ "propertyMappings": [
+ {
+ "_type": "purePropertyMapping",
+ "property": {
+ "property": "legalName",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 19,
+ "startColumn": 5,
+ "endLine": 19,
+ "endColumn": 13
+ },
+ "class": "domain::Firm"
+ },
+ "source": "",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 19,
+ "startColumn": 5,
+ "endLine": 19,
+ "endColumn": 29
+ },
+ "transform": {
+ "_type": "lambda",
+ "body": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 19,
+ "startColumn": 21,
+ "endLine": 19,
+ "endColumn": 29
+ },
+ "property": "legalName",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 19,
+ "startColumn": 16,
+ "endLine": 19,
+ "endColumn": 19
+ },
+ "name": "src"
+ }
+ ]
+ }
+ ],
+ "parameters": []
+ },
+ "explodeProperty": false
+ },
+ {
+ "_type": "purePropertyMapping",
+ "property": {
+ "property": "employees",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 20,
+ "startColumn": 5,
+ "endLine": 20,
+ "endColumn": 13
+ },
+ "class": "domain::Firm"
+ },
+ "source": "",
+ "target": "domain_Person",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 20,
+ "startColumn": 5,
+ "endLine": 20,
+ "endColumn": 44
+ },
+ "transform": {
+ "_type": "lambda",
+ "body": [
+ {
+ "_type": "property",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 20,
+ "startColumn": 36,
+ "endLine": 20,
+ "endColumn": 44
+ },
+ "property": "employees",
+ "parameters": [
+ {
+ "_type": "var",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 20,
+ "startColumn": 31,
+ "endLine": 20,
+ "endColumn": 34
+ },
+ "name": "src"
+ }
+ ]
+ }
+ ],
+ "parameters": []
+ },
+ "explodeProperty": false
+ }
+ ],
+ "sourceClassSourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 18,
+ "startColumn": 10,
+ "endLine": 18,
+ "endColumn": 23
+ },
+ "class": "domain::Firm"
+ }
+ ],
+ "includedMappings": [],
+ "associationMappings": [],
+ "enumerationMappings": [],
+ "tests": [
+ {
+ "name": "test_1",
+ "query": {
+ "_type": "lambda",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 27,
+ "startColumn": 14,
+ "endLine": 47,
+ "endColumn": 1
+ },
+ "body": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 37,
+ "startColumn": 4,
+ "endLine": 37,
+ "endColumn": 12
+ },
+ "function": "serialize",
+ "parameters": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 27,
+ "startColumn": 35,
+ "endLine": 27,
+ "endColumn": 44
+ },
+ "function": "graphFetch",
+ "parameters": [
+ {
+ "_type": "func",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 27,
+ "startColumn": 27,
+ "endLine": 27,
+ "endColumn": 32
+ },
+ "function": "getAll",
+ "parameters": [
+ {
+ "_type": "packageableElementPtr",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 27,
+ "startColumn": 15,
+ "endLine": 27,
+ "endColumn": 26
+ },
+ "fullPath": "domain::Firm"
+ }
+ ]
+ },
+ {
+ "_type": "rootGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 29,
+ "startColumn": 5,
+ "endLine": 29,
+ "endColumn": 16
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 30,
+ "startColumn": 7,
+ "endLine": 30,
+ "endColumn": 15
+ },
+ "subTrees": [],
+ "property": "legalName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 31,
+ "startColumn": 7,
+ "endLine": 31,
+ "endColumn": 15
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 32,
+ "startColumn": 9,
+ "endLine": 32,
+ "endColumn": 17
+ },
+ "subTrees": [],
+ "property": "firstName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 33,
+ "startColumn": 9,
+ "endLine": 33,
+ "endColumn": 16
+ },
+ "subTrees": [],
+ "property": "lastName",
+ "parameters": []
+ }
+ ],
+ "property": "employees",
+ "parameters": []
+ }
+ ],
+ "class": "domain::Firm"
+ }
+ ]
+ },
+ {
+ "_type": "rootGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 39,
+ "startColumn": 5,
+ "endLine": 39,
+ "endColumn": 16
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 40,
+ "startColumn": 7,
+ "endLine": 40,
+ "endColumn": 15
+ },
+ "subTrees": [],
+ "property": "legalName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 41,
+ "startColumn": 7,
+ "endLine": 41,
+ "endColumn": 15
+ },
+ "subTrees": [
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 42,
+ "startColumn": 9,
+ "endLine": 42,
+ "endColumn": 17
+ },
+ "subTrees": [],
+ "property": "firstName",
+ "parameters": []
+ },
+ {
+ "_type": "propertyGraphFetchTree",
+ "sourceInformation": {
+ "sourceId": "mapping::m2m::Firm_Person",
+ "startLine": 43,
+ "startColumn": 9,
+ "endLine": 43,
+ "endColumn": 16
+ },
+ "subTrees": [],
+ "property": "lastName",
+ "parameters": []
+ }
+ ],
+ "property": "employees",
+ "parameters": []
+ }
+ ],
+ "class": "domain::Firm"
+ }
+ ]
+ }
+ ],
+ "parameters": []
+ },
+ "inputData": [
+ {
+ "_type": "object",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 50,
+ "startColumn": 9,
+ "endLine": 50,
+ "endColumn": 240
+ },
+ "sourceClass": "domain::S_Firm",
+ "data": "[{\"employees\":[{\"fullName\":\"Road Runner\"},{\"fullName\":\"Wile Coyote\"}],\"legalName\":\"ACME Corp.\"},{\"employees\":[{\"fullName\":\"Jake Sullivan\"},{\"fullName\":\"Mike Wazwoski\"}],\"legalName\":\"Monsters Inc.\"}]",
+ "inputType": "JSON"
+ }
+ ],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 25,
+ "startColumn": 5,
+ "endLine": 53,
+ "endColumn": 5
+ },
+ "assert": {
+ "_type": "expectedOutputMappingTestAssert",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 52,
+ "startColumn": 7,
+ "endLine": 52,
+ "endColumn": 271
+ },
+ "expectedOutput": "[{\"legalName\":\"ACME Corp.\",\"employees\":[{\"firstName\":\"Road\",\"lastName\":\"Runner\"},{\"firstName\":\"Wile\",\"lastName\":\"Coyote\"}]},{\"legalName\":\"Monsters Inc.\",\"employees\":[{\"firstName\":\"Jake\",\"lastName\":\"Sullivan\"},{\"firstName\":\"Mike\",\"lastName\":\"Wazwoski\"}]}]"
+ }
+ }
+ ],
+ "package": "mapping::m2m"
+ },
+ "classifierPath": "meta::pure::mapping::Mapping"
+ },
+ {
+ "path": "domain::S_Firm_S_Person",
+ "content": {
+ "_type": "association",
+ "name": "S_Firm_S_Person",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 5,
+ "endColumn": 1
+ },
+ "properties": [
+ {
+ "name": "firm",
+ "type": "domain::S_Firm",
+ "multiplicity": {
+ "lowerBound": 1,
+ "upperBound": 1
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 3,
+ "endLine": 3,
+ "endColumn": 26
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 22
+ }
+ },
+ {
+ "name": "employees",
+ "type": "domain::S_Person",
+ "multiplicity": {
+ "lowerBound": 0
+ },
+ "stereotypes": [],
+ "taggedValues": [],
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 4,
+ "endColumn": 33
+ },
+ "propertyTypeSourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 14,
+ "endLine": 4,
+ "endColumn": 29
+ }
+ }
+ ],
+ "originalMilestonedProperties": [],
+ "qualifiedProperties": [],
+ "stereotypes": [],
+ "taggedValues": [],
+ "package": "domain"
+ },
+ "classifierPath": "meta::pure::metamodel::relationship::Association"
+ },
+ {
+ "path": "connection::h2",
+ "content": {
+ "_type": "connection",
+ "name": "h2",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 22,
+ "endColumn": 1
+ },
+ "connectionValue": {
+ "_type": "RelationalDatabaseConnection",
+ "element": "database::h2",
+ "elementSourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 10,
+ "endLine": 4,
+ "endColumn": 21
+ },
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 22,
+ "endColumn": 1
+ },
+ "type": "H2",
+ "postProcessorWithParameter": [],
+ "datasourceSpecification": {
+ "_type": "h2Local",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 6,
+ "startColumn": 3,
+ "endLine": 20,
+ "endColumn": 4
+ },
+ "testDataSetupSqls": [
+ "drop table if exists FIRM",
+ "create table FIRM(ID INTEGER, LEGAL_NAME VARCHAR(200))",
+ "insert into FIRM(ID, LEGAL_NAME) values(100, 'ACME Corp.')",
+ "insert into FIRM(ID, LEGAL_NAME) values(200, 'Monsters Inc.')",
+ "drop table if exists PERSON;",
+ "create table PERSON(ID INTEGER, FIRMID INTEGER, FIRST_NAME VARCHAR(200), LAST_NAME VARCHAR(200))",
+ "insert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(1, 100, 'Road', 'Runner')",
+ "insert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(2, 100, 'Wile', 'Coyote')",
+ "insert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(3, 200, 'Jake', 'Sullivan')",
+ "insert into PERSON(ID, FIRMID, FIRST_NAME, LAST_NAME) values(4, 200, 'Mike', 'Wazwoski')"
+ ]
+ },
+ "authenticationStrategy": {
+ "_type": "h2Default",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 21,
+ "startColumn": 3,
+ "endLine": 21,
+ "endColumn": 18
+ }
+ },
+ "databaseType": "H2"
+ },
+ "package": "connection"
+ },
+ "classifierPath": "meta::pure::runtime::PackageableConnection"
+ },
+ {
+ "path": "diagram::all",
+ "content": {
+ "_type": "diagram",
+ "name": "all",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 2,
+ "startColumn": 1,
+ "endLine": 30,
+ "endColumn": 1
+ },
+ "classViews": [
+ {
+ "rectangle": {
+ "width": 134.32373046875,
+ "height": 58.0
+ },
+ "position": {
+ "x": 639.0,
+ "y": 202.0
+ },
+ "id": "0dee659c-6d6d-41d0-a326-dd0e63250732",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 4,
+ "startColumn": 3,
+ "endLine": 9,
+ "endColumn": 3
+ },
+ "classSourceInformation": {
+ "sourceId": "",
+ "startLine": 6,
+ "startColumn": 12,
+ "endLine": 6,
+ "endColumn": 23
+ },
+ "class": "domain::Firm"
+ },
+ {
+ "rectangle": {
+ "width": 124.521484375,
+ "height": 58.0
+ },
+ "position": {
+ "x": 894.0,
+ "y": 202.0
+ },
+ "id": "860aafab-2ae2-4714-8f4e-7d8924c6cec8",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 10,
+ "startColumn": 3,
+ "endLine": 15,
+ "endColumn": 3
+ },
+ "classSourceInformation": {
+ "sourceId": "",
+ "startLine": 12,
+ "startColumn": 12,
+ "endLine": 12,
+ "endColumn": 25
+ },
+ "class": "domain::Person"
+ }
+ ],
+ "propertyViews": [
+ {
+ "sourceView": "860aafab-2ae2-4714-8f4e-7d8924c6cec8",
+ "targetView": "0dee659c-6d6d-41d0-a326-dd0e63250732",
+ "line": {
+ "points": [
+ {
+ "x": 956.2607421875,
+ "y": 232.0
+ },
+ {
+ "x": 706.161865234375,
+ "y": 231.0
+ }
+ ]
+ },
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 16,
+ "startColumn": 3,
+ "endLine": 22,
+ "endColumn": 3
+ },
+ "sourceViewSourceInformation": {
+ "sourceId": "",
+ "startLine": 19,
+ "startColumn": 13,
+ "endLine": 19,
+ "endColumn": 48
+ },
+ "targetViewSourceInformation": {
+ "sourceId": "",
+ "startLine": 20,
+ "startColumn": 13,
+ "endLine": 20,
+ "endColumn": 48
+ },
+ "property": {
+ "property": "firm",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 18,
+ "startColumn": 15,
+ "endLine": 18,
+ "endColumn": 28
+ },
+ "class": "domain::Person"
+ }
+ },
+ {
+ "sourceView": "0dee659c-6d6d-41d0-a326-dd0e63250732",
+ "targetView": "860aafab-2ae2-4714-8f4e-7d8924c6cec8",
+ "line": {
+ "points": [
+ {
+ "x": 706.161865234375,
+ "y": 231.0
+ },
+ {
+ "x": 956.2607421875,
+ "y": 231.0
+ }
+ ]
+ },
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 23,
+ "startColumn": 3,
+ "endLine": 29,
+ "endColumn": 3
+ },
+ "sourceViewSourceInformation": {
+ "sourceId": "",
+ "startLine": 26,
+ "startColumn": 13,
+ "endLine": 26,
+ "endColumn": 48
+ },
+ "targetViewSourceInformation": {
+ "sourceId": "",
+ "startLine": 27,
+ "startColumn": 13,
+ "endLine": 27,
+ "endColumn": 48
+ },
+ "property": {
+ "property": "employees",
+ "sourceInformation": {
+ "sourceId": "",
+ "startLine": 25,
+ "startColumn": 15,
+ "endLine": 25,
+ "endColumn": 26
+ },
+ "class": "domain::Firm"
+ }
+ }
+ ],
+ "generalizationViews": [],
+ "package": "diagram"
+ },
+ "classifierPath": "meta::pure::metamodel::diagram::Diagram"
+ }
+]
\ No newline at end of file
diff --git a/legend-sdlc-server-demo/src/main/resources/docker/config/config.json b/legend-sdlc-server-demo/src/main/resources/docker/config/config.json
new file mode 100644
index 0000000000..29299658bf
--- /dev/null
+++ b/legend-sdlc-server-demo/src/main/resources/docker/config/config.json
@@ -0,0 +1,117 @@
+{
+ "applicationName": "Legend SDLC",
+ "sessionCookie": "LEGEND_SDLC_JSESSIONID",
+ "server": {
+ "adminContextPath": "/admin",
+ "applicationConnectors": [
+ {
+ "type": "http",
+ "port": ${SDLC_PORT},
+ "maxRequestHeaderSize": "128KiB"
+ }
+ ],
+ "adminConnectors": [
+ {
+ "type": "http",
+ "port": ${SDLC_ADMIN_PORT}
+ }
+ ],
+ "gzip": {
+ "includedMethods": [
+ "GET",
+ "POST"
+ ]
+ },
+ "requestLog": {
+ "type": "classic",
+ "level": "OFF",
+ "appenders": [
+ {
+ "type": "console",
+ "logFormat": "OFF"
+ }
+ ]
+ },
+ "rootPath": "/api"
+ },
+ "projectStructure": {
+ "projectCreation": {
+ },
+ "extensionProvider": {
+ "org.finos.legend.sdlc.server.gitlab.finos.FinosGitlabProjectStructureExtensionProvider": {}
+ },
+ "platforms": {
+ "legend-engine": {
+ "groupId": "org.finos.legend.engine",
+ "platformVersion": {
+ "version": "${ENGINE_MAVEN_VERSION}"
+ }
+ },
+ "legend-sdlc": {
+ "groupId": "org.finos.legend.sdlc",
+ "platformVersion":{
+ "version": "${SDLC_MAVEN_VERSION}"
+ }
+ }
+ }
+ },
+ "filterPriorities": {
+ "GitLab": 1,
+ "org.pac4j.j2e.filter.CallbackFilter": 2,
+ "org.pac4j.j2e.filter.SecurityFilter": 3,
+ "CORS": 4
+ },
+ "pac4j": {
+ "callbackPrefix": "/api/pac4j/login",
+ "clients": [
+ {
+ "org.finos.legend.server.pac4j.gitlab.GitlabClient": {
+ "name": "gitlab",
+ "clientId": "${GITLAB_APP_ID}",
+ "secret": "${GITLAB_APP_SECRET}",
+ "discoveryUri": "https://${GITLAB_HOST}/.well-known/openid-configuration",
+ "scope": "openid profile api"
+ }
+ }
+ ],
+ "mongoSession": {
+ "enabled": "${MONGO_SESSION_ENABLED}",
+ "collection": "userSessions"
+ },
+ "bypassPaths": [
+ "/api/info"
+ ]
+ },
+ "features": {
+ "canCreateProject": true,
+ "canCreateVersion": true
+ },
+ "gitLab": {
+ "newProjectVisibility": "public",
+ "projectTag": "${SDLC_PROJECT_TAG}",
+ "server": {
+ "scheme": "https",
+ "host": "${GITLAB_HOST}"
+ },
+ "app": {
+ "id": "${GITLAB_APP_ID}",
+ "secret": "${GITLAB_APP_SECRET}",
+ "redirectURI": "${SDLC_REDIRECT_URI}"
+ }
+ },
+ "logging": {
+ "level": "INFO",
+ "appenders": [
+ {
+ "type": "console",
+ "logFormat": "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%thread] %c - %m%n"
+ }
+ ]
+ },
+ "swagger": {
+ "resourcePackage": "org.finos.legend.sdlc.server.resources",
+ "title": "Legend LEGEND_SDLC",
+ "version": "local-snapshot",
+ "schemes": []
+ }
+}
diff --git a/legend-sdlc-server-demo/src/test/resources/config-demo.yml b/legend-sdlc-server-demo/src/test/resources/config-demo.yml
new file mode 100644
index 0000000000..6e09cfcb02
--- /dev/null
+++ b/legend-sdlc-server-demo/src/test/resources/config-demo.yml
@@ -0,0 +1,86 @@
+# Copyright 2020 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.
+
+applicationName: Legend SDLC
+
+sessionCookie: LEGEND_SDLC_JSESSIONID
+
+cors:
+ allowedHeaders:
+ - X-Requested-With
+ - Content-Type
+ - Accept
+ - Origin
+ - Access-Control-Allow-Credentials
+ - x-b3-parentspanid
+ - x-b3-sampled
+ - x-b3-spanid
+ - x-b3-traceid
+ - legend-test-pat
+
+server:
+ applicationConnectors:
+ - type: http
+ port: 8888
+ maxRequestHeaderSize: 128KiB
+ adminConnectors:
+ - type: http
+ port: 8889
+ gzip:
+ includedMethods:
+ - GET
+ - POST
+ requestLog:
+ type: classic
+ level: OFF
+ appenders:
+ - type: console
+ logFormat: "OFF"
+ rootPath: /api
+
+filterPriorities:
+ GitLab: 1
+ org.pac4j.j2e.filter.CallbackFilter: 2
+ org.pac4j.j2e.filter.SecurityFilter: 3
+ CORS: 4
+
+pac4j:
+ clients:
+ - org.pac4j.core.client.direct.AnonymousClient: {}
+ bypassPaths:
+ - /api/info
+ - /api/server/info
+ - /api/server/platforms
+ - /api/auth/authorized
+
+features:
+ canCreateProject: true
+ canCreateVersion: false
+
+projectStructure:
+ projectCreation:
+ groupIdPattern: ^org\.finos\.legend\..+
+
+logging:
+ # Change this to affect library class logging
+ level: INFO
+ appenders:
+ - type: console
+ logFormat: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%thread] %c - %m%n"
+
+swagger:
+ resourcePackage: org.finos.legend.sdlc.server.resources
+ title: Legend SDLC
+ version: local-snapshot
+ schemes: []
\ No newline at end of file
diff --git a/legend-sdlc-server-demo/src/test/resources/logback-test.xml b/legend-sdlc-server-demo/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..dc7e552e0a
--- /dev/null
+++ b/legend-sdlc-server-demo/src/test/resources/logback-test.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/backend/InMemoryBackend.java b/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/backend/InMemoryBackend.java
index 11499a626e..9d17986951 100644
--- a/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/backend/InMemoryBackend.java
+++ b/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/backend/InMemoryBackend.java
@@ -301,7 +301,7 @@ public InMemoryReview getReview(String reviewId)
{
return this.project.getReview(reviewId);
}
-
+
public InMemoryReview addReview(String reviewId)
{
return this.project.addReview(reviewId);
diff --git a/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/domain/api/InMemoryProject.java b/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/domain/api/InMemoryProject.java
index 757f426626..10aacbcd89 100644
--- a/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/domain/api/InMemoryProject.java
+++ b/legend-sdlc-server/src/test/java/org/finos/legend/sdlc/server/inmemory/domain/api/InMemoryProject.java
@@ -220,7 +220,7 @@ public MutableList getReviews(ReviewState state, Iterablelegend-sdlc-language-pure-compiler
legend-sdlc-server-shared
legend-sdlc-server
+ legend-sdlc-server-demo
legend-sdlc-generation-shared
legend-sdlc-generation-file
legend-sdlc-generation-service
@@ -541,6 +542,11 @@
test-jar
test
+
+ org.finos.legend.sdlc
+ legend-sdlc-server-demo
+ ${project.version}
+