Monday, July 24, 2023

GSoC 2023 at OpenMRS | Coding Period Week 08

 


Introduction

Greetings, readers!

Welcome to my blog documenting my incredible journey through the 8th week of Google Summer of Code (GSoC). Over the past weeks, i have had the privilege of working with the OpenMRS community, contributing to the fhir2 module. With each passing week, i have learned and grown as a developer, and the 8th week was no exception. Let's dive into the highlights of the eventful week!

Highlights

Add Support for Patch Operations on Immunization resource

implemented all patch operations on the Immunization resource i.e Json Merge Patch, Json Patch and Xml Patch. This one needed careful handling since it was being saved as an Obs object.

Add Support for Update and Patch on Observation resource

this was continuation from last week and i had not yet figured out i was losing the functionality of creating a new obsid when patching an observation like it is in updating an obs object. However, i achieved that and it was more to do with the data set i was using for the integration test.

Others include:

Conclusion

The 8th week was a whirlwind of challenges and accomplishments. The support and mentorship from Ian Bacher and Abert Namanya and the entire community has been instrumental in my growth as a developer.

As i reflect on last week's achievements, i am reminded of the power of open-source collaboration and the impact we make by working together. GSoC has been an unforgettable experience, and i am excited to continue contributing to open-source beyond this program.

Thank you for joining me on this incredible journey. Stay tuned for more updates as i embark on the final leg of GSoC, with new challenges and opportunities awaiting.

Until next time!
Cheers!

Monday, July 17, 2023

GSoC 2023 at OpenMRS | Coding Period Week 07

Introduction

Greetings, dear readers!

I am delighted to share with you an update on my exhilarating coding journey during WEEK 7 of the Google Summer of Code (GSoC) program. This incredible experience has allowed me to delve into the depths of programming, further honing my skills and embracing new challenges along the way.

Over the past 6 weeks, i have been engaged in an exciting project called Add Support for FHIR Patch operations. The program has provided me with an invaluable platform to collaborate with mentors and work on a real-world software development project. To have a recap of how the six weeks have been, please look through my weekly blogs so far.  You can aswell find the short demo video for my midterm evaluation at https://www.youtube.com/watch?v=P-0gj-8LOCE.

Week 7 Recap

In week 7 i embarked on completing the resources that i had not yet covered for XML PATCHing which included Location resource, Encounter resource. Below are the pull requests for the two resources:-

As part of week 7, i also attempted an issue to clean up parameter passing on the condition resource. I realized there is a little more work needed in making the right functionality come out. This is so because the OpenMRS FHIR implementation of the Condition Resource was twice because in the versions below OpenMRS 2.2.0, the Condition resource was not supported. So the translation of that resource in the Fhir2 module was based off of the Obs object. And in the second implementation, it was based off the Condition object which was introduced in the openmrs data model in the versions 2.2.0 and above. The integration tests for the versions below 2.2.0 were not properly written since they included the clinicalStatus which wasn't part of that particular version. Below is the pull request for that more.
The task i had in Week 7 was to ensure that the Observation Resource supports PATCHing operations. However, to introduce that i had to ensure that it can support UPDATING requests which i did in the commit below:-
Maybe a little context of what actually takes place here, the Obs object in OpenMRS is a unique object and hence usually refered to as immutable. This can further be explained that when an existing obs object is edited/updated, the existing obs object with the existing obsId is voided and a new obs object with a new obsId is created hence a new row in the database altogether.
After supporting UPDATE, next task i attempted was ensuring that it supports PATCHing. However, the challenge here that has blocked me from completing this task this week is that unlike the UPDATE which voids the existing obs object when updating it, with PATCHing the behavious is not really coming out as it should. It does not void the exisiting obs object hence returning the same object but patched. The saveObs() method seems to consider the patched object  as a saveObsNotDirty() yet it is supposed to be a saveExistingObs(). Below is the commit for patching;-

Looking Ahead

As i step into the 8th week, i remain confident that the challenges i am having on Observation Resource will be overcome and it will be able to support PATCHing as it should. I will continue to follow the project timeline diligently, seeking guidance from my mentors and the entire community and give feedback when needed to ensure the successful completion of my assigned tasks.

