1 /* - - - - LEIDOS COPYRIGHT NOTICE - - - - /////////////////////////////////////////////////////////////////////////////////// // Project Name: Leidos Enterprise Application Framework (LEAF), Formerly Distributed Command and Control Framework (DC2F) // This file is part of the LEAF project. LEAF can not be copied and/or distributed // without the express permission of Leidos. // Company: Leidos, Inc // Copyright (C): Copyright 2004 - 2018, Leidos, All rights reserved. // Organizations: Leidos, 215 Don Knotts Blvd, Morgantown, WV 26501, (304) 284-9000 /////////////////////////////////////////////////////////////////////////////////// */ /** * This module contains classes representing LEAF business objects. * * @module leaf-beans */ class DataObject { /** * * DataObjects in LEAF are specific instances of a {{#crossLink "BeanMetadata"}}{{/crossLink}}. For example, a * Person BeanMetadata may have fields for Name, Height and DOB. The DataObjects Elise, Charlotte, Dorothy, Mark, * and John are instances of this Person BeanMetadata that each have their own Name, Height, and DOB.
*
* DataObjects are "strictly" versioned. *
*
The constructor can be passed a data object JSON object to convert to a DataObject. * * @class DataObject * @constructor * @module leaf-beans * @param {Object} [dataObject] The JSON object to convert to a DataObject. * @param {String} [dataObject.alternateId] An alternate ID for the data object; This System FieldMetadata is typically * used when you are importing data from an external system. * @param {Number} [dataObject.createdDate] Lists the date that this data object was created * @param {String} [dataObject.createdByUsername] The username of the User who created this data object. * @param {Object} [dataObject.dataObjectSecurityToken] * @param {String} [dataObject.dataObjectServiceName] The name of the DataObjectService to retrieve the * BeanMetadata from in order to get type info when * setting property values. * @param {String} [dataObject.displayLabel] The value of the data object property specified by * preferredDisplayPropName in the Metadata Definition for this type * of data object.
*
e.g. You have a BeanMetadata called Person who has * preferredDisplayPropName set to LastName. You create a Person data * object whose LastName property = "Blatt". That data object's * DisplayLabelFieldMetadata would = "Blatt". * @param {String} [dataObject.id] Unique string used to reference this data object. * @param {String} [dataObject.lastModifiedByUsername] Username of the user who last modified this object. * @param {Number} [dataObject.lastModifiedDate] The date that this data object was last changed. * @param {String} [dataObject.parentId] ID of this object's parent object, if applicable. * @param {String} [dataObject.qualifiedId] * @param {String} [dataObject.qualifiedType] * @param {String} [dataObject.rootId] The ID of the highest data object in this hierarchy. * @param {String} [dataObject.rootType] The type of the highest data object in this hierarchy. * @param {String} [dataObject.securityGroupId] * @param {String} [dataObject.securityGroupName] * @param {String} [dataObject.tags] The tags that have been added to this data object. * @param {String} [dataObject.type] The type of this data object (the bean name). */ constructor(dataObject) { if (dataObject) { delete dataObject.__beanMetadata; Object.keys(dataObject).forEach(prop => { if (dataObject.typeInfo != null) { let type = dataObject.typeInfo[prop]; switch (type) { case "CalculatedAltitude": this[prop] = new Altitude(dataObject[prop]); break; case "CalculatedDistance": this[prop] = new Distance(dataObject[prop]); break; case "List": dataObject.typeInfo[prop] = "ListOfDataObjects"; case "ListOfDataObjects": this[prop] = []; for (let i = 0; i < dataObject[prop].length; i++) { this[prop].push(new DataObject(dataObject[prop][i])); } break; default: this[prop] = dataObject[prop]; } } else { this[prop] = dataObject[prop]; } }); if (this.foreignRefs && Object.keys(this.foreignRefs).length > 0) { Object.keys(this.foreignRefs).forEach(foreignRef => { if (typeof this.foreignRefs[foreignRef] === "string") { let values = this.foreignRefs[foreignRef].split(":"); this.foreignRefs[foreignRef] = { serviceName: values[0], id: values[1] }; } }); } } this.typeInfo = this.typeInfo || {}; this.typeInfo[LeafConstants.SYSTEM_FIELDS.TYPE] = "String"; } /******************************** * DataObject Methods ********************************/ /** * Gets the value of the DataObject property. * * @method getValue * @param {String} propName Name of the DataObject property. * @returns {*} Value of the DataObject property. */ getValue(propName) { return this[propName]; } /** * Gets the value of the DataObject property with the given property name as a String. * * @param {String} propName Name of the DataObject property. * @returns {String} String representation of the DataObject's property value. */ getValueAsString(propName) { return this.serializeValue(this.getValue(propName), this.typeInfo[propName]); } /** * Sets the value of the DataObject property. * * @method setValue * @param {String} propName Name of the DataObject property to set value for. * @param {*} value Value to set for the DataObject property. */ setValue(propName, value) { if (arguments.length !== 2) { throw Error("Incorrect parameters in method 'setValue': Must pass in value (even if null) and propName"); } const fieldMetadata = this._beanMetadata.getFieldMetadata(propName); if (!fieldMetadata) { throw "FieldMetadata not found for propName: " + propName; } if (value != null) { this[propName] = value; if (fieldMetadata.valueClass === "List") { this.typeInfo[fieldMetadata.propName] = "ListOfDataObjects"; } else { this.typeInfo[fieldMetadata.propName] = fieldMetadata.valueClass; } } else { delete this[fieldMetadata.propName]; delete this.typeInfo[fieldMetadata.propName]; } } /** * Gets the id of the foreign DataObject containing the property. * * @method getForeignRefId * @param {String} propName The property name to obtain the foreign DataObject id for. * @returns {String} The foreign DataObject id of the DataObject property. */ getForeignRefId(propName) { return this.foreignRefs && this.foreignRefs[propName]; } /** * Sets the foreign DataObject id of the DataObject property. The object being set on the foreignRefs map is a * representation of the ForeignReference class on LEAF-Services. * * @method setForeignRef * @param {String} propName The property to set the foreign field identifier for. * @param {String} foreignDataObjectId The foreign DataObject property's DataObject id. * @param {String} foreignServiceName The service name of the service which contains the foreign DataObject. * @returns {DataObject} The updated data object. */ setForeignRef(propName, foreignDataObjectId, foreignServiceName) { if (this.foreignRefs == null) { this.foreignRefs = {}; } this.foreignRefs[propName] = {id: foreignDataObjectId, serviceName: foreignServiceName}; return this; } /** * Gets the value of the 'tags' property as a String Array. * * @method getTagsAsArray * @returns {String[]} The value of the 'tags' property as a String Array. */ getTagsAsArray() { const tagsString = this.getValue(LeafConstants.SYSTEM_FIELDS.TAGS); return tagsString != null && tagsString !== "" ? tagsString.split(",") : []; } /** * Sets the value of the 'tags' property as a comma-separated String from the given tags String Array. * * @method setTagsFromArray * @param {String[]} tagsArray The String Array of tags to set the value of the * 'tags' property to as a comma-separated String. */ setTagsFromArray(tagsArray) { this.setValue(LeafConstants.SYSTEM_FIELDS.TAGS, tagsArray.join(",")); } /** * Compares and checks two data objects for complete properties equality (in terms of equality). * * @param {DataObject} dataObjectToCompare The data object for use of comparison. * @returns {Boolean} True if the data object properties are equal. */ equals(dataObjectToCompare) { let dataObjectsAreEqual = true; const thisPropertyList = Object.keys(this); const dataObjectToComparePropertyList = Object.keys(dataObjectToCompare); if (thisPropertyList.length === dataObjectToComparePropertyList.length) { for (const propertyKey in thisPropertyList) { const propName = thisPropertyList[propertyKey]; if (CollectionUtils.doesArrayContain(dataObjectToComparePropertyList, propName) === -1) { dataObjectsAreEqual = false; break; } const thisValue = this.getValueAsString(propName); const dataObjectToCompareValue = dataObjectToCompare.getValueAsString(propName); if (thisValue !== dataObjectToCompareValue) { dataObjectsAreEqual = false; break; } } } else { dataObjectsAreEqual = false; } return dataObjectsAreEqual; } /** * Returns a deep copy of the DataObject. * * @method copyObject * @return {DataObject} A deep copy of the DataObject. */ copyObject() { return new DataObject(ObjectUtils.assign({}, this)); } /** * Creates a copy of this data object, then replaces the foreignRefs Map values with their serialized values and * returns the copy. * * @method toJSON * @return {DataObject} A deep copy of the DataObject with foreignRefs serialized. */ toJSON() { let copy = this.copyObject(); if (copy.foreignRefs != null) { Object.keys(copy.foreignRefs).forEach(foreignRef => { copy.foreignRefs[foreignRef] = copy.foreignRefs[foreignRef].serviceName + ":" + copy.foreignRefs[foreignRef].id; }); } return copy; } /******************************** * Utility Methods ********************************/ /** * Serializes the list of DataObjects with the fields specified. * * @method serializeToVariableString * @static * @param {DataObject[]} dataObjectList List of DataObjects to serialize. * @param {Object[]} fieldMetadataToSerialize Determines column headers and props to serialize. * @param {String} separator Character(s) to insert between properties. * @return {String} String with serialized values separated by the provided separator String. */ static serializeToVariableString(dataObjectList, fieldMetadataToSerialize, separator) { let separatedVariableString = fieldMetadataToSerialize.map(fm => { return fm.shortName; }).join(separator); separatedVariableString += "\n"; dataObjectList.forEach((dataObject, index) => { let dataString = fieldMetadataToSerialize.map(fm => { let valueAsString = ""; if (fm.isCalendarField()) { valueAsString += moment(dataObject.getValue(fm.propName)).formatWithJDF(fm.format); } else { valueAsString += dataObject.getValueAsString(fm.propName); } valueAsString = valueAsString.replace(/,/g, " "); return valueAsString; }).join(separator); separatedVariableString += index < dataObjectList.length ? dataString + "\n" : dataString; }); return separatedVariableString; } /******************************** * Private Accessors ********************************/ get _beanMetadata() { if (!this.__beanMetadata) { this.__beanMetadata = LEAF.serviceManager.getMetadataService().getBeanMetadata(this.type); } return this.__beanMetadata; } } (function () { const serializerMap = {}; serializerMap[window.LeafConstants.Serializers.STRING_CLASS] = function (val) { return val.toString(); }; serializerMap[window.LeafConstants.Serializers.ENCRYPTED_STRING_CLASS] = function (val) { return JSON.stringify(val); }; serializerMap[window.LeafConstants.Serializers.BOOLEAN_CLASS] = function (val) { return val.toString(); }; serializerMap[window.LeafConstants.Serializers.INTEGER_CLASS] = function (val) { return val.toString(); }; serializerMap[window.LeafConstants.Serializers.LONG_CLASS] = serializerMap[window.LeafConstants.Serializers.INTEGER_CLASS]; serializerMap[window.LeafConstants.Serializers.FLOAT_CLASS] = serializerMap[window.LeafConstants.Serializers.INTEGER_CLASS]; serializerMap[window.LeafConstants.Serializers.DOUBLE_CLASS] = serializerMap[window.LeafConstants.Serializers.INTEGER_CLASS]; serializerMap[window.LeafConstants.Serializers.IALTITUDE_CLASS] = function (val) { return val.toString(); }; serializerMap[window.LeafConstants.Serializers.CALCULATED_ALTITUDE_CLASS] = serializerMap[window.LeafConstants.Serializers.IALTITUDE_CLASS]; serializerMap[window.LeafConstants.Serializers.IDISTANCE_CLASS] = function (val) { return val.toString(); }; serializerMap[window.LeafConstants.Serializers.CALCULATED_DISTANCE_CLASS] = serializerMap[window.LeafConstants.Serializers.IDISTANCE_CLASS]; serializerMap[window.LeafConstants.Serializers.ICOORDINATE_CLASS] = function (val) { return window.CoordinateUtils.coordinateToString(val).toUpperCase(); }; serializerMap[window.LeafConstants.Serializers.CALCULATED_COORDINATE_CLASS] = serializerMap[window.LeafConstants.Serializers.ICOORDINATE_CLASS]; serializerMap[window.LeafConstants.Serializers.DATE_TIME_CLASS] = function (val) { return val.toString(); }; /** * Serializes the property value depending on object type. * * @method serializeValue * @param {Object} value The property value to be serialized. * @param {String} serializerName The serializer to use. * @return {String} The serialized property value. */ DataObject.prototype.serializeValue = function (value, serializerName) { let stringValue = ""; if (value != null && serializerName) { if (!serializerMap[serializerName]) { throw Error("serializeValue failed for unknown type: " + serializerName); } stringValue = serializerMap[serializerName](value); } return stringValue; }; })(); window.DataObject = DataObject;