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

Commit 286dd2e

Browse files
committed
#128 New command for generating model artifacts
1 parent 16bd5b3 commit 286dd2e

File tree

12 files changed

+504
-23
lines changed

12 files changed

+504
-23
lines changed

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
.gradle
33
.settings
44
/build/
5+
/out/
56
.project
67
.classpath
78
.idea
89
src/test/resources/user.properties
910
setenv.bat
1011
src/test/resources/scaffold-test/
11-
.DS_Store
12+
.DS_Store
13+
src/test/resources/entity-services-project/src/main/ml-modules
14+
src/test/resources/entity-services-project/src/main/ml-schemas
15+
src/test/resources/entity-services-project/src/main/ml-config/databases/content-database-GENERATED.json
16+

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
group=com.marklogic
22
javadocsDir=../gh-pages-marklogic-java/javadocs
3-
version=2.4.0
3+
version=2.5.0

src/main/java/com/marklogic/appdeployer/AppConfig.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,17 @@ public class AppConfig {
122122

123123
private Map<String, Integer> forestCounts = new HashMap<>();
124124

125-
public AppConfig() {
125+
// Entity Services properties
126+
private String modelsPath = "data/entity-services";
127+
private String instanceConverterPath = "ext/entity-services";
128+
129+
private boolean generateInstanceConverter = true;
130+
private boolean generateSchema = true;
131+
private boolean generateDatabaseProperties = true;
132+
private boolean generateExtractionTemplate = true;
133+
private boolean generateSearchOptions = true;
134+
135+
public AppConfig() {
126136
this(DEFAULT_MODULES_PATH, DEFAULT_SCHEMAS_PATH);
127137
}
128138

@@ -620,4 +630,62 @@ public boolean isBulkLoadAssets() {
620630
public void setBulkLoadAssets(boolean bulkLoadAssets) {
621631
this.bulkLoadAssets = bulkLoadAssets;
622632
}
633+
634+
public String getModelsPath() {
635+
return modelsPath;
636+
}
637+
638+
public void setModelsPath(String modelsPath) {
639+
this.modelsPath = modelsPath;
640+
}
641+
642+
public String getInstanceConverterPath() {
643+
return instanceConverterPath;
644+
}
645+
646+
public void setInstanceConverterPath(String instanceConverterPath) {
647+
this.instanceConverterPath = instanceConverterPath;
648+
}
649+
650+
651+
public void setGenerateInstanceConverter(boolean generateInstanceConverter) {
652+
this.generateInstanceConverter = generateInstanceConverter;
653+
}
654+
655+
public void setGenerateSchema(boolean generateSchema) {
656+
this.generateSchema = generateSchema;
657+
}
658+
659+
public void setGenerateDatabaseProperties(boolean generateDatabaseProperties) {
660+
this.generateDatabaseProperties = generateDatabaseProperties;
661+
}
662+
663+
public void setGenerateExtractionTemplate(boolean generateExtractionTemplate) {
664+
this.generateExtractionTemplate = generateExtractionTemplate;
665+
}
666+
667+
public void setGenerateSearchOptions(boolean generateSearchOptions) {
668+
this.generateSearchOptions = generateSearchOptions;
669+
}
670+
671+
public boolean isGenerateInstanceConverter() {
672+
return generateInstanceConverter;
673+
}
674+
675+
public boolean isGenerateSchema() {
676+
return generateSchema;
677+
}
678+
679+
public boolean isGenerateDatabaseProperties() {
680+
return generateDatabaseProperties;
681+
}
682+
683+
public boolean isGenerateExtractionTemplate() {
684+
return generateExtractionTemplate;
685+
}
686+
687+
public boolean isGenerateSearchOptions() {
688+
return generateSearchOptions;
689+
}
690+
623691
}

src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,48 @@ public AppConfig newAppConfig() {
275275
c.setStaticCheckLibraryAssets(Boolean.parseBoolean(prop));
276276
}
277277

278+
prop = getProperty("mlModelsPath");
279+
if (prop != null) {
280+
logger.info("Entity Services models path: " + prop);
281+
c.setModelsPath(prop);
282+
}
283+
284+
prop = getProperty("mlInstanceConverterPath");
285+
if (prop != null) {
286+
logger.info("Entity Services instance converter path: " + prop);
287+
c.setInstanceConverterPath(prop);
288+
}
289+
290+
prop = getProperty("mlGenerateInstanceConverter");
291+
if (prop != null) {
292+
logger.info("Entity Services generate instance converter: " + prop);
293+
c.setGenerateInstanceConverter(Boolean.parseBoolean(prop));
294+
}
295+
296+
prop = getProperty("mlGenerateSchema");
297+
if (prop != null) {
298+
logger.info("Entity Services generate schema: " + prop);
299+
c.setGenerateSchema(Boolean.parseBoolean(prop));
300+
}
301+
302+
prop = getProperty("mlGenerateSearchOptions");
303+
if (prop != null) {
304+
logger.info("Entity Services generate search options: " + prop);
305+
c.setGenerateSearchOptions(Boolean.parseBoolean(prop));
306+
}
307+
308+
prop = getProperty("mlGenerateDatabaseProperties");
309+
if (prop != null) {
310+
logger.info("Entity Services generate database properties: " + prop);
311+
c.setGenerateDatabaseProperties(Boolean.parseBoolean(prop));
312+
}
313+
314+
prop = getProperty("mlGenerateExtractionTemplate");
315+
if (prop != null) {
316+
logger.info("Entity Services generate extraction template: " + prop);
317+
c.setGenerateExtractionTemplate(Boolean.parseBoolean(prop));
318+
}
319+
278320
return c;
279321
}
280322

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
package com.marklogic.appdeployer.command.es;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.appdeployer.command.AbstractCommand;
5+
import com.marklogic.appdeployer.command.CommandContext;
6+
import com.marklogic.appdeployer.command.SortOrderConstants;
7+
import com.marklogic.client.DatabaseClient;
8+
import com.marklogic.client.es.CodeGenerationRequest;
9+
import com.marklogic.client.es.EntityServicesManager;
10+
import com.marklogic.client.es.GeneratedCode;
11+
import com.sun.org.apache.bcel.internal.classfile.Code;
12+
import org.springframework.util.FileCopyUtils;
13+
14+
import java.io.File;
15+
import java.io.IOException;
16+
import java.util.List;
17+
18+
/**
19+
* Generates Entity Services model artifacts based on model definitions. This is implemented as a command, though it's
20+
* not likely to be invoked as part of e.g. an "mlDeploy" call in ml-gradle. But implementing it as a command does
21+
* allow for that possibility, and it's also easy to invoke by itself in ml-gradle too.
22+
*/
23+
public class GenerateModelArtifactsCommand extends AbstractCommand {
24+
25+
// Should be very rare to need to override this, but just in case
26+
private String optionsPath = "options";
27+
28+
public GenerateModelArtifactsCommand() {
29+
int order = SortOrderConstants.LOAD_SCHEMAS - 1;
30+
if (SortOrderConstants.LOAD_SCHEMAS > SortOrderConstants.LOAD_MODULES) {
31+
order = SortOrderConstants.LOAD_MODULES - 1;
32+
}
33+
setExecuteSortOrder(order);
34+
}
35+
36+
@Override
37+
public void execute(CommandContext context) {
38+
AppConfig appConfig = context.getAppConfig();
39+
String modelsPath = appConfig.getModelsPath();
40+
File modelsDir = new File(modelsPath);
41+
if (modelsDir.exists()) {
42+
DatabaseClient client = appConfig.newDatabaseClient();
43+
EntityServicesManager mgr = new EntityServicesManager(client);
44+
for (File f : modelsDir.listFiles()) {
45+
GeneratedCode code = loadModelDefinition(appConfig, f, mgr);
46+
47+
File modulesDir = selectModulesDir(appConfig);
48+
modulesDir.mkdirs();
49+
50+
generateInstanceConverter(appConfig, code, modulesDir);
51+
generateSearchOptions(code, modulesDir);
52+
generateDatabaseProperties(appConfig, code);
53+
generateSchema(appConfig, code);
54+
generateExtractionTemplate(appConfig, code);
55+
}
56+
}
57+
}
58+
59+
protected GeneratedCode loadModelDefinition(AppConfig appConfig, File f, EntityServicesManager mgr) {
60+
String name = f.getName();
61+
String modelDefinition = null;
62+
try {
63+
modelDefinition = new String(FileCopyUtils.copyToByteArray(f));
64+
} catch (IOException e) {
65+
throw new RuntimeException("Unable to read model definition from file: " + f.getAbsolutePath(), e);
66+
}
67+
String modelUri = mgr.loadModel(name, modelDefinition);
68+
return mgr.generateCode(modelUri, buildCodeGenerationRequest(appConfig));
69+
}
70+
71+
protected CodeGenerationRequest buildCodeGenerationRequest(AppConfig appConfig) {
72+
CodeGenerationRequest request = new CodeGenerationRequest();
73+
request.setGenerateDatabaseProperties(appConfig.isGenerateDatabaseProperties());
74+
request.setGenerateExtractionTemplate(appConfig.isGenerateExtractionTemplate());
75+
request.setGenerateInstanceConverter(appConfig.isGenerateInstanceConverter());
76+
request.setGenerateSchema(appConfig.isGenerateSchema());
77+
request.setGenerateSearchOptions(appConfig.isGenerateSearchOptions());
78+
return request;
79+
}
80+
81+
/**
82+
* Selects the last path from appConfig.getModulePaths, the assumption being that any paths before the last one
83+
* are for dependencies.
84+
*
85+
* @param appConfig
86+
* @return
87+
*/
88+
protected File selectModulesDir(AppConfig appConfig) {
89+
List<String> modulePaths = appConfig.getModulePaths();
90+
String lastPath = modulePaths.get(modulePaths.size() - 1);
91+
return new File(lastPath);
92+
}
93+
94+
protected void generateInstanceConverter(AppConfig appConfig, GeneratedCode code, File modulesDir) {
95+
String instanceConverter = code.getInstanceConverter();
96+
if (instanceConverter != null) {
97+
File esDir = new File(modulesDir, appConfig.getInstanceConverterPath());
98+
esDir.mkdirs();
99+
File out = new File(esDir, code.getTitle() + "-" + code.getVersion() + ".xqy");
100+
if (out.exists()) {
101+
out = new File(esDir, code.getTitle() + "-" + code.getVersion() + "-GENERATED.xqy");
102+
}
103+
try {
104+
FileCopyUtils.copy(instanceConverter.getBytes(), out);
105+
if (logger.isInfoEnabled()) {
106+
logger.info("Wrote instance converter to: " + out.getAbsolutePath());
107+
}
108+
} catch (IOException e) {
109+
throw new RuntimeException("Unable to write instance converter to: " + out.getAbsolutePath(), e);
110+
}
111+
}
112+
}
113+
114+
protected void generateSearchOptions(GeneratedCode code, File modulesDir) {
115+
String searchOptions = code.getSearchOptions();
116+
if (searchOptions != null) {
117+
File optionsDir = new File(modulesDir, optionsPath);
118+
optionsDir.mkdirs();
119+
File out = new File(optionsDir, code.getTitle() + ".xml");
120+
if (out.exists()) {
121+
out = new File(optionsDir, code.getTitle() + "-GENERATED.xml");
122+
}
123+
try {
124+
FileCopyUtils.copy(searchOptions.getBytes(), out);
125+
if (logger.isInfoEnabled()) {
126+
logger.info("Wrote search options to: " + out.getAbsolutePath());
127+
}
128+
} catch (IOException e) {
129+
throw new RuntimeException("Unable to write search options to file: " + out.getAbsolutePath(), e);
130+
}
131+
}
132+
}
133+
134+
protected void generateDatabaseProperties(AppConfig appConfig, GeneratedCode code) {
135+
String props = code.getDatabaseProperties();
136+
if (props != null) {
137+
File dir = appConfig.getConfigDir().getDatabasesDir();
138+
dir.mkdirs();
139+
File out = new File(dir, "content-database.json");
140+
if (out.exists()) {
141+
out = new File(dir, "content-database-GENERATED.json");
142+
}
143+
try {
144+
FileCopyUtils.copy(props.getBytes(), out);
145+
if (logger.isInfoEnabled()) {
146+
logger.info("Wrote database properties to: " + out.getAbsolutePath());
147+
}
148+
} catch (IOException e) {
149+
throw new RuntimeException("Unable to write database properties to file: " + out.getAbsolutePath(), e);
150+
}
151+
}
152+
}
153+
154+
protected void generateSchema(AppConfig appConfig, GeneratedCode code) {
155+
String schema = code.getSchema();
156+
if (schema != null) {
157+
File dir = new File(appConfig.getSchemasPath());
158+
dir.mkdirs();
159+
File out = new File(dir, code.getTitle() + "-" + code.getVersion() + ".xsd");
160+
if (out.exists()) {
161+
out = new File(dir, code.getTitle() + "-" + code.getVersion() + "-GENERATED.xsd");
162+
}
163+
try {
164+
FileCopyUtils.copy(schema.getBytes(), out);
165+
if (logger.isInfoEnabled()) {
166+
logger.info("Wrote schema to: " + out.getAbsolutePath());
167+
}
168+
} catch (IOException e) {
169+
throw new RuntimeException("Unable to write schema to file: " + out.getAbsolutePath(), e);
170+
}
171+
}
172+
}
173+
174+
protected void generateExtractionTemplate(AppConfig appConfig, GeneratedCode code) {
175+
String template = code.getExtractionTemplate();
176+
if (template != null) {
177+
File dir = new File(appConfig.getSchemasPath());
178+
dir.mkdirs();
179+
File out = new File(dir, code.getTitle() + "-" + code.getVersion() + ".tdex");
180+
if (out.exists()) {
181+
out = new File(dir, code.getTitle() + "-" + code.getVersion() + "-GENERATED.tdex");
182+
}
183+
try {
184+
FileCopyUtils.copy(template.getBytes(), out);
185+
if (logger.isInfoEnabled()) {
186+
logger.info("Wrote extraction template to: " + out.getAbsolutePath());
187+
}
188+
} catch (IOException e) {
189+
throw new RuntimeException("Unable to write extraction template to file: " + out.getAbsolutePath(), e);
190+
}
191+
}
192+
}
193+
194+
public void setOptionsPath(String optionsPath) {
195+
this.optionsPath = optionsPath;
196+
}
197+
}
198+

0 commit comments

Comments
 (0)