Stay tuned for more updates as i continue this exhilarating journey! 
Thank you for joining me on this blog post, and until next time!

cheers,
mherman22

Monday, July 10, 2023

GSoC 2023 at OpenMRS | Coding Period Week 06

 

Welcome to the sixth week of my Google Summer of Code (GSoC) journey! It's hard to believe how quickly time has flown by as I continue to dive deeper into my project and explore new territories. This week has been full of exciting challenges and rewarding accomplishments, pushing me further towards my goals.

Throughout the program, I have had the opportunity to work closely with dedicated mentors and a vibrant community of like-minded developers at OpenMRS. Their guidance and support have been invaluable in shaping my understanding the FHIR Api and how OpenMRS leverages its functionality. As I reflect on the progress made so far, I am filled with a sense of gratitude and enthusiasm for the road ahead.

In this blog post, I will delve into the highlights and key learnings from the sixth week of my GSoC project. I will share the hurdles I encountered, the strategies I employed to overcome them, and the valuable insights gained along the way. Additionally, I will provide updates on the project's overall direction and discuss the exciting features and improvements implemented during this period.

Join me as I recount the fascinating moments, breakthroughs, and challenges encountered in the sixth week of my GSoC journey. I hope that my experiences and insights can inspire and resonate with fellow developers, and perhaps even offer valuable takeaways for those embarking on similar endeavors.

Without further ado, let's dive into the adventures of the past week and explore the strides taken towards making a meaningful contribution to the open-source community through my GSoC project.

Goal of the week

  • Ensure that XML PATCHing works as it should on all the Fhir Resources that support patching in the OpenMRS Fhir2 Module. They should be able to take in an xml document like the one shown below:
<?xml version="1.0" encoding="UTF-8" ?>
<!--
    This Source Code Form is subject to the terms of the Mozilla Public License,
    v. 2.0. If a copy of the MPL was not distributed with this file, You can
    obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
    the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
    Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
    graphic logo is a trademark of OpenMRS Inc.
-->
<diff xmlns:fhir="http://hl7.org/fhir">
	<replace sel="/fhir:MedicationDispense/fhir:status/@value">
		completed
	</replace>
</diff>

Let us break down the xml document for better understanding of what is going on there:-
  1. The root element is named diff and it belongs to the XML namespace "http://hl7.org/fhir". Namespaces allow for the differentiation of elements with the same name but belonging to different contexts or specifications. 
  2. Within the diff element, there is a child element named replace. It specifies the XPath expression sel attribute which selects a specific attribute value in the XML document. In this case, it selects the value attribute of the status element under the MedicationDispense element in the FHIR namespace. The text content within the replace element is completed, indicating the new value that will replace the selected attribute's current value.Therefore, the above XML patch document  modifies an existing XML document in the OpenMRS Fhir2 Module.

Highlights / Pull Requests


Thanks for taking time to go through the blog! 
Nice week ahead, cheers!

Sunday, July 2, 2023

GSoC 2023 at OpenMRS | Coding Period Week 05

 


 Welcome to this week's blog that gives an account of what happened last week as I continue in this journey. Last week was an eventful week in terms of getting most of my pull requests merged into the openmrs-module-fhir2. Most of these pull requests were catering for JSON PATCHing and XML PATCHing operations.

The merged pull requests include the following:-

For the past week i have looked into https://issues.openmrs.org/browse/FM2-591 which ensures to fully translate the ServiceRequest Fhir Resource into the OpenMRS datamodel's object called TestOrder. I created a talk post at https://talk.openmrs.org/t/toopenmrstype-translator-for-servicerequest-should-be-implemented/39980/1 where i needed help in translating some elements of the ServiceRequest resource like intent, status and performer

During our weekly meetings, my mentors took me through how i should overcome the issue. For the intent element, there is no need to translate it to openmrsType since it is hardcoded as ServiceRequest.ServiceRequestIntent.ORDER.

