Summary Table

Categories Total Count
PII 0
URL 1
DNS 0
EKL 0
IP 0
PORT 0
VsID 0
CF 0
AI 0
VPD 0
PL 0
Other 0

File Content

define(['angular', 'app', 'lodash', 'localResourceDirectoryService', 'authentication_service'], function(angular, app, _) {
"use strict";
app.service('fhirResources', function($http, $q, $timeout, localResourceDirectoryService, authenticationService) {

var META_PROVENANCE_SYSTEM_KEY = "https://
URL /display/PGDMS/Client+Provenance+Mapping";
var META_PROVENANCE_APP_UUID = "f6879a68-49da-490b-a964-b6899ab4cd6b";
var META_PROVENANCE_APP_DISPLAY = "My VA Images";
var provenanceTag = {
"system": META_PROVENANCE_SYSTEM_KEY,
"code": META_PROVENANCE_APP_UUID,
"display": META_PROVENANCE_APP_DISPLAY
};

var fhirBaseUrl = '';
var fhirResources = {};

var practitionerReqs = [];
var locationReqs = [];
var fhirResourceReqs = [];

fhirResources.getSystem = function(){
return META_PROVENANCE_SYSTEM_KEY;
};

fhirResources.getFhirBaseUrl = function(){
return fhirBaseUrl
};


/**
* The appendProvenanceMetadata() function provides the meta.tag for FHIR resources when data is from My VA Images app
*
* @param data
*/
fhirResources.appendProvenanceMetadata = function(data) {
if (!data.meta) {
data.meta = {tag: []};
} else if (!data.meta.tag) {
data.meta.tag = [];
}
var provenanceIndex = _.findIndex(data.meta.tag, function(item) {
return item["system"] == META_PROVENANCE_SYSTEM_KEY;
});
if (provenanceIndex >= 0) { //update provenance if an entry already exists
data.meta.tag[provenanceIndex] = provenanceTag;
}
else {
data.meta.tag.push(provenanceTag);
}
//Need to delete this meta portion to avoid FHIR server error when updating a resource
delete data.meta.lastUpdated;
delete data.meta.profile;
delete data.meta.versionId;
};

/**
* The resolveFhirResourceByReference() service function intends to retrieve the reference data from FHIR resource.
*
* @param reference: <Resource Name>/<id #>
* return <Resource Data>
*/
fhirResources.resolveFhirResourceByReference = function(reference) {
if (fhirResourceReqs[reference]) return fhirResourceReqs[reference].promise;

var fhirResourcePromise = $q.defer();
$q.all([localResourceDirectoryService.fetch(), authenticationService.checkAuthStatus()]).then(
function(response) {
if (response[1]) {
fhirBaseUrl = response[0]['fhir-baseUrl'];
$http.get(response[0]['fhir-baseUrl'] + "/" + reference).then(function(response1) {
fhirResourcePromise.resolve(response1.data);
});
fhirResourceReqs[reference] = fhirResourcePromise;
}
},
function(error) {
fhirResourcePromise.reject(error);
fhirResourcePromise = null;
}
);
return fhirResourcePromise.promise;
};

/**
* The deleteFhirResourceByReference() service function intends to delete reference data from FHIR resource
*
* @param reference: <Resource Name>/<id #> [,data]
* note: here data param is optional. if data is not empty, do PUT first and then DELETE
* return <OperationOutcome>
*/
fhirResources.deleteFhirResourceByReference = function(reference, data) {
var fhirResourcePromise = $q.defer(),
fhirResourcePromises = [];

function updateFhirResource() {
var refs = $q.defer();

fhirResources.createUpdateFhirResource({method: "PUT", resourceName: reference, data: data}).then(
function(response) {
refs.resolve(response);
}, function(error) {
refs.reject(error);
});
return refs.promise;
};

function deleteFhirResource() {
$q.all([localResourceDirectoryService.fetch(), authenticationService.checkAuthStatus()]).then(
function(response) {
if (response[1]) {
$http.delete(response[0]['fhir-baseUrl'] + "/" + reference).then(function(response1) {
fhirResourcePromise.resolve(response1);
}, function(error) {
fhirResourcePromise.reject(error);
});
}
},
function(error) {
fhirResourcePromise.reject(error);
}
);
return fhirResourcePromise.promise;
};

if (!reference) return fhirResourcePromise.promise;

if (fhirResourceReqs[reference]) {
fhirResourceReqs.splice(fhirResourceReqs.indexOf(reference), 1);
fhirResourceReqs[reference] = null;
}

if (data) fhirResourcePromises.push(updateFhirResource);
fhirResourcePromises.push(deleteFhirResource);

fhirResources.serialRequestCalls(fhirResourcePromises);

return fhirResourcePromise.promise;
};

/**
* The resolveFhirResourceByParams() service function intends to retrieve all the data entries
* from given FHIR resourceName along with params.
*
* @param resourceName, params
* return <Resource Data List>
*/
fhirResources.resolveFhirResourceByParams = function(resourceName, params) {
var attachSuffix = function(paramsObj, suffixStr) {
if (!paramsObj || !suffixStr || (paramsObj === {})) return paramsObj;

var tParams = {};
angular.forEach(Object.keys(paramsObj), function(elem) {
tParams[elem+suffixStr] = paramsObj[elem];
});
return tParams;
};

var fhirResourcePromise = $q.defer();
$q.all([localResourceDirectoryService.fetch(), authenticationService.checkAuthStatus()]).then(
function(response) {
if (response[1]) { //given a successful auth check and local resource directory fetch
fhirBaseUrl = response[0]['fhir-baseUrl'];
var httpConfig = {
method: 'GET',
url: fhirBaseUrl + "/" + resourceName,
params: attachSuffix(params, "")
};
$http(httpConfig).then(function(response1) {
if (response1.data.total > 0) {
fhirResourcePromise.resolve(response1.data.entry);
//ToDo: need to handle FHIR server pagination here (because of _count=10 by default, maximum=100)
}
else {
fhirResourcePromise.resolve(0);
}
});
}
},
function(error) {
fhirResourcePromise.reject(error);
fhirResourcePromise = null;
}
);
return fhirResourcePromise.promise;
};

/**
* The createUpdateFhirResource() service function intends to post/put data into designated FHIR resource.
* If succeeded, the posted/put data entry will be returned.
*
* @param resourceConfig : {method, resourceName, data}
* note: for method=POST, resourceName = <Resource Name>; for method=PUT, resourceName = <Resource Name/id #>
* return {Resource Name/id #}
*/
fhirResources.createUpdateFhirResource = function(resourceConfig) {
var fhirResourcePromise = $q.defer();

$q.all([localResourceDirectoryService.fetch(), authenticationService.checkAuthStatus()]).then(
function(response) {
if (response[1]) {
fhirBaseUrl = response[0]['fhir-baseUrl'];
if (typeof (resourceConfig.data) === 'object') {
fhirResources.appendProvenanceMetadata(resourceConfig.data);
}

var httpConfig = {
method: resourceConfig.method,
url: fhirBaseUrl + "/" + resourceConfig.resourceName,
data: resourceConfig.data
};
$http(httpConfig).then(
function(response) {
if (resourceConfig.method === "POST") {
httpConfig.url = resourceConfig.resourceName + "/" +
response.headers('Location').split(resourceConfig.resourceName)[1].split("/")[1];
fhirResourcePromise.resolve(httpConfig.url);
}
else if (resourceConfig.method === "PUT") {
if (fhirResourceReqs[resourceConfig.resourceName]) {
fhirResourceReqs.splice(fhirResourceReqs.indexOf(resourceConfig.resourceName), 1);
fhirResourceReqs[resourceConfig.resourceName] = null;
}
fhirResourcePromise.resolve(resourceConfig.resourceName);
}
//ToDo: need to implement code for PATCH
},
function(error) {
fhirResourcePromise.reject(error);
}
);
}
}
);
return fhirResourcePromise.promise;
};

fhirResources.createFhirResource = function(resourceName, data) {
var fhirResourcePromise = $q.defer();

var httpConfig = {
method: "POST",
resourceName: resourceName,
data: data
};
fhirResources.createUpdateFhirResource(httpConfig).then(
function(response) {
fhirResourcePromise.resolve(response);
}, function(error) {
fhirResourcePromise.reject(error);
}
);

return fhirResourcePromise.promise;
};

/**
* The resolveFhirResource() service function intends to search for an existing entry from FHIR resource.
* If found, the first matched entry is returned. If nothing is found, a new data entry is posted.
*
* @param resourceName, data, params [,otherParams]
* return {Resource Name/id #}
*/
fhirResources.resolveFhirResource = function(resourceName, data, params) {
var fhirResourcePromise = $q.defer();

function searchFhirResource() {
var refs = $q.defer();

fhirResources.resolveFhirResourceByParams(resourceName, params).then(
function(response) {
refs.resolve(response);
}, function(error) {
refs.reject(error);
});
return refs.promise;
}

function matchResource(responseItem) {
if (!responseItem) { //if no entry is found, create new one
fhirResources.createFhirResource(resourceName, data).then(
function(response) {
fhirResourcePromise.resolve(response);
}, function(error) {
fhirResourcePromise.reject(error);
});
}
else { //Otherwise, return the first matched entry
fhirResourcePromise.resolve(responseItem[0].resource.resourceType + "/" + responseItem[0].resource.id);
//TODO: need to implement a comparator for other params FHIR server does not support
}
return fhirResourcePromise.promise;
}

fhirResources.serialRequestCalls([searchFhirResource, matchResource]);

return fhirResourcePromise.promise;
};

fhirResources.serialRequestCalls = function(calls) {
var prevCallPromise = null;
angular.forEach(calls, function(call) {
if (!prevCallPromise) { //For the first call()
prevCallPromise = call();
}
else {
prevCallPromise = prevCallPromise.then(call);
}
});
return prevCallPromise;
};

return fhirResources;
});
});