blob: 8d94c037a32c07dd8946c8db7ecd6a1a63e891ee [file] [log] [blame]
import BaseModel from "./BaseModel";
import DataType from "./DataType";
import BooleanExpressionEvaluator from "./dependencies/BooleanExpressionEvaluator";
import uuidv4 from "uuid/v4";
import ValidatorFactory from "./validators/ValidatorFactory";
const FIELDS = [
"name",
"value",
{
name: "type",
type: DataType,
default: DataType.STRING,
},
"applicationArgument",
{
name: "standardInput",
type: "boolean",
default: false,
},
"userFriendlyDescription",
"metaData",
"inputOrder",
{
name: "isRequired",
type: "boolean",
default: false,
},
{
name: "requiredToAddedToCommandLine",
type: "boolean",
default: false,
},
{
name: "dataStaged",
type: "boolean",
default: false,
},
"storageResourceId",
{
name: "isReadOnly",
type: "boolean",
default: false,
},
"overrideFilename",
];
const IS_REQUIRED_DEFAULT = "This field is required.";
const IS_REQUIRED_URI_COLLECTION = "At least one file must be selected.";
export default class InputDataObjectType extends BaseModel {
constructor(data = {}) {
super(FIELDS, data);
this._key = data.key ? data.key : uuidv4();
this.show = true;
}
get key() {
return this._key;
}
/**
* Get the UI component id for the editor component to use for this input.
* Returns null if there is no editor UI component id.
*
* The expected JSON schema for the editor UI component id is the following:
* {
* "editor": {
* "ui-component-id": "input-editor-component-id",
* ...
* }
* }
*/
get editorUIComponentId() {
const metadata = this._getMetadata();
if (
metadata &&
"editor" in metadata &&
"ui-component-id" in metadata["editor"]
) {
return metadata["editor"]["ui-component-id"];
} else {
return null;
}
}
/**
* Get the configuration for the editor component, which will be available
* to the editor component for customizing its look and functionality.
* Returns empty object if there is no editor config.
*
* The expected JSON schema for the editor config is the following:
* {
* "editor": {
* "config": {
* ... anything can go here ...
* }
* ...
* }
* }
*/
get editorConfig() {
const metadata = this._getMetadata();
if (metadata && "editor" in metadata && "config" in metadata["editor"]) {
return metadata["editor"]["config"];
} else {
return {};
}
}
/**
* Get the validations for the editor component. See ValidatorFactory for a
* list of available validations. Returns empty array if there are no
* validations.
*
* The expected JSON schema for the editor validations is the following:
* {
* "editor": {
* "validations": [
* {
* "type": "validation-name",
* "value": "some value for configuring validation, passed to validator constructor",
* "message": "(Optional) custom validation error message"
* },
* ... additional validations go here ...
* ]
* ...
* }
* }
*
* Note: "message" is optional for all validations.
*/
get editorValidations() {
const metadata = this._getMetadata();
if (
metadata &&
"editor" in metadata &&
"validations" in metadata["editor"]
) {
return metadata["editor"]["validations"];
} else {
return [];
}
}
/**
* Get the dependencies for the editor component. Returns empty object if
* there are no dependencies. See evaluateDependencies for a list of
* available kinds of dependencies.
*
* The expected JSON schema for the editor validations is the following:
* {
* "editor": {
* "dependencies": {
* "show": {
* "AND": [ // Boolean operator ("AND", "OR")
* {
* "INPUT_1": { // Name of other application input
* "comparison": "equals", // Name of comparison type
* "value": "1" // Value to compare with
* }
* },
* {
* "NOT": { // "NOT" is given a single input comparison or "AND" or "OR" expression
* "INPUT_2": {
* ...
* }
* }
* }
* ... additional boolean expressions ("AND", "OR", "NOT")
* ... additional application input comparisons
* ]
* },
* "showOptions": { // Optional
* "isRequired": true // Set isRequired to true when shown, false otherwise (Note:
* // REST API automatically adds and updates this metadata as needed)
* }
* }
* }
* }
*/
get editorDependencies() {
const metadata = this._getMetadata();
if (
metadata &&
"editor" in metadata &&
"dependencies" in metadata["editor"]
) {
return metadata["editor"]["dependencies"];
} else {
return {};
}
}
_getMetadata() {
// metaData could really be anything, here we expect it to be an object
// so safely check if it is first
if (this.metaData && typeof this.metaData === "object") {
return this.metaData;
} else {
return null;
}
}
validate(value = undefined) {
let inputValue = typeof value != "undefined" ? value : this.value;
let results = {};
// Skip running validations when the input isn't shown
if (!this.show) {
return results;
}
let valueErrorMessages = [];
if (this.isRequired && this.isEmpty(inputValue)) {
if (this.type === DataType.URI_COLLECTION) {
valueErrorMessages.push(IS_REQUIRED_URI_COLLECTION);
} else {
valueErrorMessages.push(IS_REQUIRED_DEFAULT);
}
}
// Run through any validations if configured
if (this.editorValidations.length > 0) {
const validatorFactory = new ValidatorFactory();
valueErrorMessages = valueErrorMessages.concat(
validatorFactory.validate(this.editorValidations, inputValue)
);
}
if (valueErrorMessages.length > 0) {
results["value"] = valueErrorMessages;
}
return results;
}
/**
* Evaluate dependencies on the values of other application inputs.
*/
evaluateDependencies(inputValues) {
if (Object.keys(this.editorDependencies).length > 0) {
const booleanExpressionEvaluator = new BooleanExpressionEvaluator(
inputValues
);
if ("show" in this.editorDependencies) {
this.show = booleanExpressionEvaluator.evaluate(
this.editorDependencies.show
);
if ("showOptions" in this.editorDependencies) {
if (
"isRequired" in this.editorDependencies.showOptions &&
this.editorDependencies.showOptions.isRequired
) {
this.isRequired = this.show;
}
}
}
}
}
}
InputDataObjectType.VALID_DATA_TYPES = [
DataType.STRING,
DataType.INTEGER,
DataType.FLOAT,
DataType.URI,
DataType.URI_COLLECTION,
];