A Django site.
May 30, 2008
» Tribe as a person attribute object


So far everything was going okay. Tonight I implemented the Attributable interface. Now I can add tribe as a person attribute using the manage person attribute types page in the OpenMRS administration. But I cannot add or edit values for tribe person attribute type. I checked the source to learn how location and other person attributes are doing it.

I have to add a FieldGenHandler for the tribe object to make it editable and to let the user add or make changes to the tribe field. But so far all the FieldGenHandlers are made for core OpenMRS objects. My mentor Ben provided a fix to register handlers outside the core system. For the last 3 days Ben has checked in code to fix some issues I faced within a few minutes after I asked, without which could not proceed with coding.

May 29, 2008

Kevin Peters
KevinPeters
Google Summer of Code 2008 is about »
» Logic Web Service API Details

Below are the details I interpreted from tracing through the various Logic Service methods like getting filters and tags as well as constructing a query to more fine tune a request. Appreciate any feedback or comments on any more details or any misinterpretations that I made.

Also, the project requirements are still a work in progress but are outlined here.

Details on the API

The org.openmrs.logic.LogicService class is an interface. The org.openmrs.logic.impl.LogicServiceImpl class is the default implementation for this interface.

The get and add methods use the org.openmrs.logic.RuleFactory to return or add their data. As a temporary hack, when initialized, the RuleFactory adds the following hard coded rules: [AGE, BIRTHDATE, DEATH DATE, GENDER, HIV POSITIVE, CAUSE OF DEATH, DEAD, BIRTHDATE ESTIMATED].

The following are details on all the get methods:

  • getDefaultDataType(String token)
    • The data type for a token is returned via RuleFactory.
    • The getDefaultDatatype method of the org.openmrs.logic.rule.Rule interface is called on the token. The AgeRule, EnrolledBeforeDateRule, HIVPositiveRule, and ReferenceRule classes all implement this class and return different data types as appropriate.
  • getLogicDataSource(String name)
  • getLogicDataSources(Map<String, LogicDataSource> logicDataSources)
    • Gets all the registered logic data sources via RuleFactory.
  • getParameterList(String token)
    • Returns the expected parameters for a rule under which the passed token is registered via RuleFactory.
    • The getParameterList method of the Rule interface is called on the token (similiar to getDefaultDataType). The AgeRule, EnrolledBeforeDateRule, HIVPositiveRule, and ReferenceRule classes all implement this class. All of these implementer classes return null when queried for the parameter list.
  • getRule(String token)
    • Pass the token under which the rule was registered.
    • Uses the RuleFactory class and returns an org.openmrs.logic.rule.ReferenceRule based on that token if the token starts with "%%".
  • getTagsByToken(String token)
    • Uses the RuleFactory class and returns all of the tags that are attached to a give token.
  • getTokens()
    • returns the Set of all hardcoded rules via the RuleFactory.
  • getTokensByTag(String tag)
    • returns the Set of all hardcoded rules that match the tag argument via the RuleFactory.

The following are the details on all the add methods:

  • addRule(String token, Rule rule)
    • Uses RuleFactory to first make sure that rule doesn't already exist.
    • If rule does not already exist, the rule is registered under the given token.
  • addRule(String token, String[] tags, Rule rule)
    • Same as addRule method described above except for it assigns given tag(s) to the rule at the same time.
  • addTokenTag(String token, String tag)
    • Uses RuleFactory to add a tag to a previously registered token.

