HFE: Conditions should have a pointer for the form_field it was created through

Tags: #<Tag:0x00007f0f2391cbf0>

Thanks @angshuonline.

I didn’t mean the form name, the form namespace is what is always hardcoded to be "Bahmni".

As for the "-0" suffix. Ok, so that looks like the equivalent of what can be done with HFE’s <repeat/>, except that it’s not implemented yet in Bahmni Forms 2.0 then, is my understanding correct?

So what I’m getting at are the two components of the form namespace and path that are always hardcoded so far:

  1. the "Bahmni" namespace prefix and
  2. the "-0" suffix.

They seem to provision for a use case that is not yet implemented and I wanted to get some insight about the history of their origin.

Add more has been implemented in Bahmni Forms for many year now! 0 is not hardcoded. The index will change when you add another obs using the same control.

Regarding “Bahmni” prefix - yes. The prefix helps us to parse the formnamespace for obs that were captured using Bahmni.

@mksd so based on my understanding of the current pattern for Bahmni maybe for HFE we could do something like this:

<htmlform id="vitals-form" formUuid="68728aa6-4985-11e2-8815-657001b58a90"
          formName="Vitals" formEncounterType="4fb47712-34a6-40d2-8ed3-e153abbd25b7"

   <obs conceptId="CIEL:Weight" formPath="weight"/>

   <obsgroup conceptId="CIEL:Blood Pressure" formPath="blood_pressure">
       <obs conceptId="CIEL:Systolic" formPath="systolic"/>
       <obs conceptId="CIEL:Diastolic" formPath="diastolic"/>


obs concept_id="(primary key of CIEL:Weight concept)"

obs concept_id="(primary key of CIEL:Blood Pressure concept)"

obs concept_id="(primary key of CIEL:Systolic concept)"

obs concept_id="(primary key of CIEL:Diastolic concept)"

Not sure if we need/use the -0 prefix, but we could assume that’s implied, or add if automatically if we feel that is necessary.

Also, I just called the namespace “htmlformentry”… not sure if this is the right name (maybe just “hfe”?), or even conceptually right (ie the namespace is based on the form entry technology… we actually have some cases currently where the Registration workflow enters observations, but then we use HFE to edit them… ie we interact with the same obs via two different technologies).

Take care, Mark

Thanks @mogoodrich!

Obviously you have tried to fit to the de facto standard established by Bahmni. Aka:

{form namespace}^{form name}.{form version}/{control id}-{n}

If that works for you guys, and that no one else speaks out, then that is fine to us as well :slight_smile:

1 Like

Sure @mksd… I used a slightly different model with the form stuff I build in openmrs-react-components, which we do use in production, but that will probably become “orphaned” functionality, so better to be consistent with a standard we will use going forward across multiple form technologies, and it does sound like Bahmni is currently the de facto standard.


@mogoodrich Would the form_namespace_and_path be generated automatically?

@ssmusoke in HFE I think no, unless of course you explicitly do this kind of stuff:

<obs conceptId="CIEL:Systolic" formPath="systolic"/>

That’s because for the sake of being backward compatible the attribute formPath will remain optional.

Yes, that’s what I was thinking @ssmusoke.

Though it should become considered “best practice” to use the formPath going forward.

For all those who are good at naming, what do you prefer for the new interface:

  • FormRecordable
  • FormField
  • HasFormField
  • IsFormField
  • … ?

Looking at Obs’ existing methods, it should therefore look like this:

public interface FormField {
  String getFormFieldNamespace();
  String getFormFieldPath();
  void setFormField(String namespace, String formFieldPath);    

We would start by making Obs itself follow the new pattern:

public class Obs extends BaseChangeableOpenmrsData implements FormField {

… to then expand it to Condition and other encounter-linked entities.

@burke @dkayiwa @jdick @mogoodrich?

Cc @luis.oliveira

FWIW, this one has my vote:

It’s worth a lot! Thanks @ibacher, noted. Let’s wait a little longer for the others. And then, those who remain silent implicitly agree :wink:

My input using a longer specific interface and shorter methods

public interface FormFieldPathAndNamespace {
  String getNamespace();
  String getPath();
  void setPathAndNamespace(String namespace, String path);    

I will cast my vote after you propose javadoc descriptions to the interface and methods. :smile:

1 Like

@dkayiwa you are a very hard to please but challenge accepted

 * This interface provides a namespace and path parts on an Obs to the form field from which it was created.
 * A complete example of a pointer is '{namespace}^{formName}.{formVersion}/{path.id}'
public interface FormFieldPathAndNamespace {
     * The namespace for the form field, examples are Bahmni, OpenMRS, or implementor specific like KenyaEMR, PIHMalawi, UgandaEMR
     * @return
    String getNamespace();

     * The path to the form field within the form needs to be unique even if this functionality is not enforced in this interface
     * @return
    String getPath();

     * Set the namespace and the path for the form field, the path is optional to maintain backwards compatibility 
     * @param namespace
     * @param path
    void setPathAndNamespace(String namespace, String path);

@ssmusoke actually, it was meant for @mksd :slight_smile:

Another thought would be to try to disassociate this from “forms”, and think of it just as data that can be referenced in a consistent way with a pre-defined identifier. I’m not particularly great at naming, but something along the lines of “Identifiable” or “Trackable” or “Referencable” or something… This would also be somewhat consistent with our pattern of “Auditable”, “Attributable”, “Voidable”, and other Openmrs-related interfaces.

@mseaton Is there a use-case for this kind of thing outside of the context of “forms”? I.e., the structure being proposed here seems (to me) pretty specific to forms.

A different approach, that make some sense, is, instead of tying directly from, say, an Obs / Condition to the form field, we have some kind of look-up table for linking between Obs and the form field the obs belongs to. That could remove the form-specific stuff from Obs / Condition, etc. where, arguably, they don’t belong. That said, the nice part about this proposal is that it’s leveraging the existing data model.

@ibacher - it’s a fair point. I was just throwing it out there to raise the question, but I suspect that’s true. I’m certainly prepared to put my support behind FormRecordable.

I raised this only because it seems to me that the goal is to be able to say that - if a given question is asked and answered several times in the same encounter - that a piece of data represents a specific instance of that question and answer. It’s true that this is generally useful for associating back with the form in question that recorded it (so that data can be rendered and viewed as it was entered). Maybe this is the only use case we envision. Of course, even if this is geared around forms, it is still something that would be consumed outside of those forms (eg. reports, patient summaries, etc).

The driving use case is to be able to re-populate forms. Another use case would be to be able to track any data collected to the source and/or context in which it was collected. In a generic since, that’s provenance (which is more about the source than it is the context). I think a form-specific approach to address the initial driving use case (re-populating a form) and being able to identify context (what prompt was shown to the user when the data was collected) and leave provenance (the source of data) to a separate & broader mechanism.

@ssmusoke I’d love that, but changing the signatures is just going to make this way more complicated.

In regards to the naming, looks like folks seem to like able suffixed interfaces :wink: It’s kind of a standard, at least in OpenMRS. Thanks a bunch for the JavaDoc on my behalf :wink: However it was already there :sweat_smile:

So where are we at, form-specific or tracking from any source?