UNPKG

@ngageoint/mage.arcgis.service

Version:

A mage service plugin that synchronizes mage observations to a configured ArcGIS feature layer.

292 lines 13.9 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ObservationsSender = void 0; const env_1 = __importDefault(require("@ngageoint/mage.service/lib/environment/env")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const arcgis_rest_request_1 = require("@esri/arcgis-rest-request"); const arcgis_rest_feature_service_1 = require("@esri/arcgis-rest-feature-service"); /** * Class that transforms observations into a json string that can then be sent to an arcgis server. */ class ObservationsSender { /** * Constructor. * @param {LayerInfo} layerInfo The layer info. * @param {ArcGISPluginConfig} config The plugins configuration. * @param {ArcGISIdentityManager} identityManager The ArcGIS identity manager for authentication. * @param {Console} console Used to log to the console. */ constructor(layerInfo, config, identityManager, console) { this._url = layerInfo.url; this._console = console; this._attachmentDirectory = env_1.default.attachmentBaseDirectory; this._config = config; this._identityManager = identityManager; } /** * Converts the specified observations into a json string that can be sent to an arcgis server and * sends them to an arc server for adding. * @param {ArcObjects} observations The observations to convert. */ sendAdds(observations) { return __awaiter(this, void 0, void 0, function* () { this._console.info('ArcGIS addFeatures'); yield (0, arcgis_rest_feature_service_1.addFeatures)({ url: this._url, authentication: this._identityManager, features: observations.objects }).then(this.responseHandler(observations, false)) .catch((error) => this._console.error('Error in ObservationSender.sendAdds :: ' + error)); }); } /** * Converts the specified observations into a json string that can be sent to an arcgis server and * sends them to an arc server for updating. * @param {ArcObjects} observations The observations to convert. */ sendUpdates(observations) { return __awaiter(this, void 0, void 0, function* () { this._console.info('ArcGIS updateFeatures'); yield (0, arcgis_rest_feature_service_1.updateFeatures)({ url: this._url, authentication: this._identityManager, features: observations.objects }).then(this.responseHandler(observations, true)) .catch((error) => this._console.error('Error in ObservationSender.sendUpdates :: ' + error)); }); } /** * Delete an observation. * @param {number} id The observation id. */ sendDelete(id) { return __awaiter(this, void 0, void 0, function* () { this._console.info('ArcGIS deleteFeatures id: ' + id); yield (0, arcgis_rest_feature_service_1.deleteFeatures)({ url: this._url, authentication: this._identityManager, where: `${this._config.observationIdField} LIKE '%${id}%'`, objectIds: [] }).catch((error) => this._console.error('Error in ObservationSender.sendDelete :: ' + error)); }); } /** * Deletes all observations that are apart of a specified event. * @param {number} id The event id. */ sendDeleteEvent(id) { return __awaiter(this, void 0, void 0, function* () { this._console.info('ArcGIS deleteFeatures by event ' + this._config.observationIdField + ': ' + id); yield (0, arcgis_rest_feature_service_1.deleteFeatures)({ url: this._url, authentication: this._identityManager, where: this._config.eventIdField ? `${this._config.eventIdField} = ${id}` : `${this._config.observationIdField} LIKE '%${this._config.idSeparator + id}%'`, objectIds: [] }).catch((error) => this._console.error('Error in ObservationSender.sendDeleteEvent :: ' + error)); }); } /** * Creates an observation response handler. * @param {ArcObjects} observations The observations sent. * @param {boolean} update The update or add flag value. * @returns {(chunk: any) => void} The response handler. */ responseHandler(observations, update) { const console = this._console; return (chunk) => { console.log('ArcGIS ' + (update ? 'Update' : 'Add') + ' Response: ' + JSON.stringify(chunk)); const response = chunk; const results = response[update ? 'updateResults' : 'addResults']; if (results != null) { const obs = observations.observations; for (let i = 0; i < obs.length && i < results.length; i++) { const observation = obs[i]; const result = results[i]; if (result.success != null && result.success) { const objectId = result.objectId; if (objectId != null) { console.log((update ? 'Update' : 'Add') + ' Features Observation id: ' + observation.id + ', Object id: ' + objectId); if (update) { this.queryAndUpdateAttachments(observation, objectId); } else { this.sendAttachments(observation, objectId); } } } else if (result.error != null) { console.error('ArcGIS Error. Code: ' + result.error.code + ', Description: ' + result.error.description); } } } }; } /** * Send observation attachments. * @param {ArcObservation} observation The observation. * @param {number} objectId The arc object id of the observation. */ sendAttachments(observation, objectId) { if (observation.attachments != null) { for (const attachment of observation.attachments) { this.sendAttachment(attachment, objectId); } } } /** * Query for and update observation attachments. * @param {ArcObservation} observation The observation. * @param {number} objectId The arc object id of the observation. */ queryAndUpdateAttachments(observation, objectId) { // Query for existing attachments (0, arcgis_rest_feature_service_1.getAttachments)({ url: this._url, authentication: this._identityManager, featureId: objectId }).then((response) => { const result = response; this.updateAttachments(observation, objectId, result.attachmentInfos); }).catch((error) => this._console.error(error)); } /** * Update observation attachments. * @param {ArcObservation} observation The observation. * @param {number} objectId The arc object id of the observation. * @param {AttachmentInfo[]} attachmentInfos The arc attachment infos. */ updateAttachments(observation, objectId, attachmentInfos) { // Build a mapping between existing arc attachment names and the attachment infos const nameAttachments = new Map(); if (attachmentInfos != null) { for (const attachmentInfo of attachmentInfos) { nameAttachments.set(attachmentInfo.name, attachmentInfo); } } // Update existing attachments as needed and add new updated observation attachments if (observation.attachments != null) { for (const attachment of observation.attachments) { const fileName = this.attachmentFileName(attachment); const existingAttachment = nameAttachments.get(fileName); if (existingAttachment != null) { nameAttachments.delete(fileName); // Update the existing attachment if the file sizes do not match or last modified date updated if (attachment.size != existingAttachment.size || attachment.lastModified + this._config.attachmentModifiedTolerance >= observation.lastModified) { this.updateAttachment(attachment, objectId, existingAttachment.id); } } else { // Add the new attachment on the updated observation this.sendAttachment(attachment, objectId); } } } // Delete arc attachments that are no longer on the observation if (nameAttachments.size > 0) { this.deleteAttachments(objectId, Array.from(nameAttachments.values())); } } /** * Send an observation attachment. * @param {ArcAttachment} attachment The observation attachment. * @param {number} objectId The arc object id of the observation. */ sendAttachment(attachment, objectId) { return __awaiter(this, void 0, void 0, function* () { if (attachment.contentLocator) { const file = path_1.default.join(this._attachmentDirectory, attachment.contentLocator); const fileName = this.attachmentFileName(attachment); this._console.info('ArcGIS ' + arcgis_rest_request_1.request + ' file ' + fileName + ' from ' + file); const readStream = yield fs_1.default.openAsBlob(file); const attachmentFile = new File([readStream], fileName); (0, arcgis_rest_feature_service_1.addAttachment)({ url: this._url, authentication: this._identityManager, featureId: objectId, attachment: attachmentFile }).catch((error) => this._console.error(error)); } }); } /** * Update an observation attachment. * @param {ArcAttachment} attachment The observation attachment. * @param {number} objectId The arc object id of the observation. * @param {number} attachmentId The observation arc attachment id. */ updateAttachment(attachment, objectId, attachmentId) { return __awaiter(this, void 0, void 0, function* () { if (attachment.contentLocator) { const file = path_1.default.join(this._attachmentDirectory, attachment.contentLocator); const fileName = this.attachmentFileName(attachment); this._console.info('ArcGIS ' + arcgis_rest_request_1.request + ' file ' + fileName + ' from ' + file); const readStream = yield fs_1.default.openAsBlob(file); const attachmentFile = new File([readStream], fileName); (0, arcgis_rest_feature_service_1.updateAttachment)({ url: this._url, authentication: this._identityManager, featureId: objectId, attachmentId, attachment: attachmentFile }).catch((error) => this._console.error(error)); } }); } /** * Delete observation attachments. * @param {number} objectId The arc object id of the observation. * @param {AttachmentInfo[]} attachmentInfos The arc attachment infos. */ deleteAttachments(objectId, attachmentInfos) { const attachmentIds = []; for (const attachmentInfo of attachmentInfos) { attachmentIds.push(attachmentInfo.id); } this.deleteAttachmentIds(objectId, attachmentIds); } /** * Delete observation attachments by ids. * @param {number} objectId The arc object id of the observation. * @param {number[]} attachmentIds The arc attachment ids. */ deleteAttachmentIds(objectId, attachmentIds) { this._console.info('ArcGIS deleteAttachments ' + attachmentIds); (0, arcgis_rest_feature_service_1.deleteAttachments)({ url: this._url, authentication: this._identityManager, featureId: objectId, attachmentIds }).catch((error) => this._console.error(error)); } /** * Determine the attachment file name. * @param {ArcAttachment} attachment The observation attachment. * @returns {string} attachment file name. */ attachmentFileName(attachment) { let fileName = attachment.field + "_" + attachment.name; const extensionIndex = attachment.contentLocator.lastIndexOf('.'); if (extensionIndex != -1) { fileName += attachment.contentLocator.substring(extensionIndex); } return fileName; } } exports.ObservationsSender = ObservationsSender; //# sourceMappingURL=ObservationsSender.js.map