Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process namespace support #12

Merged
merged 4 commits into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"assets/subtype-schemas.json"
],
"dependencies": {
"@openeo/js-commons": "^1.3.0",
"@openeo/js-commons": "^1.4.0",
"ajv": "^6.12.0"
},
"devDependencies": {
Expand Down
27 changes: 12 additions & 15 deletions src/error.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
const Utils = require('./utils');

const MESSAGES = {
"MultipleResultNodes": "Multiple result nodes specified for process graph.",
"StartNodeMissing": "No start nodes found for process graph.",
"ResultNodeMissing": "No result node found for process graph.",
"MultipleResultNodesCallback": "Multiple result nodes specified for the callback in the process '{process_id}' (node: '{node_id}').",
"StartNodeMissingCallback": "No start nodes found for the callback in the process '{process_id}' (node: '{node_id}')'.",
"ResultNodeMissingCallback": "No result node found for the callback in the process '{process_id}' (node: '{node_id}').",
"ReferencedNodeMissing": "Referenced node '{node_id}' doesn't exist.",
"NodeIdInvalid": "Invalid node id specified in process graph.",
"NodeInvalid": "Process graph node '{node_id}' is not a valid object.",
"ProcessIdMissing": "Process graph node '{node_id}' doesn't contain a process id.",
"ProcessGraphParameterMissing": "Invalid parameter '{argument}' requested in the process '{process_id}' (node: '{node_id}').",
"ProcessUnsupported": "Process '{process}' is not supported.",
"ProcessArgumentUnsupported": "Process '{process}' does not support the following arguments: {arguments}",
"ProcessArgumentRequired": "Process '{process}' requires argument '{argument}'.",
"ProcessArgumentInvalid": "The argument '{argument}' in process '{process}' is invalid: {reason}",
"MultipleResultNodes": "Multiple result nodes specified for the process.",
"StartNodeMissing": "No start nodes found for the process.",
"ResultNodeMissing": "No result node found for the process.",
"ReferencedNodeMissing": "Referenced process node '{node_id}' doesn't exist.",
"NodeIdInvalid": "Invalid node id specified in the process.",
"NodeInvalid": "Process node '{node_id}' is not a valid object.",
"ProcessIdMissing": "Process node '{node_id}' doesn't contain a process id.",
"ProcessGraphParameterMissing": "Invalid parameter '{argument}' referenced in process node '{node_id}' (process: {process_id}, namespace: {namespace}).",
"ProcessUnsupported": "Process '{process}' (namespace: {namespace}) is not supported.",
"ProcessArgumentUnsupported": "Process '{process}' (namespace: {namespace}) does not support the following arguments: {arguments}",
"ProcessArgumentRequired": "Process '{process}' (namespace: {namespace}) requires argument '{argument}'.",
"ProcessArgumentInvalid": "The argument '{argument}' in process '{process}' (namespace: {namespace}) is invalid: {reason}",
"ProcessGraphMissing": "No process graph specified",
"ProcessMissing": "No process specified"
};
Expand Down
5 changes: 4 additions & 1 deletion src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ProcessGraphNode {
this.processGraph = parent;
this.source = node;
this.process_id = node.process_id;
this.namespace = node.namespace || null;
this.arguments = Utils.isObject(node.arguments) ? Utils.deepClone(node.arguments) : {};
this.description = node.description || null;
this.isResultNode = node.result || false;
Expand All @@ -36,6 +37,7 @@ class ProcessGraphNode {
let args = Utils.mapObjectValues(this.arguments, arg => Utils.isObject(arg) && typeof arg.toJSON === 'function' ? arg.toJSON() : arg);
return Object.assign({}, this.source, {
process_id: this.process_id,
namespace: this.namespace,
m-mohr marked this conversation as resolved.
Show resolved Hide resolved
description: this.description,
arguments: args,
result: this.isResultNode
Expand Down Expand Up @@ -113,7 +115,8 @@ class ProcessGraphNode {
throw new ProcessGraphError('ProcessGraphParameterMissing', {
argument: name,
node_id: this.id,
process_id: this.process_id
process_id: this.process_id,
namespace: this.namespace || 'n/a'
});
}
}
Expand Down
17 changes: 11 additions & 6 deletions src/process.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ const Utils = require('./utils');
class BaseProcess {

constructor(spec) {
this.spec = spec; // Keep original specification data
christophfriedrich marked this conversation as resolved.
Show resolved Hide resolved

// Make properties easily accessible
Object.assign(this, spec);

Expand All @@ -25,7 +23,7 @@ class BaseProcess {
}

toJSON() {
return this.spec;
return Utils.omitFromObject(this, ["validate", "validateArgument", "execute", "test"]);
}

async validate(node) {
Expand All @@ -34,6 +32,7 @@ class BaseProcess {
if (unsupportedArgs.length > 0) {
throw new ProcessGraphError('ProcessArgumentUnsupported', {
process: this.id,
namespace: this.namespace || 'n/a',
arguments: unsupportedArgs
});
}
Expand All @@ -46,6 +45,7 @@ class BaseProcess {
if (!param.optional) {
throw new ProcessGraphError('ProcessArgumentRequired', {
process: this.id,
namespace: this.namespace || 'n/a',
argument: param.name
});
}
Expand Down Expand Up @@ -73,6 +73,7 @@ class BaseProcess {
if (!JsonSchemaValidator.isSchemaCompatible(param.schema, callbackParam.schema)) {
throw new ProcessGraphError('ProcessArgumentInvalid', {
process: this.id,
namespace: this.namespace || 'n/a',
argument: path,
reason: "Schema for parameter '" + arg.from_parameter + "' not compatible with reference"
});
Expand All @@ -86,7 +87,8 @@ class BaseProcess {
throw new ProcessGraphError('ProcessGraphParameterMissing', {
argument: arg.from_parameter,
node_id: node.id,
process_id: node.process_id
process_id: node.process_id,
namespace: node.namespace || 'n/a'
});
}

Expand All @@ -98,6 +100,7 @@ class BaseProcess {
if (!JsonSchemaValidator.isSchemaCompatible(param.schema, parameter.schema)) {
throw new ProcessGraphError('ProcessArgumentInvalid', {
process: this.id,
namespace: this.namespace || 'n/a',
argument: path,
reason: "Schema for parameter '" + arg.from_parameter + "' not compatible"
});
Expand All @@ -111,6 +114,7 @@ class BaseProcess {
if (!JsonSchemaValidator.isSchemaCompatible(param.schema, process.returns.schema)) {
throw new ProcessGraphError('ProcessArgumentInvalid', {
process: this.id,
namespace: this.namespace || 'n/a',
argument: path,
reason: "Schema for result '" + arg.from_node + "' not compatible"
});
Expand Down Expand Up @@ -155,6 +159,7 @@ class BaseProcess {
if (errors.length > 0) {
throw new ProcessGraphError('ProcessArgumentInvalid', {
process: this.id,
namespace: this.namespace || 'n/a',
argument: path,
reason: errors
});
Expand All @@ -164,13 +169,13 @@ class BaseProcess {

/* istanbul ignore next */
async execute(/*node*/) {
throw "execute not implemented yet";
throw new Error(`execute not implemented yet for process '${this.id}' (namespace: ${this.namespace || 'n/a'})`);
}

/* istanbul ignore next */
test() {
// Run the tests from the examples
throw "test not implemented yet";
throw new Error(`test not implemented yet for process '${this.id}' (namespace: ${this.namespace || 'n/a'})`);
}

}
Expand Down
27 changes: 19 additions & 8 deletions src/processgraph.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const BaseProcess = require('./process');
const ErrorList = require('./errorlist');
const JsonSchemaValidator = require('./jsonschema');
const ProcessGraphError = require('./error');
Expand Down Expand Up @@ -74,6 +75,10 @@ class ProcessGraph {
return this.copyProcessGraphInstanceProperties(pg);
}

createProcessInstance(process) {
return new BaseProcess(process);
}

copyProcessGraphInstanceProperties(pg) {
pg.allowEmptyGraph = this.allowEmptyGraph;
pg.fillProcessParameters = this.fillProcessParameters;
Expand Down Expand Up @@ -472,22 +477,28 @@ class ProcessGraph {
/**
* Gets the process for the given process ID or node.
*
* @param {ProcessGraphNode|string} id
* @param {ProcessGraphNode|string} process
* @param {?string} [namespace=null]
* @returns {object|null}
* @throws {ProcessGraphError} - ProcessUnsupported
*/
getProcess(id) {
getProcess(process, namespace = null) {
if (this.processRegistry === null) {
return null;
}
if (id instanceof ProcessGraphNode) {
id = id.process_id;
let id;
if (process instanceof ProcessGraphNode) {
id = process.process_id;
namespace = process.namespace;
}
else {
id = process;
}
var process = this.processRegistry.get(id);
if (process === null) {
throw new ProcessGraphError('ProcessUnsupported', {process: id});
let spec = this.processRegistry.get(id, namespace);
if (spec === null) {
throw new ProcessGraphError('ProcessUnsupported', {process: id, namespace: namespace || 'n/a'});
}
return process;
return this.createProcessInstance(spec);
}

getParentProcessId() {
Expand Down
62 changes: 7 additions & 55 deletions src/registry.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,16 @@
const Process = require('./process');
const Utils = require('./utils');
const CommonProcessRegistry = require('@openeo/js-commons/src/processRegistry');

/**
* Central registry for processes.
*
* Implementation has been moved to @openeo/js-commons.
* This wrapper here is only available for backward compatibility.
*
* @todo Remove in 2.0.0.
* @augments CommonProcessRegistry
* @class
*/
class ProcessRegistry {

constructor(processes = []) {
// Keys added to this object must be lowercase!
this.processes = {};
this.addAll(processes);
}

addAll(processes) {
for(var i in processes) {
this.add(processes[i]);
}
}

add(process) {
if (!Utils.isObject(process)) {
throw new Error("Invalid process; not an object.");
}

let isImpl = process instanceof Process;
if (!isImpl && typeof process.toJSON === 'function') {
var json = process.toJSON();
if (Utils.isObject(json)) {
process = json;
}
}
if (typeof process.id !== 'string') {
throw new Error("Invalid process; no id specified.");
}
this.processes[process.id.toLowerCase()] = isImpl ? process : new Process(process);
}

count() {
return Utils.size(this.processes);
}

all() {
return Object.values(this.processes);
}

get(id) {
if (typeof id === 'string') {
var pid = id.toLowerCase();
if (typeof this.processes[pid] !== 'undefined') {
return this.processes[pid];
}
}
return null;
}

toJSON() {
return Object.values(this.processes).map(impl => impl.toJSON());
}
class ProcessRegistry extends CommonProcessRegistry {

}

Expand Down
2 changes: 1 addition & 1 deletion tests/errorlist.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('ErrorList test', () => {
expect(el.getAll()).toStrictEqual([e1]);
});
var e2 = new ProcessGraphError("MultipleResultNodes");
var msg2 = "Multiple result nodes specified for process graph.";
var msg2 = "Multiple result nodes specified for the process.";
test('Adding second error - custom impl.', () => {
el.add(e2);
expect(el.first()).toBe(e1);
Expand Down
2 changes: 2 additions & 0 deletions tests/node.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var subProcess = {
process_graph: {
absolute: {
process_id: "absolute",
namespace: null,
arguments: {
x: from_x
},
Expand All @@ -25,6 +26,7 @@ var contextResult = [fooDefault, undefined].concat(contextAdditionals);

var nodeObj = {
process_id: "apply",
namespace: null,
arguments: {
process: subProcess,
context: contextObj,
Expand Down
Loading