Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit 5c0dd3f

Browse files
committed
#40 Adding support for generating entity services modules
1 parent af2cbc9 commit 5c0dd3f

File tree

9 files changed

+354
-38
lines changed

9 files changed

+354
-38
lines changed

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ dependencies {
1717
compile 'com.marklogic:java-client-api:3.0.5'
1818
compile 'com.marklogic:marklogic-xcc:8.0.5'
1919
compile 'org.jdom:jdom2:2.0.5'
20-
compile 'org.springframework:spring-context:4.3.4.RELEASE'
20+
compile 'org.springframework:spring-context:4.1.5.RELEASE'
2121

2222
testCompile 'junit:junit:4+'
23-
testCompile 'org.springframework:spring-test:4.3.4.RELEASE'
23+
testCompile 'org.springframework:spring-test:4.1.5.RELEASE'
2424

2525
// Used for testing loading modules from the classpath
2626
testRuntime files("lib/modules.jar")
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.marklogic.client.es;
2+
3+
public class CodeGenerationRequest {
4+
5+
private boolean generateDatabaseProperties = true;
6+
private boolean generateExtractionTemplate = true;
7+
private boolean generateInstanceConverter = true;
8+
private boolean generateSchema = true;
9+
private boolean generateSearchOptions = true;
10+
private boolean generateVersionTranslator = true;
11+
12+
public boolean isGenerateDatabaseProperties() {
13+
return generateDatabaseProperties;
14+
}
15+
16+
public void setGenerateDatabaseProperties(boolean generateDatabaseProperties) {
17+
this.generateDatabaseProperties = generateDatabaseProperties;
18+
}
19+
20+
public boolean isGenerateExtractionTemplate() {
21+
return generateExtractionTemplate;
22+
}
23+
24+
public void setGenerateExtractionTemplate(boolean generateExtractionTemplate) {
25+
this.generateExtractionTemplate = generateExtractionTemplate;
26+
}
27+
28+
public boolean isGenerateInstanceConverter() {
29+
return generateInstanceConverter;
30+
}
31+
32+
public void setGenerateInstanceConverter(boolean generateInstanceConverter) {
33+
this.generateInstanceConverter = generateInstanceConverter;
34+
}
35+
36+
public boolean isGenerateSchema() {
37+
return generateSchema;
38+
}
39+
40+
public void setGenerateSchema(boolean generateSchema) {
41+
this.generateSchema = generateSchema;
42+
}
43+
44+
public boolean isGenerateSearchOptions() {
45+
return generateSearchOptions;
46+
}
47+
48+
public void setGenerateSearchOptions(boolean generateSearchOptions) {
49+
this.generateSearchOptions = generateSearchOptions;
50+
}
51+
52+
public boolean isGenerateVersionTranslator() {
53+
return generateVersionTranslator;
54+
}
55+
56+
public void setGenerateVersionTranslator(boolean generateVersionTranslator) {
57+
this.generateVersionTranslator = generateVersionTranslator;
58+
}
59+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.marklogic.client.es;
2+
3+
import com.marklogic.client.DatabaseClient;
4+
import com.marklogic.client.document.GenericDocumentManager;
5+
import com.marklogic.client.io.BytesHandle;
6+
import com.marklogic.client.io.DocumentMetadataHandle;
7+
import org.jdom2.Element;
8+
import org.jdom2.Namespace;
9+
import org.jdom2.input.SAXBuilder;
10+
11+
import java.io.StringReader;
12+
13+
/**
14+
* Handles loading a model and then making calls to generate code for it.
15+
*/
16+
public class EntityServicesManager {
17+
18+
private String modelCollection = "http://marklogic.com/entity-services/models";
19+
private String baseUri = "/marklogic.com/entity-services/models/";
20+
private DatabaseClient client;
21+
22+
public EntityServicesManager(DatabaseClient client) {
23+
this.client = client;
24+
}
25+
26+
/**
27+
* @param moduleName appended to the baseUri to determine the model definition URI
28+
* @param modelDefinition JSON or XML
29+
* @return
30+
*/
31+
public String loadModel(String moduleName, String modelDefinition) {
32+
GenericDocumentManager mgr = client.newDocumentManager();
33+
DocumentMetadataHandle dmh = new DocumentMetadataHandle();
34+
dmh.getCollections().add(modelCollection);
35+
String modelUri = baseUri + moduleName;
36+
mgr.write(modelUri, dmh, new BytesHandle(modelDefinition.getBytes()));
37+
return modelUri;
38+
}
39+
40+
public GeneratedCode generateCode(String modelUri, CodeGenerationRequest request) {
41+
GeneratedCode code = initializeGeneratedCode(modelUri);
42+
if (request.isGenerateDatabaseProperties()) {
43+
code.setDatabaseProperties(generateCode(modelUri, "database-properties-generate"));
44+
}
45+
if (request.isGenerateExtractionTemplate()) {
46+
code.setExtractionTemplate(generateCode(modelUri, "extraction-template-generate"));
47+
}
48+
if (request.isGenerateInstanceConverter()) {
49+
code.setInstanceConverter(generateCode(modelUri, "instance-converter-generate"));
50+
}
51+
if (request.isGenerateSchema()) {
52+
code.setSchema(generateCode(modelUri, "schema-generate"));
53+
}
54+
if (request.isGenerateSearchOptions()) {
55+
code.setSearchOptions(generateCode(modelUri, "search-options-generate"));
56+
}
57+
return code;
58+
}
59+
60+
public String generateVersionTranslator(String oldModelUri, String newModelUri) {
61+
String xquery = "import module namespace es = \"http://marklogic.com/entity-services\" at \"/MarkLogic/entity-services/entity-services.xqy\"; " +
62+
"declare variable $oldModelUri external; " +
63+
"declare variable $newModelUri external; " +
64+
"es:version-translator-generate(fn:doc($oldModelUri), fn:doc($newModelUri))";
65+
return client.newServerEval().xquery(xquery).addVariable("oldModelUri", oldModelUri).addVariable("newModelUri", newModelUri).
66+
eval().next().getString();
67+
}
68+
69+
protected GeneratedCode initializeGeneratedCode(String modelUri) {
70+
String xquery = "import module namespace es = \"http://marklogic.com/entity-services\" at \"/MarkLogic/entity-services/entity-services.xqy\"; " +
71+
"declare variable $URI external; " +
72+
"es:model-to-xml(es:model-validate(fn:doc($URI)))";
73+
String output = client.newServerEval().xquery(xquery).addVariable("URI", modelUri).eval().next().getString();
74+
Element root = null;
75+
try {
76+
root = new SAXBuilder().build(new StringReader(output)).getRootElement();
77+
} catch (Exception e) {
78+
throw new RuntimeException("Unable to parse model XML: " + e.getMessage(), e);
79+
}
80+
Namespace ns = Namespace.getNamespace("es", "http://marklogic.com/entity-services");
81+
String title = root.getChild("info", ns).getChildText("title", ns);
82+
String version = root.getChild("info", ns).getChildText("version", ns);
83+
GeneratedCode code = new GeneratedCode();
84+
code.setTitle(title);
85+
code.setVersion(version);
86+
return code;
87+
}
88+
89+
protected String generateCode(String modelUri, String functionName) {
90+
String xquery = "import module namespace es = \"http://marklogic.com/entity-services\" at \"/MarkLogic/entity-services/entity-services.xqy\"; " +
91+
"declare variable $URI external; " +
92+
String.format("es:%s(es:model-validate(fn:doc($URI)))", functionName);
93+
return client.newServerEval().xquery(xquery).addVariable("URI", modelUri).eval().next().getString();
94+
}
95+
96+
public void setModelCollection(String modelCollection) {
97+
this.modelCollection = modelCollection;
98+
}
99+
100+
public void setBaseUri(String baseUri) {
101+
this.baseUri = baseUri;
102+
}
103+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.marklogic.client.es;
2+
3+
public class GeneratedCode {
4+
5+
private String title;
6+
private String version;
7+
private String instanceConverter;
8+
private String searchOptions;
9+
private String extractionTemplate;
10+
private String databaseProperties;
11+
private String schema;
12+
13+
public String getTitle() {
14+
return title;
15+
}
16+
17+
public void setTitle(String title) {
18+
this.title = title;
19+
}
20+
21+
public String getVersion() {
22+
return version;
23+
}
24+
25+
public void setVersion(String version) {
26+
this.version = version;
27+
}
28+
29+
public String getInstanceConverter() {
30+
return instanceConverter;
31+
}
32+
33+
public void setInstanceConverter(String instanceConverter) {
34+
this.instanceConverter = instanceConverter;
35+
}
36+
37+
public String getSearchOptions() {
38+
return searchOptions;
39+
}
40+
41+
public void setSearchOptions(String searchOptions) {
42+
this.searchOptions = searchOptions;
43+
}
44+
45+
public String getExtractionTemplate() {
46+
return extractionTemplate;
47+
}
48+
49+
public void setExtractionTemplate(String extractionTemplate) {
50+
this.extractionTemplate = extractionTemplate;
51+
}
52+
53+
public String getDatabaseProperties() {
54+
return databaseProperties;
55+
}
56+
57+
public void setDatabaseProperties(String databaseProperties) {
58+
this.databaseProperties = databaseProperties;
59+
}
60+
61+
public String getSchema() {
62+
return schema;
63+
}
64+
65+
public void setSchema(String schema) {
66+
this.schema = schema;
67+
}
68+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.marklogic.client;
2+
3+
import com.marklogic.client.helper.DatabaseClientConfig;
4+
import com.marklogic.client.spring.config.MarkLogicApplicationContext;
5+
import org.junit.After;
6+
import org.junit.Assert;
7+
import org.junit.runner.RunWith;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.test.context.ContextConfiguration;
10+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11+
12+
@RunWith(SpringJUnit4ClassRunner.class)
13+
@ContextConfiguration( classes = {MarkLogicApplicationContext.class} )
14+
public class AbstractIntegrationTest extends Assert {
15+
16+
@Autowired
17+
protected DatabaseClientConfig clientConfig;
18+
protected DatabaseClient client;
19+
20+
protected DatabaseClient newClient(String database) {
21+
client = DatabaseClientFactory.newClient(clientConfig.getHost(), clientConfig.getPort(), database, clientConfig.getUsername(),
22+
clientConfig.getPassword(), DatabaseClientFactory.Authentication.DIGEST);
23+
return client;
24+
}
25+
26+
@After
27+
public void releaseClient() {
28+
if (client != null) {
29+
client.release();
30+
}
31+
}
32+
33+
34+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.marklogic.client.es;
2+
3+
import com.marklogic.client.AbstractIntegrationTest;
4+
import org.junit.Before;
5+
import org.junit.Test;
6+
7+
/**
8+
* Tests against the default Documents database. Doesn't clear it out before or after.
9+
*/
10+
public class EntityServicesTest extends AbstractIntegrationTest {
11+
12+
private final static String MODEL = "{\n" +
13+
" \"info\": {\n" +
14+
" \"title\": \"Penny\",\n" +
15+
" \"version\": \"0.0.1\",\n" +
16+
" \"baseUri\": \"http://marklogic.com/examples/\"\n" +
17+
" },\n" +
18+
" \"definitions\": {\n" +
19+
" \"employee\": {\n" +
20+
" \"description\": \"Example of an employee\",\n" +
21+
" \"properties\": {\n" +
22+
" \"id\": { \"datatype\": \"int\" },\n" +
23+
" \"last-name\": { \"datatype\": \"string\" },\n" +
24+
" \"first-name\": { \"datatype\": \"string\" },\n" +
25+
" \"email\": { \"datatype\": \"string\" },\n" +
26+
" \"department\": { \"datatype\": \"string\" },\n" +
27+
" \"salary\": { \"datatype\": \"float\" }\n" +
28+
" },\n" +
29+
" \"required\": [\"id\", \"last-name\", \"first-name\"],\n" +
30+
" \"primaryKey\": \"id\",\n" +
31+
" \"rangeIndex\": [\"salary\", \"department\"]\n" +
32+
" }\n" +
33+
" }\n" +
34+
"}";
35+
36+
@Before
37+
public void setup() {
38+
client = newClient("Documents");
39+
}
40+
41+
@Test
42+
public void generateCode() {
43+
EntityServicesManager mgr = new EntityServicesManager(client);
44+
String modelUri = mgr.loadModel("penny.json", MODEL);
45+
assertEquals("/marklogic.com/entity-services/models/penny.json", modelUri);
46+
47+
GeneratedCode code = mgr.generateCode(modelUri, new CodeGenerationRequest());
48+
assertEquals("Penny", code.getTitle());
49+
assertEquals("0.0.1", code.getVersion());
50+
assertNotNull(code.getDatabaseProperties());
51+
assertNotNull(code.getExtractionTemplate());
52+
assertNotNull(code.getInstanceConverter());
53+
assertNotNull(code.getSchema());
54+
assertNotNull(code.getSearchOptions());
55+
}
56+
57+
@Test
58+
public void generateVersionTranslator() {
59+
EntityServicesManager mgr = new EntityServicesManager(client);
60+
String modelUri = mgr.loadModel("penny.json", MODEL);
61+
62+
String newModel = MODEL.replace("department", "newDepartment");
63+
String newModelUri = mgr.loadModel("penny2.json", MODEL);
64+
65+
String output = mgr.generateVersionTranslator(modelUri, newModelUri);
66+
assertNotNull("Just making sure this doesn't throw an error", output);
67+
}
68+
}
69+
70+

0 commit comments

Comments
 (0)