There are many eval methods that are used to filter the token/tag data to return specific information. The org.openmrs.logic.LogicCriteria class is used to setup the criteria for the filtering. The eval methods are basically a series of methods that massage the query to eventually use org.openmrs.logic.LogicContext to evaluate a rule with LogicCriteria for a single patient. The evaluations can be done for a single patient or a list of patients (cohort). The following are more details on the eval methods:

  • Single patient
    • eval(Patient who, String token)
      • Gets information for a given token for a given patient.
      • A LogicCriteria object is created based on the token.
      • Uses eval(Patient who, LogicCriteria lc) discussed below.
    • eval(Patient who, String token, Map<String, Object> parameters)
      • Gets information for a given token and parameters for a given patient.
      • A LogicCriteria object is created based on the token and parameters.
      • Uses eval(Patient who, LogicCriteria lc) discussed below.
    • eval(Patient who, LogicCriteria criteria)
      • Evaluates a query for a given patient.
      • Uses eval(Patient who, LogicCriteria criteria, Map<String, Object> parameters) discussed below.
    • eval(Patient who, LogicCriteria criteria, Map<String, Object> parameters)
      • Creates a LogicContext object with the given patient.
      • The query is evaluated via the LogicContext object and an org.openmrs.logic.result.Result is returned.
  • List of patients
    • eval(Cohort who, String token)
      • Gets information for a given token for a list of patients.
      • A LogicCriteria object is created based on the token.
      • Uses eval(Cohort who, LogicCriteria criteria) discussed below.
    • eval(Cohort who, String token, Map<String, Object> parameters)
      • Gets information for a given token and parameters for a list of patients.
      • A LogicCriteria objects is created based on the token and parameters.
      • Uses eval(Cohort who, LogicCriteria criteria) discussed below.
    • eval(Cohort who, LogicCriteria criteria)
      • Evaluates a query for a list of patients.
      • Uses eval (Cohort who, LogicCriteria criteria, Map<String, Object> parameters) discussed below.
    • eval(Cohort who, LogicCriteria criteria, Map<String, Object> parameters)
      • Creates a LogicContext object with the list of patients.
      • The query is evaluated for via the LogicContext object for each patient id and a Map of Result and patient id pairs are returned.
    • eval(Cohort who, List<LogicCriteria> criterias)
      • This is similiar to the previous eval discussed above except that it evaluates a collection of queries instead of a single query for a set of patients.
      • Each query is evaluated via the LogicContext object for each id and a Map of each LogicCriteria is paired with a Map of Result and patient id pairs.

The LogicContext is what does the "work" for all the above discussed eval methods of the LogicService implementation. It evaluates a rule with criteria and parameters for a single patient. Each rule is evaluated as appropritate depending on the implementing class (AgeRule, EnrolledBeforeDateRule, HIVPositiveRule, and ReferenceRule). The Result from each class is put in a patient id / Result map. The LogicCriteria is then applied to these results via the private applyCriteria() method of the LogicContext class. For now, this method looks like it doesn't do anything and just returns the results without applying the criteria.

The following are some other miscellaneous methods:

  • findToken(String token)
    • Returns all known tokens based on the lookup string passed.
    • Uses the RuleFactory class to look through the registered tokens and return the Set that matches the lookup string.
  • findTags(String partialTag)
    • Returns a Set of tags based on the lookup string passed.
    • Uses the RuleFactory class to look through the tags and find tags that match the lookup string.
  • updateRule(String token, Rule rule)
    • Looks up the rule based on the token passed and replaces it with the rule passed.
    • The RuleFactory class makes sure that it exists and updates with the new rule if it does.
  • removeRule(String token)
    • Removes a rule for the token passed.
    • The RuleFactory class makes sure that the rule to be removed exists and removes it from the rule map if it does.
  • removeTokenTag(String token, String tag)
    • Removes a token's previously assigned tag.
    • The RuleFactory class makes sure that the the token had the given tag and then removes it.
  • registerLogicDataSource(String name, LogicDataSource logicDataSource)
    • Adds a LogicDataSource to the logic service with the given name.
  • setLogicDataSources()
    • Adds multiple LogicDataSource objects to the current data sources in the logic service.
    • Uses registerLogicDataSource method discussed above.
  • removeLogicDataSource()
    • Removes a logic data source from the list.

» Web interface of the tribe module


Tonight I assembled the tribe module and got it working. So far I have just extracted the code but did not try to run it.  Tribe add, update and retire features are working okay. So far the tribe objects are working separately from the core OpenMRS system. The tribe module can create and update the tribe objects but the tribe objects have no interaction with the rest of the system.

Now what I have to do is transform the tribe object to a person attribute compatible object. I am using the existing Location object as the reference for the implementation. But tribe object is an entity that resides in an external module, while location is an object which exist inside the core OpenMRS system.  I could not find person attribute which exist in a module. Person attributes are objects attached to a person object. By the way the patient and the user objects are derived classes of the person class. To make the tribe object a person attribute compatible object I have to implement the Attributable interface as the first step.

May 28, 2008
» GSoC 2008

It's very, very difficult to believe that a year has gone by since I started this blog, and it's already time for Google Summer of Code 2008.

I see I haven't made a post since last August. It seems that whenever I try to blog, I inevitably run into the dilemma of being busy enough to have tons of stuff to blog about, but being too busy to actually blog about it. Hopefully I'll get a good run before I end up doing that again. Here is a very brief summary of what I've been up to since last summer:

* I'm no longer working on my project for OpenMRS. It's moving on in new and exciting directions and I believe there's some GSoC work being done on it this year. I plan to work on their documentation restructuring project with Michelle Murrain, which will hopefully be a project that I continue with well after the summer.

