/**
* @file Describes a data field of the restructured data.
* @version {@link https://github.com/JohT/data-restructor-js/releases/latest latest version}
* @author JohT
* @version ${project.version}
*/
"use strict";
var module = describedFieldInternalCreateIfNotExists(module); // Fallback for vanilla js without modules
function describedFieldInternalCreateIfNotExists(objectToCheck) {
return objectToCheck || {};
}
/**
* Describes a data field of the restructured data.
* @module described_field
*/
var described_field = (module.exports = {}); // Export module for npm...
described_field.internalCreateIfNotExists = describedFieldInternalCreateIfNotExists;
/**
* Describes a field of the restructured data.
* Dynamically added properties represent custom named groups containing DescribedDataField-Arrays.
*
* @typedef {Object} module:described_field.DescribedDataField
* @property {string} [category=""] - name of the category. Could contain a short domain name like "product" or "vendor".
* @property {string} [type=""] - type of the data element. Examples: "summary" for e.g. a list overview. "detail" e.g. when a summary is selected. "filter" e.g. for field/value pair results that can be selected as data filters.
* @property {string} [abbreviation=""] - one optional character, a symbol character or a short abbreviation of the category
* @property {string} [image=""] - one optional path to an image resource
* @property {string} index - array of numbers containing the splitted index. Example: "responses[2].hits.hits[4]._source.name" will have an index of [2,4]
* @property {string[]} groupNames - array of names of all dynamically added properties representing groups
* @property {string} displayName - display name of the field
* @property {string} fieldName - field name
* @property {{*}} value - content of the field
* @property {module:described_field.DescribedDataField[]} [couldBeAnyCustomGroupName] any number of groups attached to the field each containing multiple fields
*/
described_field.DescribedDataFieldBuilder = (function () {
/**
* Builds a {@link module:described_field.DescribedDataField}.
* DescribedDataField is the main element of the restructured data and therefore considered "public".
* @constructs DescribedDataFieldBuilder
* @alias module:described_field.DescribedDataFieldBuilder
*/
function DescribedDataFieldBuilder() {
/**
* @type {module:described_field.DescribedDataField}
*/
this.describedField = {
category: "",
type: "",
abbreviation: "",
image: "",
index: [],
groupNames: [],
displayName: "",
fieldName: "",
value: ""
};
/**
* Takes over all values of the template {@link module:described_field.DescribedDataField}.
* @function
* @param {module:described_field.DescribedDataField} template
* @returns {DescribedDataFieldBuilder}
* @example fromDescribedDataField(sourceField)
*/
this.fromDescribedDataField = function (template) {
this.category(template.category);
this.type(template.type);
this.abbreviation(template.abbreviation);
this.image(template.image);
this.index(template.index);
this.groupNames(template.groupNames);
this.displayName(template.displayName);
this.fieldName(template.fieldName);
this.value(template.value);
return this;
};
/**
* Sets the category.
*
* Contains a short domain nam, for example:
* - "product" for products
* - "vendor" for vendors
*
* @function
* @param {String} [value=""]
* @returns {DescribedDataFieldBuilder}
* @example category("Product")
*/
this.category = function (value) {
this.describedField.category = withDefaultString(value, "");
return this;
};
/**
* Sets the type.
*
* Contains the type of the entry, for example:
* - "summary" for e.g. a list overview.
* - "detail" e.g. when a summary is selected.
* - "filter" e.g. for field/value pair results that can be selected as search parameters.
*
* @function
* @param {String} [value=""]
* @returns {DescribedDataFieldBuilder}
* @example type("summary")
*/
this.type = function (value) {
this.describedField.type = withDefaultString(value, "");
return this;
};
/**
* Sets the optional abbreviation.
*
* Contains a symbol character or a very short abbreviation of the category.
* - "P" for products
* - "V" for vendors
*
* @function
* @param {String} [value=""]
* @returns {DescribedDataFieldBuilder}
* @example abbreviation("P")
*/
this.abbreviation = function (value) {
this.describedField.abbreviation = withDefaultString(value, "");
return this;
};
/**
* Sets the optional path to an image resource.
*
* @function
* @param {String} [value=""]
* @returns {DescribedDataFieldBuilder}
* @example image("img/product.png")
*/
this.image = function (value) {
this.describedField.image = withDefaultString(value, "");
return this;
};
/**
* Sets the index as an array of numbers containing the splitted array indexes of the source field.
* Example: "responses[2].hits.hits[4]._source.name" will have an index of [2,4].
*
* @function
* @param {number[]} [value=[]]
* @returns {DescribedDataFieldBuilder}
* @example index([2,4])
*/
this.index = function (value) {
this.describedField.index = withDefaultArray(value, []);
return this;
};
/**
* Sets the group names as an array of strings containing the names of the dynamically added properties,
* that contain an array of {@link module:described_field.DescribedDataField}-Objects.
*
* @function
* @param {string[]} [value=[]]
* @returns {DescribedDataFieldBuilder}
* @example groupNames(["summaries","details","options"])
*/
this.groupNames = function (value) {
this.describedField.groupNames = withDefaultArray(value, []);
return this;
};
/**
* Sets the display name.
*
* @function
* @param {String} [value=""]
* @returns {DescribedDataFieldBuilder}
* @example displayName("Color")
*/
this.displayName = function (value) {
this.describedField.displayName = withDefaultString(value, "");
return this;
};
/**
* Sets the (technical) field name.
*
* @function
* @param {String} [value=""]
* @returns {DescribedDataFieldBuilder}
* @example fieldName("color")
*/
this.fieldName = function (value) {
this.describedField.fieldName = withDefaultString(value, "");
return this;
};
/**
* Sets the value/content of the field.
*
* @function
* @param {*} value
* @returns {DescribedDataFieldBuilder}
* @example value("darkblue")
*/
this.value = function (value) {
this.describedField.value = value;
return this;
};
/**
* Finalizes the settings and builds the {@link module:described_field.DescribedDataField}.
* @function
* @returns {module:described_field.DescribedDataField}
*/
this.build = function () {
return this.describedField;
};
}
function isSpecifiedString(value) {
return typeof value === "string" && value !== null && value !== "";
}
function withDefaultString(value, defaultValue) {
return isSpecifiedString(value) ? value : defaultValue;
}
function withDefaultArray(value, defaultValue) {
return value === undefined || value === null ? defaultValue : value;
}
return DescribedDataFieldBuilder;
}());
/**
* Creates a new described data field with all properties of the original one except for dynamically added groups.
* @param {module:described_field.DescribedDataField} describedDataField
* @returns {module:described_field.DescribedDataField}
* @memberof module:described_field
*/
described_field.copyWithoutGroups = function (describedDataField) {
return new described_field.DescribedDataFieldBuilder().fromDescribedDataField(describedDataField).groupNames([]).build();
};
described_field.DescribedDataFieldGroup = (function () {
/**
* Adds groups to {@link module:described_field.DescribedDataField}s. These groups are dynamically added properties
* that contain an array of sub fields of the same type {@link module:described_field.DescribedDataField}s.
*
* @param {module:described_field.DescribedDataField} dataField
* @constructs DescribedDataFieldGroup
* @alias module:described_field.DescribedDataFieldGroup
* @example new described_field.DescribedDataFieldGroup(field).addGroupEntry("details", detailField);
*/
function DescribedDataFieldGroup(dataField) {
this.dataField = dataField;
/**
* Adds an entry to the given group. If the group does not exist, it will be created.
* @function
* @param {String} groupName name of the group to which the entry will be added
* @param {module:described_field.DescribedDataField} describedField sub field that is added to the group
* @returns {DescribedDataFieldGroup}
*/
this.addGroupEntry = function (groupName, describedField) {
this.addGroupEntries(groupName, [describedField]);
return this;
};
/**
* Adds entries to the given group. If the group does not exist, it will be created.
* @function
* @param {String} groupName name of the group to which the entries will be added
* @param {module:described_field.DescribedDataField[]} describedFields sub fields that are added to the group
* @returns {DescribedDataFieldGroup}
*/
this.addGroupEntries = function (groupName, describedFields) {
if (!groupName || groupName.length === 0) {
return this;
}
if (!describedFields || describedFields.length === 0) {
return this;
}
if (this.dataField[groupName] === undefined) {
this.dataField.groupNames.push(groupName);
this.dataField[groupName] = [];
}
var index;
var describedField;
for (index = 0; index < describedFields.length; index += 1) {
describedField = describedFields[index];
this.dataField[groupName].push(describedField);
}
return this;
};
}
return DescribedDataFieldGroup;
}());