@ngageoint/mage.arcgis.service
Version:
A mage service plugin that synchronizes mage observations to a configured ArcGIS feature layer.
492 lines • 20.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObservationsTransformer = void 0;
const entities_events_forms_1 = require("@ngageoint/mage.service/lib/entities/events/entities.events.forms");
/**
* Class that transforms observations into a json string that can then be sent to an arcgis server.
*/
class ObservationsTransformer {
/**
* Constructor.
* @param {ArcGISPluginConfig} config The plugins configuration.
* @param {Console} console Used to log to the console.
*/
constructor(config, console) {
/**
* Initialized flag
*/
this._initialized = false;
/**
* Default values
*/
this._defaults = {};
/**
* Omit attributes
*/
this._omit = [];
this._config = config;
this._console = console;
}
/**
* Initialize configuration settings
*/
init() {
if (!this._initialized) {
this._initialized = true;
if (this._config.attributes != null) {
for (const attributes of Object.entries(this._config.attributes)) {
const attribute = attributes[0];
const attributeConfig = attributes[1];
const defaults = attributeConfig.defaults;
if (defaults != null && defaults.length > 0) {
this._defaults[attribute] = defaults;
}
if (attributeConfig.omit) {
this._omit.push(attribute);
}
}
}
}
}
/**
* Converts the specified observation into an ArcObservation that can be sent to an arcgis server.
* @param {ObservationAttrs} observation The observation to convert.
* @param {EventTransform} transform The Event transform.
* @param {User | null} user The MAGE user.
* @returns {ArcObservation} The ArcObservation of the observation.
*/
transform(observation, transform, user) {
this.init();
const arcObject = {};
this.observationToAttributes(observation, transform, user, arcObject);
if (observation.geometry != null) {
const geometry = observation.geometry;
const arcGeometry = this.geometryToArcGeometry(geometry);
this._console.info('ArcGIS new ' + geometry.type + ' at ' + JSON.stringify(arcGeometry) + ' with id ' + observation.id);
arcObject.geometry = arcGeometry;
}
let formIds = {};
if (observation.properties != null) {
formIds = this.propertiesToAttributes(observation.properties, transform, arcObject);
}
const arcObservation = this.createObservation(observation);
if (this._config.geometryType != null) {
this.addAttribute(this._config.geometryType, arcObservation.esriGeometryType, arcObject);
}
this.addDefaults(arcObject);
arcObservation.createdAt = new Date(observation.createdAt).getTime();
arcObservation.lastModified = new Date(observation.lastModified).getTime();
arcObservation.object = arcObject;
arcObservation.attachments = this.attachments(observation.attachments, formIds, transform);
this.removeOmissions(arcObject);
return arcObservation;
}
/**
* Creates a base ArcObservation with id and geometry type.
* @param {ObservationAttrs} observation The observation to convert.
* @returns {ArcObservation} The ArcObservation of the observation.
*/
createObservation(observation) {
const arcObservation = {};
arcObservation.id = observation.id;
arcObservation.esriGeometryType = this.esriGeometryType(observation);
return arcObservation;
}
/**
* Converts a mage geometry type to an esri geometry type.
* @param {string} mageGeometryType The mage geometry type.
* @returns {string} The esri geometry type.
*/
mageTypeToEsriType(mageGeometryType) {
switch (mageGeometryType) {
case 'Point':
return 'esriGeometryPoint';
case 'LineString':
return 'esriGeometryPolyline';
case 'Polygon':
return 'esriGeometryPolygon';
default:
return '';
}
}
/**
* Determine the observation Esri geometry type.
* @param {ObservationAttrs} observation The observation.
* @returns {string} The Esri geometry type.
*/
esriGeometryType(observation) {
let esriGeometryType = '';
if (observation.geometry != null) {
esriGeometryType = this.mageTypeToEsriType(observation.geometry.type);
}
return esriGeometryType;
}
/**
* Converts and adds observation values to ArcObject attributes.
* @param {ObservationAttrs} observation The observation to convert.
* @param {EventTransform} transform The Event transform.
* @param {User | null} user The MAGE user.
* @param {ArcObject} arcObject The converted ArcObject.
*/
observationToAttributes(observation, transform, user, arcObject) {
let observationIdValue = observation.id;
if (this._config.eventIdField == null) {
observationIdValue += this._config.idSeparator + observation.eventId;
}
else {
this.addAttribute(this._config.eventIdField, observation.eventId, arcObject);
}
this.addAttribute(this._config.observationIdField, observationIdValue, arcObject);
const mageEvent = transform.mageEvent;
if (this._config.eventNameField != null && mageEvent != null) {
this.addAttribute(this._config.eventNameField, mageEvent.name, arcObject);
}
if (this._config.userIdField != null && observation.userId != null) {
this.addAttribute(this._config.userIdField, observation.userId, arcObject);
}
if (user != null) {
if (this._config.usernameField != null) {
this.addAttribute(this._config.usernameField, user.username, arcObject);
}
if (this._config.userDisplayNameField != null) {
this.addAttribute(this._config.userDisplayNameField, user.displayName, arcObject);
}
}
if (this._config.deviceIdField != null && observation.deviceId != null) {
this.addAttribute(this._config.deviceIdField, observation.deviceId, arcObject);
}
if (this._config.createdAtField != null) {
this.addAttribute(this._config.createdAtField, observation.createdAt, arcObject);
}
if (this._config.lastModifiedField != null) {
this.addAttribute(this._config.lastModifiedField, observation.lastModified, arcObject);
}
}
/**
* Converts an observation geometry to an ArcGeometry.
* @param {Geometry} geometry The observation geometry to convert.
* @returns {ArcGeometry} The converted ArcGeometry.
*/
geometryToArcGeometry(geometry) {
let arcGeometry = {};
switch (geometry.type) {
case 'Point':
arcGeometry = this.pointToArcPoint(geometry);
break;
case 'LineString':
arcGeometry = this.lineStringToArcPolyline(geometry);
break;
case 'Polygon':
arcGeometry = this.polygonToArcPolygon(geometry);
break;
default:
break;
}
arcGeometry.spatialReference = { wkid: 4326 };
return arcGeometry;
}
/**
* Converts an observation Point to an ArcPoint.
* @param {Point} point The observation Point to convert.
* @returns {ArcPoint} The converted ArcPoint.
*/
pointToArcPoint(point) {
const arcPoint = {};
arcPoint.x = point.coordinates[0];
arcPoint.y = point.coordinates[1];
return arcPoint;
}
/**
* Converts an observation LineString to an ArcPolyline.
* @param {LineString} lineString The observation LineString to convert.
* @returns {ArcPolyline} The converted ArcPolyline.
*/
lineStringToArcPolyline(lineString) {
const arcPolyline = {};
arcPolyline.paths = [lineString.coordinates];
return arcPolyline;
}
/**
* Converts an observation Polygon to an ArcPolygon.
* @param {Polygon} polygon The observation Polygon to convert.
* @returns {ArcPolygon} The converted ArcPolygon.
*/
polygonToArcPolygon(polygon) {
const arcPolygon = {};
arcPolygon.rings = polygon.coordinates;
return arcPolygon;
}
/**
* Converts and adds observation properties to ArcObject attributes.
* @param {{ [name: string]: unknown }} properties The observation properties to convert.
* @param {EventTransform} transform The Event transform.
* @param {ArcObject} arcObject The converted ArcObject.
* @returns {{ [name: string]: number }} form ids map
*/
propertiesToAttributes(properties, transform, arcObject) {
let formIds = {};
for (const property in properties) {
const value = properties[property];
if (property === 'forms') {
formIds = this.formsToAttributes(value, transform, arcObject);
}
else {
this.addAttribute(property, value, arcObject);
}
}
return formIds;
}
/**
* Converts and adds observation property forms data to ArcObject attributes.
* @param {[{ [name: string]: unknown }]} forms The observation property forms to convert.
* @param {EventTransform} transform The Event transform.
* @param {ArcObject} arcObject The converted ArcObject.
* @returns {{ [name: string]: number }} form ids map
*/
formsToAttributes(forms, transform, arcObject) {
const formIds = {};
const formIdCount = {};
const mageEvent = transform.mageEvent;
for (let i = 0; i < forms.length; i++) {
const form = forms[i];
const formId = form['formId'];
const id = form['id'];
let fields = null;
let formCount = 1;
if (formId != null && id != null) {
formIds[id] = formId;
let count = formIdCount[formId];
if (count == null) {
count = 0;
}
formCount = count + 1;
formIdCount[formId] = formCount;
fields = transform.get(formId);
}
for (const formProperty in form) {
let value = form[formProperty];
if (value != null) {
if (mageEvent != null && formId != null) {
const field = mageEvent.formFieldFor(formProperty, formId);
if (field != null && field.type !== entities_events_forms_1.FormFieldType.Attachment) {
let title = field.title;
if (fields != null) {
const fieldTitle = fields.get(title);
if (fieldTitle != null) {
const sanitizedName = ObservationsTransformer.replaceSpaces(fieldTitle);
const sanitizedFormName = ObservationsTransformer.replaceSpaces(fields.name);
title = `${sanitizedFormName}_${sanitizedName}`.toLowerCase();
}
}
if (field.type === entities_events_forms_1.FormFieldType.Geometry) {
value = this.geometryToArcGeometry(value);
}
this.addFormAttribute(title, formCount, value, arcObject);
}
}
else {
this.addFormAttribute(formProperty, formCount, value, arcObject);
}
}
}
}
return formIds;
}
/**
* Add an ArcObject attribute for a form field.
* @param {string} name The attribute name.
* @param {number} count The form count.
* @param {unknown} value The attribute value.
* @param {ArcObject} arcObject The converted ArcObject.
*/
addFormAttribute(name, count, value, arcObject) {
var _a;
if (count > 1 && this._config.attributes != null) {
const concat = (_a = this._config.attributes[name]) === null || _a === void 0 ? void 0 : _a.concatenation;
if (concat != null && (concat.sameForms == null || concat.sameForms)) {
count = 1;
}
}
const attribute = this.appendCount(name, count);
this.addAttribute(attribute, value, arcObject);
}
/**
* Add an ArcObject attribute.
* @param {string} name The attribute name.
* @param {unknown} value The attribute value.
* @param {ArcObject} arcObject The converted ArcObject.
*/
addAttribute(name, value, arcObject) {
if (value != null) {
if (arcObject.attributes == null) {
arcObject.attributes = {};
}
let attribute = ObservationsTransformer.replaceSpaces(name);
if (Object.prototype.toString.call(value) === '[object Date]') {
value = new Date(value).getTime();
}
let config = null;
if (this._config.attributes != null) {
config = this._config.attributes[name];
}
if ((config === null || config === void 0 ? void 0 : config.mappings) != null) {
const fieldValue = config.mappings[value];
if (fieldValue != null) {
value = fieldValue;
}
}
const existingValue = arcObject.attributes[attribute];
if (existingValue !== undefined) {
const concat = config === null || config === void 0 ? void 0 : config.concatenation;
if (concat != null && (concat.differentForms == null || concat.differentForms)) {
let delimiter = concat.delimiter;
if (delimiter == null) {
delimiter = ', ';
}
value = existingValue + delimiter + value;
}
else {
let baseKey = attribute;
let count = 1;
const countIndex = attribute.lastIndexOf('_');
if (countIndex !== -1) {
const countString = attribute.substring(countIndex + 1);
if (countString != null && countString !== '') {
const countNumber = Number(countString);
if (!isNaN(countNumber)) {
baseKey = attribute.substring(0, countIndex);
count = countNumber;
}
}
}
do {
count += 1;
attribute = this.appendCount(baseKey, count);
} while (arcObject.attributes[attribute] !== undefined);
}
}
arcObject.attributes[attribute] = value;
}
}
/**
* Add ArcObject attribute defaults.
* @param {ArcObject} arcObject The converted ArcObject.
*/
addDefaults(arcObject) {
for (const attributeDefaults of Object.entries(this._defaults)) {
const attribute = attributeDefaults[0];
if (arcObject.attributes[attribute] == null) {
const defaults = attributeDefaults[1];
for (const attributeDefault of defaults) {
let setDefault = true;
const condition = attributeDefault.condition;
if (condition != null && condition.length > 0) {
for (const valueConfig of condition) {
const value = arcObject.attributes[valueConfig.attribute];
const values = valueConfig.values;
if (values.length === 0) {
setDefault = value == null;
}
else {
setDefault = values.includes(value);
}
if (!setDefault) {
break;
}
}
}
if (setDefault) {
arcObject.attributes[attribute] = attributeDefault.value;
break;
}
}
}
}
}
/**
* Transform observation attachments.
* @param {readonly Attachment[]} attachments The observation attachments.
* @param {{ [name: string]: number }} formIds Form ids map.
* @param {EventTransform} transform The Event transform.
* @returns {ArcAttachment[]} The converted ArcAttachments.
*/
attachments(attachments, formIds, transform) {
const arcAttachments = [];
const mageEvent = transform.mageEvent;
for (const attachment of attachments) {
if (attachment.contentLocator != null) {
let fieldName = attachment.fieldName;
if (mageEvent != null) {
const formId = formIds[attachment.observationFormId];
if (formId != null) {
const field = mageEvent.formFieldFor(fieldName, formId);
if (field != null) {
fieldName = field.title;
}
}
}
const arcAttachment = {};
arcAttachment.field = ObservationsTransformer.replaceSpaces(fieldName);
if (attachment.lastModified != null) {
arcAttachment.lastModified = new Date(attachment.lastModified).getTime();
}
if (attachment.size != null) {
arcAttachment.size = attachment.size;
}
if (attachment.name != null) {
const extensionIndex = attachment.name.lastIndexOf('.');
if (extensionIndex !== -1) {
arcAttachment.name = attachment.name.substring(0, extensionIndex);
}
else {
arcAttachment.name = attachment.name;
}
}
else {
arcAttachment.name = attachment.id;
}
arcAttachment.contentLocator = attachment.contentLocator;
arcAttachments.push(arcAttachment);
}
}
return arcAttachments;
}
/**
* Replace spaces in the name with underscores.
* @param {string} name The name.
* @returns {string} name with replaced spaces.
*/
static replaceSpaces(name) {
return name.replace(/ /g, '_');
}
/**
* Append a count to a name for additional duplicate field names.
* @param {string} name The name.
* @param {number} count The count.
* @returns {string} name with count.
*/
appendCount(name, count) {
let value = name;
if (count > 1) {
value += '_' + count;
}
return value;
}
/**
* Remove ArcObject attribute omissions.
* @param {ArcObject} arcObject The converted ArcObject.
*/
removeOmissions(arcObject) {
const attributes = arcObject.attributes;
const attributeKeys = Object.keys(attributes);
for (const omit of this._omit) {
const regex = new RegExp('^' + omit + '(_\\d+)?$');
const regexAttributes = attributeKeys.filter((name) => regex.test(name));
for (const attribute of regexAttributes) {
delete attributes[attribute];
}
}
}
}
exports.ObservationsTransformer = ObservationsTransformer;
//# sourceMappingURL=ObservationsTransformer.js.map