@ngageoint/mage.arcgis.service
Version:
A mage service plugin that synchronizes mage observations to a configured ArcGIS feature layer.
292 lines • 13.9 kB
JavaScript
"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