diff --git a/Jenkinsfile b/Jenkinsfile
index 99c6255..3bf37ff 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -13,7 +13,7 @@ def isMasterBranch = 'master'.equals(env.BRANCH_NAME);
pipeline {
agent {
node {
- label 'alpine-jdk8-mvn-3.5'
+ label 'alpine-jdk8-mvn3.6'
}
}
parameters {
diff --git a/README.md b/README.md
index e996f8d..20e0b6d 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@
# strongbox-db
## The goal of this project
-This project has been created in order speed up the building of the OrientDB database snapshots during the initial [Strongbox](https://github.com/strongbox/strongbox) startup. Before this project was born, it took some time to do all of the database changes from the beginning of time up until the most recent version, so that the OrientDB database structure would be populated properly.
+This project has been created in order speed up the building of the JanusGraph database snapshots during the initial [Strongbox](https://github.com/strongbox/strongbox) startup. Before this project was born, it took some time to do all of the database changes from the beginning of time up until the most recent version, so that the JanusGraph database structure would be populated properly.
## Architecture
This application consists of the following modules:
-* `strongbox-db-liquibase` which creates a `jar` file consiting of the liquibase changesets that construct the [Strongbox](https://github.com/strongbox/strongbox) OrientDB database schema
+* `strongbox-db-schema` which creates a `jar` file consiting of the changesets that construct the [Strongbox](https://github.com/strongbox/strongbox) JanusGraph database schema
* `strongbox-db-import` which creates a `zip` file with packed built database snapshot built from the liquibase changesets
## How is this project used in [strongbox](https://github.com/strongbox/strongbox) ?
-[strongbox](https://github.com/strongbox/strongbox) uses this project submodules as required dependencies. During the startup of [Strongbox](https://github.com/strongbox/strongbox), the application detects if an OrientDB database already exists. If not, then the application uses an extracted empty OrientDB database snapshot from the `strongbox-db-import` artifact. If the OrientDB database already exists, then the application applies all missing liquibase changesets from the `strongbox-db-liquibase` artifact.
+[strongbox](https://github.com/strongbox/strongbox) uses this project submodules as required dependencies. During the startup of [Strongbox](https://github.com/strongbox/strongbox), the application detects if a JanusGraph database already exists. If one doesn't exist, it uses an extracted empty JanusGraph database snapshot from the `strongbox-db-import` artifact; if a database exists, then the application applies all missing changesets from the `strongbox-db-schema` artifact.
## How to build this project ?
To build the code, simply execute:
@@ -17,5 +17,5 @@ To build the code, simply execute:
## What's the result of the build process ?
This project produces the following artifacts:
-* `strongbox-db-liquibase-${version}.jar` : Located in `strongbox-db-liquibase/target`, which contains current database liquibase changesets
+* `strongbox-db-schema-${version}.jar` : Located in `strongbox-db-schema/target`, which contains current database changesets
* `strongbox-db-import-${version}.zip` : Located in `strongbox-db-import/target`, which contains zipped fresh database snapshot built from the above changesets
diff --git a/pom.xml b/pom.xml
index 7cad30f..54af1ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,17 +2,17 @@
4.0.0
-
+
org.carlspring.strongbox
strongbox-parent
- 1.0-SNAPSHOT
+ 1.0-PR-62-SNAPSHOT
-
+
strongbox-db
pom
- 1.0-SNAPSHOT
-
+ 1.0-PR-19-SNAPSHOT
+
@@ -48,7 +48,7 @@
- strongbox-db-liquibase
+ strongbox-db-schema
strongbox-db-import
strongbox-db-server
diff --git a/strongbox-db-import/pom.xml b/strongbox-db-import/pom.xml
index 4d89a31..3ee1c95 100644
--- a/strongbox-db-import/pom.xml
+++ b/strongbox-db-import/pom.xml
@@ -8,37 +8,28 @@
org.carlspring.strongbox
strongbox-db
- 1.0-SNAPSHOT
+ 1.0-PR-19-SNAPSHOT
../pom.xml
strongbox-db-import
2019
-
- ${project.build.directory}/db
-
-
${project.groupId}
- strongbox-db-liquibase
+ strongbox-db-server
${project.version}
${project.groupId}
- strongbox-db-server
+ strongbox-db-schema
${project.version}
org.springframework.boot
- spring-boot-starter-jdbc
-
-
-
- com.orientechnologies
- orientdb-jdbc
+ spring-boot-starter
@@ -46,49 +37,9 @@
commons-beanutils
-
-
- org.apache.ant
- ant
- 1.10.5
-
-
- org.liquibase
- liquibase-core
-
-
- org.apache.ant
- ant
-
-
-
-
- org.unbroken-dome.liquibase-orientdb
- liquibase-orientdb
-
-
- com.mattbertolini
- liquibase-slf4j
-
-
- org.hibernate.validator
- hibernate-validator
-
-
-
-
- org.apache.commons
- commons-lang3
-
-
-
- src/main/resources
- true
-
-
org.springframework.boot
@@ -101,7 +52,30 @@
run
- -Xmx1024m
+
+ -Xmx1024m
+ -Djdk.attach.allowAttachSelf=true
+ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
+ --add-exports java.base/jdk.internal.ref=ALL-UNNAMED
+ --add-exports java.base/sun.nio.ch=ALL-UNNAMED
+ --add-exports java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED
+ --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED
+ --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED
+ --add-exports java.sql/java.sql=ALL-UNNAMED
+
+ --add-opens java.base/java.lang.module=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.loader=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.ref=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.math=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.module=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.util.jar=ALL-UNNAMED
+ --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
+
+
+ --strongbox.db.janus-graph.storage-root=${project.build.directory}/db
+ --strongbox.dbimport.root=${project.build.directory}
+
@@ -120,11 +94,107 @@
src/main/assembly/db-schema.xml
-
+
-
+
+
+
+ jdk-default
+
+ !11
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ strongbox-export-db
+ prepare-package
+
+ run
+
+
+
+ -Xmx1024m
+
+
+ --strongbox.db.janus-graph.storage-root=${project.build.directory}/db
+ --strongbox.dbimport.root=${project.build.directory}
+
+
+
+
+
+
+
+
+
+ jdk11
+
+ 11
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ strongbox-export-db
+ prepare-package
+
+ run
+
+
+
+ -Xmx1024m
+ -Djdk.attach.allowAttachSelf=true
+ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
+ --add-exports java.base/jdk.internal.ref=ALL-UNNAMED
+ --add-exports java.base/sun.nio.ch=ALL-UNNAMED
+ --add-exports
+ java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED
+ --add-exports
+ java.rmi/sun.rmi.registry=ALL-UNNAMED
+ --add-exports
+ java.rmi/sun.rmi.server=ALL-UNNAMED
+ --add-exports
+ java.sql/java.sql=ALL-UNNAMED
+
+ --add-opens
+ java.base/java.lang.module=ALL-UNNAMED
+ --add-opens
+ java.base/jdk.internal.loader=ALL-UNNAMED
+ --add-opens
+ java.base/jdk.internal.ref=ALL-UNNAMED
+ --add-opens
+ java.base/jdk.internal.reflect=ALL-UNNAMED
+ --add-opens
+ java.base/jdk.internal.math=ALL-UNNAMED
+ --add-opens
+ java.base/jdk.internal.module=ALL-UNNAMED
+ --add-opens
+ java.base/jdk.internal.util.jar=ALL-UNNAMED
+ --add-opens
+ jdk.management/com.sun.management.internal=ALL-UNNAMED
+
+
+ --strongbox.db.janus-graph.storage-root=${project.build.directory}/db
+ --strongbox.dbimport.root=${project.build.directory}
+
+
+
+
+
+
+
+
+
+
diff --git a/strongbox-db-import/src/main/assembly/db-schema.xml b/strongbox-db-import/src/main/assembly/db-schema.xml
index 794716a..e2f794f 100644
--- a/strongbox-db-import/src/main/assembly/db-schema.xml
+++ b/strongbox-db-import/src/main/assembly/db-schema.xml
@@ -9,8 +9,8 @@
- ${project.build.directory}/db/strongbox
- META-INF/resources/strongbox/db/strongbox
+ ${project.build.directory}/db
+ META-INF/org/carlsparing/strongbox/db
\ No newline at end of file
diff --git a/strongbox-db-import/src/main/java/org/carlspring/strongbox/db/orient/OrientDbConfiguration.java b/strongbox-db-import/src/main/java/org/carlspring/strongbox/db/orient/OrientDbConfiguration.java
deleted file mode 100644
index bff6c37..0000000
--- a/strongbox-db-import/src/main/java/org/carlspring/strongbox/db/orient/OrientDbConfiguration.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.carlspring.strongbox.db.orient;
-
-import java.lang.reflect.Field;
-import java.util.Properties;
-
-import javax.sql.DataSource;
-
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.liquibase.LiquibaseDataSource;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.DependsOn;
-import org.springframework.util.ReflectionUtils;
-import org.strongbox.db.server.EmbeddedOrientDbServer;
-import org.strongbox.db.server.OrientDbServer;
-import org.strongbox.db.server.OrientDbServerConfiguration;
-import org.strongbox.db.server.OrientDbServerProperties;
-import org.strongbox.db.server.OrientDbStudioConfiguration;
-import org.strongbox.db.server.OrientDbStudioProperties;
-
-import com.orientechnologies.orient.core.db.ODatabasePool;
-import com.orientechnologies.orient.core.db.ODatabaseType;
-import com.orientechnologies.orient.core.db.OrientDB;
-import com.orientechnologies.orient.core.db.OrientDBConfig;
-import com.orientechnologies.orient.jdbc.OrientDataSource;
-
-/**
- * @author Przemyslaw Fusik
- */
-@Configuration
-class OrientDbConfiguration
-{
-
- private static final Logger logger = LoggerFactory.getLogger(OrientDbConfiguration.class);
-
- @Bean
- OrientDbServer orientDbServer(OrientDbServerConfiguration serverProperties, OrientDbStudioConfiguration studioProperties) {
- return new EmbeddedOrientDbServer(studioProperties, serverProperties);
- }
-
- @Bean
- @ConfigurationProperties(prefix = "strongbox.orientdb.studio")
- OrientDbStudioConfiguration orientDbStudioProperties() {
- return new OrientDbStudioProperties();
- }
-
- @Bean
- @ConfigurationProperties(prefix = "strongbox.orientdb.server")
- OrientDbServerConfiguration orientDbServerProperties() {
- return new OrientDbServerProperties();
- }
-
- @Bean(destroyMethod = "close")
- @DependsOn("orientDbServer")
- OrientDB orientDB(OrientDbServerConfiguration orientDbServerProperties)
- {
- OrientDB orientDB = new OrientDB(StringUtils.substringBeforeLast(orientDbServerProperties.getUrl(), "/"),
- orientDbServerProperties.getUsername(),
- orientDbServerProperties.getPassword(),
- OrientDBConfig.defaultConfig());
- String database = orientDbServerProperties.getDatabase();
-
- if (!orientDB.exists(database))
- {
- logger.info(String.format("Creating database [%s]...", database));
-
- orientDB.create(database, ODatabaseType.PLOCAL);
- }
- else
- {
- logger.info("Re-using existing database " + database + ".");
- }
- return orientDB;
- }
-
- @Bean
- @LiquibaseDataSource
- DataSource dataSource(ODatabasePool pool,
- OrientDB orientDB)
- {
- OrientDataSource ds = new OrientDataSource(orientDB);
-
- ds.setInfo(new Properties());
-
- // DEV note:
- // NPEx hotfix for OrientDataSource.java:134 :)
- Field poolField = ReflectionUtils.findField(OrientDataSource.class, "pool");
- ReflectionUtils.makeAccessible(poolField);
- ReflectionUtils.setField(poolField, ds, pool);
-
- return ds;
- }
-
- @Bean(destroyMethod = "close")
- ODatabasePool databasePool(OrientDB orientDB, OrientDbServerConfiguration orientDbServerProperties)
- {
- return new ODatabasePool(orientDB,
- orientDbServerProperties.getDatabase(),
- orientDbServerProperties.getUsername(),
- orientDbServerProperties.getPassword());
- }
-
-}
diff --git a/strongbox-db-import/src/main/java/org/carlspring/strongbox/db/Application.java b/strongbox-db-import/src/main/java/org/carlspring/strongbox/dbimport/Application.java
similarity index 61%
rename from strongbox-db-import/src/main/java/org/carlspring/strongbox/db/Application.java
rename to strongbox-db-import/src/main/java/org/carlspring/strongbox/dbimport/Application.java
index 2bdd916..6ea2137 100644
--- a/strongbox-db-import/src/main/java/org/carlspring/strongbox/db/Application.java
+++ b/strongbox-db-import/src/main/java/org/carlspring/strongbox/dbimport/Application.java
@@ -1,19 +1,23 @@
-package org.carlspring.strongbox.db;
+package org.carlspring.strongbox.dbimport;
+import org.janusgraph.core.JanusGraph;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @author Przemyslaw Fusik
*/
-@SpringBootApplication
+@SpringBootApplication(exclude = ValidationAutoConfiguration.class)
public class Application
{
public static void main(String[] args)
{
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
+ ctx.getBean(JanusGraph.class);
+
SpringApplication.exit(ctx, () -> 0);
}
}
diff --git a/strongbox-db-import/src/main/java/org/carlspring/strongbox/dbimport/EmbeddedDbServerConfiguration.java b/strongbox-db-import/src/main/java/org/carlspring/strongbox/dbimport/EmbeddedDbServerConfiguration.java
new file mode 100644
index 0000000..1cb36d4
--- /dev/null
+++ b/strongbox-db-import/src/main/java/org/carlspring/strongbox/dbimport/EmbeddedDbServerConfiguration.java
@@ -0,0 +1,67 @@
+package org.carlspring.strongbox.dbimport;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.carlspring.strongbox.db.schema.StrongboxSchema;
+import org.janusgraph.core.JanusGraph;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.strongbox.db.server.CassandraEmbeddedConfiguration;
+import org.strongbox.db.server.CassandraEmbeddedProperties;
+import org.strongbox.db.server.JanusGraphConfiguration;
+import org.strongbox.db.server.JanusGraphProperties;
+import org.strongbox.db.server.JanusGraphServer;
+import org.strongbox.db.server.JanusGraphWithEmbeddedCassandra;
+import org.strongbox.util.ConfigurationUtils;
+
+/**
+ * @author Przemyslaw Fusik
+ * @author sbespalov
+ */
+@Configuration
+@ConfigurationPropertiesScan
+class EmbeddedDbServerConfiguration
+{
+
+ @Bean
+ JanusGraphServer embeddedDbServer(CassandraEmbeddedConfiguration cassandraConfiguration,
+ JanusGraphConfiguration janusGraphConfiguration)
+ throws IOException
+ {
+ return new JanusGraphWithEmbeddedCassandra(cassandraConfiguration, janusGraphConfiguration, () -> null);
+ }
+
+ @Bean
+ JanusGraph janusGraph(JanusGraphServer server)
+ throws Exception
+ {
+ return new StrongboxSchema().createSchema(server.getJanusGraph());
+ }
+
+ @Bean
+ JanusGraphProperties dbImportJanusGraphProperties(@Value("${strongbox.dbimport.root}") String dbImportRoot)
+ throws IOException
+ {
+ ConfigurationUtils.extractConfigurationFile(dbImportRoot, "janusgraph-cassandra.properties");
+ Path configFilePath = Paths.get(dbImportRoot).resolve("etc").resolve("conf").resolve("janusgraph-cassandra.properties");
+
+ return new JanusGraphProperties( String.format("file:%s", configFilePath.toAbsolutePath().toString()));
+ }
+
+ @Bean
+ CassandraEmbeddedProperties dbImportCassandraEmbeddedProperties(@Value("${strongbox.dbimport.root}") String dbImportRoot)
+ throws IOException
+ {
+ ConfigurationUtils.extractConfigurationFile(dbImportRoot, "cassandra.yaml");
+ Path rootPath = Paths.get(dbImportRoot).toAbsolutePath();
+ Path configFilePath = rootPath.resolve("etc").resolve("conf").resolve("cassandra.yaml");
+ Path storageRootPath = rootPath.resolve("db");
+
+ return new CassandraEmbeddedProperties(storageRootPath.toString(), String.format("file:%s", configFilePath.toString()));
+ }
+
+}
diff --git a/strongbox-db-import/src/main/resources/application.yml b/strongbox-db-import/src/main/resources/application.yml
index 620fd9d..2a5aef6 100644
--- a/strongbox-db-import/src/main/resources/application.yml
+++ b/strongbox-db-import/src/main/resources/application.yml
@@ -1,23 +1,6 @@
spring:
main:
web-application-type: NONE
- liquibase:
- change-log: classpath:/db/changelog/db.changelog-master.xml
strongbox:
- orientdb:
- server:
- protocol: remote
- host: 127.0.0.1
- port: "2025"
- database: strongbox
- username: admin
- password: password
- path: @strongbox.orientdb.path@
- studio:
- ipAddress: 127.0.0.1
- port: 2480
- enabled: true
- path: @strongbox.orientdb.path@
-logging:
- level:
- liquibase: INFO
\ No newline at end of file
+ dbimport:
+ root: ./target
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/db.changelog-master.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/db.changelog-master.xml
deleted file mode 100644
index 6523632..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/db.changelog-master.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/db.changelog-1.0.0.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/db.changelog-1.0.0.xml
deleted file mode 100644
index 5811154..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/db.changelog-1.0.0.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.10__ArtifactEntry.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.10__ArtifactEntry.xml
deleted file mode 100644
index 3a29163..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.10__ArtifactEntry.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.11__ArtifactEntry_cleanup.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.11__ArtifactEntry_cleanup.xml
deleted file mode 100644
index e08ec53..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.11__ArtifactEntry_cleanup.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- artifactCoordinates IS NULL
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.12__Configuration_cleanup.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.12__Configuration_cleanup.xml
deleted file mode 100644
index 237a238..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.12__Configuration_cleanup.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.13__ArtifactEntry_path.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.13__ArtifactEntry_path.xml
deleted file mode 100644
index 374ec08..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.13__ArtifactEntry_path.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.14__User_cleanup.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.14__User_cleanup.xml
deleted file mode 100644
index 05e66fb..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.14__User_cleanup.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.15__Authorization_cleanup.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.15__Authorization_cleanup.xml
deleted file mode 100644
index 656fd39..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.15__Authorization_cleanup.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.16__CronTaskConfiguration_cleanup.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.16__CronTaskConfiguration_cleanup.xml
deleted file mode 100644
index 717a529..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.16__CronTaskConfiguration_cleanup.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.17__ArtifactArchiveListing.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.17__ArtifactArchiveListing.xml
deleted file mode 100644
index 9dab10f..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.17__ArtifactArchiveListing.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.18__ArtifactGroup.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.18__ArtifactGroup.xml
deleted file mode 100644
index 76ec48e..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.18__ArtifactGroup.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.19__ArtifactEntry.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.19__ArtifactEntry.xml
deleted file mode 100644
index c8291f1..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.19__ArtifactEntry.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.1__GenericEntity.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.1__GenericEntity.xml
deleted file mode 100644
index 9c5f443..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.1__GenericEntity.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.20__User.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.20__User.xml
deleted file mode 100644
index 3a15116..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.20__User.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.21__ArtifactEntry.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.21__ArtifactEntry.xml
deleted file mode 100644
index fde581f..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.21__ArtifactEntry.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.22__UserEntry.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.22__UserEntry.xml
deleted file mode 100644
index 4329f5c..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.22__UserEntry.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.2__ArtifactEntry.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.2__ArtifactEntry.xml
deleted file mode 100644
index 14aaf94..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.2__ArtifactEntry.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.3__AuthorizationConfig.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.3__AuthorizationConfig.xml
deleted file mode 100644
index 97f69be..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.3__AuthorizationConfig.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.4__BinaryConfiguration.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.4__BinaryConfiguration.xml
deleted file mode 100644
index 7351386..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.4__BinaryConfiguration.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.5__CronTaskConfiguration.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.5__CronTaskConfiguration.xml
deleted file mode 100644
index e6ed941..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.5__CronTaskConfiguration.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.6__User.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.6__User.xml
deleted file mode 100644
index fff2dd9..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.6__User.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.7__Configuration.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.7__Configuration.xml
deleted file mode 100644
index bffbc8a..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.7__Configuration.xml
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.8__AuthorizationConfig.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.8__AuthorizationConfig.xml
deleted file mode 100644
index 43b3b9b..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.8__AuthorizationConfig.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.9__Repository.xml b/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.9__Repository.xml
deleted file mode 100644
index 71e2de4..0000000
--- a/strongbox-db-liquibase/src/main/resources/db/changelog/v1.0.0/v1.0.0.9__Repository.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/strongbox-db-liquibase/pom.xml b/strongbox-db-schema/pom.xml
similarity index 60%
rename from strongbox-db-liquibase/pom.xml
rename to strongbox-db-schema/pom.xml
index 8a79119..447701e 100644
--- a/strongbox-db-liquibase/pom.xml
+++ b/strongbox-db-schema/pom.xml
@@ -8,18 +8,23 @@
org.carlspring.strongbox
strongbox-db
- 1.0-SNAPSHOT
+ 1.0-PR-19-SNAPSHOT
../pom.xml
- strongbox-db-liquibase
+ strongbox-db-schema
2019
- com.google.guava
- guava
+ ${project.groupId}
+ strongbox-db-server
+ ${project.version}
+
+
+ org.janusgraph
+ janusgraph-core
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Edges.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Edges.java
new file mode 100644
index 0000000..e61bb1b
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Edges.java
@@ -0,0 +1,13 @@
+package org.carlspring.strongbox.db.schema;
+
+public interface Edges
+{
+
+ String ARTIFACT_HAS_ARTIFACT_COORDINATES = "ArtifactHasArtifactCoordinates";
+ String ARTIFACT_HAS_TAGS = "ArtifactHasTags";
+ String ARTIFACT_GROUP_HAS_ARTIFACTS = "ArtifactGroupHasArtifacts";
+ String ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS = "ArtifactGroupHasTaggedArtifacts";
+ String EXTENDS = "Extends";
+ String USER_HAS_SECURITY_ROLES = "UserHasSecurityRoles";
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Properties.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Properties.java
new file mode 100644
index 0000000..7ce4739
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Properties.java
@@ -0,0 +1,48 @@
+package org.carlspring.strongbox.db.schema;
+
+/**
+ * @author ankit.tomar
+ */
+public interface Properties
+{
+
+ String UUID = "uuid";
+ String STORAGE_ID = "storageId";
+ String REPOSITORY_ID = "repositoryId";
+ String NAME = "name";
+ String LAST_UPDATED = "lastUpdated";
+ String SIZE_IN_BYTES = "sizeInBytes";
+ String LAST_USED = "lastUsed";
+ String CREATED = "created";
+ String DOWNLOAD_COUNT = "downloadCount";
+ String CHECKSUMS = "checksums";
+ String ARTIFACT_FILE_EXISTS = "artifactFileExists";
+ String VERSION = "version";
+ String USERNAME = "username";
+ String PASSWORD = "password";
+ String ENABLED = "enabled";
+ String SECURITY_TOKEN_KEY = "securityTokenKey";
+ String SOURCE_ID = "sourceId";
+ String FILE_NAMES = "filenames";
+ String TAG_NAME = "tagName";
+ String COORDINATES_EXTENSION = "coordinates.extension";
+ String COORDINATES_NAME = "coordinates.name";
+ String COORDINATES_GROUP_ID = "coordinates.groupId";
+ String COORDINATES_ARTIFACT_ID = "coordinates.artifactId";
+ String COORDINATES_CLASSIFIER = "coordinates.classifier";
+ String COORDINATES_SCOPE = "coordinates.scope";
+ String COORDINATES_ID = "coordinates.id";
+ String COORDINATES_FILENAME = "coordinates.filename";
+ String COORDINATES_BUILD = "coordinates.build";
+ String COORDINATES_ABI = "coordinates.abi";
+ String COORDINATES_PLATFORM = "coordinates.platform";
+ String COORDINATES_PACKAGING = "coordinates.packaging";
+ String COORDINATES_DISTRIBUTION = "coordinates.distribution";
+ String COORDINATES_PATH = "coordinates.path";
+ String COORDINATES_BASE_NAME = "coordinates.base_name";
+ String COORDINATES_RELEASE = "coordinates.release";
+ String COORDINATES_ARCHITECTURE = "coordinates.architecture";
+ String COORDINATES_PACKAGE_TYPE = "coordinates.package_type";
+ String COORDINATES_LANGUAGE_IMPLEMENTATION_VERSION = "coordinates.languageImplementationVersion";
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/SchemaTemplate.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/SchemaTemplate.java
new file mode 100644
index 0000000..ae96f08
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/SchemaTemplate.java
@@ -0,0 +1,95 @@
+package org.carlspring.strongbox.db.schema;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.carlspring.strongbox.db.schema.migration.Changeset;
+import org.janusgraph.core.JanusGraph;
+import org.janusgraph.core.schema.JanusGraphManagement;
+import org.janusgraph.graphdb.database.management.ManagementSystem;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author sbespalov
+ */
+public class SchemaTemplate
+{
+ private static final Logger logger = LoggerFactory.getLogger(SchemaTemplate.class);
+
+ private final JanusGraph jg;
+
+ public SchemaTemplate(JanusGraph jg)
+ {
+ this.jg = jg;
+ }
+
+ public void applyChangeset(Changeset changeset)
+ {
+ logger.info(String.format("Apply changeset [%s]-[%s].", changeset.getVersion(), changeset.getName()));
+
+ JanusGraphManagement jgm = jg.openManagement();
+ Set compositeIndexes;
+ Map relationIndexes;
+ try
+ {
+ changeset.applySchemaChanges(jgm);
+
+ logger.info(String.format("Create indexes [%s]-[%s].", changeset.getVersion(), changeset.getName()));
+ compositeIndexes = changeset.createVertexIndexes(jgm);
+ relationIndexes = changeset.createRelationIndexes(jgm);
+
+ jgm.commit();
+ }
+ catch (Exception e)
+ {
+ jgm.rollback();
+ throw new RuntimeException(String.format("Failed to apply changeset [%s]-[%s].",
+ changeset.getVersion(),
+ changeset.getName()),
+ e);
+ }
+
+ GraphTraversalSource g = jg.traversal();
+ try
+ {
+ changeset.applyGraphChanges(g);
+ g.tx().commit();
+ }
+ catch (Exception e)
+ {
+ g.tx().rollback();
+ throw new RuntimeException(String.format("Failed to apply changeset [%s]-[%s].",
+ changeset.getVersion(),
+ changeset.getName()),
+ e);
+ }
+
+ // Waiting index status
+ try
+ {
+ for (String janusGraphIndex : compositeIndexes)
+ {
+ logger.info(String.format("Wait index [%s] to be registered.", janusGraphIndex));
+ ManagementSystem.awaitGraphIndexStatus(jg, janusGraphIndex).call();
+ }
+
+ for (Entry relationIndex : relationIndexes.entrySet())
+ {
+ logger.info(String.format("Wait index [%s] to be registered.", relationIndex.getKey()));
+ ManagementSystem.awaitRelationIndexStatus(jg, relationIndex.getKey(), relationIndex.getValue()).call();
+ }
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException(String.format("Failed to enable indexes for [%s]-[%s].",
+ changeset.getVersion(),
+ changeset.getName()),
+ e);
+ }
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/StrongboxSchema.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/StrongboxSchema.java
new file mode 100644
index 0000000..5354500
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/StrongboxSchema.java
@@ -0,0 +1,182 @@
+package org.carlspring.strongbox.db.schema;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.carlspring.strongbox.db.schema.changelog.Changelog;
+import org.carlspring.strongbox.db.schema.migration.Changeset;
+import org.carlspring.strongbox.db.schema.migration.ChangesetVersion;
+import org.carlspring.strongbox.db.schema.migration.JanusgraphChangelogStorage;
+import org.janusgraph.core.JanusGraph;
+import org.janusgraph.core.RelationType;
+import org.janusgraph.core.schema.JanusGraphIndex;
+import org.janusgraph.core.schema.JanusGraphManagement;
+import org.janusgraph.core.schema.JanusGraphManagement.IndexJobFuture;
+import org.janusgraph.core.schema.SchemaAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author sbespalov
+ */
+public class StrongboxSchema
+{
+
+ private static final Logger logger = LoggerFactory.getLogger(StrongboxSchema.class);
+
+ private final SortedSet changeSets;
+
+ public StrongboxSchema()
+ {
+ this(Changelog.changeSets);
+ }
+
+ public StrongboxSchema(SortedSet changeSets)
+ {
+ this.changeSets = changeSets;
+ }
+
+ public JanusGraph createSchema(JanusGraph jg)
+ throws InterruptedException
+ {
+ logger.info("Apply schema changes.");
+ applyChangesets(jg);
+ enableIndexes(jg);
+ printSchema(jg);
+ logger.info("Schema changes applied.");
+
+ return jg;
+ }
+
+ private void printSchema(JanusGraph jg)
+ {
+ JanusGraphManagement jgm = jg.openManagement();
+ try
+ {
+ logger.info(String.format("Schema: %n%s", jgm.printSchema()));
+ }
+ finally
+ {
+ jgm.rollback();
+ }
+ }
+
+ private void enableIndexes(JanusGraph jg)
+ {
+ JanusGraphManagement jgm = jg.openManagement();
+ try
+ {
+ Set vertexIndexes = fetchVertexIndexes(jgm);
+ Map relationIndexes = fetchRelationIndexes(jgm);
+
+ enableVertexIndexes(jgm, vertexIndexes);
+ enableRelationIndexes(jgm, relationIndexes);
+
+ jgm.commit();
+ }
+ catch (Exception e)
+ {
+ logger.error("Failed to enable indexes.", e);
+ jgm.rollback();
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void applyChangesets(JanusGraph jg)
+ {
+ JanusgraphChangelogStorage changelogStorage = new JanusgraphChangelogStorage(jg);
+ changelogStorage.init();
+
+ ChangesetVersion schemaVersion = changelogStorage.getSchemaVersion();
+ logger.info("Current schema version {}", schemaVersion.getVersion());
+ SchemaTemplate schemaTemplate = new SchemaTemplate(jg);
+ for (Changeset changeset : changeSets)
+ {
+ if (schemaVersion.compareTo(changeset) >= 0)
+ {
+ continue;
+ }
+
+ Changeset storedChangeset = changelogStorage.prepare(changeset);
+ try
+ {
+ schemaTemplate.applyChangeset(storedChangeset);
+ }
+ catch (Exception e)
+ {
+ logger.error(String.format("Failed to apply changeset [%s]-[%s]", changeset.getVersion(), changeset.getName()), e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private Map fetchRelationIndexes(JanusGraphManagement jgm)
+ {
+ Iterable relationTypes = jgm.getRelationTypes(RelationType.class);
+
+ return StreamSupport.stream(relationTypes.spliterator(), false)
+ .flatMap(r -> StreamSupport.stream(jgm.getRelationIndexes(r).spliterator(), false))
+ .collect(Collectors.toMap(e -> e.name(), e -> e.getType().name()));
+ }
+
+ private Set fetchVertexIndexes(JanusGraphManagement jgm)
+ {
+ Iterable vertexIndexes = jgm.getGraphIndexes(Vertex.class);
+ return StreamSupport.stream(vertexIndexes.spliterator(), false)
+ .map(JanusGraphIndex::name)
+ .collect(Collectors.toSet());
+ }
+
+ protected void enableVertexIndexes(JanusGraphManagement jgm,
+ Set indexes)
+ throws InterruptedException,
+ ExecutionException
+ {
+ for (String janusGraphIndex : indexes)
+ {
+ logger.info(String.format("Enabling index [%s].", janusGraphIndex));
+ Optional.ofNullable(jgm.updateIndex(jgm.getGraphIndex(janusGraphIndex), SchemaAction.ENABLE_INDEX))
+ .ifPresent(this::waitIndexUpdate);
+ }
+ }
+
+ private void waitIndexUpdate(IndexJobFuture future)
+ {
+ try
+ {
+ future.get();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException(e);
+ }
+ catch (ExecutionException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void enableRelationIndexes(JanusGraphManagement jgm,
+ Map indexes)
+ throws InterruptedException,
+ ExecutionException
+ {
+ Set> entrySet = indexes.entrySet();
+ for (Entry e : entrySet)
+ {
+ logger.info(String.format("Enabling index [%s].", e.getKey()));
+ Optional.ofNullable(jgm.updateIndex(jgm.getRelationIndex(jgm.getRelationType(e.getValue()), e.getKey()),
+ SchemaAction.ENABLE_INDEX))
+ .ifPresent(this::waitIndexUpdate);
+ }
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Vertices.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Vertices.java
new file mode 100644
index 0000000..bd5000e
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/Vertices.java
@@ -0,0 +1,18 @@
+package org.carlspring.strongbox.db.schema;
+
+public interface Vertices
+{
+
+ String ARTIFACT = "Artifact";
+ String GENERIC_ARTIFACT_COORDINATES = "GenericArtifactCoordinates";
+ String RAW_ARTIFACT_COORDINATES = "RawArtifactCoordinates";
+ String MAVEN_ARTIFACT_COORDINATES = "MavenArtifactCoordinates";
+ String NPM_ARTIFACT_COORDINATES = "NpmArtifactCoordinates";
+ String NUGET_ARTIFACT_COORDINATES = "NugetArtifactCoordinates";
+ String PYPI_ARTIFACT_COORDINATES = "PypiArtifactCoordinates";
+ String RPM_ARTIFACT_COORDINATES = "RpmArtifactCoordinates";
+ String ARTIFACT_TAG = "ArtifactTag";
+ String ARTIFACT_ID_GROUP = "ArtifactIdGroup";
+ String USER = "User";
+ String SECURITY_ROLE = "SecurityRole";
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/Changelog.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/Changelog.java
new file mode 100644
index 0000000..580568d
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/Changelog.java
@@ -0,0 +1,18 @@
+package org.carlspring.strongbox.db.schema.changelog;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.carlspring.strongbox.db.schema.migration.Changeset;
+
+public interface Changelog
+{
+
+ SortedSet changeSets = Collections.unmodifiableSortedSet(new TreeSet<>(
+ Arrays.asList(new Changeset[] { new V1_0_0_1_InitialSchema(),
+ new V1_0_0_2_InitialIndexes()
+ })));
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/V1_0_0_1_InitialSchema.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/V1_0_0_1_InitialSchema.java
new file mode 100644
index 0000000..8a4a28e
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/V1_0_0_1_InitialSchema.java
@@ -0,0 +1,360 @@
+package org.carlspring.strongbox.db.schema.changelog;
+
+import static org.carlspring.strongbox.db.schema.Edges.ARTIFACT_GROUP_HAS_ARTIFACTS;
+import static org.carlspring.strongbox.db.schema.Edges.ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS;
+import static org.carlspring.strongbox.db.schema.Edges.ARTIFACT_HAS_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Edges.ARTIFACT_HAS_TAGS;
+import static org.carlspring.strongbox.db.schema.Edges.EXTENDS;
+import static org.carlspring.strongbox.db.schema.Edges.USER_HAS_SECURITY_ROLES;
+import static org.carlspring.strongbox.db.schema.Properties.ARTIFACT_FILE_EXISTS;
+import static org.carlspring.strongbox.db.schema.Properties.CHECKSUMS;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_ABI;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_ARCHITECTURE;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_ARTIFACT_ID;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_BASE_NAME;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_BUILD;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_CLASSIFIER;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_DISTRIBUTION;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_EXTENSION;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_FILENAME;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_GROUP_ID;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_ID;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_LANGUAGE_IMPLEMENTATION_VERSION;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_NAME;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_PACKAGE_TYPE;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_PACKAGING;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_PATH;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_PLATFORM;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_RELEASE;
+import static org.carlspring.strongbox.db.schema.Properties.COORDINATES_SCOPE;
+import static org.carlspring.strongbox.db.schema.Properties.CREATED;
+import static org.carlspring.strongbox.db.schema.Properties.DOWNLOAD_COUNT;
+import static org.carlspring.strongbox.db.schema.Properties.ENABLED;
+import static org.carlspring.strongbox.db.schema.Properties.FILE_NAMES;
+import static org.carlspring.strongbox.db.schema.Properties.LAST_UPDATED;
+import static org.carlspring.strongbox.db.schema.Properties.LAST_USED;
+import static org.carlspring.strongbox.db.schema.Properties.NAME;
+import static org.carlspring.strongbox.db.schema.Properties.PASSWORD;
+import static org.carlspring.strongbox.db.schema.Properties.REPOSITORY_ID;
+import static org.carlspring.strongbox.db.schema.Properties.SECURITY_TOKEN_KEY;
+import static org.carlspring.strongbox.db.schema.Properties.SIZE_IN_BYTES;
+import static org.carlspring.strongbox.db.schema.Properties.SOURCE_ID;
+import static org.carlspring.strongbox.db.schema.Properties.STORAGE_ID;
+import static org.carlspring.strongbox.db.schema.Properties.TAG_NAME;
+import static org.carlspring.strongbox.db.schema.Properties.UUID;
+import static org.carlspring.strongbox.db.schema.Properties.VERSION;
+import static org.carlspring.strongbox.db.schema.Vertices.ARTIFACT;
+import static org.carlspring.strongbox.db.schema.Vertices.ARTIFACT_ID_GROUP;
+import static org.carlspring.strongbox.db.schema.Vertices.ARTIFACT_TAG;
+import static org.carlspring.strongbox.db.schema.Vertices.GENERIC_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Vertices.MAVEN_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Vertices.NPM_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Vertices.NUGET_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Vertices.PYPI_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Vertices.RAW_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Vertices.SECURITY_ROLE;
+import static org.carlspring.strongbox.db.schema.Vertices.USER;
+import static org.carlspring.strongbox.db.schema.util.SchemaUtils.addEdgePropertyConstraints;
+import static org.carlspring.strongbox.db.schema.util.SchemaUtils.addVertexPropertyConstraints;
+import static org.janusgraph.core.Multiplicity.MANY2ONE;
+import static org.janusgraph.core.Multiplicity.MULTI;
+import static org.janusgraph.core.Multiplicity.ONE2MANY;
+import static org.janusgraph.core.Multiplicity.ONE2ONE;
+
+import java.util.Optional;
+
+import org.carlspring.strongbox.db.schema.migration.Changeset;
+import org.janusgraph.core.Cardinality;
+import org.janusgraph.core.schema.ConsistencyModifier;
+import org.janusgraph.core.schema.JanusGraphManagement;
+
+public class V1_0_0_1_InitialSchema implements Changeset
+{
+
+ @Override
+ public String getVersion()
+ {
+ return "1.0.0.1";
+ }
+
+ @Override
+ public String getAuthor()
+ {
+ return "serge.bespalov@gmail.com";
+ }
+
+ @Override
+ public void applySchemaChanges(JanusGraphManagement jgm)
+ {
+ // Properties
+ makeProperties(jgm);
+
+ // Vertices
+ makeVertices(jgm);
+
+ // Edges
+ makeEdges(jgm);
+
+ // Add property constraints
+ makeVertexConstraints(jgm);
+
+ // Add connection constraints
+ makeEdgeConstraints(jgm);
+ }
+
+ private void makeProperties(JanusGraphManagement jgm)
+ {
+ Optional.of(jgm.makePropertyKey(UUID).dataType(String.class).make())
+ .ifPresent(p -> jgm.setConsistency(p, ConsistencyModifier.LOCK));
+ jgm.makePropertyKey(STORAGE_ID).dataType(String.class).make();
+ jgm.makePropertyKey(REPOSITORY_ID).dataType(String.class).make();
+ jgm.makePropertyKey(NAME).dataType(String.class).make();
+ jgm.makePropertyKey(LAST_UPDATED).dataType(Long.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(TAG_NAME).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // Artifact
+ jgm.makePropertyKey(SIZE_IN_BYTES).dataType(Long.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(LAST_USED).dataType(Long.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(CREATED).dataType(Long.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(DOWNLOAD_COUNT).dataType(Integer.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(FILE_NAMES).dataType(String.class).cardinality(Cardinality.SET).make();
+ jgm.makePropertyKey(CHECKSUMS).dataType(String.class).cardinality(Cardinality.SET).make();
+
+ // RemoteArtifact
+ jgm.makePropertyKey(ARTIFACT_FILE_EXISTS).dataType(Boolean.class).cardinality(Cardinality.SINGLE).make();
+
+ // Common coordinates
+ jgm.makePropertyKey(VERSION).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_EXTENSION).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_NAME).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // Maven
+ jgm.makePropertyKey(COORDINATES_GROUP_ID).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_ARTIFACT_ID).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_CLASSIFIER).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // Npm
+ jgm.makePropertyKey(COORDINATES_SCOPE).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // Nuget
+ jgm.makePropertyKey(COORDINATES_ID).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // P2
+ jgm.makePropertyKey(COORDINATES_FILENAME).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // Pypi
+ jgm.makePropertyKey(COORDINATES_BUILD).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_LANGUAGE_IMPLEMENTATION_VERSION).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_ABI).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_PLATFORM).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_PACKAGING).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_DISTRIBUTION).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // Raw
+ jgm.makePropertyKey(COORDINATES_PATH).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // Rpm
+ jgm.makePropertyKey(COORDINATES_BASE_NAME).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_RELEASE).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_ARCHITECTURE).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(COORDINATES_PACKAGE_TYPE).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+
+ // User
+ jgm.makePropertyKey(PASSWORD).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(ENABLED).dataType(Boolean.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(SECURITY_TOKEN_KEY).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ jgm.makePropertyKey(SOURCE_ID).dataType(String.class).cardinality(Cardinality.SINGLE).make();
+ }
+
+ private void makeVertices(JanusGraphManagement jgm)
+ {
+ jgm.makeVertexLabel(ARTIFACT).make();
+ jgm.makeVertexLabel(GENERIC_ARTIFACT_COORDINATES).make();
+ jgm.makeVertexLabel(RAW_ARTIFACT_COORDINATES).make();
+ jgm.makeVertexLabel(MAVEN_ARTIFACT_COORDINATES).make();
+ jgm.makeVertexLabel(NPM_ARTIFACT_COORDINATES).make();
+ jgm.makeVertexLabel(NUGET_ARTIFACT_COORDINATES).make();
+ jgm.makeVertexLabel(PYPI_ARTIFACT_COORDINATES).make();
+ jgm.makeVertexLabel(ARTIFACT_TAG).make();
+ jgm.makeVertexLabel(ARTIFACT_ID_GROUP).make();
+ jgm.makeVertexLabel(USER).make();
+ jgm.makeVertexLabel(SECURITY_ROLE).make();
+ }
+
+ private void makeEdges(JanusGraphManagement jgm)
+ {
+ jgm.makeEdgeLabel(ARTIFACT_HAS_ARTIFACT_COORDINATES).multiplicity(MANY2ONE).make();
+ jgm.makeEdgeLabel(ARTIFACT_HAS_TAGS).multiplicity(MULTI).make();
+ jgm.makeEdgeLabel(EXTENDS).multiplicity(ONE2ONE).make();
+ jgm.makeEdgeLabel(ARTIFACT_GROUP_HAS_ARTIFACTS).multiplicity(ONE2MANY).make();
+ jgm.makeEdgeLabel(ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS).multiplicity(MULTI).make();
+ jgm.makeEdgeLabel(USER_HAS_SECURITY_ROLES).multiplicity(MULTI).make();
+ }
+
+ private void makeVertexConstraints(JanusGraphManagement jgm)
+ {
+ // Vertex Property Constraints
+ addVertexPropertyConstraints(jgm,
+ ARTIFACT,
+ UUID,
+ STORAGE_ID,
+ REPOSITORY_ID,
+ CREATED,
+ LAST_UPDATED,
+ LAST_USED,
+ SIZE_IN_BYTES,
+ DOWNLOAD_COUNT,
+ FILE_NAMES,
+ CHECKSUMS,
+ ARTIFACT_FILE_EXISTS);
+
+ addVertexPropertyConstraints(jgm,
+ GENERIC_ARTIFACT_COORDINATES,
+ UUID,
+ VERSION,
+ COORDINATES_ID,
+ COORDINATES_EXTENSION,
+ COORDINATES_NAME,
+ COORDINATES_PATH,
+ COORDINATES_SCOPE,
+ COORDINATES_GROUP_ID,
+ COORDINATES_ARTIFACT_ID,
+ COORDINATES_CLASSIFIER,
+ COORDINATES_DISTRIBUTION,
+ COORDINATES_BUILD,
+ COORDINATES_ABI,
+ COORDINATES_PLATFORM,
+ COORDINATES_PACKAGING,
+ COORDINATES_LANGUAGE_IMPLEMENTATION_VERSION,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ RAW_ARTIFACT_COORDINATES,
+ UUID,
+ VERSION,
+ COORDINATES_EXTENSION,
+ COORDINATES_NAME,
+ COORDINATES_PATH,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ MAVEN_ARTIFACT_COORDINATES,
+ UUID,
+ VERSION,
+ COORDINATES_EXTENSION,
+ COORDINATES_NAME,
+ COORDINATES_GROUP_ID,
+ COORDINATES_ARTIFACT_ID,
+ COORDINATES_CLASSIFIER,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ NPM_ARTIFACT_COORDINATES,
+ UUID,
+ VERSION,
+ COORDINATES_EXTENSION,
+ COORDINATES_NAME,
+ COORDINATES_SCOPE,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ NUGET_ARTIFACT_COORDINATES,
+ UUID,
+ VERSION,
+ COORDINATES_EXTENSION,
+ COORDINATES_NAME,
+ COORDINATES_ID,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ PYPI_ARTIFACT_COORDINATES,
+ UUID,
+ VERSION,
+ COORDINATES_EXTENSION,
+ COORDINATES_NAME,
+ COORDINATES_BUILD,
+ COORDINATES_ABI,
+ COORDINATES_PLATFORM,
+ COORDINATES_PACKAGING,
+ COORDINATES_DISTRIBUTION,
+ COORDINATES_LANGUAGE_IMPLEMENTATION_VERSION,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ ARTIFACT_TAG,
+ UUID,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ ARTIFACT_ID_GROUP,
+ UUID,
+ STORAGE_ID,
+ REPOSITORY_ID,
+ NAME,
+ CREATED);
+
+ addVertexPropertyConstraints(jgm,
+ USER,
+ UUID,
+ PASSWORD,
+ ENABLED,
+ SECURITY_TOKEN_KEY,
+ SOURCE_ID,
+ CREATED,
+ LAST_UPDATED);
+
+ addVertexPropertyConstraints(jgm,
+ SECURITY_ROLE,
+ UUID,
+ CREATED);
+
+ addEdgePropertyConstraints(jgm,
+ ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS,
+ TAG_NAME);
+ }
+
+ private void makeEdgeConstraints(JanusGraphManagement jgm)
+ {
+ jgm.addConnection(jgm.getEdgeLabel(ARTIFACT_HAS_ARTIFACT_COORDINATES),
+ jgm.getVertexLabel(ARTIFACT),
+ jgm.getVertexLabel(GENERIC_ARTIFACT_COORDINATES));
+
+ jgm.addConnection(jgm.getEdgeLabel(ARTIFACT_HAS_TAGS),
+ jgm.getVertexLabel(ARTIFACT),
+ jgm.getVertexLabel(ARTIFACT_TAG));
+
+ jgm.addConnection(jgm.getEdgeLabel(ARTIFACT_GROUP_HAS_ARTIFACTS),
+ jgm.getVertexLabel(ARTIFACT_ID_GROUP),
+ jgm.getVertexLabel(ARTIFACT));
+
+ jgm.addConnection(jgm.getEdgeLabel(ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS),
+ jgm.getVertexLabel(ARTIFACT_ID_GROUP),
+ jgm.getVertexLabel(ARTIFACT));
+
+ jgm.addConnection(jgm.getEdgeLabel(EXTENDS),
+ jgm.getVertexLabel(RAW_ARTIFACT_COORDINATES),
+ jgm.getVertexLabel(GENERIC_ARTIFACT_COORDINATES));
+
+ jgm.addConnection(jgm.getEdgeLabel(EXTENDS),
+ jgm.getVertexLabel(NUGET_ARTIFACT_COORDINATES),
+ jgm.getVertexLabel(GENERIC_ARTIFACT_COORDINATES));
+
+ jgm.addConnection(jgm.getEdgeLabel(EXTENDS),
+ jgm.getVertexLabel(NPM_ARTIFACT_COORDINATES),
+ jgm.getVertexLabel(GENERIC_ARTIFACT_COORDINATES));
+
+ jgm.addConnection(jgm.getEdgeLabel(EXTENDS),
+ jgm.getVertexLabel(MAVEN_ARTIFACT_COORDINATES),
+ jgm.getVertexLabel(GENERIC_ARTIFACT_COORDINATES));
+
+ jgm.addConnection(jgm.getEdgeLabel(EXTENDS),
+ jgm.getVertexLabel(PYPI_ARTIFACT_COORDINATES),
+ jgm.getVertexLabel(GENERIC_ARTIFACT_COORDINATES));
+
+ jgm.addConnection(jgm.getEdgeLabel(USER_HAS_SECURITY_ROLES),
+ jgm.getVertexLabel(USER),
+ jgm.getVertexLabel(SECURITY_ROLE));
+
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/V1_0_0_2_InitialIndexes.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/V1_0_0_2_InitialIndexes.java
new file mode 100644
index 0000000..68c631e
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/changelog/V1_0_0_2_InitialIndexes.java
@@ -0,0 +1,103 @@
+package org.carlspring.strongbox.db.schema.changelog;
+
+import static org.carlspring.strongbox.db.schema.Edges.ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS;
+import static org.carlspring.strongbox.db.schema.Properties.REPOSITORY_ID;
+import static org.carlspring.strongbox.db.schema.Properties.STORAGE_ID;
+import static org.carlspring.strongbox.db.schema.Properties.TAG_NAME;
+import static org.carlspring.strongbox.db.schema.Properties.UUID;
+import static org.carlspring.strongbox.db.schema.Vertices.ARTIFACT;
+import static org.carlspring.strongbox.db.schema.Vertices.ARTIFACT_ID_GROUP;
+import static org.carlspring.strongbox.db.schema.Vertices.ARTIFACT_TAG;
+import static org.carlspring.strongbox.db.schema.Vertices.GENERIC_ARTIFACT_COORDINATES;
+import static org.carlspring.strongbox.db.schema.Vertices.SECURITY_ROLE;
+import static org.carlspring.strongbox.db.schema.Vertices.USER;
+import static org.carlspring.strongbox.db.schema.util.SchemaUtils.buildIndex;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.carlspring.strongbox.db.schema.migration.Changeset;
+import org.janusgraph.core.schema.JanusGraphManagement;
+
+public class V1_0_0_2_InitialIndexes implements Changeset
+{
+
+ @Override
+ public String getVersion()
+ {
+ return "1.0.0.2";
+ }
+
+ @Override
+ public String getAuthor()
+ {
+ return "serge.bespalov@gmail.com";
+ }
+
+ @Override
+ public Set createVertexIndexes(JanusGraphManagement jgm)
+ {
+ Set result = new HashSet<>();
+
+ result.add(buildIndex(jgm,
+ Vertex.class,
+ jgm.getVertexLabel(ARTIFACT),
+ true,
+ jgm.getPropertyKey(UUID)));
+ result.add(buildIndex(jgm,
+ Vertex.class,
+ jgm.getVertexLabel(GENERIC_ARTIFACT_COORDINATES),
+ true,
+ jgm.getPropertyKey(UUID)));
+ result.add(buildIndex(jgm,
+ Vertex.class,
+ jgm.getVertexLabel(ARTIFACT_TAG),
+ true,
+ true,
+ jgm.getPropertyKey(UUID)));
+ result.add(buildIndex(jgm,
+ Vertex.class,
+ jgm.getVertexLabel(ARTIFACT_ID_GROUP),
+ true,
+ jgm.getPropertyKey(UUID)));
+ result.add(buildIndex(jgm,
+ Vertex.class,
+ jgm.getVertexLabel(ARTIFACT_ID_GROUP),
+ false,
+ false,
+ jgm.getPropertyKey(STORAGE_ID),
+ jgm.getPropertyKey(REPOSITORY_ID)));
+ result.add(buildIndex(jgm,
+ Vertex.class,
+ jgm.getVertexLabel(USER),
+ true,
+ jgm.getPropertyKey(UUID)));
+ result.add(buildIndex(jgm,
+ Vertex.class,
+ jgm.getVertexLabel(SECURITY_ROLE),
+ true,
+ jgm.getPropertyKey(UUID)));
+
+ return result;
+ }
+
+ @Override
+ public Map createRelationIndexes(JanusGraphManagement jgm)
+ {
+ Map result = new HashMap<>();
+ String name = ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS + "By" + StringUtils.capitalize(TAG_NAME);
+ jgm.buildEdgeIndex(jgm.getEdgeLabel(ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS),
+ name,
+ Direction.OUT,
+ jgm.getPropertyKey(TAG_NAME));
+ result.put(name, ARTIFACT_GROUP_HAS_TAGGED_ARTIFACTS);
+
+ return result;
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangelogStorage.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangelogStorage.java
new file mode 100644
index 0000000..c0f5046
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangelogStorage.java
@@ -0,0 +1,22 @@
+package org.carlspring.strongbox.db.schema.migration;
+
+/**
+ * @author sbespalov
+ */
+public interface ChangelogStorage
+{
+
+ String EDGE_CHANGESET = "Changeset";
+ String VERTEX_SCHEMA_VERSION = "SchemaVersion";
+ String PROPERTY_VERSION_VALUE = "versionValue";
+ String PROPERTY_APPLY_DATE = "applyDate";
+ String PROPERTY_CHANGESET_NAME = "changesetName";
+ String PROPERTY_AUTHOR = "changesetAuthor";
+
+ void init();
+
+ ChangesetVersion getSchemaVersion();
+
+ void upgrade(Changeset version);
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/Changeset.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/Changeset.java
new file mode 100644
index 0000000..ef632ec
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/Changeset.java
@@ -0,0 +1,42 @@
+package org.carlspring.strongbox.db.schema.migration;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.janusgraph.core.schema.JanusGraphManagement;
+
+/**
+ * @author sbespalov
+ */
+public interface Changeset extends ChangesetVersion
+{
+ default String getName()
+ {
+ return getClass().getSimpleName();
+ }
+
+ String getAuthor();
+
+ default void applySchemaChanges(JanusGraphManagement jgm)
+ {
+
+ }
+
+ default Set createVertexIndexes(JanusGraphManagement jgm)
+ {
+ return Collections.emptySet();
+ }
+
+ default Map createRelationIndexes(JanusGraphManagement jgm)
+ {
+ return Collections.emptyMap();
+ }
+
+ default void applyGraphChanges(GraphTraversalSource g)
+ {
+
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangesetVersion.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangesetVersion.java
new file mode 100644
index 0000000..e4bf3a3
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangesetVersion.java
@@ -0,0 +1,35 @@
+package org.carlspring.strongbox.db.schema.migration;
+
+/**
+ * @author sbespalov
+ */
+public interface ChangesetVersion extends Comparable
+{
+
+ String getVersion();
+
+ @Override
+ default int compareTo(ChangesetVersion other)
+ {
+ String version1 = this.getVersion();
+ String version2 = other.getVersion();
+
+ String[] levels1 = version1.split("\\.");
+ String[] levels2 = version2.split("\\.");
+
+ int length = Math.max(levels1.length, levels2.length);
+ for (int i = 0; i < length; i++)
+ {
+ Integer v1 = i < levels1.length ? Integer.parseInt(levels1[i]) : 0;
+ Integer v2 = i < levels2.length ? Integer.parseInt(levels2[i]) : 0;
+ int compare = v1.compareTo(v2);
+ if (compare != 0)
+ {
+ return compare;
+ }
+ }
+
+ return 0;
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangesetVersionValue.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangesetVersionValue.java
new file mode 100644
index 0000000..a52c76b
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/ChangesetVersionValue.java
@@ -0,0 +1,24 @@
+package org.carlspring.strongbox.db.schema.migration;
+
+/**
+ * @author sbespalov
+ */
+public class ChangesetVersionValue implements ChangesetVersion
+{
+
+ public static ChangesetVersion ZERO = new ChangesetVersionValue("0");
+
+ private final String version;
+
+ public ChangesetVersionValue(String version)
+ {
+ this.version = version;
+ }
+
+ @Override
+ public String getVersion()
+ {
+ return version;
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/JanusgraphChangelogStorage.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/JanusgraphChangelogStorage.java
new file mode 100644
index 0000000..3b1509d
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/migration/JanusgraphChangelogStorage.java
@@ -0,0 +1,228 @@
+package org.carlspring.strongbox.db.schema.migration;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.janusgraph.core.EdgeLabel;
+import org.janusgraph.core.JanusGraph;
+import org.janusgraph.core.PropertyKey;
+import org.janusgraph.core.VertexLabel;
+import org.janusgraph.core.schema.ConsistencyModifier;
+import org.janusgraph.core.schema.JanusGraphManagement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author sbespalov
+ */
+public class JanusgraphChangelogStorage implements ChangelogStorage
+{
+
+ private static final Logger logger = LoggerFactory.getLogger(JanusgraphChangelogStorage.class);
+
+ private final JanusGraph jg;
+
+ public JanusgraphChangelogStorage(JanusGraph jg)
+ {
+ this.jg = jg;
+ }
+
+ @Override
+ public void init()
+ {
+ JanusGraphManagement jgm = jg.openManagement();
+ try
+ {
+ initSchema(jgm);
+ jgm.commit();
+ }
+ catch (Throwable e)
+ {
+ jgm.rollback();
+ throw new RuntimeException("Failed to init schema storage.", e);
+ }
+ }
+
+ private void initSchema(JanusGraphManagement jgm)
+ {
+ logger.info("Check the changelog storage schema to be initialized.");
+ VertexLabel schemaVersionLabel = Optional.ofNullable(jgm.getVertexLabel(VERTEX_SCHEMA_VERSION))
+ .orElseGet(() -> jgm.makeVertexLabel(VERTEX_SCHEMA_VERSION).make());
+ EdgeLabel changesetLabel = Optional.ofNullable(jgm.getEdgeLabel(EDGE_CHANGESET))
+ .orElseGet(() -> jgm.makeEdgeLabel(EDGE_CHANGESET).make());
+ if (schemaVersionLabel.mappedConnections().isEmpty())
+ {
+ jgm.addConnection(changesetLabel,
+ schemaVersionLabel,
+ schemaVersionLabel);
+ }
+
+ if (jgm.getPropertyKey(PROPERTY_VERSION_VALUE) == null)
+ {
+ PropertyKey property = jgm.makePropertyKey(PROPERTY_VERSION_VALUE).dataType(String.class).make();
+ jgm.setConsistency(property, ConsistencyModifier.LOCK);
+ jgm.addProperties(schemaVersionLabel, property);
+ }
+ if (jgm.getPropertyKey(PROPERTY_APPLY_DATE) == null)
+ {
+ PropertyKey property = jgm.makePropertyKey(PROPERTY_APPLY_DATE).dataType(Date.class).make();
+ jgm.addProperties(changesetLabel, property);
+ }
+ if (jgm.getPropertyKey(PROPERTY_AUTHOR) == null)
+ {
+ PropertyKey property = jgm.makePropertyKey(PROPERTY_AUTHOR).dataType(String.class).make();
+ jgm.addProperties(changesetLabel, property);
+ }
+ if (jgm.getPropertyKey(PROPERTY_CHANGESET_NAME) == null)
+ {
+ PropertyKey property = jgm.makePropertyKey(PROPERTY_CHANGESET_NAME).dataType(String.class).make();
+ jgm.addProperties(changesetLabel, property);
+ }
+ }
+
+ @Override
+ public ChangesetVersion getSchemaVersion()
+ {
+ GraphTraversalSource g = jg.traversal();
+ try
+ {
+ ChangesetVersion version = fetchSchemaVersion(g);
+ g.tx().commit();
+ return version;
+ }
+ catch (Throwable e)
+ {
+ g.tx().rollback();
+ throw new RuntimeException("Failed to get stored schema version.", e);
+ }
+ }
+
+ private ChangesetVersion fetchSchemaVersion(GraphTraversalSource g)
+ {
+ GraphTraversal t = g.V()
+ .hasLabel(VERTEX_SCHEMA_VERSION)
+ .not(__.inE(EDGE_CHANGESET))
+ .until(__.not(__.out(EDGE_CHANGESET)))
+ .repeat(__.out());
+ if (t.hasNext())
+ {
+ return new ChangesetVersionValue((String) t.next().property(PROPERTY_VERSION_VALUE).value());
+ }
+
+ return g.addV(VERTEX_SCHEMA_VERSION)
+ .property(PROPERTY_VERSION_VALUE, ChangesetVersionValue.ZERO.getVersion())
+ .map(v -> new ChangesetVersionValue((String) v.get().property(PROPERTY_VERSION_VALUE).value()))
+ .next();
+ }
+
+ public Changeset prepare(Changeset changeset)
+ {
+ return new StoredChangeset(changeset);
+ }
+
+ @Override
+ public void upgrade(Changeset version)
+ {
+ ChangesetVersion currentVersion = getSchemaVersion();
+ GraphTraversalSource g = jg.traversal();
+ try
+ {
+ upgrade(g, currentVersion, version);
+ g.tx().commit();
+ }
+ catch (Exception e)
+ {
+ g.tx().rollback();
+ throw new RuntimeException(String.format("Failed to upgrade schema version from [%s] to [%s]", currentVersion, version),
+ e);
+ }
+ }
+
+ private void upgrade(GraphTraversalSource g,
+ ChangesetVersion from,
+ Changeset to)
+ {
+ GraphTraversal updateSchemaVersion = g.V()
+ .hasLabel(VERTEX_SCHEMA_VERSION)
+ .has(PROPERTY_VERSION_VALUE, from.getVersion())
+ .addE(EDGE_CHANGESET)
+ .property(PROPERTY_APPLY_DATE, new Date())
+ .property(PROPERTY_CHANGESET_NAME, to.getName())
+ .property(PROPERTY_AUTHOR, to.getAuthor())
+ .to(__.addV(VERTEX_SCHEMA_VERSION)
+ .property(PROPERTY_VERSION_VALUE, to.getVersion()));
+ if (updateSchemaVersion.hasNext())
+ {
+ updateSchemaVersion.next();
+ }
+ else
+ {
+ g.addV(VERTEX_SCHEMA_VERSION).property(PROPERTY_VERSION_VALUE, to.getVersion()).next();
+ }
+ }
+
+ /**
+ * @author sbespalov
+ */
+ public class StoredChangeset implements Changeset
+ {
+
+ private final Changeset target;
+
+ public StoredChangeset(Changeset target)
+ {
+ this.target = target;
+ }
+
+ public String getName()
+ {
+ return target.getName();
+ }
+
+ public String getAuthor()
+ {
+ return target.getAuthor();
+ }
+
+ public String getVersion()
+ {
+ return target.getVersion();
+ }
+
+ public void applySchemaChanges(JanusGraphManagement jgm)
+ {
+ target.applySchemaChanges(jgm);
+ }
+
+ public int compareTo(ChangesetVersion other)
+ {
+ return target.compareTo(other);
+ }
+
+ public Set createVertexIndexes(JanusGraphManagement jgm)
+ {
+ return target.createVertexIndexes(jgm);
+ }
+
+ public Map createRelationIndexes(JanusGraphManagement jgm)
+ {
+ return target.createRelationIndexes(jgm);
+ }
+
+ @Override
+ public void applyGraphChanges(GraphTraversalSource g)
+ {
+ target.applyGraphChanges(g);
+ upgrade(g, fetchSchemaVersion(g), target);
+ }
+
+ }
+
+}
diff --git a/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/util/SchemaUtils.java b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/util/SchemaUtils.java
new file mode 100644
index 0000000..1405877
--- /dev/null
+++ b/strongbox-db-schema/src/main/java/org/carlspring/strongbox/db/schema/util/SchemaUtils.java
@@ -0,0 +1,81 @@
+package org.carlspring.strongbox.db.schema.util;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.janusgraph.core.EdgeLabel;
+import org.janusgraph.core.PropertyKey;
+import org.janusgraph.core.VertexLabel;
+import org.janusgraph.core.schema.ConsistencyModifier;
+import org.janusgraph.core.schema.JanusGraphIndex;
+import org.janusgraph.core.schema.JanusGraphManagement;
+import org.janusgraph.core.schema.JanusGraphSchemaType;
+import org.janusgraph.core.schema.JanusGraphManagement.IndexBuilder;
+
+public class SchemaUtils
+{
+
+ public static void addVertexPropertyConstraints(JanusGraphManagement jgm,
+ String vertex,
+ String... propertykeys)
+ {
+ VertexLabel vertexLabel = jgm.getVertexLabel(vertex);
+ for (String propertyKey : propertykeys)
+ {
+ jgm.addProperties(vertexLabel, jgm.getPropertyKey(propertyKey));
+ }
+ }
+
+ public static void addEdgePropertyConstraints(JanusGraphManagement jgm,
+ String label,
+ String... propertykeys)
+ {
+ EdgeLabel edge = jgm.getEdgeLabel(label);
+ for (String propertyKey : propertykeys)
+ {
+ jgm.addProperties(edge, jgm.getPropertyKey(propertyKey));
+ }
+ }
+
+ public static String buildIndex(final JanusGraphManagement jgm,
+ final Class extends Element> elementType,
+ final JanusGraphSchemaType schemaType,
+ final boolean unique,
+ final PropertyKey... properties)
+ {
+ return buildIndex(jgm, elementType, schemaType, unique, true, properties);
+ }
+
+ public static String buildIndex(final JanusGraphManagement jgm,
+ final Class extends Element> elementType,
+ final JanusGraphSchemaType schemaType,
+ final boolean unique,
+ final boolean consistent,
+ final PropertyKey... properties)
+ {
+ final String name = schemaType.name() + "By" + Arrays.stream(properties)
+ .map(PropertyKey::name)
+ .map(StringUtils::capitalize)
+ .reduce((p1,
+ p2) -> p1 + "And" + p2)
+ .get();
+
+ IndexBuilder indexBuilder = jgm.buildIndex(name, elementType)
+ .indexOnly(schemaType);
+ Arrays.stream(properties).forEach(indexBuilder::addKey);
+
+ if (unique)
+ {
+ indexBuilder = indexBuilder.unique();
+ }
+ JanusGraphIndex intex = indexBuilder.buildCompositeIndex();
+ if (consistent)
+ {
+ jgm.setConsistency(intex, ConsistencyModifier.LOCK);
+ }
+
+ return intex.name();
+ }
+}
diff --git a/strongbox-db-schema/src/test/java/org/carlspring/strongbox/db/schema/SchemaMigrationTest.java b/strongbox-db-schema/src/test/java/org/carlspring/strongbox/db/schema/SchemaMigrationTest.java
new file mode 100644
index 0000000..a6b00f8
--- /dev/null
+++ b/strongbox-db-schema/src/test/java/org/carlspring/strongbox/db/schema/SchemaMigrationTest.java
@@ -0,0 +1,131 @@
+package org.carlspring.strongbox.db.schema;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.IOException;
+import java.util.TreeSet;
+
+import org.carlspring.strongbox.db.schema.migration.Changeset;
+import org.carlspring.strongbox.db.schema.migration.ChangesetVersionValue;
+import org.carlspring.strongbox.db.schema.migration.JanusgraphChangelogStorage;
+import org.janusgraph.core.JanusGraph;
+import org.janusgraph.core.schema.JanusGraphManagement;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.strongbox.db.server.InMemoryJanusGraphServer;
+import org.strongbox.db.server.JanusGraphConfiguration;
+import org.strongbox.db.server.JanusGraphProperties;
+import org.strongbox.db.server.JanusGraphServer;
+import org.strongbox.util.ConfigurationUtils;
+
+public class SchemaMigrationTest
+{
+
+ private static final Changeset V1 = new Changeset()
+ {
+
+ @Override
+ public String getVersion()
+ {
+ return "1.0.0.1";
+ }
+
+ @Override
+ public String getAuthor()
+ {
+ return "sbespalov";
+ }
+
+ };
+
+ private static final Changeset V2 = new Changeset()
+ {
+
+ @Override
+ public String getVersion()
+ {
+ return "1.0.0.2";
+ }
+
+ @Override
+ public String getAuthor()
+ {
+ return "sbespalov";
+ }
+
+ };
+
+ private static final Changeset V3 = new Changeset()
+ {
+
+ @Override
+ public String getVersion()
+ {
+ return "1.0.0.3";
+ }
+
+ @Override
+ public void applySchemaChanges(JanusGraphManagement jgm)
+ {
+ throw new RuntimeException(getVersion());
+ }
+
+ @Override
+ public String getAuthor()
+ {
+ return "sbespalov";
+ }
+
+ };
+
+ private JanusGraphServer janusGraphServer;
+
+ @BeforeAll
+ public static void init()
+ throws IOException
+ {
+ ConfigurationUtils.extractConfigurationFile("./target", "janusgraph-inmemory.properties");
+ }
+
+ @BeforeEach
+ public void setUp()
+ throws Exception
+ {
+ JanusGraphConfiguration janusGraphConfiguration = new JanusGraphProperties(
+ "file:./target/etc/conf/janusgraph-inmemory.properties");
+ janusGraphServer = new InMemoryJanusGraphServer(janusGraphConfiguration, () -> null);
+ janusGraphServer.start();
+ }
+
+ @Test
+ public void testUpdateSchemaVersion()
+ throws InterruptedException
+ {
+ JanusGraph jg = janusGraphServer.getJanusGraph();
+ JanusgraphChangelogStorage changelogStorage = new JanusgraphChangelogStorage(jg);
+ TreeSet changeSets = new TreeSet<>();
+ StrongboxSchema strongboxSchema = new StrongboxSchema(changeSets);
+
+ strongboxSchema.createSchema(jg);
+ assertThat(changelogStorage.getSchemaVersion().getVersion()).isEqualTo(ChangesetVersionValue.ZERO.getVersion());
+
+ changeSets.add(V2);
+ strongboxSchema.createSchema(jg);
+ assertThat(changelogStorage.getSchemaVersion().getVersion()).isEqualTo(V2.getVersion());
+
+ changeSets.add(V3);
+ assertThatThrownBy(() -> strongboxSchema.createSchema(jg)).withFailMessage("Failed to apply changeset [1.0.0.3]-[]");
+ assertThat(changelogStorage.getSchemaVersion().getVersion()).isEqualTo(V2.getVersion());
+ }
+
+ @AfterEach
+ public void tearDwon()
+ throws Exception
+ {
+ janusGraphServer.stop();
+ }
+
+}
diff --git a/strongbox-db-server/pom.xml b/strongbox-db-server/pom.xml
index 9a40a73..b08ea5a 100644
--- a/strongbox-db-server/pom.xml
+++ b/strongbox-db-server/pom.xml
@@ -1,15 +1,15 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4.0.0
org.carlspring.strongbox
strongbox-db
- 1.0-SNAPSHOT
+ 1.0-PR-19-SNAPSHOT
../pom.xml
@@ -21,37 +21,80 @@
UTF-8
-
-
+
+
com.fasterxml.jackson.core
jackson-databind
- com.orientechnologies
- orientdb-core
+ org.janusgraph
+ janusgraph-cql
+
+
+ org.janusgraph
+ janusgraph-inmemory
- com.orientechnologies
- orientdb-client
+ org.apache.cassandra
+ cassandra-all
- com.orientechnologies
- orientdb-server
+ io.dropwizard.metrics
+ metrics-core
+
- com.orientechnologies
- orientdb-object
+ org.apache.tinkerpop
+ gremlin-core
- com.orientechnologies
- orientdb-graphdb
+ org.apache.tinkerpop
+ gremlin-driver
-
-
- org.webjars
- orientdb-studio
+
+ org.apache.tinkerpop
+ gremlin-server
+
+
+ org.apache.tinkerpop
+ gremlin-groovy
+
+
+ org.opencypher.gremlin
+ cypher-gremlin-neo4j-driver
+
+
+ org.opencypher.gremlin
+ cypher-gremlin-server-plugin
+
+
+
+ org.neo4j.driver
+ neo4j-java-driver
+
+
+ org.neo4j
+ neo4j-ogm-api
+
+
+
+
+
+ commons-lang
+ commons-lang
+ 2.6
+
+
+
+ javax.annotation
+ javax.annotation-api
+
+
diff --git a/strongbox-db-server/src/main/java/org/opencypher/gremlin/neo4j/driver/CypherGremlinStatementRunner.java b/strongbox-db-server/src/main/java/org/opencypher/gremlin/neo4j/driver/CypherGremlinStatementRunner.java
new file mode 100644
index 0000000..093dad1
--- /dev/null
+++ b/strongbox-db-server/src/main/java/org/opencypher/gremlin/neo4j/driver/CypherGremlinStatementRunner.java
@@ -0,0 +1,168 @@
+package org.opencypher.gremlin.neo4j.driver;
+
+import static org.opencypher.gremlin.translation.ReturnProperties.ID;
+import static org.opencypher.gremlin.translation.ReturnProperties.INV;
+import static org.opencypher.gremlin.translation.ReturnProperties.LABEL;
+import static org.opencypher.gremlin.translation.ReturnProperties.OUTV;
+import static org.opencypher.gremlin.translation.ReturnProperties.RELATIONSHIP_TYPE;
+import static org.opencypher.gremlin.translation.ReturnProperties.TYPE;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.CompletionStage;
+
+import org.janusgraph.core.JanusGraphTransaction;
+import org.janusgraph.core.JanusGraphVertex;
+import org.janusgraph.graphdb.relations.RelationIdentifier;
+import org.neo4j.driver.v1.Record;
+import org.neo4j.driver.v1.Session;
+import org.neo4j.driver.v1.Statement;
+import org.neo4j.driver.v1.StatementResult;
+import org.neo4j.driver.v1.StatementResultCursor;
+import org.neo4j.driver.v1.StatementRunner;
+import org.neo4j.driver.v1.Value;
+import org.neo4j.driver.v1.types.TypeSystem;
+import org.opencypher.gremlin.client.CypherGremlinClient;
+import org.opencypher.gremlin.neo4j.ogm.transaction.GremlinTransaction;
+import org.strongbox.util.Commons;
+
+/**
+ * @author sbespalov
+ */
+public class CypherGremlinStatementRunner implements StatementRunner
+{
+
+ private final Session session;
+ private final GremlinTransaction gremlinTransaction;
+
+ public CypherGremlinStatementRunner(GremlinTransaction gremlinTransaction)
+ {
+ this.gremlinTransaction = gremlinTransaction;
+ this.session = new GremlinServerSession(null,
+ CypherGremlinClient.inMemory(gremlinTransaction.getNativeTransaction().traversal()),
+ new JanusGraphValueConverter(false));
+ }
+
+ public StatementResult run(String statementTemplate,
+ Value parameters)
+ {
+ return session.run(statementTemplate, parameters);
+ }
+
+ public StatementResult run(String statementTemplate,
+ Map statementParameters)
+ {
+ return session.run(statementTemplate, statementParameters);
+ }
+
+ public StatementResult run(String statementTemplate,
+ Record statementParameters)
+ {
+ return session.run(statementTemplate, statementParameters);
+ }
+
+ public StatementResult run(String statementTemplate)
+ {
+ return session.run(statementTemplate);
+ }
+
+ public StatementResult run(Statement statement)
+ {
+ return session.run(statement);
+ }
+
+ public TypeSystem typeSystem()
+ {
+ return session.typeSystem();
+ }
+
+ class JanusGraphValueConverter extends GremlinCypherValueConverter
+ {
+
+ public JanusGraphValueConverter(boolean ignoreIds)
+ {
+ super(ignoreIds);
+ }
+
+ @Override
+ Record toRecord(Map map)
+ {
+ map.entrySet().forEach(this::normalizeValue);
+
+ return super.toRecord(map);
+ }
+
+ private void normalizeValue(Entry e)
+ {
+ Object value = e.getValue();
+ if (value instanceof Map)
+ {
+ Map nodeMap = (Map) value;
+ nodeMap.entrySet().forEach(this::normalizeValue);
+ }
+ else if (e.getValue() instanceof RelationIdentifier)
+ {
+ JanusGraphTransaction tx = (JanusGraphTransaction) gremlinTransaction.getNativeTransaction();
+ RelationIdentifier relationIdentifier = (RelationIdentifier) e.getValue();
+ if (ID.equals(e.getKey()))
+ {
+ e.setValue(relationIdentifier.getRelationId());
+
+ return;
+ }
+
+ Map expectedValue = new HashMap<>();
+ expectedValue.put(TYPE, RELATIONSHIP_TYPE);
+ expectedValue.put(ID, relationIdentifier.getRelationId());
+ expectedValue.put(OUTV, relationIdentifier.getOutVertexId());
+ expectedValue.put(INV, relationIdentifier.getInVertexId());
+
+ JanusGraphVertex typeVertex = tx.getVertex(relationIdentifier.getTypeId());
+ expectedValue.put(LABEL, typeVertex.label());
+
+ e.setValue(expectedValue);
+ }
+ else if (value instanceof Date)
+ {
+ e.setValue(Commons.toLocalDateTime((Date) value));
+ }
+ }
+
+ }
+
+ @Override
+ public CompletionStage runAsync(String statementTemplate,
+ Value parameters)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CompletionStage runAsync(String statementTemplate,
+ Map statementParameters)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CompletionStage runAsync(String statementTemplate,
+ Record statementParameters)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CompletionStage runAsync(String statementTemplate)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CompletionStage runAsync(Statement statement)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/strongbox-db-server/src/main/java/org/opencypher/gremlin/neo4j/driver/Neo4jDriverEntityAdapter.java b/strongbox-db-server/src/main/java/org/opencypher/gremlin/neo4j/driver/Neo4jDriverEntityAdapter.java
new file mode 100644
index 0000000..8b17ed2
--- /dev/null
+++ b/strongbox-db-server/src/main/java/org/opencypher/gremlin/neo4j/driver/Neo4jDriverEntityAdapter.java
@@ -0,0 +1,117 @@
+package org.opencypher.gremlin.neo4j.driver;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.neo4j.driver.internal.value.ListValue;
+import org.neo4j.driver.v1.Value;
+import org.neo4j.driver.v1.types.Entity;
+import org.neo4j.driver.v1.types.Node;
+import org.neo4j.driver.v1.types.Path;
+import org.neo4j.driver.v1.types.Relationship;
+import org.neo4j.ogm.driver.TypeSystem.NoNativeTypes;
+
+/**
+ * @author sbespalov
+ */
+public class Neo4jDriverEntityAdapter
+{
+
+ public boolean isPath(Object value)
+ {
+ return value instanceof Path;
+ }
+
+ public boolean isNode(Object value)
+ {
+ return value instanceof Node;
+ }
+
+ public boolean isRelationship(Object value)
+ {
+ return value instanceof Relationship;
+ }
+
+ public long nodeId(Object node)
+ {
+ return ((Node) node).id();
+ }
+
+ public List labels(Object value)
+ {
+ Node node = (Node) value;
+ List labels = new ArrayList<>();
+ for (String label : node.labels())
+ {
+ labels.add(label);
+ }
+ return labels;
+ }
+
+ public long relationshipId(Object relationship)
+ {
+ return ((Relationship) relationship).id();
+ }
+
+ public String relationshipType(Object relationship)
+ {
+ return ((Relationship) relationship).type();
+ }
+
+ public Long startNodeId(Object relationship)
+ {
+ return ((Relationship) relationship).startNodeId();
+ }
+
+ public Long endNodeId(Object relationship)
+ {
+ return ((Relationship) relationship).endNodeId();
+ }
+
+ public Map properties(Object container)
+ {
+ return ((Entity) container).asMap(this::toMapped);
+ }
+
+ public List