webin-rest.service.ts 9 KB
Newer Older
Rasko Leinonen's avatar
Rasko Leinonen committed
1 2 3 4 5 6 7 8 9 10 11
/*
 * Copyright 2018 EMBL - European Bioinformatics Institute
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

Rasko Leinonen's avatar
Rasko Leinonen committed
12
import { Injectable } from '@angular/core';
13
import { HttpClient, HttpHeaders } from '@angular/common/http';
14
import { environment } from '../environments/environment';
Rasko Leinonen's avatar
Rasko Leinonen committed
15
import { Observable } from 'rxjs';
Rajkumar-D's avatar
Rajkumar-D committed
16
import { tap, startWith, map, debounceTime, catchError } from 'rxjs/operators';
rajkumar's avatar
rajkumar committed
17

18

19
import { ReportType } from './report-type.enum';
20
import { WebinRestServiceInterface } from './webin-rest.service.interface';
21
import { WebinAuthenticationService } from './webin-authentication.service';
22

rajkumar's avatar
rajkumar committed
23

Rasko Leinonen's avatar
Rasko Leinonen committed
24
@Injectable()
25
export class WebinRestService implements WebinRestServiceInterface {
Rasko Leinonen's avatar
Rasko Leinonen committed
26

Rajkumar-D's avatar
Rajkumar-D committed
27
  private _baseUrl = environment.webinRestUrl + "/submit/";
28

29
  private _xmlParser = new DOMParser();
Rasko Leinonen's avatar
Rasko Leinonen committed
30

31
  constructor(private _http: HttpClient,
Rajkumar-D's avatar
Rajkumar-D committed
32
    private _webinAuthenticationService: WebinAuthenticationService) { }
Rasko Leinonen's avatar
Rasko Leinonen committed
33

34
  private headers() {
35
    return new HttpHeaders();
Rasko Leinonen's avatar
Rasko Leinonen committed
36
  }
Rasko Leinonen's avatar
Rasko Leinonen committed
37

38
  private appendXml(formData: FormData, name: string, blob: Blob) {
39
    if (blob) {
Rasko Leinonen's avatar
Rasko Leinonen committed
40
      let fileName: string = (blob as File).name;
41
      if (!fileName) {
42
        fileName = name.toLowerCase() + '.xml';
43 44
      }
      formData.append(name, blob, fileName);
Rasko Leinonen's avatar
Rasko Leinonen committed
45 46
    }
  }
Rasko Leinonen's avatar
Rasko Leinonen committed
47

Rajkumar-D's avatar
Rajkumar-D committed
48
  private post(formData: FormData, parameters?): Observable<string> {
Rasko Leinonen's avatar
Rasko Leinonen committed
49
    const headers = this.headers();
Rajkumar-D's avatar
Rajkumar-D committed
50
    return this._http.post(this._baseUrl + "?" + parameters, formData, { headers, responseType: 'text' });
Rasko Leinonen's avatar
Rasko Leinonen committed
51
  }
52

rajkumar's avatar
rajkumar committed
53 54
  private postTaxon(formData: FormData): Observable<string> {
    const headers = this.headers();
Rajkumar-D's avatar
Rajkumar-D committed
55
    return this._http.post(environment.webinRestUrl + "/portal/register/taxonomy", formData, { headers, responseType: 'text' });
rajkumar's avatar
rajkumar committed
56 57 58
  }

  private postEmail(mail) {
Rajkumar-D's avatar
Rajkumar-D committed
59
    return this._http.post(environment.webinRestUrl + '/email', mail);
rajkumar's avatar
rajkumar committed
60 61
  }

Rajkumar-D's avatar
Rajkumar-D committed
62
  submitProjectXml(formData) {
rajkumar's avatar
rajkumar committed
63 64 65
    const headers = this.headers();
    return this._http.post(this._baseUrl, formData, { headers, responseType: 'text' }).
      pipe(
Rajkumar-D's avatar
Rajkumar-D committed
66 67 68
        map((data: any) => {
          return data;
        })
rajkumar's avatar
rajkumar committed
69 70
      )
  }
Rajkumar-D's avatar
Rajkumar-D committed
71

rajkumar's avatar
rajkumar committed
72

73
  updateXml(
74
    reportType: ReportType,
rajkumar's avatar
rajkumar committed
75
    xml: Blob,
rajkumar's avatar
rajkumar committed
76
    action: Object,
Rajkumar-D's avatar
Rajkumar-D committed
77 78
    releaseDate?: any,
    form?): Observable<string> {
Rajkumar-D's avatar
Rajkumar-D committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
    console.log('** Update XML **');
    const formData: FormData = new FormData();
    var mode = action["name"];

    var releaseDateStr = this.getReleaseDateStr(action, mode, releaseDate)
    var actionString = this.getActionStr(action, mode);
    var submissionAttr = this.getSubmissionAttrStr();
    let submissionXml: Blob = new Blob([
      '<SUBMISSION_SET>' +
      '  <SUBMISSION>' +
      '	<ACTIONS>' +
      actionString +
      releaseDateStr +
      '    	</ACTIONS>' +
      submissionAttr +
      '    </SUBMISSION>' +
      '</SUBMISSION_SET>']);
    if (this._webinAuthenticationService.ega) {
      submissionXml = new Blob([
        '<SUBMISSION_SET>' +
        '  <SUBMISSION broker_name="EGA">' +
        '	<ACTIONS>' +
        actionString +
        '    		<ACTION>' +
        '    			<PROTECT/>' +
        '    		</ACTION>' +
        releaseDateStr +
        '    	</ACTIONS>' +
        submissionAttr +
        '    </SUBMISSION>' +
        '</SUBMISSION_SET>']);
110
    }
Rajkumar-D's avatar
Rajkumar-D committed
111
    this.appendXml(formData, 'SUBMISSION', submissionXml);
112

Rajkumar-D's avatar
Rajkumar-D committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    switch (reportType) {
      case ReportType.studies: {
        this.appendXml(formData, 'STUDY', xml);
        break;
      }
      case ReportType.projects: {
        this.appendXml(formData, 'PROJECT', xml);
        break;
      }
      case ReportType.samples: {
        this.appendXml(formData, 'SAMPLE', xml);
        break;
      }
      case ReportType.experiments: {
        this.appendXml(formData, 'EXPERIMENT', xml);
        break;
      }
      case ReportType.runs: {
        this.appendXml(formData, 'RUN', xml);
        break;
      }
      case ReportType.analyses: {
        this.appendXml(formData, 'ANALYSIS', xml);
        break;
      }
      case ReportType.dacs: {
        this.appendXml(formData, 'DAC', xml);
        break;
      }
      case ReportType.policies: {
        this.appendXml(formData, 'POLICY', xml);
        break;
      }
      case ReportType.datasets: {
        this.appendXml(formData, 'DATASET', xml);
        break;
      }
150 151
    }

Rajkumar-D's avatar
Rajkumar-D committed
152 153 154 155
    let postParam = "";
    if (form) {
      postParam = this.getCenterNamePostParam(form.centerName);
    }
156
    console.log('** webin submission form data **', formData);
Rajkumar-D's avatar
Rajkumar-D committed
157
    return this.post(formData, postParam);
Rajkumar-D's avatar
Rajkumar-D committed
158

Rasko Leinonen's avatar
Rasko Leinonen committed
159 160
  }

Rajkumar-D's avatar
Rajkumar-D committed
161

162
  submitXml(
163 164 165 166 167 168 169 170 171
    submissionXml: Blob,
    studyXml: Blob,
    projectXml: Blob,
    sampleXml: Blob,
    experimentXml: Blob,
    runXml: Blob,
    analysisXml: Blob,
    dacXml: Blob,
    policyXml: Blob,
Rajkumar-D's avatar
Rajkumar-D committed
172 173
    datasetXml: Blob,
    centerName?): Observable<string> {
174

175
    console.log('** Submit XML **');
Rasko Leinonen's avatar
Rasko Leinonen committed
176
    const formData: FormData = new FormData();
177 178 179 180 181 182 183 184 185 186
    this.appendXml(formData, 'SUBMISSION', submissionXml);
    this.appendXml(formData, 'STUDY', studyXml);
    this.appendXml(formData, 'PROJECT', projectXml);
    this.appendXml(formData, 'SAMPLE', sampleXml);
    this.appendXml(formData, 'EXPERIMENT', experimentXml);
    this.appendXml(formData, 'RUN', runXml);
    this.appendXml(formData, 'ANALYSIS', analysisXml);
    this.appendXml(formData, 'DAC', dacXml);
    this.appendXml(formData, 'POLICY', policyXml);
    this.appendXml(formData, 'DATASET', datasetXml);
Rajkumar-D's avatar
Rajkumar-D committed
187 188 189 190 191 192 193 194 195 196 197 198 199

    let postParam = "";
    if (centerName) {
      postParam = this.getCenterNamePostParam(centerName);
    }

    return this.post(formData, postParam);
  }

  getCenterNamePostParam(centerName) {
    if (centerName) {
      return "CENTER_NAME=" + centerName;
    }
Rasko Leinonen's avatar
Rasko Leinonen committed
200
  }
201

202
  parseResult(data: string) {
203

204
    const xmlDoc = this._xmlParser.parseFromString(data, 'text/xml');
205 206 207
    const rootNode: any = xmlDoc.getElementsByTagName('RECEIPT')[0];
    const isError: boolean = (rootNode.getAttribute('success') !== 'true');
    const date: string = rootNode.getAttribute('receiptDate');
208

209
    const receipt = {
210
      isError: isError,
211
      xml: data,
212
      date: date,
213 214 215 216
      accessions: [],
      errors: []
    };

217
    let i = 0;
218 219

    if (!isError) {
220
      const nodes = rootNode.childNodes;
221
      // Safer not use forEach for NodeList.
222
      for (i = 0; i < nodes.length; i++) {
223 224
        const childNode = nodes[i];
        if (childNode.tagName === 'ANALYSIS' ||
Rajkumar-D's avatar
Rajkumar-D committed
225 226 227 228 229 230 231 232 233
          childNode.tagName === 'EXPERIMENT' ||
          childNode.tagName === 'RUN' ||
          childNode.tagName === 'SAMPLE' ||
          childNode.tagName === 'STUDY' ||
          childNode.tagName === 'DAC' ||
          childNode.tagName === 'POLICY' ||
          childNode.tagName === 'DATASET' ||
          childNode.tagName === 'PROJECT' ||
          (childNode.tagName === 'SUBMISSION' && childNode.getAttribute('accession'))) {
234 235
          receipt.accessions.push(
            {
236 237 238
              type: childNode.tagName,
              accession: childNode.getAttribute('accession'),
              alias: childNode.getAttribute('alias')
239 240
            });
        }
241
      }
242 243 244
    } else {
      const messageRootNode = rootNode.getElementsByTagName('MESSAGES')[0];
      const nodes = messageRootNode.getElementsByTagName('ERROR');
245
      // Safer not use forEach for NodeList.
246 247 248 249 250 251 252 253 254 255
      for (i = 0; i < nodes.length; i++) {
        receipt.errors.push(
          {
            error: nodes[i].textContent
          });
      }
    }

    return receipt;
  }
rajkumar's avatar
rajkumar committed
256

Rajkumar-D's avatar
Rajkumar-D committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270
  getActionStr(action, mode) {
    var actionStr = "";
    if (mode === "Edit") {

      actionStr = '<ACTION>' +
        '  <MODIFY/>' +
        '</ACTION>';
    } else {
      actionStr = '<ACTION>' +
        '    			    <ADD/>' +
        '    		    </ACTION>'
    }

    return actionStr;
rajkumar's avatar
rajkumar committed
271 272
  }

Rajkumar-D's avatar
Rajkumar-D committed
273 274 275 276 277 278 279 280 281 282 283 284
  getReleaseDateStr(action, mode, releaseDate) {
    var releaseDateStr = "";
    var targetStr = "";

    if (mode === "Edit" && action["id"]) {
      targetStr = 'target="' + action["id"] + '"';
    }
    if (!this._webinAuthenticationService.ega) {
      if (releaseDate) {
        releaseDateStr = '<ACTION>' +
          '<HOLD ' + targetStr + ' HoldUntilDate="' + releaseDate + '"></HOLD>' +
          '</ACTION>';
rajkumar's avatar
rajkumar committed
285 286
      }
    }
Rajkumar-D's avatar
Rajkumar-D committed
287 288 289 290 291 292 293 294 295 296 297
    return releaseDateStr;
  }

  getSubmissionAttrStr() {
    return "<SUBMISSION_ATTRIBUTES>" +
      "<SUBMISSION_ATTRIBUTE>" +
      "<TAG>ENA-SUBMISSION-TOOL</TAG>" +
      "<VALUE>Webin-Portal</VALUE>" +
      "</SUBMISSION_ATTRIBUTE>" +
      "</SUBMISSION_ATTRIBUTES>";

rajkumar's avatar
rajkumar committed
298
  }
rajkumar's avatar
rajkumar committed
299 300 301 302 303 304 305 306

  uploadTaxonTemplate(taxonTemplate: Blob): Observable<any> {
    console.log('** Submit tacon template **');
    const formData: FormData = new FormData();
    formData.append('taxonomyRegistrationFile', taxonTemplate, 'taxonomyTemplate.tsv');
    return this.postTaxon(formData);
  }

Rajkumar-D's avatar
Rajkumar-D committed
307
  sendTaxonEmail(mail: any) {
rajkumar's avatar
rajkumar committed
308 309 310
    console.log('** Send email for taxon **');
    return this.postEmail(mail)
  }
Rajkumar-D's avatar
Rajkumar-D committed
311

Rasko Leinonen's avatar
Rasko Leinonen committed
312
}