For performer. i would have to reverse engineer the current implement in the toFhirResource method.  Here is the method to reverse engineer. and after doing so i will go through all the other elements that need to be translated and hopefully have this implemented this week.

	private Reference determineServiceRequestPerformer(String orderUuid) {
		IBundleProvider results = taskService.searchForTasks(new TaskSearchParams(
		    new ReferenceAndListParam()
		            .addAnd(new ReferenceOrListParam().add(new ReferenceParam("ServiceRequest", null, orderUuid))),
		    null, null, null, null, null, null));
		
		Collection<Task> serviceRequestTasks = results.getResources(START_INDEX, END_INDEX).stream().map(p -> (Task) p)
		        .collect(Collectors.toList());
		
		if (serviceRequestTasks.size() != 1) {
			return null;
		}
		
		return serviceRequestTasks.iterator().next().getOwner();
	}

With the merging of the above pull requests that catered for JSON PATCHing, JSON MERGE PATCHing and the XMLPATCHUtils class that introduces XML PATCHing, i can now(this week) move onto writing integration tests for the other resources to ensure and confirm they implement XML Patching operations.

Thanks for taking time and reading through.

Monday, June 26, 2023

GSoC 2023 at OpenMRS | Coding Period Week 04

You are welcome to this week's blog. This marks week number 4 of this year's GSoC coding period. I am excited to share what i have been able to achieve throughout this entire week. 

This week i have laboured to look into XML PATCHing and how to implement that in the OpenMRS Fhir2 Module. I started off by creating a utils class in the Util directory within the api directory. I will break down the contents of the class below, please follow along;-

First of all, it contains a static method applyXmlPatch that handles XML patch operations for resources in the context of the FHIR (Fast Healthcare Interoperability Resources) standard.

public static <T extends IBaseResource> T applyXmlPatch(FhirContext theCtx, T theResourceToUpdate, String thePatchBody) {

The applyXmlPatch method is declared as public static, which means it can be accessed without creating an instance of the XmlPatchUtils class. It takes three parameters: 

  • theCtx: An instance of FhirContext representing the FHIR context. 
  • theResourceToUpdate: An object of type T that extends IBaseResource, which represents the resource to be updated.
  • thePatchBody: A String containing the XML patch to be applied to the resource.
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) theResourceToUpdate.getClass();

The above line retrieves the class of the theResourceToUpdate object and casts it to Class<T>. It is used later for parsing the patched resource.

String inputResource = theCtx.newXmlParser().encodeResourceToString(theResourceToUpdate);

This line encodes the theResourceToUpdate object into an XML string using the newXmlParser() method of the theCtx object.

ByteArrayOutputStream result = new ByteArrayOutputStream();
try {
    Patcher.patch(new ByteArrayInputStream(inputResource.getBytes(Constants.CHARSET_UTF8)),
        new ByteArrayInputStream(thePatchBody.getBytes(Constants.CHARSET_UTF8)), result);
}
catch (IOException e) {
    throw new InvalidRequestException(e);
}


 The above block of code performs the XML patching operation using the Patcher.patch method. It takes the encoded input resource as a ByteArrayInputStream, the patch body as another ByteArrayInputStream, and writes the patched result to the result ByteArrayOutputStream.

return theCtx.newXmlParser().parseResource(clazz, toUtf8String(result.toByteArray()));

Finally, this line parses the patched resource from the result byte array using the newXmlParser() method of the theCtx object. It specifies the resource class (clazz) and uses the toUtf8String method to convert the byte array to a UTF-8 encoded string.

Overall, this code provides a utility method for applying XML patches to FHIR resources using the FHIR context and XML parsing capabilities provided by the FhirContext class.

To achieve the patching, we have utilized a library developed by dnaut and can be found at https://github.com/dnault/xml-patch.

I added the dependency to the root pom.xml file in the OpenMRS Module Fhir2 as shown below:-

            <dependency>
                <groupId>com.github.dnault</groupId>
                <artifactId>xml-patch</artifactId>
                <version>0.3.1</version>
            </dependency>

This and more can be accessed from the pull request at https://github.com/openmrs/openmrs-module-fhir2/pull/493.

Thanks for taking time to read through.

Monday, June 19, 2023

GSoC 2023 at OpenMRS | Coding Period Week 03

 

