"use strict"; /* exported logger */ var Promise = require("bluebird"); var logger = require('./logger'); var request = require('request'); var HttpStatus = require('http-status-codes'); var Alias = require('./map/data/Alias'); var Annotation = require('./map/data/Annotation'); var Chemical = require('./map/data/Chemical'); var Comment = require('./map/data/Comment'); var Configuration = require('./Configuration'); var Drug = require('./map/data/Drug'); var ConfigurationType = require('./ConfigurationType'); var IdentifiedElement = require('./map/data/IdentifiedElement'); var InvalidCredentialsError = require('./InvalidCredentialsError'); var LayoutAlias = require('./map/data/LayoutAlias'); var LayoutData = require('./map/data/LayoutData'); var LayoutReaction = require('./map/data/LayoutReaction'); var MapModel = require('./map/data/MapModel'); var Mesh = require('./map/data/Mesh'); var MiRna = require('./map/data/MiRna'); var NetworkError = require('./NetworkError'); var Project = require('./map/data/Project'); var ProjectStatistics = require('./map/data/ProjectStatistics'); var Reaction = require('./map/data/Reaction'); var ReferenceGenome = require('./map/data/ReferenceGenome'); var SbmlFunction = require('./map/data/SbmlFunction'); var SbmlParameter = require('./map/data/SbmlParameter'); var SecurityError = require('./SecurityError'); var SessionData = require('./SessionData'); var User = require('./map/data/User'); var GuiConnector = require('./GuiConnector'); var ObjectWithListeners = require('./ObjectWithListeners'); /** * This object contains methods that will communicate with server. */ var ServerConnector = new ObjectWithListeners(); ServerConnector.init = function () { var self = this; self._configurationParam = []; self._projects = []; self._projectsById = []; self._users = []; self._usersByLogin = []; self._customMap = null; self._sessionData = undefined; self._configuration = undefined; self._loggedUser = undefined; self._serverBaseUrl = undefined; var i; var listeners = self.getListeners("onDataLoadStart"); for (i = 0; i < listeners.length; i++) { self.removeListener("onDataLoadStart", listeners[i]); } listeners = self.getListeners("onDataLoadStop"); for (i = 0; i < listeners.length; i++) { self.removeListener("onDataLoadStop", listeners[i]); } }; ServerConnector.registerListenerType("onDataLoadStart"); ServerConnector.registerListenerType("onDataLoadStop"); ServerConnector.init(); ServerConnector.getMinOverlayColorInt = function () { var self = this; return self.getLoggedUser().then(function (user) { var userColor = user.getMinColor(); return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.MIN_COLOR_VAL)); }); }; ServerConnector.returnUserOrSystemColor = function (userColor, systemPromisedColor) { return systemPromisedColor.then(function (systemColor) { var color = userColor; if (userColor === null || userColor === undefined || userColor === "") { color = systemColor; } color = parseInt(color, 16); /* jslint bitwise: true */ color = (color & 0xFFFFFF); return color; }); }; ServerConnector.getSimpleOverlayColorInt = function () { var self = this; return self.getLoggedUser().then(function (user) { var userColor = user.getSimpleColor(); return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.SIMPLE_COLOR_VAL)); }); }; ServerConnector.getMaxOverlayColorInt = function () { var self = this; return self.getLoggedUser().then(function (user) { var userColor = user.getMaxColor(); return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.MAX_COLOR_VAL)); }); }; ServerConnector.getNeutralOverlayColorInt = function () { var self = this; return self.getLoggedUser().then(function (user) { var userColor = user.getNeutralColor(); return self.returnUserOrSystemColor(userColor, self.getConfigurationParam(ConfigurationType.NEUTRAL_COLOR_VAL)); }); }; ServerConnector.sendGetRequest = function (url, description) { return this.sendRequest({ url: url, description: description, method: "GET" }); }; ServerConnector.sendRequest = function (params) { var self = this; if (arguments.length > 1) { return Promise.reject(new Error("Only two arguments are supported")); } if (self.getSessionData().getToken() === undefined) { self.getSessionData().setLogin(undefined); window.location.reload(false); } var description = params.url; if (params.description !== undefined) { description = params.description; params.description = undefined; } var content; return self.callListeners("onDataLoadStart", description).then(function () { return self._sendRequest(params); }).then(function (result) { content = result; return self.callListeners("onDataLoadStop", description); }, function (error) { return self.callListeners("onDataLoadStop", description).then(function () { return Promise.reject(error); }); }).then(function () { return content; }, function (error) { if (error instanceof NetworkError) { if (error.statusCode === HttpStatus.FORBIDDEN && error.content.indexOf('"reason":"Invalid token"') >= 0) { self.getSessionData().setToken(undefined); if (self.getSessionData().getLogin() === "anonymous") { window.location.reload(false); } else { window.location.href = ServerConnector.getServerBaseUrl() + "login.xhtml?from=" + encodeURI(window.location.href); } } } return Promise.reject(error); }); }; ServerConnector._sendRequest = function (params) { return new Promise(function (resolve, reject) { request(params, function (error, response, body) { if (error) { reject(new NetworkError(error.message, { content: body, url: params.url })); } else if (response.statusCode !== 200) { reject(new NetworkError(params.url + " rejected with status code: " + response.statusCode, { content: body, url: params.url, statusCode: response.statusCode })); } else { // for some reason sometimes result is an object not a string if (typeof body === 'string' || body instanceof String) { resolve(body); } else { resolve(JSON.stringify(body)); } } }); }); }; ServerConnector.sendPostRequest = function (url, params) { return this.sendRequest({ method: "POST", url: url, form: params }); }; ServerConnector.sendDeleteRequest = function (url, json) { return this.sendRequest({ method: "DELETE", url: url, json: json }); }; ServerConnector.sendPatchRequest = function (url, json) { return this.sendRequest({ method: "PATCH", url: url, json: json }); }; ServerConnector.getToken = function () { var self = this; var login = self.getSessionData(null).getLogin(); var token = self.getSessionData(null).getToken(); if (token === undefined || login === undefined) { return self.login(); } else { // if the project is not initialized then check if we can download data // using current token if (self.getSessionData().getProject() === null) { return self.getConfiguration().then(function () { return token; // if there was an error accessing configuration it means our token is // invalid }, function () { return self.login(); }); } else { return Promise.resolve(token); } } }; ServerConnector.getApiBaseUrl = function () { return this.getServerBaseUrl() + "/api/"; }; ServerConnector.getServerBaseUrl = function () { if (this._serverBaseUrl === undefined) { var url = "" + window.location.href; if (url.indexOf("?") >= 0) { url = url.substr(0, url.indexOf("?")); } if (!url.endsWith("/")) { url = url.substr(0, url.lastIndexOf("/") + 1); } this._serverBaseUrl = url; } return this._serverBaseUrl; }; ServerConnector.createGetParams = function (params, prefix) { var sorted = [], key; for (key in params) { if (params.hasOwnProperty(key)) { sorted.push(key); } } sorted.sort(); var result = ""; for (var i = 0; i < sorted.length; i++) { key = sorted[i]; var value = params[key]; if (prefix !== undefined) { key = prefix + "." + key; } if (value instanceof google.maps.Point) { value = this.pointToString(value); } else if (Object.prototype.toString.call(value) === '[object Array]') { value = this.idsToString(value); } else if (typeof value === 'string' || value instanceof String || !isNaN(value)) { } else { result += this.createGetParams(value, key); value = undefined; } if (value !== undefined && value !== "") { result += key + "=" + value + "&"; } } return result; }; ServerConnector.getApiUrl = function (paramObj) { var type = paramObj.type; var params = this.createGetParams(paramObj.params); var result = paramObj.url; if (result === undefined) { result = this.getApiBaseUrl() + "/" + type; } if (params !== "") { result += "?" + params; } return result; }; ServerConnector.getProjectsUrl = function (queryParams, filterParams) { return this.getApiUrl({ type: "projects/", params: filterParams }); }; ServerConnector.getProjectUrl = function (queryParams, filterParams) { var id = this.getIdOrAsterisk(queryParams.projectId); return this.getApiUrl({ url: this.getProjectsUrl(queryParams) + id + "/", params: filterParams }); }; ServerConnector.getProjectStatisticsUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "statistics/", params: filterParams }); }; ServerConnector.getPublicationsUrl = function (queryParams, filterParams) { filterParams.start = filterParams.start || 0; filterParams.length = filterParams.length || 10; return this.getApiUrl({ url: this.getModelsUrl(queryParams) + "publications/", params: filterParams }); }; ServerConnector.getProjectLogsUrl = function (queryParams, filterParams) { filterParams.start = filterParams.start || 0; filterParams.length = filterParams.length || 10; return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "logs/", params: filterParams }); }; ServerConnector.getMeshUrl = function (queryParams, filterParams) { return this.getApiUrl({ type: "mesh/" + queryParams.id, params: filterParams }); }; ServerConnector.getSbmlFunctionUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getModelsUrl(queryParams) + "functions/" + queryParams.functionId, params: filterParams }); }; ServerConnector.getSbmlParameterUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getModelsUrl(queryParams) + "parameters/" + queryParams.parameterId, params: filterParams }); }; ServerConnector.getReferenceGenomeUrl = function (queryParams, filterParams) { var version = this.getIdOrAsterisk(queryParams.version); return this.getApiUrl({ type: "genomics/taxonomies/" + queryParams.organism + "/genomeTypes/" + queryParams.type + "/versions/" + version + "/", params: filterParams }); }; ServerConnector.loginUrl = function () { return this.getApiUrl({ type: "/doLogin" }); }; ServerConnector.logoutUrl = function () { return this.getApiUrl({ type: "/doLogout" }); }; ServerConnector.getSuggestedQueryListUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getBioEntitiesUrl(queryParams) + "suggestedQueryList/", params: filterParams }); }; ServerConnector.getChemicalSuggestedQueryListUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "chemicals/suggestedQueryList", params: filterParams }); }; ServerConnector.getDrugSuggestedQueryListUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "drugs/suggestedQueryList", params: filterParams }); }; ServerConnector.getMiRnaSuggestedQueryListUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "miRnas/suggestedQueryList", params: filterParams }); }; ServerConnector.addCommentUrl = function (queryParams) { return this.getApiUrl({ url: this.getCommentsUrl(queryParams) }); }; ServerConnector.addOverlayUrl = function (queryParams) { return this.getApiUrl({ url: this.getOverlaysUrl(queryParams) }); }; ServerConnector.updateOverlayUrl = function (queryParams) { return this.getApiUrl({ url: this.getOverlayByIdUrl(queryParams) }); }; ServerConnector.updateModelUrl = function (queryParams) { return this.getApiUrl({ url: this.getModelsUrl(queryParams) }); }; ServerConnector.deleteOverlayUrl = function (queryParams) { return this.getApiUrl({ url: this.getOverlayByIdUrl(queryParams) }); }; ServerConnector.deleteCommentUrl = function (queryParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "comments/" + queryParams.commentId + "/" }); }; ServerConnector.getOverlaysUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "overlays/", params: filterParams }); }; ServerConnector.getCommentsUrl = function (queryParams, filterParams) { var modelId = this.getIdOrAsterisk(queryParams.modelId); var url = this.getProjectUrl(queryParams) + "comments/models/" + modelId + "/"; if (queryParams.elementType !== undefined) { if (queryParams.elementType === "ALIAS") { url += "bioEntities/elements/" + queryParams.elementId; } else if (queryParams.elementType === "REACTION") { url += "bioEntities/reactions/" + queryParams.elementId; } else if (queryParams.elementType === "POINT") { url += "points/" + queryParams.coordinates; } else { throw new Error("Unknown element type: " + queryParams.elementType); } } return this.getApiUrl({ url: url, params: filterParams }); }; ServerConnector.getOverlayByIdUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getOverlaysUrl(queryParams) + queryParams.overlayId + "/", params: filterParams }); }; ServerConnector.getOverlayElementsUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getModelsUrl(queryParams) + "bioEntities/", params: filterParams }); }; ServerConnector.getFullOverlayElementUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getAliasesUrl(queryParams) + queryParams.id + "/", params: filterParams }); }; ServerConnector.idsToString = function (ids) { var result = ""; if (ids !== undefined) { ids.sort(function (a, b) { if (typeof a === "string") { return a.localeCompare(b); } else { return a - b; } }); for (var i = 0; i < ids.length; i++) { if (result !== "") { if (ids[i - 1] !== ids[i]) { result = result + "," + ids[i]; } // we ignore duplicates } else { result = ids[i]; } } } return result; }; ServerConnector.pointToString = function (point) { return point.x.toFixed(2) + "," + point.y.toFixed(2); }; ServerConnector.getModelsUrl = function (queryParams) { var modelId = this.getIdOrAsterisk(queryParams.modelId); var overlayId = queryParams.overlayId; var url = this.getProjectUrl(queryParams); if (overlayId !== undefined) { url = this.getOverlayByIdUrl(queryParams); } return this.getApiUrl({ url: url + "models/" + modelId + "/" }); }; ServerConnector.getBioEntitiesUrl = function (queryParams) { return this.getApiUrl({ url: this.getModelsUrl(queryParams) + "bioEntities/" }); }; ServerConnector.getIdOrAsterisk = function (id) { if (id === undefined || id === "" || id === null) { return "*"; } else { return id; } }; ServerConnector.getReactionsUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getBioEntitiesUrl(queryParams) + "reactions/", params: filterParams }); }; ServerConnector.getAliasesUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getBioEntitiesUrl(queryParams) + "elements/", params: filterParams }); }; ServerConnector.getConfigurationUrl = function (queryParams, filterParams) { return this.getApiUrl({ type: "configuration/", params: filterParams }); }; ServerConnector.getConfigurationOptionUrl = function (queryParams, filterParams) { var self = this; return self.getApiUrl({ url: self.getConfigurationUrl() + "options/" + queryParams.type, params: filterParams }); }; ServerConnector.getSearchUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getModelsUrl(queryParams) + "bioEntities:search", params: filterParams }); }; ServerConnector.getSearchDrugsUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "drugs:search", params: filterParams }); }; ServerConnector.getSearchMiRnasUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "miRnas:search", params: filterParams }); }; ServerConnector.getSearchChemicalsUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "chemicals:search", params: filterParams }); }; ServerConnector.getOverlaySourceUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getOverlaysUrl(queryParams) + queryParams.overlayId + ":downloadSource", params: filterParams }); }; ServerConnector.getImageUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "models/" + queryParams.modelId + ":downloadImage", params: filterParams }); }; ServerConnector.getModelPartUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getProjectUrl(queryParams) + "models/" + queryParams.modelId + ":downloadModel", params: filterParams }); }; ServerConnector.getProjectSourceUrl = function (queryParams, filterParams) { return this.getApiUrl({ type: "projects/" + queryParams.projectId + ":downloadSource", params: filterParams }); }; ServerConnector.getFilesUrl = function () { return this.getApiUrl({ type: "files/" }); }; ServerConnector.getCreateFileUrl = function () { return this.getApiUrl({ url: this.getFilesUrl() }); }; ServerConnector.getFileUrl = function (queryParams) { return this.getApiUrl({ url: this.getFilesUrl() + "/" + queryParams.id }); }; ServerConnector.getUploadFileUrl = function (queryParams) { return this.getApiUrl({ url: this.getFileUrl(queryParams) + ":uploadContent" }); }; ServerConnector.getUsersUrl = function (queryParams, filterParams) { return this.getApiUrl({ type: "users/", params: filterParams }); }; ServerConnector.getUserUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getUsersUrl() + queryParams.login, params: filterParams }); }; ServerConnector.getUpdateUserPrivilegesUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getUserUrl(queryParams) + ":updatePrivileges", params: filterParams }); }; ServerConnector.getUpdateUserPreferencesUrl = function (queryParams, filterParams) { return this.getApiUrl({ url: this.getUserUrl(queryParams) + ":updatePreferences", params: filterParams }); }; ServerConnector.getConfiguration = function () { var self = this; if (this._configuration === undefined) { return self.sendGetRequest(self.getConfigurationUrl()).then(function (content) { self._configuration = new Configuration(JSON.parse(content)); return Promise.resolve(self._configuration); }); } else { return Promise.resolve(self._configuration); } }; ServerConnector.getConfigurationParam = function (paramId) { if (paramId === undefined) { return Promise.reject(new Error("Unknown param type")); } var self = this; return self.getConfiguration().then(function (configuration) { var option = configuration.getOption(paramId); if (option.getValue !== undefined) { return option.getValue(); } else { return option; } }); }; ServerConnector.updateConfigurationOption = function (option) { var self = this; var queryParams = { type: option.getType() }; var filterParams = { option: { type: option.getType(), value: option.getValue() } }; return self.sendPatchRequest(self.getConfigurationOptionUrl(queryParams), filterParams); }; ServerConnector.getModels = function (projectId) { var queryParams = {}; var filterParams = {}; var self = this; return self.getProjectId(projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getModelsUrl(queryParams, filterParams)); }).then(function (content) { var models = []; var parsedJson = JSON.parse(content); for (var i = 0; i < parsedJson.length; i++) { models.push(new MapModel(parsedJson[i])); } return models; }); }; ServerConnector.getProject = function (projectId) { var queryParams = {}; var filterParams = {}; var project; var self = this; return self.getProjectId(projectId).then(function (result) { projectId = result; queryParams.projectId = result; return self.sendGetRequest(self.getProjectUrl(queryParams, filterParams)); }).then(function (content) { var downloadedProject = new Project(content); if (self._projectsById[projectId] !== undefined) { self._projectsById[projectId].update(downloadedProject); } else { self._projectsById[projectId] = downloadedProject; } project = self._projectsById[projectId]; return self.getModels(projectId); }).then(function (models) { project.setModel(models[0]); return self.getLoggedUser(); }).then(function (user) { return self.getOverlays({ projectId: projectId, creator: user.getLogin(), publicOverlay: false }); }).then(function (overlays) { if (project.getModel() !== undefined) { project.getModel().addLayouts(overlays); } else { if (overlays.length > 0) { logger.warn("Cannot add overlays to the project: " + project.getProjectId()); } } return project; }).then(null, function (error) { if ((error instanceof NetworkError)) { switch (error.statusCode) { case HttpStatus.NOT_FOUND: return null; case HttpStatus.FORBIDDEN: return Promise.reject(new SecurityError("Access denied.")); default: return Promise.reject(error); } } else { return Promise.reject(error); } }); }; ServerConnector.updateProject = function (project) { var self = this; var queryParams = { projectId: project.getProjectId() }; var filterParams = { project: { name: project.getName(), version: project.getVersion(), notifyEmail: project.getNotifyEmail(), organism: self.serialize(project.getOrganism()), disease: self.serialize(project.getDisease()) } }; return self.sendPatchRequest(self.getProjectUrl(queryParams), filterParams).then(function (content) { var downloadedProject = new Project(content); project.update(downloadedProject); return project; }).then(null, function (error) { if ((error instanceof NetworkError)) { switch (error.statusCode) { case HttpStatus.FORBIDDEN: return Promise.reject(new SecurityError("Access denied.")); default: return Promise.reject(error); } } else { return Promise.reject(error); } }); }; ServerConnector.removeProject = function (projectId) { var self = this; var queryParams = { projectId: projectId }; return self.sendDeleteRequest(self.getProjectUrl(queryParams)).then(function (content) { var project = new Project(content); if (self._projectsById[project.getProjectId()] !== undefined) { self._projectsById[project.getProjectId()].update(project); } else { self._projectsById[project.getProjectId()] = project; } return self._projectsById[project.getProjectId()]; }).then(null, function (error) { if ((error instanceof NetworkError)) { switch (error.statusCode) { case HttpStatus.FORBIDDEN: return Promise.reject(new SecurityError("Access denied.")); default: return Promise.reject(error); } } else { return Promise.reject(error); } }); }; ServerConnector.addProject = function (options) { var self = this; var queryParams = { projectId: options.projectId }; return self.sendPostRequest(self.getProjectUrl(queryParams), options).then(function (content) { var project = new Project(content); if (self._projectsById[project.getProjectId()] !== undefined) { self._projectsById[project.getProjectId()].update(project); } else { self._projectsById[project.getProjectId()] = project; } return project; }).then(null, function (error) { if ((error instanceof NetworkError)) { switch (error.statusCode) { case HttpStatus.FORBIDDEN: return Promise.reject(new SecurityError("Access denied.")); default: return Promise.reject(error); } } else { return Promise.reject(error); } }); }; ServerConnector.serialize = function (object) { var result = {}; if (object instanceof Annotation) { result.type = object.getType(); result.resource = object.getResource(); } else if (object === undefined) { result = undefined; } else { throw new Error("Unhandled object type: " + (typeof object)); } return result; }; ServerConnector.getProjects = function (reload) { var self = this; if (self._projects.length > 0 && !reload) { return Promise.resolve(self._projects); } else { return self.sendGetRequest(self.getProjectsUrl()).then(function (content) { var parsedData = JSON.parse(content); self._projects.length = 0; for (var i = 0; i < parsedData.length; i++) { var project = new Project(JSON.stringify(parsedData[i])); if (self._projectsById[project.getProjectId()] !== undefined) { self._projectsById[project.getProjectId()].update(project); } else { self._projectsById[project.getProjectId()] = project; } self._projects.push(self._projectsById[project.getProjectId()]); } return self._projects; }); } }; ServerConnector.getProjectStatistics = function (projectId) { var queryParams = {}; var filterParams = {}; var self = this; var content; return self.getProjectId(projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getProjectStatisticsUrl(queryParams, filterParams)); }).then(function (result) { content = JSON.parse(result); return self.getConfiguration(); }).then(function (configuration) { return new ProjectStatistics(content, configuration); }); }; ServerConnector.getLoggedUser = function () { var self = this; if (self._loggedUser !== undefined) { return Promise.resolve(self._loggedUser); } else { return self.getUser(self.getSessionData().getLogin()).then(function (user) { self._loggedUser = user; return self._loggedUser; }); } }; ServerConnector.getUser = function (login) { var self = this; var queryParams = { login: login }; var filterParams = {}; return self.sendGetRequest(self.getUserUrl(queryParams, filterParams)).then(function (content) { var obj = JSON.parse(content); var user = new User(obj); if (self._usersByLogin[user.getLogin()] !== undefined) { self._usersByLogin[user.getLogin()].update(user); } else { self._usersByLogin[user.getLogin()] = user; } return self._usersByLogin[user.getLogin()]; }).then(null, function (error) { return self.processNetworkError(error); }); }; ServerConnector.updateUser = function (user) { var self = this; var queryParams = { login: user.getLogin() }; var filterParams = { user: { name: user.getName(), surname: user.getSurname(), password: user.getPassword(), email: user.getEmail() } }; return self.sendPatchRequest(self.getUserUrl(queryParams), filterParams).then(function () { return self.getConfiguration(); }).then(function (configuration) { return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)}); }); }; ServerConnector.addUser = function (user) { var self = this; var queryParams = { login: user.getLogin() }; var filterParams = { login: user.getLogin(), name: user.getName(), surname: user.getSurname(), password: user.getPassword(), email: user.getEmail() }; return self.sendPostRequest(self.getUserUrl(queryParams), filterParams).then(function () { return self.getConfiguration(); }).then(function (configuration) { return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)}); }); }; ServerConnector.removeUser = function (login) { var self = this; var queryParams = { login: login }; return self.sendDeleteRequest(self.getUserUrl(queryParams)); }; ServerConnector.updateUserPrivileges = function (params) { var self = this; var queryParams = { login: params.user.getLogin() }; return self.sendPatchRequest(self.getUpdateUserPrivilegesUrl(queryParams), { privileges: params.privileges }).then(function (content) { var obj = JSON.parse(content); var user = new User(obj); if (self._usersByLogin[user.getLogin()] !== undefined) { self._usersByLogin[user.getLogin()].update(user); } else { self._usersByLogin[user.getLogin()] = user; } return self._usersByLogin[user.getLogin()]; }).then(null, function (error) { return self.processNetworkError(error); }); }; ServerConnector.processNetworkError = function (error) { if ((error instanceof NetworkError)) { switch (error.statusCode) { case HttpStatus.NOT_FOUND: return null; case HttpStatus.FORBIDDEN: return Promise.reject(new SecurityError("Access denied.")); default: return Promise.reject(error); } } else { return Promise.reject(error); } }; ServerConnector.updateUserPreferences = function (params) { var self = this; var queryParams = { login: params.user.getLogin() }; return self.sendPatchRequest(self.getUpdateUserPreferencesUrl(queryParams), { preferences: params.preferences.toExport() }).then(function (content) { var obj = JSON.parse(content); var user = new User(obj); if (self._usersByLogin[user.getLogin()] !== undefined) { self._usersByLogin[user.getLogin()].update(user); } else { self._usersByLogin[user.getLogin()] = user; } return self._usersByLogin[user.getLogin()]; }); }; ServerConnector.getUsers = function (forceRefresh) { var self = this; if (self._users.length > 0 && !forceRefresh) { return Promise.resolve(self._users); } else { return self.sendGetRequest(self.getUsersUrl()).then(function (content) { var parsedData = JSON.parse(content); self._users.length = 0; for (var i = 0; i < parsedData.length; i++) { var user = new User(parsedData[i]); if (self._usersByLogin[user.getLogin()] !== undefined) { self._usersByLogin[user.getLogin()].update(user); } else { self._usersByLogin[user.getLogin()] = user; } self._users.push(self._usersByLogin[user.getLogin()]); } return self._users; }).then(null, function (error) { return self.processNetworkError(error); }); } }; ServerConnector.getOverlays = function (params) { var self = this; if (params === undefined) { params = {}; } var queryParams = {}; var filterParams = { creator: params.creator, publicOverlay: params.publicOverlay }; return new Promise(function (resolve, reject) { self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getOverlaysUrl(queryParams, filterParams)); }).then(function (content) { var arr = JSON.parse(content); var result = []; for (var i = 0; i < arr.length; i++) { var overlay = new LayoutData(arr[i]); result.push(overlay); } resolve(result); }, reject); }); }; ServerConnector.getOverlayElements = function (overlayId, projectId) { var self = this; if (overlayId === undefined) { throw new Error("Layout id must be defined"); } var queryParams = { overlayId: overlayId, modelId: "*" }; var filterParams = {}; return self.getProjectId(projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getOverlayElementsUrl(queryParams, filterParams)); }).then(function (content) { var arr = JSON.parse(content); var result = []; for (var i = 0; i < arr.length; i++) { var element = arr[i]; if (element.type === "REACTION") { result.push(new LayoutReaction(element.overlayContent)); } else if (element.type === "ALIAS") { result.push(new LayoutAlias(element.overlayContent)); } else { throw new Error("Unknown element type: " + element.type); } } return result; }); }; ServerConnector.getFullOverlayElement = function (params) { var self = this; var queryParams = { overlayId: params.overlay.getId(), modelId: params.element.getModelId(), id: params.element.getId() }; var filterParams = {}; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getFullOverlayElementUrl(queryParams, filterParams)); }).then(function (content) { var element = JSON.parse(content); var result = null; if (element.type === "REACTION") { result = new LayoutReaction(element.overlayContent); } else if (element.type === "ALIAS") { result = new LayoutAlias(element.overlayContent); } else { throw new Error("Unknown element type: " + element.type); } return result; }); }; ServerConnector.getProjectId = function (projectId) { var self = this; if (projectId !== undefined && projectId !== null && projectId !== "") { return Promise.resolve(projectId); } else if (GuiConnector.getParams['id'] !== undefined) { return Promise.resolve(GuiConnector.getParams['id']); } else { return self.getConfigurationParam(ConfigurationType.DEFAULT_MAP); } }; ServerConnector.getLogoImg = function () { return this.getConfigurationParam(ConfigurationType.LOGO_IMG); }; ServerConnector.getLogoLink = function () { return this.getConfigurationParam(ConfigurationType.LOGO_LINK); }; ServerConnector.getMaxSearchDistance = function () { return this.getConfigurationParam(ConfigurationType.SEARCH_DISTANCE); }; ServerConnector.getOverlayById = function (overlayId, projectId) { var self = this; var queryParams = { overlayId: overlayId }; var filterParams = {}; return self.getProjectId(projectId).then(function (data) { queryParams.projectId = data; return self.sendGetRequest(self.getOverlayByIdUrl(queryParams, filterParams)); }).then(function (content) { return new LayoutData(JSON.parse(content)); }); }; ServerConnector.getReactions = function (params) { var self = this; var queryParams = { modelId: params.modelId }; if (params.ids === undefined) { params.ids = []; } if (params.participantId === undefined) { params.participantId = []; } var filterParams = { id: params.ids, columns: params.columns, participantId: params.participantId }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; if (filterParams.id.length > 100 || filterParams.participantId.length > 100) { return self.sendPostRequest(self.getReactionsUrl(queryParams), filterParams); } else { return self.sendGetRequest(self.getReactionsUrl(queryParams, filterParams)); } }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new Reaction(array[i])); } return result; }); }; ServerConnector.getAliases = function (params) { var self = this; var queryParams = { modelId: params.modelId }; if (params.ids === undefined) { params.ids = []; } if (params.includedCompartmentIds === undefined) { params.includedCompartmentIds = []; } if (params.excludedCompartmentIds === undefined) { params.excludedCompartmentIds = []; } var filterParams = { id: params.ids, columns: params.columns, type: params.type, excludedCompartmentIds: params.excludedCompartmentIds, includedCompartmentIds: params.includedCompartmentIds }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; if (filterParams.id.length > 100) { return self.sendPostRequest(self.getAliasesUrl(queryParams), filterParams); } else { return self.sendGetRequest(self.getAliasesUrl(queryParams, filterParams)); } }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new Alias(array[i])); } return result; }); }; ServerConnector.getLightComments = function (params) { params.columns = ["id", "elementId", "modelId", "type", "icon", "removed", "pinned"]; return this.getComments(params); }; ServerConnector.getComments = function (params) { var self = this; var queryParams = { elementId: params.elementId, elementType: params.elementType, coordinates: params.coordinates }; var filterParams = { columns: params.columns }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getCommentsUrl(queryParams, filterParams)); }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new Comment(array[i])); } return result; }); }; ServerConnector.getSessionData = function (project) { if (this._sessionData === undefined) { this._sessionData = new SessionData(project); } if (project !== undefined && this._sessionData.getProject() === null) { this._sessionData.setProject(project); } return this._sessionData; }; ServerConnector.getClosestElementsByCoordinates = function (params) { var self = this; var queryParams = { modelId: params.modelId }; var filterParams = { coordinates: params.coordinates, count: params.count }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getSearchUrl(queryParams, filterParams)); }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new IdentifiedElement(array[i])); } return result; }); }; ServerConnector.login = function (login, password) { var self = this; var params = {}; if (login !== undefined && login !== "") { params.login = login; params.password = password; } else { params.login = "anonymous"; } self.getSessionData().setToken(""); return self.sendPostRequest(self.loginUrl(), params).then(function () { self.getSessionData().setLogin(params.login); return Promise.resolve(self.getSessionData().getToken()); }, function (error) { if (error instanceof NetworkError && error.statusCode === HttpStatus.FORBIDDEN) { throw new InvalidCredentialsError("Invalid credentials"); } else { throw error; } }); }; ServerConnector.logout = function () { var self = this; return self.sendGetRequest(self.logoutUrl()).then(function () { self.getSessionData().setToken(undefined); self.getSessionData().setLogin(undefined); window.location.reload(false); }); }; ServerConnector.getElementsByQuery = function (params) { var self = this; var queryParams = { modelId: params.modelId }; var filterParams = { query: params.query, perfectMatch: params.perfectMatch }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.getConfigurationParam(ConfigurationType.SEARCH_RESULT_NUMBER); }).then(function (defaultCount) { if (params.count !== undefined) { filterParams.count = params.count; } else { filterParams.count = defaultCount; } return self.sendGetRequest(self.getSearchUrl(queryParams, filterParams)); }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new IdentifiedElement(array[i])); } return result; }); }; ServerConnector.getDrugsByQuery = function (params) { var self = this; var queryParams = {}; var filterParams = { query: params.query }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getSearchDrugsUrl(queryParams, filterParams)); }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new Drug(array[i])); } return result; }); }; ServerConnector.getMiRnasByQuery = function (params) { var self = this; var queryParams = {}; var filterParams = { query: params.query }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getSearchMiRnasUrl(queryParams, filterParams)); }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new MiRna(array[i])); } return result; }); }; ServerConnector.getChemicalsByQuery = function (params) { var self = this; var queryParams = {}; var filterParams = { query: params.query }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getSearchChemicalsUrl(queryParams, filterParams)); }).then(function (content) { var array = JSON.parse(content); var result = []; for (var i = 0; i < array.length; i++) { result.push(new Chemical(array[i])); } return result; }); }; ServerConnector.getOverlaySourceDownloadUrl = function (params) { var self = this; var queryParams = { overlayId: params.overlayId }; var filterParams = {}; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.getOverlaySourceUrl(queryParams, filterParams); }); }; ServerConnector.getImageDownloadUrl = function (params) { var self = this; var queryParams = { projectId: params.projectId, modelId: params.modelId }; var filterParams = { token: params.token, polygonString: params.polygonString, handlerClass: params.handlerClass, backgroundOverlayId: params.backgroundOverlayId, zoomLevel: params.zoomLevel, overlayIds: this.idsToString(params.overlayIds) }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.getImageUrl(queryParams, filterParams); }); }; ServerConnector.getModelDownloadUrl = function (params) { var self = this; var queryParams = { projectId: params.projectId, modelId: params.modelId }; var filterParams = { token: params.token, polygonString: params.polygonString, handlerClass: params.handlerClass, backgroundOverlayId: params.backgroundOverlayId, zoomLevel: params.zoomLevel, overlayIds: this.idsToString(params.overlayIds) }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.getModelPartUrl(queryParams, filterParams); }); }; ServerConnector.getImageConverters = function () { var self = this; return self.getConfiguration().then(function (configuration) { return configuration.getImageConverters(); }); }; ServerConnector.getModelConverters = function () { var self = this; return self.getConfiguration().then(function (configuration) { return configuration.getModelConverters(); }); }; ServerConnector.getProjectSourceDownloadUrl = function (params) { if (params === undefined) { params = {}; } var queryParams = {}; var filterParams = {}; var self = this; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.getProjectSourceUrl(queryParams, filterParams); }); }; ServerConnector.getDrugNamesByTarget = function (params) { var self = this; var queryParams = {}; var filterParams = { columns: ["name"], target: params.target.getType() + ":" + params.target.getId() }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getSearchDrugsUrl(queryParams, filterParams)); }).then(function (content) { var result = []; var object = JSON.parse(content); for (var i = 0; i < object.length; i++) { result.push(object[i].name); } return result; }); }; ServerConnector.getMiRnaNamesByTarget = function (params) { var self = this; var queryParams = {}; var filterParams = { columns: ["name"], target: params.target.getType() + ":" + params.target.getId() }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getSearchMiRnasUrl(queryParams, filterParams)); }).then(function (content) { var result = []; var object = JSON.parse(content); for (var i = 0; i < object.length; i++) { result.push(object[i].name); } return result; }); }; ServerConnector.getChemicalNamesByTarget = function (params) { var self = this; var queryParams = {}; var filterParams = { columns: ["name"], target: params.target.getType() + ":" + params.target.getId() }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getSearchChemicalsUrl(queryParams, filterParams)); }).then(function (content) { var result = []; var object = JSON.parse(content); for (var i = 0; i < object.length; i++) { result.push(object[i].name); } return result; }); }; ServerConnector.addComment = function (params) { var self = this; var queryParams = { elementId: params.elementId, elementType: params.elementType, coordinates: self.pointToString(params.coordinates), modelId: params.modelId }; var filterParams = params; delete filterParams.elementId; delete filterParams.elementType; if (queryParams.elementType === "POINT") { delete filterParams.coordinates; } else { filterParams.coordinates = self.pointToString(params.coordinates); } delete filterParams.modelId; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendPostRequest(self.addCommentUrl(queryParams), filterParams); }).then(function (content) { var response = JSON.parse(content); return new Comment(response); }); }; ServerConnector.addOverlay = function (params) { var overlay = params.overlay; if (!(overlay instanceof LayoutData)) { throw new Error("Invalid overlay: " + overlay); } var self = this; var queryParams = {}; var data = { name: overlay.getName(), description: overlay.getDescription(), content: overlay.getContent(), filename: overlay.getFilename(), fileId: params.fileId }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendPostRequest(self.addOverlayUrl(queryParams), data); }).then(function (content) { return new LayoutData(JSON.parse(content)); }); }; ServerConnector.updateOverlay = function (overlay) { var self = this; var queryParams = { overlayId: overlay.getId() }; var filterParams = { overlay: { name: overlay.getName(), description: overlay.getDescription(), creator: overlay.getCreator(), publicOverlay: overlay.getPublicOverlay(), defaultOverlay: overlay.isDefaultOverlay() } }; return self.sendPatchRequest(self.updateOverlayUrl(queryParams), filterParams); }; ServerConnector.updateModel = function (params) { var self = this; var model = params.model; var queryParams = { projectId: params.projectId, modelId: model.getId() }; var filterParams = { model: { id: model.getId(), defaultCenterX: model.getDefaultCenterX(), defaultCenterY: model.getDefaultCenterY(), defaultZoomLevel: model.getDefaultZoomLevel() } }; return self.sendPatchRequest(self.updateModelUrl(queryParams), filterParams); }; ServerConnector.removeOverlay = function (params) { var self = this; var queryParams = { overlayId: params.overlayId }; var filterParams = {}; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendDeleteRequest(self.deleteOverlayUrl(queryParams), filterParams); }); }; ServerConnector.removeComment = function (params) { var self = this; var queryParams = { commentId: params.commentId }; var filterParams = { reason: params.reason }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendDeleteRequest(self.deleteCommentUrl(queryParams), filterParams); }); }; ServerConnector.getSuggestedQueryList = function (projectId) { var self = this; return self.getProjectId(projectId).then(function (result) { projectId = result; return self.sendGetRequest(self.getSuggestedQueryListUrl({ projectId: projectId })); }).then(function (content) { return JSON.parse(content); }); }; ServerConnector.getChemicalSuggestedQueryList = function (projectId) { var self = this; return self.getProjectId(projectId).then(function (result) { projectId = result; return self.sendGetRequest(self.getChemicalSuggestedQueryListUrl({ projectId: projectId })); }).then(function (content) { return JSON.parse(content); }); }; ServerConnector.getMiRnaSuggestedQueryList = function (projectId) { var self = this; return self.getProjectId(projectId).then(function (result) { projectId = result; return self.sendGetRequest(self.getMiRnaSuggestedQueryListUrl({ projectId: projectId })); }).then(function (content) { return JSON.parse(content); }); }; ServerConnector.getDrugSuggestedQueryList = function (projectId) { var self = this; return self.getProjectId(projectId).then(function (result) { projectId = result; return self.sendGetRequest(self.getDrugSuggestedQueryListUrl({ projectId: projectId })); }).then(function (content) { return JSON.parse(content); }); }; ServerConnector.getOverlayTypes = function () { var self = this; return self.getConfiguration().then(function (configuration) { return configuration.getOverlayTypes(); }); }; ServerConnector.getPublications = function (params) { var self = this; if (params === undefined) { params = {}; } var queryParams = {}; var filterParams = { start: params.start, length: params.length, sortColumn: params.sortColumn, sortOrder: params.sortOrder, search: params.search }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getPublicationsUrl(queryParams, filterParams)); }).then(function (content) { return JSON.parse(content); }); }; ServerConnector.getReferenceGenome = function (params) { var self = this; var filterParams = {}; return self.sendGetRequest(self.getReferenceGenomeUrl(params, filterParams)).then(function (content) { return new ReferenceGenome(JSON.parse(content)); }); }; ServerConnector.uploadFile = function (params) { var CHUNK_SIZE = 65535; var self = this; var data = new Uint8Array(params.content); var filterParams = { filename: params.filename, length: data.length }; return self.sendPostRequest(self.getCreateFileUrl(), filterParams).then(function (response) { var uploadedLength = 0; var createPromise = function (resultFileJson) { var resultFile = JSON.parse(resultFileJson); if (uploadedLength >= data.length) { return Promise.resolve(resultFile); } else { var chunk = data.slice(uploadedLength, uploadedLength + CHUNK_SIZE); var url = self.getUploadFileUrl({id: resultFile.id}); return self.sendRequest({method: "POST", url: url, body: chunk}).then(function (resultFileJson) { uploadedLength += chunk.length; return createPromise(resultFileJson); }) } }; return createPromise(response); }); }; ServerConnector.getProjectLogs = function (params) { var self = this; if (params === undefined) { params = {}; } var queryParams = {}; var filterParams = { start: params.start, length: params.length, sortColumn: params.sortColumn, sortOrder: params.sortOrder, search: params.search, level: params.level }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendGetRequest(self.getProjectLogsUrl(queryParams, filterParams)); }).then(function (content) { return JSON.parse(content); }); }; ServerConnector.getMesh = function (params) { var self = this; if (params === undefined) { params = {}; } return self.sendGetRequest(self.getMeshUrl(params)).then(function (content) { return new Mesh(JSON.parse(content)); }); }; ServerConnector.getSbmlFunction = function (params) { var self = this; if (params === undefined) { params = {}; } return self.getProjectId(params.projectId).then(function (result) { params.projectId = result; return self.sendGetRequest(self.getSbmlFunctionUrl(params)); }).then(function (content) { return new SbmlFunction(JSON.parse(content)); }); }; ServerConnector.getSbmlParameter = function (params) { var self = this; if (params === undefined) { params = {}; } return self.getProjectId(params.projectId).then(function (result) { params.projectId = result; return self.sendGetRequest(self.getSbmlParameterUrl(params)); }).then(function (content) { return new SbmlParameter(JSON.parse(content)); }); }; module.exports = ServerConnector;