use of org.structr.schema.action.ActionContext in project structr by structr.
the class DeployCommand method doImport.
// ----- private methods -----
private void doImport(final Map<String, Object> attributes) throws FrameworkException {
final long startTime = System.currentTimeMillis();
customHeaders.put("start", new Date(startTime).toString());
final String path = (String) attributes.get("source");
final SecurityContext ctx = SecurityContext.getSuperUserInstance();
final App app = StructrApp.getInstance(ctx);
ctx.setDoTransactionNotifications(false);
ctx.disableEnsureCardinality();
ctx.disableModificationOfAccessTime();
final Map<String, Object> componentsConf = new HashMap<>();
final Map<String, Object> templatesConf = new HashMap<>();
final Map<String, Object> pagesConf = new HashMap<>();
final Map<String, Object> filesConf = new HashMap<>();
if (StringUtils.isBlank(path)) {
throw new FrameworkException(422, "Please provide 'source' attribute for deployment source directory path.");
}
final Path source = Paths.get(path);
if (!Files.exists(source)) {
throw new FrameworkException(422, "Source path " + path + " does not exist.");
}
if (!Files.isDirectory(source)) {
throw new FrameworkException(422, "Source path " + path + " is not a directory.");
}
final Map<String, Object> broadcastData = new HashMap();
broadcastData.put("type", DEPLOYMENT_IMPORT_STATUS);
broadcastData.put("subtype", DEPLOYMENT_STATUS_BEGIN);
broadcastData.put("start", startTime);
broadcastData.put("source", source);
TransactionCommand.simpleBroadcastGenericMessage(broadcastData);
// apply configuration
final Path preDeployConf = source.resolve("pre-deploy.conf");
if (Files.exists(preDeployConf)) {
try (final Tx tx = app.tx()) {
final String confSource = new String(Files.readAllBytes(preDeployConf), Charset.forName("utf-8")).trim();
if (confSource.length() > 0) {
info("Applying pre-deployment configuration from {}", preDeployConf);
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Applying pre-deployment configuration");
Scripting.evaluate(new ActionContext(ctx), null, confSource, "pre-deploy.conf");
} else {
info("Ignoring empty pre-deployment configuration {}", preDeployConf);
}
tx.success();
} catch (Throwable t) {
logger.warn("", t);
publishDeploymentWarningMessage("Exception caught while importing pre-deploy.conf", t.toString());
}
}
// backup previous value of change log setting
// temporary disable creation of change log
final boolean changeLogEnabled = Settings.ChangelogEnabled.getValue();
Settings.ChangelogEnabled.setValue(false);
// read grants.json
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing resource access grants");
final Path grantsConf = source.resolve("security/grants.json");
if (Files.exists(grantsConf)) {
info("Reading {}", grantsConf);
importListData(ResourceAccess.class, readConfigList(grantsConf));
}
// read schema-methods.json
final Path schemaMethodsConf = source.resolve("schema-methods.json");
if (Files.exists(schemaMethodsConf)) {
info("Reading {}", schemaMethodsConf);
final String title = "Deprecation warning";
final String text = "Found file 'schema-methods.json'. Newer versions store global schema methods in the schema snapshot file. Recreate the export with the current version to avoid compatibility issues. Support for importing this file will be dropped in future versions.";
info(title + ": " + text);
publishDeploymentWarningMessage(title, text);
importListData(SchemaMethod.class, readConfigList(schemaMethodsConf));
}
// read mail-templates.json
final Path mailTemplatesConf = source.resolve("mail-templates.json");
if (Files.exists(mailTemplatesConf)) {
info("Reading {}", mailTemplatesConf);
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing mail templates");
importListData(MailTemplate.class, readConfigList(mailTemplatesConf));
}
// read widgets.json
final Path widgetsConf = source.resolve("widgets.json");
if (Files.exists(widgetsConf)) {
info("Reading {}", widgetsConf);
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing widgets");
importListData(Widget.class, readConfigList(widgetsConf));
}
// read localizations.json
final Path localizationsConf = source.resolve("localizations.json");
if (Files.exists(localizationsConf)) {
final PropertyMap additionalData = new PropertyMap();
// Question: shouldn't this be true? No, 'imported' is a flag for legacy-localization which
// have been imported from a legacy-system which was replaced by structr.
// it is a way to differentiate between new and old localization strings
additionalData.put(StructrApp.key(Localization.class, "imported"), false);
info("Reading {}", localizationsConf);
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing localizations");
importListData(Localization.class, readConfigList(localizationsConf), additionalData);
}
// read files.conf
final Path filesConfFile = source.resolve("files.json");
if (Files.exists(filesConfFile)) {
info("Reading {}", filesConfFile);
filesConf.putAll(readConfigMap(filesConfFile));
}
// read pages.conf
final Path pagesConfFile = source.resolve("pages.json");
if (Files.exists(pagesConfFile)) {
info("Reading {}", pagesConfFile);
pagesConf.putAll(readConfigMap(pagesConfFile));
}
// read components.conf
final Path componentsConfFile = source.resolve("components.json");
if (Files.exists(componentsConfFile)) {
info("Reading {}", componentsConfFile);
componentsConf.putAll(readConfigMap(componentsConfFile));
}
// read templates.conf
final Path templatesConfFile = source.resolve("templates.json");
if (Files.exists(templatesConfFile)) {
info("Reading {}", templatesConfFile);
templatesConf.putAll(readConfigMap(templatesConfFile));
}
// import schema
final Path schema = source.resolve("schema");
if (Files.exists(schema)) {
try {
info("Importing data from schema/ directory");
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing schema");
Files.walkFileTree(schema, new SchemaImportVisitor(schema));
} catch (IOException ioex) {
logger.warn("Exception while importing schema", ioex);
}
}
// import files
final Path files = source.resolve("files");
if (Files.exists(files)) {
try {
info("Importing files (unchanged files will be skipped)");
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing files");
FileImportVisitor fiv = new FileImportVisitor(files, filesConf);
Files.walkFileTree(files, fiv);
fiv.handleDeferredFiles();
} catch (IOException ioex) {
logger.warn("Exception while importing files", ioex);
}
}
for (StructrModule module : StructrApp.getConfiguration().getModules().values()) {
if (module.hasDeploymentData()) {
info("Importing deployment data for module {}", module.getName());
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing deployment data for module " + module.getName());
final Path moduleFolder = source.resolve("modules/" + module.getName() + "/");
module.importDeploymentData(moduleFolder, getGson());
}
}
// construct paths
final Path templates = source.resolve("templates");
final Path components = source.resolve("components");
final Path pages = source.resolve("pages");
// an empty directory was specified accidentially).
if (Files.exists(templates) && Files.exists(components) && Files.exists(pages)) {
try (final Tx tx = app.tx()) {
final String tenantIdentifier = app.getDatabaseService().getTenantIdentifier();
info("Removing pages, templates and components");
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Removing pages, templates and components");
if (tenantIdentifier != null) {
app.cypher("MATCH (n:" + tenantIdentifier + ":DOMNode) DETACH DELETE n", null);
} else {
app.cypher("MATCH (n:DOMNode) DETACH DELETE n", null);
}
FlushCachesCommand.flushAll();
tx.success();
}
} else {
logger.info("Import directory does not seem to contain pages, templates or components, NOT removing any data.");
}
// import templates, must be done before pages so the templates exist
if (Files.exists(templates)) {
try {
info("Importing templates");
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing templates");
Files.walkFileTree(templates, new TemplateImportVisitor(templatesConf));
} catch (IOException ioex) {
logger.warn("Exception while importing templates", ioex);
}
}
// import components, must be done before pages so the shared components exist
if (Files.exists(components)) {
try {
info("Importing shared components");
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing shared components");
Files.walkFileTree(components, new ComponentImportVisitor(componentsConf));
} catch (IOException ioex) {
logger.warn("Exception while importing shared components", ioex);
}
}
// import pages
if (Files.exists(pages)) {
try {
info("Importing pages");
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Importing pages");
Files.walkFileTree(pages, new PageImportVisitor(pages, pagesConf));
} catch (IOException ioex) {
logger.warn("Exception while importing pages", ioex);
}
}
try (final Tx tx = app.tx()) {
deferredPageLinks.forEach((String linkableUUID, String pagePath) -> {
try {
final DOMNode page = StructrApp.getInstance().get(DOMNode.class, linkableUUID);
final Linkable linkedPage = StructrApp.getInstance().nodeQuery(Linkable.class).and(StructrApp.key(Page.class, "path"), pagePath).or(Page.name, pagePath).getFirst();
((LinkSource) page).setLinkable(linkedPage);
} catch (FrameworkException ex) {
}
});
deferredPageLinks.clear();
tx.success();
}
// apply configuration
final Path postDeployConf = source.resolve("post-deploy.conf");
if (Files.exists(postDeployConf)) {
try (final Tx tx = app.tx()) {
final String confSource = new String(Files.readAllBytes(postDeployConf), Charset.forName("utf-8")).trim();
if (confSource.length() > 0) {
info("Applying post-deployment configuration from {}", postDeployConf);
publishDeploymentProgressMessage(DEPLOYMENT_IMPORT_STATUS, "Applying post-deployment configuration");
Scripting.evaluate(new ActionContext(ctx), null, confSource, "post-deploy.conf");
} else {
info("Ignoring empty post-deployment configuration {}", postDeployConf);
}
tx.success();
} catch (Throwable t) {
logger.warn("", t);
publishDeploymentWarningMessage("Exception caught while importing post-deploy.conf", t.toString());
}
}
// restore saved value
Settings.ChangelogEnabled.setValue(changeLogEnabled);
final long endTime = System.currentTimeMillis();
DecimalFormat decimalFormat = new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
final String duration = decimalFormat.format(((endTime - startTime) / 1000.0)) + "s";
customHeaders.put("end", new Date(endTime).toString());
customHeaders.put("duration", duration);
info("Import from {} done. (Took {})", source.toString(), duration);
broadcastData.put("subtype", DEPLOYMENT_STATUS_END);
broadcastData.put("end", endTime);
broadcastData.put("duration", duration);
TransactionCommand.simpleBroadcastGenericMessage(broadcastData);
}
use of org.structr.schema.action.ActionContext in project structr by structr.
the class FunctionProperty method getProperty.
@Override
public T getProperty(final SecurityContext securityContext, final GraphObject obj, final boolean applyConverter, final Predicate<GraphObject> predicate) {
try {
if (obj != null && readFunction != null) {
final ActionContext actionContext = new ActionContext(securityContext);
// don't ignore predicate
actionContext.setPredicate(predicate);
return (T) Scripting.evaluate(actionContext, obj, "${".concat(readFunction).concat("}"), "getProperty(" + jsonName + ")");
} else {
logger.warn("Unable to evaluate function property {}, object was null.", jsonName());
}
} catch (Throwable t) {
t.printStackTrace();
logger.warn("Exception while evaluating read function in Function property \"{}\"", jsonName());
}
return null;
}
use of org.structr.schema.action.ActionContext in project structr by structr.
the class CypherQueryProperty method getProperty.
@Override
public List<GraphObject> getProperty(SecurityContext securityContext, GraphObject obj, boolean applyConverter, Predicate<GraphObject> predicate) {
if (obj instanceof AbstractNode) {
try {
final String query = Scripting.replaceVariables(new ActionContext(securityContext), obj, this.format);
final Map<String, Object> parameters = new LinkedHashMap<>();
parameters.put("id", obj.getUuid());
parameters.put("type", obj.getType());
return StructrApp.getInstance(securityContext).command(CypherQueryCommand.class).execute(query, parameters);
} catch (Throwable t) {
logger.warn("", t);
}
}
return null;
}
use of org.structr.schema.action.ActionContext in project structr by structr.
the class CsvFunctionsTest method testCsvFunctions.
@Test
public void testCsvFunctions() {
List<CsvTestOne> csvTestOnes = null;
CsvTestTwo csvTestTwo = null;
int index = 0;
try (final Tx tx = app.tx()) {
csvTestOnes = createTestNodes(CsvTestOne.class, 5);
csvTestTwo = createTestNode(CsvTestTwo.class);
final PropertyMap indexLocalizationProperties = new PropertyMap();
final PropertyMap nameLocalizationProperties = new PropertyMap();
final PropertyMap indexLocalizationPropertiesWithDomain = new PropertyMap();
final PropertyMap nameLocalizationPropertiesWithDomain = new PropertyMap();
indexLocalizationProperties.put(StructrApp.key(Localization.class, "name"), "index");
indexLocalizationProperties.put(StructrApp.key(Localization.class, "localizedName"), "Localized INDEX");
indexLocalizationProperties.put(StructrApp.key(Localization.class, "locale"), "en");
nameLocalizationProperties.put(StructrApp.key(Localization.class, "name"), "name");
nameLocalizationProperties.put(StructrApp.key(Localization.class, "localizedName"), "Localized NAME");
nameLocalizationProperties.put(StructrApp.key(Localization.class, "locale"), "en");
indexLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "name"), "index");
indexLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "localizedName"), "Localized INDEX with DOMAIN");
indexLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "locale"), "en");
indexLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "domain"), "CSV TEST Domain");
nameLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "name"), "name");
nameLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "localizedName"), "Localized NAME with DOMAIN");
nameLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "locale"), "en");
nameLocalizationPropertiesWithDomain.put(StructrApp.key(Localization.class, "domain"), "CSV TEST Domain");
app.create(Localization.class, indexLocalizationProperties);
app.create(Localization.class, nameLocalizationProperties);
app.create(Localization.class, indexLocalizationPropertiesWithDomain);
app.create(Localization.class, nameLocalizationPropertiesWithDomain);
for (final CsvTestOne csvTestOne : csvTestOnes) {
csvTestOne.setProperty(CsvTestOne.name, "CSV Test Node " + StringUtils.leftPad(Integer.toString(index + 1), 4, "0"));
csvTestOne.setProperty(CsvTestOne.index, index + 1);
if (index == 0) {
// set string array on test four
csvTestOne.setProperty(CsvTestOne.stringArrayProperty, new String[] { "one", "two", "three", "four" });
}
if (index == 2) {
// set string array on test four
csvTestOne.setProperty(CsvTestOne.enumProperty, CsvTestEnum.EnumValue2);
}
index++;
}
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
fail("Unexpected exception");
}
try (final Tx tx = app.tx()) {
final ActionContext ctx = new ActionContext(securityContext, null);
ctx.setLocale(Locale.ENGLISH);
/**
* The expected results
*/
final String expectedDefaultCsv = "\"name\";\"index\";\"type\";\"stringArrayProperty\";\"enumProperty\"\n" + "\"CSV Test Node 0001\";\"1\";\"CsvTestOne\";\"[\\\"one\\\", \\\"two\\\", \\\"three\\\", \\\"four\\\"]\";\"\"\n" + "\"CSV Test Node 0002\";\"2\";\"CsvTestOne\";\"\";\"\"\n" + "\"CSV Test Node 0003\";\"3\";\"CsvTestOne\";\"\";\"EnumValue2\"\n" + "\"CSV Test Node 0004\";\"4\";\"CsvTestOne\";\"\";\"\"\n" + "\"CSV Test Node 0005\";\"5\";\"CsvTestOne\";\"\";\"\"\n";
final String expectedCsvWithNameAndIndex = "\"name\";\"index\"\n" + "\"CSV Test Node 0001\";\"1\"\n" + "\"CSV Test Node 0002\";\"2\"\n" + "\"CSV Test Node 0003\";\"3\"\n" + "\"CSV Test Node 0004\";\"4\"\n" + "\"CSV Test Node 0005\";\"5\"\n";
final String expectedCsvWithIndexAndName = "\"index\";\"name\"\n" + "\"1\";\"CSV Test Node 0001\"\n" + "\"2\";\"CSV Test Node 0002\"\n" + "\"3\";\"CSV Test Node 0003\"\n" + "\"4\";\"CSV Test Node 0004\"\n" + "\"5\";\"CSV Test Node 0005\"\n";
final String expectedCsvWithNameAndIndexAndCustomDelimiterPipe = "\"name\"|\"index\"\n" + "\"CSV Test Node 0001\"|\"1\"\n" + "\"CSV Test Node 0002\"|\"2\"\n" + "\"CSV Test Node 0003\"|\"3\"\n" + "\"CSV Test Node 0004\"|\"4\"\n" + "\"CSV Test Node 0005\"|\"5\"\n";
final String expectedCsvWithNameAndIndexAndCustomDelimiterXXX = "\"name\"X\"index\"\n" + "\"CSV Test Node 0001\"X\"1\"\n" + "\"CSV Test Node 0002\"X\"2\"\n" + "\"CSV Test Node 0003\"X\"3\"\n" + "\"CSV Test Node 0004\"X\"4\"\n" + "\"CSV Test Node 0005\"X\"5\"\n";
final String expectedCsvWithIndexAndNameAndSingleQuote = "'index';'name'\n" + "'1';'CSV Test Node 0001'\n" + "'2';'CSV Test Node 0002'\n" + "'3';'CSV Test Node 0003'\n" + "'4';'CSV Test Node 0004'\n" + "'5';'CSV Test Node 0005'\n";
final String expectedCsvWithIndexAndNameAndSingleQuoteAfterRoundTrip = "'index';'name'\n" + "'1';'CSV Test Node 0001'\n" + "'2';'CSV Test Node 0002'\n" + "'3';'CSV Test Node 0003'\n" + "'4';'CSV Test Node 0004'\n" + "'5';'CSV Test Node 0005'\n";
final String expectedCsvWithIndexAndNameAndSingleQuoteAndCRLF = "'index';'name'\r\n" + "'1';'CSV Test Node 0001'\r\n" + "'2';'CSV Test Node 0002'\r\n" + "'3';'CSV Test Node 0003'\r\n" + "'4';'CSV Test Node 0004'\r\n" + "'5';'CSV Test Node 0005'\r\n";
final String expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFNoHeader = "'1';'CSV Test Node 0001'\r\n" + "'2';'CSV Test Node 0002'\r\n" + "'3';'CSV Test Node 0003'\r\n" + "'4';'CSV Test Node 0004'\r\n" + "'5';'CSV Test Node 0005'\r\n";
final String expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithExplicitHeader = "'index';'name'\r\n" + "'1';'CSV Test Node 0001'\r\n" + "'2';'CSV Test Node 0002'\r\n" + "'3';'CSV Test Node 0003'\r\n" + "'4';'CSV Test Node 0004'\r\n" + "'5';'CSV Test Node 0005'\r\n";
final String expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithLocalizedHeader = "'Localized INDEX';'Localized NAME'\r\n" + "'1';'CSV Test Node 0001'\r\n" + "'2';'CSV Test Node 0002'\r\n" + "'3';'CSV Test Node 0003'\r\n" + "'4';'CSV Test Node 0004'\r\n" + "'5';'CSV Test Node 0005'\r\n";
final String expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithLocalizedHeaderWithDomain = "'Localized INDEX with DOMAIN';'Localized NAME with DOMAIN'\r\n" + "'1';'CSV Test Node 0001'\r\n" + "'2';'CSV Test Node 0002'\r\n" + "'3';'CSV Test Node 0003'\r\n" + "'4';'CSV Test Node 0004'\r\n" + "'5';'CSV Test Node 0005'\r\n";
final String expectedCsvForCustomJavaScriptObjects = "\"id\";\"customField\";\"name\"\n" + "\"abcd0001\";\"extra1\";\"my 1st custom object\"\n" + "\"bcde0002\";\"extra2\";\"my 2nd custom object\"\n" + "\"cdef0003\";\"extra3\";\"my 3rd custom object\"\n";
final String expectedCsvForObjectsWithNewlineCharacters = "\"multi\"\n" + "\"Multi\\nLine\\nTest\"\n";
/**
* First everything in StructrScript
*/
assertEquals("Invalid result of default to_csv() call (StructrScript)", expectedDefaultCsv, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), 'csv')}"));
assertEquals("Invalid result of to_csv() call with only name,index (StructrScript)", expectedCsvWithNameAndIndex, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('name', 'index'))}"));
assertEquals("Invalid result of to_csv() call with only name,index (StructrScript)", expectedCsvWithIndexAndName, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('index', 'name'))}"));
assertEquals("Invalid result of to_csv() with delimiterChar = '|'. (StructrScript)", expectedCsvWithNameAndIndexAndCustomDelimiterPipe, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('name', 'index'), '|')}"));
assertEquals("Invalid result of to_csv() with delimiterChar = 'XXX'. Only first character should be used! (StructrScript)", expectedCsvWithNameAndIndexAndCustomDelimiterXXX, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('name', 'index'), 'XXX')}"));
assertEquals("Invalid result of to_csv() call with only index,name AND quote character = ' (StructrScript)", expectedCsvWithIndexAndNameAndSingleQuote, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('index', 'name'), ';', \"'\")}"));
assertEquals("Invalid result of to_csv() call with only index,name AND quote character = ' AFTER round-trip through to_csv, from_csv and to_csv (StructrScript)", expectedCsvWithIndexAndNameAndSingleQuoteAfterRoundTrip, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(from_csv(to_csv(find('CsvTestOne'), merge('index', 'name'), ';', \"'\"), ';', \"'\"), merge('index', 'name'), ';', \"'\")}"));
assertEquals("Invalid result of to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator (StructrScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLF, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('index', 'name'), ';', \"'\", '\\r\\n')}"));
assertEquals("Invalid result of to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and no header (StructrScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFNoHeader, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('index', 'name'), ';', \"'\", '\\r\\n', false)}"));
assertEquals("Invalid result of to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and explicit header (StructrScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithExplicitHeader, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('index', 'name'), ';', \"'\", '\\r\\n', true)}"));
assertEquals("Invalid result of to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and localized header (without domain) (StructrScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithLocalizedHeader, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('index', 'name'), ';', \"'\", '\\r\\n', true, true)}"));
assertEquals("Invalid result of to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and localized header (with domain) (StructrScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithLocalizedHeaderWithDomain, Scripting.replaceVariables(ctx, csvTestTwo, "${to_csv(find('CsvTestOne'), merge('index', 'name'), ';', \"'\", '\\r\\n', true, true, 'CSV TEST Domain')}"));
/**
* Then everything again in JavaScript
*/
assertEquals("Invalid result of default Structr.to_csv() call (JavaScript)", expectedDefaultCsv, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), 'csv'))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only name,index (JavaScript)", expectedCsvWithNameAndIndex, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['name', 'index']))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only name,index (JavaScript)", expectedCsvWithIndexAndName, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name']))}}"));
assertEquals("Invalid result of Structr.to_csv() with delimiterChar = '|'. (JavaScript)", expectedCsvWithNameAndIndexAndCustomDelimiterPipe, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['name', 'index'], '|'))}}"));
assertEquals("Invalid result of Structr.to_csv() with delimiterChar = 'XXX'. Only first character should be used! (JavaScript)", expectedCsvWithNameAndIndexAndCustomDelimiterXXX, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['name', 'index'], 'XXX'))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only index,name AND quote character = ' (JavaScript)", expectedCsvWithIndexAndNameAndSingleQuote, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name'], ';', \"'\"))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only index,name AND quote character = ' AFTER round-trip through to_csv, from_csv and to_csv (JavaScript)", expectedCsvWithIndexAndNameAndSingleQuoteAfterRoundTrip, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.from_csv(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name'], ';', \"'\"), ';', \"'\"), ['index', 'name'], ';', \"'\"))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator (JavaScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLF, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name'], ';', \"'\", '\\r\\n'))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and no header (JavaScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFNoHeader, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name'], ';', \"'\", '\\r\\n', false))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and explicit header (JavaScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithExplicitHeader, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name'], ';', \"'\", '\\r\\n', true))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and localized header (without domain) (JavaScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithLocalizedHeader, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name'], ';', \"'\", '\\r\\n', true, true))}}"));
assertEquals("Invalid result of Structr.to_csv() call with only index,name, singleQuoted and CRLF as recordSeparator and localized header (with domain) (JavaScript)", expectedCsvWithIndexAndNameAndSingleQuoteAndCRLFWithLocalizedHeaderWithDomain, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv(Structr.find('CsvTestOne'), ['index', 'name'], ';', \"'\", '\\r\\n', true, true, 'CSV TEST Domain'))}}"));
assertEquals("Invalid result of Structr.to_csv() call for a collection of custom objects (JavaScript)", expectedCsvForCustomJavaScriptObjects, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv([{id: 'abcd0001', name: 'my 1st custom object', customField: 'extra1'}, {id: 'bcde0002', name: 'my 2nd custom object', customField: 'extra2'}, {id: 'cdef0003', name: 'my 3rd custom object', customField: 'extra3'}], ['id', 'customField', 'name']))}}"));
assertEquals("Invalid result of Structr.to_csv() call for source objects with newlines (JavaScript)", expectedCsvForObjectsWithNewlineCharacters, Scripting.replaceVariables(ctx, csvTestTwo, "${{Structr.print(Structr.to_csv([{multi:'Multi\\nLine\\nTest'}], ['multi']))}}"));
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
fail(fex.getMessage());
}
}
use of org.structr.schema.action.ActionContext in project structr by structr.
the class Scripting method evaluateJavascript.
public static Object evaluateJavascript(final ActionContext actionContext, final GraphObject entity, final Snippet snippet) throws FrameworkException {
final String entityName = entity != null ? entity.getProperty(AbstractNode.name) : null;
final String entityDescription = entity != null ? (StringUtils.isNotBlank(entityName) ? "\"" + entityName + "\":" : "") + entity.getUuid() : "anonymous";
final Context scriptingContext = Scripting.setupJavascriptContext();
try {
// enable some optimizations..
scriptingContext.setLanguageVersion(Context.VERSION_1_2);
scriptingContext.setOptimizationLevel(9);
scriptingContext.setInstructionObserverThreshold(0);
scriptingContext.setGenerateObserverCount(false);
scriptingContext.setGeneratingDebug(true);
final Scriptable scope = scriptingContext.initStandardObjects();
final StructrScriptable scriptable = new StructrScriptable(actionContext, entity, scriptingContext);
scriptable.setParentScope(scope);
// register Structr scriptable
scope.put("Structr", scope, scriptable);
// clear output buffer
actionContext.clear();
// compile or use provided script
Script compiledScript = snippet.getCompiledScript();
if (compiledScript == null) {
final String sourceLocation = snippet.getName() + " [" + entityDescription + "], line ";
final String embeddedSourceCode = embedInFunction(actionContext, snippet.getSource());
compiledScript = compileOrGetCached(scriptingContext, embeddedSourceCode, sourceLocation, 1);
}
Object extractedValue = compiledScript.exec(scriptingContext, scope);
if (scriptable.hasException()) {
throw scriptable.getException();
}
// prioritize written output over result returned from method
final String output = actionContext.getOutput();
if (output != null && !output.isEmpty()) {
extractedValue = output;
}
if (extractedValue == null || extractedValue == Undefined.instance) {
extractedValue = scriptable.unwrap(scope.get("_structrMainResult", scope));
}
if (extractedValue == null || extractedValue == Undefined.instance) {
extractedValue = "";
}
return extractedValue;
} catch (final FrameworkException fex) {
fex.printStackTrace();
// just throw the FrameworkException so we dont lose the information contained
throw fex;
} catch (final Throwable t) {
t.printStackTrace();
// if any other kind of Throwable is encountered throw a new FrameworkException and be done with it
throw new FrameworkException(422, t.getMessage());
} finally {
Scripting.destroyJavascriptContext();
}
}
Aggregations