1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
110
111
112
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
150
151
152
use std::sync::Arc;

use serde::{Deserialize, Serialize};
use tracing::debug;
use tracing::instrument;

use htsget_config::types::Format;
use htsget_search::HtsGet;

use crate::ConfigServiceInfo;
use crate::Endpoint;

const READS_FORMATS: [&str; 2] = ["BAM", "CRAM"];
const VARIANTS_FORMATS: [&str; 2] = ["VCF", "BCF"];

/// A struct representing the information that should be present in a service-info response.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ServiceInfo {
  pub id: String,
  pub name: String,
  pub version: String,
  pub organization: Organisation,
  #[serde(rename = "type")]
  pub service_type: Type,
  pub htsget: Htsget,
  pub contact_url: String,
  pub documentation_url: String,
  pub created_at: String,
  pub updated_at: String,
  pub environment: String,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct Organisation {
  pub name: String,
  pub url: String,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct Type {
  pub group: String,
  pub artifact: String,
  pub version: String,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct Htsget {
  pub datatype: String,
  pub formats: Vec<String>,
  pub fields_parameters_effective: bool,
  pub tags_parameters_effective: bool,
}

pub fn get_service_info_with(
  endpoint: Endpoint,
  supported_formats: &[Format],
  fields_effective: bool,
  tags_effective: bool,
) -> ServiceInfo {
  let htsget_info = Htsget {
    datatype: match endpoint {
      Endpoint::Reads => "reads",
      Endpoint::Variants => "variants",
    }
    .to_string(),
    formats: supported_formats
      .iter()
      .map(|format| format.to_string())
      .filter(|format| match endpoint {
        Endpoint::Reads => READS_FORMATS.contains(&format.as_str()),
        Endpoint::Variants => VARIANTS_FORMATS.contains(&format.as_str()),
      })
      .collect(),
    fields_parameters_effective: fields_effective,
    tags_parameters_effective: tags_effective,
  };

  ServiceInfo {
    id: "".to_string(),
    name: "".to_string(),
    version: "".to_string(),
    organization: Default::default(),
    service_type: Default::default(),
    htsget: htsget_info,
    contact_url: "".to_string(),
    documentation_url: "".to_string(),
    created_at: "".to_string(),
    updated_at: "".to_string(),
    environment: "".to_string(),
  }
}

#[instrument(level = "debug", skip_all)]
pub fn get_service_info_json(
  endpoint: Endpoint,
  searcher: Arc<impl HtsGet + Send + Sync + 'static>,
  config: &ConfigServiceInfo,
) -> ServiceInfo {
  debug!(endpoint = ?endpoint,"getting service-info response for endpoint");
  fill_out_service_info_json(
    get_service_info_with(
      endpoint,
      &searcher.get_supported_formats(),
      searcher.are_field_parameters_effective(),
      searcher.are_tag_parameters_effective(),
    ),
    config,
  )
}

/// Fills the service-info json with the data from the server config
fn fill_out_service_info_json(
  mut service_info_json: ServiceInfo,
  config: &ConfigServiceInfo,
) -> ServiceInfo {
  if let Some(id) = config.id() {
    service_info_json.id = id.to_string();
  }
  if let Some(name) = config.name() {
    service_info_json.name = name.to_string();
  }
  if let Some(version) = config.version() {
    service_info_json.version = version.to_string();
  }
  if let Some(organization_name) = config.organization_name() {
    service_info_json.organization.name = organization_name.to_string();
  }
  if let Some(organization_url) = config.organization_url() {
    service_info_json.organization.url = organization_url.to_string();
  }
  if let Some(contact_url) = config.contact_url() {
    service_info_json.contact_url = contact_url.to_string();
  }
  if let Some(documentation_url) = config.documentation_url() {
    service_info_json.documentation_url = documentation_url.to_string();
  }
  if let Some(created_at) = config.created_at() {
    service_info_json.created_at = created_at.to_string();
  }
  if let Some(updated_at) = config.updated_at() {
    service_info_json.updated_at = updated_at.to_string();
  }
  if let Some(environment) = config.environment() {
    service_info_json.environment = environment.to_string();
  }

  service_info_json
}