Week three(03) of my GSoC journey was a move into the right direction since it involved assessment of my work so far on my part so as to forge a way forward to meeting all the project objectives. Welcome to the past week's blog post and i hope you enjoy the read or better yet pick something useful from it.

Like the forecast was from last week, this week was more into code reviews and finishing up on some of the resources. I began the week by adding Encounter resource to the resources that need to support json merge patch and json patch operations. 

However the patching was not happening for the Encounter resource and the error below was being returned. Actually this blocker consumed a big chunk of my time this week.

Expected: response with HTTP status indicating request was handled successfully
     but: response with status code <500> with message "Failed to call access method: org.hibernate.HibernateException: A collection with cascade=\"all-delete-orphan\" was no longer referenced by the owning entity instance: org.openmrs.Encounter.encounterProviders"

The issue here was that somehow we deleted an encounter but not the encounterproviders attached to the encounter. This was brought about by how the translation of the Fhir Encounter resource to the OpenMRS Encounter data model was done. On further investigation and consultation with my mentor, we came with a fix for that as can be seen at https://github.com/openmrs/openmrs-module-fhir2/pull/489.

The rest of the week i embarked on making changes as was advised by my mentor especially on the integrations. I  had to migrate them the Integration tests 2.2 directory to the integration tests directory. The former is based of openmrs v2.2 whereas the latter is based off openmrs v2.0.5 so since most resources were supported by openmrs v2.0.5, it was fine to have all our integration tests in that folder save for a few which are not supported upto until version 2.2.

During our weekly meetings with my mentor, part of agenda was the discussion on the need to discuss the projected length of the project for administrative purpose. I wont dive into the reasons here, i am just highlighting it among the developments from last week.

Part of my projections last week was to be able to start on XML Patching but most of the week was taken up in fixing the Encounter resource and making changes as advised on our weekly call.

Appreciation to my mentor Ian for the time he offers to have me unblocked or learn something new. 

Thanks for the taking your time to read through.

Onto next week enthusiastically 😎

Sunday, June 11, 2023

GSoC 2023 at OpenMRS | Coding Period Week 02

Comes another opportunity for me to update my blog with the experience i have had in the past week as i was working on my GSoC project. Here's the Coding Period Week 01 blog in case you missed it. I will breakdown my writing today into the various tickets/issues i encountered throughout this week. I was lucky to have some of work merged this week and it felt awesome 😍.

toOpenmrsType translators should set uuid to id part of id, not full: This ticket was created to fix the bug that was on a couple of the resources. This would cause an error where the uuid provided would exceed the maximum length which is 38. For example when i tried doing a patch operation on the patient resource, the error i got was failed to validate with reason: uuid: This value exceeds the maximum length of 38 permitted for this field. This was fixed and merged into master to cater for all other resources it could be affecting.

Add support for Json Patch operations - Patient Resource: This was meant to introduce the json patches to work along with the json merge patches as i explained in the previous blog. This work was also merged into master and it was able to unblock all the other tickets that would wish to implement any of the two patch formats. The rest of  the implementation can be at this commit.

Add Support for Json Merge Patch - Service Request Resource: This was meant to introduce json merge patch operations to the Service Request resource. However, this resource was not fully translated into the OpenMRS data model. Hence after spending hours on it, my mentor advised that i created a ticket for it but that could be out of scope for this project. So for future work on the module i ticketed the required changes at https://issues.openmrs.org/browse/FM2-591. This therefore means that the Service Request resource could also be out of scope for this project unless towards the end i get sometime at hand to dive into fully translating the resource.

Add support for Json Merge Patch operations - Medication: This was meant to introduce json merge patch operations to the Medication Resource. The pull request has been sent in and it is await review and hopefully merging into master. While working on this, i realized that the OpenMRS fhirIG index page didn't cater for the Medication resource so that it is easier to locate on the IG so i pushed a followup commit to ensure it does that and it is awaiting review and merging.

This was pretty much it from this past week and i am hoping this week will be more of review of the many pull requests i have created and having them merged. I also intend to work on the integration tests to test out the json patch functionality on the resources.

Thanks for taking your time to through, cheers 🍸🍷