{"id":20801908,"url":"https://github.com/philips-software/kotlin-hsdp-sdk","last_synced_at":"2026-04-12T07:31:56.869Z","repository":{"id":37980451,"uuid":"422149630","full_name":"philips-software/kotlin-hsdp-sdk","owner":"philips-software","description":"Client library to interact with various HSDP APIs in a simple and uniform way","archived":false,"fork":false,"pushed_at":"2023-06-19T07:59:55.000Z","size":354,"stargazers_count":2,"open_issues_count":6,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-18T12:34:24.683Z","etag":null,"topics":["android","hsdp","hsdp-api","iam","java","jvm","kotlin","provisioning","tdr"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/philips-software.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-28T09:50:52.000Z","updated_at":"2023-12-22T09:15:14.000Z","dependencies_parsed_at":"2025-01-18T12:39:22.250Z","dependency_job_id":null,"html_url":"https://github.com/philips-software/kotlin-hsdp-sdk","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philips-software%2Fkotlin-hsdp-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philips-software%2Fkotlin-hsdp-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philips-software%2Fkotlin-hsdp-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philips-software%2Fkotlin-hsdp-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/philips-software","download_url":"https://codeload.github.com/philips-software/kotlin-hsdp-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243147272,"owners_count":20243745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","hsdp","hsdp-api","iam","java","jvm","kotlin","provisioning","tdr"],"created_at":"2024-11-17T18:25:31.397Z","updated_at":"2026-04-12T07:31:51.835Z","avatar_url":"https://github.com/philips-software.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kotlin-hsdp-sdk\n\n[![Build](https://github.com/philips-software/kotlin-hsdp-api/actions/workflows/gradle.yml/badge.svg?branch=main)](https://github.com/philips-software/kotlin-hsdp-api/actions/workflows/gradle.yml?query=workflow%3Agradle)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nThis SDK provides a simple interface to features offered by the various services of HSDP.\n\nThe output of the project is a JAR-file that can be used in either a Java or Kotlin backend service \nor an Android application.\n\n## Table of contents\n\n- [Using in your projects](#using-in-your-projects)\n  - [Gradle Kotlin DSL](#gradle-kotlin-dsl)\n  - [Gradle](#gradle)\n  - [Maven](#maven)\n- [Basic usage](#basic-usage)\n  - [Android](#android)\n  - [Kotlin backend](#kotlin-backend)\n  - [Java backend](#java-backend)\n- [Supported APIs](#supported-apis)\n- [Logging implementation examples](#logging-implementation-examples)\n  - [Timber logger for Android](#timber-logger-for-android)\n  - [Log4j2 logger for Kotlin backend applications](#log4j2-logger-for-kotlin-backend-applications)\n  - [Simple logger for Java backend applications](#simple-logger-for-java-backend-applications)\n- [Todo](#todo)\n- [Issues](#issues)\n- [Contact / Getting help](#contact--geting-help)\n- [License](#license)\n\n\n## Using in your projects\n\nThe library dependency can be included in your projects in different ways.\n\n### Gradle Kotlin DSL\n\n```kotlin\nrepositories {\n    // Other repos...\n    maven { setUrl(\"https://jitpack.io\") }\n}\n\ndependencies {\n  // Other dependencies...\n  implementation(\"com.github.philips-software:kotlin-hsdp-sdk:0.2.0\")\n}\n```\n\n### Gradle\n\n```groovy\n\nrepositories {\n    // Other repos...\n    maven { url 'https://jitpack.io' }\n}\n\ndependencies {\n    // Other dependencies...\n    implementation \"com.github.philips-software:kotlin-hsdp-sdk:0.2.0\"\n}\n```\n\n### Maven\n\n```maven\n\u003crepositories\u003e\n    ...\n    \u003crepository\u003e\n        \u003cid\u003ejitpack.io\u003c/id\u003e\n        \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n\u003cdependencies\u003e\n    ...\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.github.philips-software\u003c/groupId\u003e\n        \u003cartifactId\u003ekotlin-hsdp-sdk\u003c/artifactId\u003e\n        \u003cversion\u003e0.2.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n\n## Basic usage\n\nSimple examples for Android and backend (Kotlin \u0026 Java) applications are provided to give you a quick start.\n\nThe library externalized the choice of a logging system by providing an abstract logger factory and a logger interface.\nIt is up to the application developer to provide implementations of both, and to register the concrete logger factory\nto the logger manager before instantiating any SDK services.\n\n### Android\n\nNext code example shows how to use the library in an Android project written in Kotlin.\n\n```kotlin\nclass MainActivity : AppCompatActivity() {\n\n  private val scope = CoroutineScope(Dispatchers.IO)\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    setContentView(R.layout.activity_main)\n\n    // First register the concrete logger factory, before creating any of the services!\n    // This will allow (future) versions of the SDK services to also log something in their construction phase.\n    PlatformLoggerFactory.registerConcreteFactory(TimberLoggerFactory)\n    logger = PlatformLoggerFactory.create(\"Main\", javaClass)\n\n    val httpClient = HttpClient()\n    val iamOAuth2 = IamOAuth2(iamUrl, basicAuthUsername, basicAuthPassword, httpClient, initialToken)\n    val tdr = TDR(tdrUrl, httpClient)\n    scope.launch {\n      try {\n        if (iamOAuth2.token.isNotValid) {\n          logger.error { \"no valid token\" }\n          val token = iamOAuth2.login(username, password)\n        }\n        val contracts = tdr.getContracts(\n          ContractQuery(\n            organizationQuery = OrganizationQuery(tenant),\n            countQuery = CountQuery(10)\n          )\n        )\n        logger.info { \"Getting contracts for $tenant returned page with ${contracts.data.size} items\" }\n        logger.info { \"revoke token\" }\n        val revokedToken = iamOAuth2.revokeToken()\n      } catch (ex: IOException) {\n        logger.error { ex.toString() }\n      } catch (httpEx: HttpException) {\n        logger.error { httpEx.toString() }\n      } catch (serializationException: SerializationException) {\n        logger.error { serializationException.toString() }\n      }\n    }\n  }\n}\n```\n\nNotes:\n- The example registers a `TimberLoggerFactory` to the `PlatformLoggerFactory`. Former will be detailed in the \n  logging section.\n- `iamUrl`, `basicAuthUsername`, `basicAuthPassword`, `tdrUrl`, `tenant`, `username` and `password` are somehow \n  provided by the application.\n- `initialToken` can be provided, to allow the application to store the last obtained token somewhere safely, so that \n  upon reopening of the application there is no need for logging in again when the token is still valid.\n\n### Kotlin backend\n\nNext code example shows how to use the library in a Kotlin backend project.\n\n```kotlin\nimport some.sdk.packages\n\nfun main() {\n  // First register the concrete logger factory, before creating any of the services!\n  // This will allow (future) versions of the SDK services to also log something in their construction phase.\n  PlatformLoggerFactory.registerConcreteFactory(Log4j2LoggerFactory)\n  \n  val httpClient = HttpClient()\n  val iamOAuth2 = IamOAuth2(iamUrl, basicAuthUsername, basicAuthPassword, httpClient)\n  val tdr = TDR(tdrUrl, httpClient)\n  runBlocking {\n    iamOAuth2.login(username, password)\n    val dataItems = tdr.getDataItems(\n      query = DataItemQuery(organizationQuery = OrganizationQuery(tenant))\n    )\n    println(dataItems)\n    iamOAuth2.revokeToken()\n  }\n}\n```\n\nNotes:\n- The example registers a `Log4j2LoggerFactory` to the `PlatformLoggerFactory`. Former will be detailed in the\n  logging section.\n- `iamUrl`, `basicAuthUsername`, `basicAuthPassword`, `tdrUrl`, `tenant`, `username` and `password` are somehow\n  provided by the application.\n\n### Java backend\n\nAs mentioned in the design decisions, the Java application must instantiate the service proxies instead of\nthe services themselves.\n\nNext code example shows how to use the library in a Java Spring Boot backend project.\n\n```java\n@SpringBootApplication\npublic class SimpleApplication {\n\n    public static void main(String[] args) {\n        PlatformLoggerFactory.registerConcreteFactory(new SimpleLoggerFactory());\n        SpringApplication.run(SimpleApplication.class, args);\n    }\n\n    @Bean\n    HttpClient getHttpClient() {\n        return new HttpClient();\n    }\n\n    @Bean\n    IamOAuth2JavaProxy getIamOAuth2() {\n        return new IamOAuth2JavaProxy(\n                iamUrl,\n                basicAuthUsername,\n                basicAuthPassword,\n                getHttpClient()\n        );\n    }\n\n    @Bean\n    TDRJavaProxy getTDR() {\n        return new TDRJavaProxy(\n                tdrUrl,\n                getHttpClient()\n        );\n    }\n}\n```\n\nAn example REST controller that performs calls to the SDK services for IAM and TDR:\n\n```java\n@RestController\n@RequestMapping(\"/tdr\")\nclass TdrController {\n    private final HttpClient httpClient;\n    private final IamOAuth2JavaProxy iamOAuth2;\n    private final TDRJavaProxy tdr;\n  \n    public TdrController(HttpClient httpClient, IamOAuth2JavaProxy iamOAuth2, TDRJavaProxy tdr) {\n        this.httpClient = httpClient;\n        this.iamOAuth2 = iamOAuth2;\n        this.tdr = tdr;\n    }\n  \n    @GetMapping(\"contracts\")\n    public CompletableFuture\u003cContractsDto\u003e getContracts() {\n        return ascertainToken()\n                .thenCompose(s -\u003e {\n                    ContractQuery contractQuery = new ContractQueryBuilder()\n                        .organizationQuery(new OrganizationQuery(tenant))\n                        .countQuery(new CountQuery(10))\n                        .offsetQuery(new OffsetQuery(0))\n                        .build();\n                    return tdr.getContracts(contractQuery);\n                });\n    }\n    \n    private CompletableFuture\u003cVoid\u003e ascertainToken() {\n        if (!httpClient.getToken().isValid()) {\n            return iamOAuth2.login(username, password)\n                  .thenAccept(token -\u003e System.out.println(token.getAccessToken()));\n        }\n        return CompletableFuture.completedFuture(null);\n    }\n}\n```\n\nNotes:\n- The example registers a `SimpleLoggerFactory` to the `PlatformLoggerFactory`. Former will be detailed in the\n  logging section.\n- `iamUrl`, `basicAuthUsername`, `basicAuthPassword`, `tdrUrl`, `tenant`, `username` and `password` are somehow\n  provided by the application.\n\n\n## Supported APIs\n\nThe current implementation covers only a subset of HSDP APIs. Additional functionality is built as needed.\n\n- [x] IAM Identity and Access Management (IAM)\n  - [ ] Access Management\n    - [ ] Federation\n    - [x] OAuth2\n      - [x] OAuth2 Authorization\n      - [x] OAuth2 Token Revocation\n      - [x] OpenID Connect UserInfo\n      - [x] Introspect\n      - [ ] Session (refresh, terminate)\n      - [ ] OpenID (configuration, JWKS)\n    - [ ] Token\n  - [x] Identity Management\n    - [x] User\n      - [x] Search user account\n      - [x] Register a user account\n      - [x] Delete a user account\n      - [x] Set password for user account\n      - [x] Change user password\n      - [x] Reset password service with kba validation\n      - [x] Enables user password to be reset by admin\n      - [x] Resend account activation email to the user\n      - [x] Unlock user account\n      - [x] Retrieve saved kba challenges questions for a user\n      - [x] Get effective password policy for a user\n      - [x] Send verification code (OTP) to secondary auth factors like email and SMS\n      - [x] Verify the code (OTP) sent to secondary auth factors like email and SMS\n      - [x] Remove OTP device registration\n      - [x] Update user's login ID\n      - [ ] Enables a user to delegate access to another user to act on its behalf\n      - [ ] Revoke delegation granted to given delegatee\n  - [ ] Policy Management\n- [x] Clinical Data Repository (CDR)\n  - [x] Read\n  - [x] VRead (versioned read)\n  - [x] Create\n  - [x] Update\n  - [x] Patch\n  - [x] Delete\n  - [ ] Get History\n  - [x] Batch operation\n  - [ ] Get Capabilities\n- [x] Telemetry Data Repository (TDR)\n  - [x] Contracts\n  - [x] Data Items\n- [x] Provisioning\n  - [ ] Provisioning\n    - [ ] Provision\n    - [x] Create Identity\n  - [ ] Reprovision\n  - [ ] Unprovisioning\n  - [ ] Reset\n  - [ ] Identity Certificate\n  - [ ] Task\n\nOther services will follow later.\n\n\n## Logging implementation examples\n\n### Timber logger for Android\n\nA possible implementation for logging with Timber:\n\n```kotlin\nobject TimberLoggerFactory: AbstractPlatformLoggerFactory {\n    init {\n        Timber.plant(Timber.DebugTree())\n    }\n\n    override fun create(tag: String, ofClass: Class\u003c*\u003e): PlatformLogger = TimberLogger(tag)\n}\n\nclass TimberLogger(private val tag: String): PlatformLogger {\n    private val traceLevel = 1\n\n    override fun fatal(message: () -\u003e String) {\n        Timber.tag(tag).wtf(message())\n    }\n\n    override fun error(message: () -\u003eString) {\n        Timber.tag(tag).e(message())\n    }\n\n    override fun warn(message: () -\u003e String) {\n        Timber.tag(tag).w(message())\n    }\n\n    override fun info(message: () -\u003e String) {\n        Timber.tag(tag).i(message())\n    }\n\n    override fun debug(message: () -\u003e String) {\n        Timber.tag(tag).d(message())\n    }\n\n    override fun trace(message: () -\u003e String) {\n        Timber.tag(tag).log(traceLevel, message())\n    }\n}\n```\n\n### Log4j2 logger for Kotlin backend applications\n\nA possible implementation for logging with Log4j2:\n\n```kotlin\nimport com.philips.hsdp.apis.support.logging.AbstractPlatformLoggerFactory\nimport com.philips.hsdp.apis.support.logging.PlatformLogger\nimport org.apache.logging.log4j.kotlin.loggerOf\n\n\nobject Log4j2LoggerFactory: AbstractPlatformLoggerFactory {\n    override fun create(tag: String, ofClass: Class\u003c*\u003e): PlatformLogger = Log4j2Logger(tag, ofClass)\n}\n\nclass Log4j2Logger(private val tag: String, ofClass: Class\u003c*\u003e) : PlatformLogger {\n    private val logger = loggerOf(ofClass)\n    override fun fatal(message: () -\u003e String) {\n        logger.fatal(message)\n    }\n\n    override fun error(message: () -\u003e String) {\n        logger.error(message)\n    }\n\n    override fun warn(message: () -\u003e String) {\n        logger.warn(message)\n    }\n\n    override fun info(message: () -\u003e String) {\n        logger.info(message)\n    }\n\n    override fun debug(message: () -\u003e String) {\n        logger.debug(message)\n    }\n\n    override fun trace(message: () -\u003e String) {\n        logger.trace(message)\n    }\n}\n```\n\n### Simple logger for Java backend applications\n\nA possible implementation for logging with just println:\n\n```java\npublic class SimpleLoggerFactory implements AbstractPlatformLoggerFactory {\n    @NotNull\n    @Override\n    public PlatformLogger create(@NotNull String tag, @NotNull Class\u003c?\u003e ofClass) {\n        return new SimpleLogger(tag, ofClass);\n    }\n}\n\nclass SimpleLogger implements PlatformLogger {\n  private final String tag;\n  private final Class\u003c?\u003e ofClass;\n\n  public SimpleLogger(String tag, Class\u003c?\u003e ofClass) {\n    this.tag = tag;\n    this.ofClass = ofClass;\n  }\n\n  @Override\n  public void debug(@NotNull Function0\u003cString\u003e message) {\n    System.out.println(buildMessage(\"DEBUG\", message));\n  }\n\n  @Override\n  public void error(@NotNull Function0\u003cString\u003e message) {\n    System.out.println(buildMessage(\"ERROR\", message));\n  }\n\n  @Override\n  public void fatal(@NotNull Function0\u003cString\u003e message) {\n    System.out.println(buildMessage(\"FATAL\", message));\n  }\n\n  @Override\n  public void info(@NotNull Function0\u003cString\u003e message) {\n    System.out.println(buildMessage(\"INFO\", message));\n  }\n\n  @Override\n  public void trace(@NotNull Function0\u003cString\u003e message) {\n    System.out.println(buildMessage(\"TRACE\", message));\n  }\n\n  @Override\n  public void warn(@NotNull Function0\u003cString\u003e message) {\n    System.out.println(buildMessage(\"WARN\", message));\n  }\n\n  private String buildMessage(String level, Function0\u003cString\u003e message) {\n    return level + \" \" + ofClass.getSimpleName() + \" \" + message.invoke();\n  }\n}\n```\n\n\n## Todo\n\n- Implement more HSDP API calls\n\n\n## Issues\n\n- If you have an issue: report it on the [issue tracker](https://github.com/philips-software/kotlin-hsdp-api/issues)\n\n\n## Contact / Getting help\n\nAad Rijnberg (\u003caad.rijnberg@philips.com\u003e) \\\nMeindert Schuitema (\u003cmeindert.schuitema@philips.com\u003e) \\\nMartijn van Welie (\u003cmartijn.van.welie@philips.com\u003e)\n\n## License\n\nSee [LICENSE.md](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilips-software%2Fkotlin-hsdp-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphilips-software%2Fkotlin-hsdp-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilips-software%2Fkotlin-hsdp-sdk/lists"}