* I have an iPhone! It's fantastic. I've never owned a cell phone before, but this is so much more than a phone. I immediately jailbroke it and installed many extraordinarily useful applications. I don't know what I'd do without this - I've gotten so much utility out of it. It's great having Internet everywhere I am, even if it is EDGE. Now that the iPhone SDK is out, I really hope I'll have some time to hack around and make my own apps.

* I got an XO! I asked for the give one get one program for Christmas. Unfortunately, I haven't had much time to dedicate to hacking on it, but I have some ideas.

* I took "Intro to Computation" in school, which is basically discrete math. I learned a lot of really cool things, and next semester I'm taking Intro to Algorithms, Intro to Software Engineering, and Programming Language Paradigms. Good stuff.

* My ThinkPad died =( Something weird happened - it would cycle from battery to AC adapter rapidly, and wouldn't hold a charge. One day the plastic of the adapter melted within the plug, and I can't charge or use it. Otherwise, it's fully functional, and I was thinking of getting a dock and charger to see if I could use it like that.

* I replaced the ThinkPad with...a Blackbook! Wonderful machine. The built-in resolution is a bit small, but I have it hooked up to my 19" LCD and am using a dual-monitor setup so I have lots of screen real estate. Good stuff.

* I have a couple of awesome new lenses for my camera, but that's a story for another blog =)

This year, I've been accepted to GSoC to work with the Software Freedom Conservancy on a project to modernize their web annotation system. Proposal here. I'll be working with JavaScript and jQuery to write the system, so I've been reading tutorials for both and playing around. jQuery looks really, really cool. I'm excited. I'm working with Joshua Gay, an active member of the free software community. I've actually known him for years now - we met through a mutual friend and he used to go to the same school as me. I anticipate having a really good working relationship with him and getting some good stuff done.

That's all for now. Check back for updates!

» OpenMRS Registration Module Begins

The Google Summer of Code 2008 timeline shows that we start coding from 26th May and I've already started coding. Before the coding there was thislogo "Community Bonding Period", and I'm not sure if I've done bonding with my community members, but sure I've been talking with my mentor Brian... and he's really a cool guy! We talked a lot about technical as well as personal stuff. He invited me to this house virtually through Google Street View and it was really nice talking to him. I bonded with him well !!

In the meantime, I have been pondering and working on the ideas for the OpenMRS Registration Module.  My Introductory post on OpenMRS showed a lot of interest from friends and got a lot of questions from colleagues. Thanks to r0bby, who told me on the IRC about SoC and talked about contributing to OpenMRS.

The work on the Registration Module has begun and I created the Registration Module documentation page. It is still incomplete on the UML diagrams, but is good enough to show the workflow through the Use-case. Brian and I have also worked on my project plan and have made a timeline that I need to follow. The timeline is a good motivator and will be putting that up on the project page as well. OpenMRS and open-source developers in general, advocate the idea of quick and early commits. OpenMRS shares the Story of FLOSS to make this idea stand out. I'm still trying to get into this mould of development, coz I mainly advocate the planning/design approach. You take twice as much time to design compared to code, but I need to get agile and work on the Bazaar way of open-source. More eyes... More interest and faster working deliverable!!

With this in mind, I tried to commit the basic module changed to registration module, but it gives me a 403 error:

Error: CHECKOUT of '/!svn/ver/4193/openmrs-modules/registration': 403 Forbidden (http://svn.openmrs.org)

I can login through the trac web page. So probably some issue with either my SVN client (TortoiseSVN) settings... or something on the SVN server side!!

» Removing tribe from the core OpenMRS


Tonight I went through the OpenMRS source and removed the tribe functionality.  The useful parts were extracted to the new tribe module. The tribe module will host the tribe object and functionality to create, update and delete tribe modules. Tribe administration page will be hooked up to the OpenMRS from the OpenMRS administration page through an extension point. OpenMRS code is a pleasure to work with. In a couple of hours I was able to clean up the tribe code from the OpenMRS code.

May 27, 2008
» OPENMRS: GSoC 2008 Coding Starts


Before this “Code up” date starts,it was a community bonding period .I was supposed to get know more about the organization (OPENMRS), have the coding environment set up and running on my machine and get familiar with the project code . I think the biggest challenge was to get my project running . Even after checking out the source code from the repository via Subversion, there was so many settings to run in MySql , Tomcat , System Variables change some login privileges and roles in the code and others. I think this may be a common challenge in Open source development when you are disconnected from the online community , and it’s hard to find someone else to help you .

During the community bonding period I had a Conference call with my mentor Maros and sometimes logged into the OpenMRS IRC just for some technical assistance and see what is going on with the other guys .Today I got introduced to e new OpenMRS developer who is going to work in Rwanda for PIH Mr. Chase . I hope I should have a visit there in Rwinkwavu and Kirehe and see the performance of OpenMRS , especially the Synchronization process while implementing the Admin UI of it .This should be encouraging for me because 1)

OpenMRS Synchronization Administration User Interface , that is my first open source project. I just made the project description on the wiki http://openmrs.org/wiki/Data_Synchronization_Admin_UI_Project. During this first week I have to deal with the Implementation Plans while reading more on different Apis and Frameworks on which OpenMRS relies . Talking about Data Synchronization , here is a help message that gives an understanding of the process:

What is Synchronization?

Synchronization is when you have multiple sites using OpenMRS, and you want them to copy data to each other. In this situation, one site has to act as the “Parent”, and one acts as the “Child”. The Parent is always the computer or site that is most central. Any site can choose only one Parent. However, a Parent can have many Child sites/servers.

What is the difference between “Synchronization” vs. “Generic Import” and “Generic Export”?

Synchronization means that the machines copying data to each other keep track of what has or hasn’t been sent. Generically importing and exporting allows you to export patient data from your system, and then import it to another system, but the 2 systems do not keep track of what data has been passed.

” How do I use Synchronization?

There are 2 different ways to use Synchronization, depending on your connectivity. You can:

  1. Synchronize via File/Disk
  2. Synchronize via Web

Synchronizing via File/Disk means that the Child server will copy all of its new data to a file, which you can save on a disk. That disk can then be carried to a Parent server at a different site, and then the file can be uploaded on the Parent server. In this situation, the Parent server generates a response to be carried back to the Child. This technique allows you to synchronize without Internet connectivity.

Synchronizing via the Web allows you to simply click a button to send data to the Parent, receive the response, and process it. The technique is useful if there is connectivity between the Parent and Child.”

Because the Sync process involves a Parent and Child , I plan to have two OpenMRS installations on different networked machines for testing Sync via web .

For any other issue in concern please feel free to feedback me.

Antoine


Sri Prasanna
SriPrasanna
And so it begins. is about »
» Address Hierarchy Support Project Plan


Background

Address Hierarchy Support is one of the important module needed for enhanced user experience and easier administration. OpenMRS implementations need a way to enter patient location through a hierarchical approach — e.g., select a district from a drop-down list, then pick a village from within the district, then a location within the village.

Goal

Create a module which will allow the admin from within OpenMRS to easily create a location and to define custom location hierarchies. And the user from within OpenMRS to easily create a patient details with the flowing location hierarchy.

Targets

  • Create two new tables address_hierarchy_type and address_hierarchy_type_value. address_hierarchy_type is to store and maintain the hierarchy components and address_hierarchy_type_value is to store the hierarchy component values or simply locations.
  • Adding a new column to the table person_address named location_attribute_type_value_id. Its function is explained clearly in the example below.
  • Adding a page under the module which enables admin to create locations in a hierarchical order and the values are stored in address_hierarchy_type_value.
  • Editing the newPatientForm.jsp and its dependencies for enabling users to create the patient’s location hierarchically and only the location_attribute_type_value_id of the last member in the hierarchy is copied from address_hierarchy_type_value table to location_attribute_type_value_id of person_address table.
  • For a clear working picture of the module please see below.

Deliverables

  • The code for the module page which allows admin to create locations interactively and saves the locations in the location_attribute_type_value table and the hierarchy components in the location_attribute_type table. This will be my delivery for the mid-term evaluation.
  • The rest of the project i.e. Editing the newPatientForm.jsp and its dependencies will be done after the mid term which enables users to select the locations hierarchically.

Example

For working example click here.

P.S: Please leave your comments and suggestions.

» Ready...Set...Code: Google Summer of Code has started!

Today was the official start of Google Summer of Code 2008 Hopefully everybody is finding it a pleasant experience. I have yet to start coding as today was a US Holiday (Memorial Day).

The project plan for the summer has been finalized. I decided to set two-week blocks, rather than do a weekly thing. I chose this, as it's extremely flexible and can scale items either back or forward.

The project plan can be found here. A Google Doc which my mentor and I used to plan the project can be found here. Finally, See my general plan written as a previous blog post.

Best of luck to all the summer of code students!

May 26, 2008
» Creating a module in OpenMRS


Tribe project needs to create a OpenMRS module. There are lots of modules developed already which extend the core OpenMRS system with various enhancements. Some of them are listed in here. I started out with the basicmodule. Basic module provides the skeleton but a working module out of the box. I followed the instructions and created the module for the tribe feature.