Skip to content

Commit bccff07

Browse files
authored
Merge pull request #6 from colinfindlay/feature-dbcreate
Feature for automatically creating database from GraphQL schema
2 parents 6ca7975 + 1bac1e3 commit bccff07

File tree

5 files changed

+488
-0
lines changed

5 files changed

+488
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.arangodb.graphql.create;
2+
3+
import com.arangodb.graphql.schema.ArangoVertexDirective;
4+
import graphql.schema.*;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
public class ArgumentIndexMapping {
10+
11+
private GraphQLFieldDefinition fieldDefinition;
12+
13+
private List<String> fields;
14+
15+
private String collection;
16+
17+
public ArgumentIndexMapping(GraphQLFieldDefinition fieldDefinition){
18+
this.fieldDefinition = fieldDefinition;
19+
init();
20+
}
21+
22+
23+
private void init(){
24+
25+
fields = new ArrayList<>();
26+
27+
List<GraphQLArgument> arguments = fieldDefinition.getArguments();
28+
29+
boolean firstMandatoryArgFound = false;
30+
for(GraphQLArgument argument : arguments){
31+
if(firstMandatoryArgFound){
32+
fields.add(argument.getName());
33+
}
34+
else {
35+
boolean nonNull = GraphQLTypeUtil.isNonNull(argument.getType());
36+
if (nonNull) {
37+
firstMandatoryArgFound = true;
38+
fields.add(0, argument.getName());
39+
} else {
40+
fields.add(argument.getName());
41+
}
42+
}
43+
44+
}
45+
46+
GraphQLUnmodifiedType type = GraphQLTypeUtil.unwrapAll(fieldDefinition.getType());
47+
if(type instanceof GraphQLDirectiveContainer) {
48+
ArangoVertexDirective vertexDirective = new ArangoVertexDirective((GraphQLDirectiveContainer)type);
49+
this.collection = vertexDirective.getCollection();
50+
}
51+
}
52+
53+
public String getCollection() {
54+
return collection;
55+
}
56+
57+
public List<String> getFields() {
58+
return fields;
59+
}
60+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package com.arangodb.graphql.create;
2+
3+
import com.arangodb.ArangoDB;
4+
import com.arangodb.ArangoDatabase;
5+
import com.arangodb.entity.CollectionType;
6+
import com.arangodb.graphql.schema.ArangoEdgeDirective;
7+
import com.arangodb.graphql.schema.ArangoVertexDirective;
8+
import com.arangodb.model.CollectionCreateOptions;
9+
import com.arangodb.model.HashIndexOptions;
10+
import graphql.schema.GraphQLArgument;
11+
import graphql.schema.GraphQLObjectType;
12+
import graphql.schema.GraphQLSchema;
13+
import graphql.schema.GraphQLType;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
17+
import java.util.*;
18+
19+
public class DatabaseObjectCreator {
20+
21+
private final Logger logger = LoggerFactory.getLogger(this.getClass());
22+
private final ArangoDB arango;
23+
private final String databaseName;
24+
private final GraphQLSchema graphQLSchema;
25+
26+
public DatabaseObjectCreator(ArangoDB arango, String databaseName, GraphQLSchema graphQLSchema) {
27+
this.arango = arango;
28+
this.databaseName = databaseName;
29+
this.graphQLSchema = graphQLSchema;
30+
}
31+
32+
private List<TypeCollectionMapping> createTypeMappings(){
33+
34+
List<GraphQLType> types = graphQLSchema.getAllTypesAsList();
35+
36+
List<TypeCollectionMapping> mappings = new ArrayList<>();
37+
types.forEach(type -> {
38+
if(type instanceof GraphQLObjectType){
39+
GraphQLObjectType objectType = (GraphQLObjectType) type;
40+
ArangoVertexDirective vertexDirective = new ArangoVertexDirective(objectType);
41+
String collection = vertexDirective.getCollection();
42+
if(collection != null){
43+
TypeCollectionMapping mapping = new TypeCollectionMapping(collection);
44+
45+
objectType.getFieldDefinitions().forEach(graphQLFieldDefinition -> {
46+
ArangoEdgeDirective arangoEdgeDirective = new ArangoEdgeDirective(graphQLFieldDefinition);
47+
String edgeCollectionName = arangoEdgeDirective.getCollection();
48+
if(edgeCollectionName != null){
49+
mapping.addEdgeCollection(edgeCollectionName);
50+
}
51+
});
52+
53+
mappings.add(mapping);
54+
55+
}
56+
}
57+
});
58+
59+
return mappings;
60+
61+
}
62+
63+
public void createDatabase(){
64+
ArangoDatabase db = arango.db(databaseName);
65+
if(!db.exists()){
66+
logger.info("Auto Create Database {}", databaseName);
67+
db.create();
68+
}
69+
else{
70+
logger.info("Database {} already exists", databaseName);
71+
}
72+
}
73+
74+
public void createCollections(){
75+
76+
List<TypeCollectionMapping> mappings = createTypeMappings();
77+
mappings.forEach(mapping -> {
78+
String vertex = mapping.getVertexCollection();
79+
createCollection(vertex, CollectionType.DOCUMENT);
80+
Set<String> edgeCollections = mapping.getEdgeCollections();
81+
edgeCollections.forEach(edgeCollection -> {
82+
createCollection(edgeCollection, CollectionType.EDGES);
83+
});
84+
});
85+
86+
}
87+
88+
public void createIndexes(){
89+
90+
ArangoDatabase database = arango.db(databaseName);
91+
GraphQLObjectType queryType = graphQLSchema.getQueryType();
92+
queryType.getFieldDefinitions().forEach(graphQLFieldDefinition -> {
93+
ArgumentIndexMapping mapping = new ArgumentIndexMapping(graphQLFieldDefinition);
94+
95+
String collection = mapping.getCollection();
96+
if(collection != null){
97+
logger.info("Auto Create Index on collection {} for fields {}", collection, mapping.getFields());
98+
database.collection(collection).ensureHashIndex(mapping.getFields(), new HashIndexOptions());
99+
}
100+
101+
});
102+
}
103+
104+
protected CollectionCreateOptions createCollectionCreateOptions(CollectionType collectionType){
105+
return new CollectionCreateOptions().type(collectionType);
106+
}
107+
108+
private void createCollection(String name, CollectionType collectionType) {
109+
110+
CollectionCreateOptions collectionCreateOptions = createCollectionCreateOptions(collectionType);
111+
ArangoDatabase database = arango.db(databaseName);
112+
113+
if(!database.collection(name).exists()){
114+
logger.info("Auto Create Collection {}:{}", name, collectionType);
115+
database.collection(name).create(collectionCreateOptions);
116+
}
117+
else{
118+
logger.info("Collection already exists {}:{}", name, collectionType);
119+
}
120+
121+
}
122+
123+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.arangodb.graphql.create;
2+
3+
import java.util.HashSet;
4+
import java.util.Set;
5+
6+
public class TypeCollectionMapping {
7+
8+
private final String vertexCollection;
9+
10+
private final Set<String> edgeCollections;
11+
12+
public TypeCollectionMapping(String vertexCollection){
13+
this.vertexCollection = vertexCollection;
14+
this.edgeCollections = new HashSet<>();
15+
}
16+
17+
public void addEdgeCollection(String edgeCollection){
18+
this.edgeCollections.add(edgeCollection);
19+
}
20+
21+
22+
public String getVertexCollection() {
23+
return vertexCollection;
24+
}
25+
26+
public Set<String> getEdgeCollections() {
27+
return edgeCollections;
28+
}
29+
}

0 commit comments

Comments
 (0)