jsonpretty: handy when playing with web services

October 17, 2011

I just ran into a handy little utility: jsonpretty.

$sudo gem install json jsonpretty

While

$curl -i http://localhost:8081/openmrs-standalone/ws/rest/v1/catalog

gives you something like this:

{"catalog":[{"name":"Cohort","operations":[{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort?q","description":"Fetch all non-retired that match this parameter"},{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}","description":"Fetch by unique uuid"},{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort","description":"Fetch all non-retired"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort","description":"Create with properties in request"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}","description":"Edit with given uuid, only modifying properties in request"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?!purge","description":"Delete this object from the database"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?purge","description":"Delete this object from the database"}],"url":"http://localhost:8081/openmrs/ws/rest/v1/cohort","representations":[{"name":"ref","properties":["uuid","display","links"]},{"name":"default","properties":["uuid","name","description","voided","memberIds","links"]},{"name":"full","properties":["uuid","name","description","memberIds","voided","auditInfo","links"]}]},{"name":"CohortMember","operations":[{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}","description":"Fetch by unique uuid"},{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members","description":"Fetch all non-retired"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members","description":"Create with properties in request"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}","description":"Edit with given uuid, only modifying properties in request"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}?!purge","description":"Delete this object from the database"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}?purge","description":"Delete this object from the database"}],...

adding jsonpretty:

$curl -i http://localhost:8081/openmrs-standalone/ws/rest/v1/catalog | jsonpretty

gets you something much prettier:

{
  "catalog": [
    {
      "name": "Cohort",
      "operations": [
        {
          "name": "GET http://localhost:8081/openmrs/ws/rest/v1/cohort?q",
          "description": "Fetch all non-retired that match this parameter"
        },
        {
          "name": "GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}",
          "description": "Fetch by unique uuid"
        },
        {
          "name": "GET http://localhost:8081/openmrs/ws/rest/v1/cohort",
          "description": "Fetch all non-retired"
        },
        {
          "name": "POST http://localhost:8081/openmrs/ws/rest/v1/cohort",
          "description": "Create with properties in request"
        },
        {
          "name": "POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}",
          "description": "Edit with given uuid, only modifying properties in request"
        },
        {
          "name": "DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?!purge",
          "description": "Delete this object from the database"
        },
        {
          "name": "DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?purge",
          "description": "Delete this object from the database"
        }
      ],
      "url": "http://localhost:8081/openmrs/ws/rest/v1/cohort",
      "representations": [
        {
          "name": "ref",
          "properties": [
            "uuid",
            "display",
            "links"
          ]
        },
        {
          "name": "default",
          "properties": [
            "uuid",
            "name",
            "description",
            "voided",
            "memberIds",
            "links"
          ]
        },
        {
          "name": "full",
          "properties": [
            "uuid",
            "name",
            "description",
            "memberIds",
            "voided",
            "auditInfo",
            "links"
          ]
        }
      ]
    },
    ...

Nice! Thank you jsonpretty! 🙂

Displaying OpenMRS observations using Groovy

July 11, 2011

I wanted to list out some observations for a patient and used the following Groovy script:

def sql(s) {admin.executeSQL(s,true) }

patientIdentifier = "999-3" // a test patient, of course

sql("""
select
date(o.obs_datetime),
(select name from concept_name where concept_id=o.concept_id limit 1) as question,
case c.datatype_id
when 1  /* numeric  */ then cast(o.value_numeric as char)
when 2  /* coded    */ then (select min(name) from concept_name where concept_id=o.value_coded)
when 3  /* text     */ then value_text
when 6  /* date     */ then cast(date(o.value_datetime) as char)
when 7  /* time     */ then cast(time(o.value_datetime) as char)
when 8  /* datetime */ then cast(o.value_datetime as char)
when 10 /* boolean  */ then if(o.value_numeric=1,'TRUE','FALSE')
else '?'
end as answer
from
obs o
left outer join
concept c
on c.concept_id=o.concept_id
where
o.person_id = (select patient_id from patient_identifier where identifier = '$patientIdentifier' limit 1)
order by
o.obs_datetime desc
""").collect{ it.join(": ") }.join("n")

which generated output like this:

2011-02-18: PATIENT HAD SEX IN LAST 6MO: TRUE
2011-02-18: PlAN FOR METHOD OF FAMILY PLANNING, DETAILED: ?
2011-02-18: QUANTITY: 5
2011-02-18: FAMILY PLANNING METHOD PLAN: INITIATION
2011-02-18: METHOD OF FAMILY PLANNING: ECPS
2011-02-18: HIV DISCLOSURE TO ANYONE, SPECIFIC: OTHER HOUSEHOLD MEMBER
2011-02-18: REASON FOR REFUSAL - FAMILY PLANNING: TRYING TO CONCEIVE NOW
2011-02-18: PlAN FOR METHOD OF FAMILY PLANNING, DETAILED: ?
2011-02-18: METHOD OF FAMILY PLANNING: MALE CONDOMS
2011-02-18: QUANTITY: 5
2011-02-18: FAMILY PLANNING METHOD PLAN: INITIATION
2011-02-18: METHOD OF FAMILY PLANNING: BTL
2011-02-18: FREETEXT, GENERAL: POSITIVE
2011-02-18: REASON FOR REFUSAL - FAMILY PLANNING: ABSTINENCE
2011-02-18: FAMILY PLANNING: TRUE
2011-02-18: REVIEW OF MEDICAL HISTORY: ICTERUS
2011-02-18: PATIENT REPORTED PROBLEM: YES
2011-02-18: CURRENT MEDICATIONS: ALUVIA
2011-02-18: REVIEW OF MEDICAL HISTORY: DEPRESSION

Sometimes you need a little web server

July 2, 2011

Here’s a simple jetty server using a short Groovy script:

@Grab(group='org.mortbay.jetty', module='jetty-embedded', version='6.1.14')

import org.mortbay.jetty.*
import org.mortbay.jetty.servlet.*
import groovy.servlet.*
import javax.servlet.*
import javax.servlet.http.*

class MyServlet extends HttpServlet  {
  void doPost(HttpServletRequest request, HttpServletResponse response) {
    println "--- Received ${new Date()}n" + request.getParameter('data')
  }
}

def server = new Server(8888)
def root = new Context(server, "/", Context.SESSIONS)
root.setResourceBase(".")
root.addServlet(new ServletHolder(new MyServlet()), "/")
server.start()

Running the script with groovy AtlasServer.groovy will accept HTTP POSTs at the designated port (8888) and dump posted data to the screen.  For example:

$ curl -X POST -d "data=Hello world!" http://localhost:8888/

should dump “Hello world!” to the screen.  Press Ctrl+C to abort the server.

Flowsheet Code Jam in Chennai

January 15, 2011

Here’s a shout out to our friends at ThoughtWorks. They had a code jam on the Flowsheet Module a few weeks ago and knocked out over half a dozen key tickets in a single day as well as making progress on others. The Flowsheet Module is being installed into OpenMRS at AMPATH in Kenya to allow both data managers and providers convenient access to their patients’ data and to help improve the efficiency and quality of care for the over 300,000 patients within the system… thanks to: Khaarthigha S, Rajiv RA, Pavithra K, Geetha B, Saravana K, Arvind Kumar C, Senthil V S, Prabha P, Shanum, Ponnulingam R, Alexal, Vinoth KR, Nithyan, Gobinath T, Balaji G, Ragavan G, and Chandru. You all rock! And it looks like you had some fun in the process. I especially enjoyed the image of two laptops per lap!

Swipe down to close tab in FF4

November 16, 2010

Just upgraded to Firefox 4 beta 7 on my MacBook Pro and the (three finger) swipe down gesture I had grown to love (thanks to Will Henderson’s MultiClutch), suddenly became a “show tab view” gesture.  This is no good!  I’ve already become accustomed to swiping down to close tabs in Firefox.

A little googling, and I was able to get back my swipe-down-to-close-tab gesture and move the show tab view gesture to SHIFT + swipe down:

  1. Open up a tab and browse to “about:config” to bring up the Firefox configuration — proceed at your own risk.
  2. Type “gesture” in the Filter field to filter down to gesture-related preferences.
  3. You should see the preference browser.gesture.swipe.down of type string set to value Browser:ShowTabView.
  4. Right-click on the preference name and select New –> String from the context menu.
  5. Enter browser.gesture.swipe.down.shift as the new preference name.
  6. Enter Browser:ShowTabView as the new preference’s value.
  7. So, now you have added a SHIFT + swipe down gesture (swiping three fingers down while holding down the shift key) to perform the default function of swipe down.  Now we take back our swipe down gesture…
  8. Double-click on the value of the browser.gesture.swipe.down preference and change it to cmd_close.
  9. You’re done!  Swipe down and the about:config tab should disappear.  Hold down shift while swiping down and you’ll see the tab view.

Now that gestures are supported on Firefox, I no longer need MultiClutch settings for Firefox.

The Fisherman

October 6, 2010

The fish he caught…

fisherman1

and the story he told…

fisherman2

Tags

iPad Pro

April 17, 2010

Own a MacBook Pro and an iPad?  Tired of carrying around both?  Meet the iPad Pro.

I’m looking forward to the day when the monitor of my MacBook Pro becomes an iPad.  No extra things to carry around.  If you want to run to a quick meeting or browse on the couch, just snap off your monitor and go (it’s an iPad).  Miss your keyboard, DVD drive, extra ports, extra battery life, etc.?  Just plug your iPad back onto the iPad Pro base and you’ve got a full laptop.  Keep a cloth in your bag to wipe off those fingerprints and stop freaking out when people touch your monitor — it’s a multitouch monitor, after all.

Improving OpenMRS Code Review

April 15, 2010

Trying to figure out how we can improve the efficiency of our code reviews.  Finding some interesting stuff on the web…

Like this article: Limit the checklist to 7±2 items.  Automate the automate-able and let existing code review data drive the list of common mistakes.

Here is a list of articles, white-papers, and documentation around peer code review.  Hmmm. Several resources, but not enough time to look at them all.

Some nice pointers here, but nothing game changing.

A good summary article here.

And here (and here) is an interesting take by Torvalds that Paul found.

Plan on talking with developers to brainstorm on it…

Dad

November 11, 2009

It appears that the folks at Shapiro’s Deli are almost as proud of Dad as I am…

Dad-Shapiros

The World is Flat

October 26, 2009

At the IMeCA Meeting in Lima, Peru listening to Hamish present about OpenMRS in English with real-time Spanish translation … and Hamish is in Kigali, Rwanda!  Now that is cool!