Archive for the ‘groovy’ Category

What are the first 10 consecutive digits of e that form a prime number?

Sunday, January 22nd, 2012

After seeing some sample Google Interview Questions that included this question, I couldn’t resist the challenge…

def bigE() {
  BigDecimal e = new BigDecimal(1.0G)
  BigDecimal temp = new BigDecimal(1.0G)
  for (int i in 1..100) {
    temp *= i
    e += new BigDecimal("1")
         .divide(temp, new java.math.MathContext(10000))
  }
  return e.toString()
}
 
def isPrime(long n) {
  if (n < 2) return false
  if (n == 2 || n == 3) return true
  if (n%2 == 0 || n%3 == 0) return false
  long sqrtN = (long)Math.sqrt(n)+1
  for (long i=6L; i < sqrtN; i += 6) {
    if (n%(i-1) == 0 || n%(i+1) == 0) return false
  }
  return true
}
 
def firstPrimeBySize(n) {
  String e = bigE()
  for (int i in 2..e.size()-n) {
    String chunk = e.substring(i,i+n)
    if (isPrime(new BigDecimal(chunk).toLong())) {
      return "$chunk at position $i"
    }
  }
}
 
assert firstPrimeBySize(10) == "7427466391 at position 100"

Displaying OpenMRS observations using Groovy

Monday, July 11th, 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

Saturday, July 2nd, 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.

Groovy thought

Friday, August 21st, 2009

During some noodling about OpenMRS design issues with Paul, we wanted to look at the most recent version of some of our tables.  Did I open up MySQL?  No sirree!  I have 1.6 dev running on an appliance, so I just opened the Groovy module and ran this script:

/* Let's make a convenient function for executing SQL */
def sql = { s -> admin.executeSQL(s, false /* read-only */ ) }
 
sql("describe obs")
.collect{ """
  <b>${it[0]}</b>
  <small><em><font color=gray>${it[1]}</font></em></small>
  """ }
.join("n") /* separate lines */

Which dumps out this:

obs_id int(11)
person_id int(11)
concept_id int(11)
encounter_id int(11)
order_id int(11)
obs_datetime datetime
location_id int(11)
obs_group_id int(11)
accession_number varchar(255)
value_group_id int(11)
value_boolean tinyint(1)
value_coded int(11)
value_coded_name_id int(11)
value_drug int(11)
value_datetime datetime
value_numeric double
value_modifier varchar(2)
value_text text
date_started datetime
date_stopped datetime
comments varchar(255)
creator int(11)
date_created datetime
voided smallint(6)
voided_by int(11)
date_voided datetime
void_reason varchar(255)
value_complex varchar(255)
uuid char(36)

Translating Listserv archive to mbox format

Sunday, November 30th, 2008

We wanted to import our old mailing list entries from the OpenMRS mailing list Listserv archives into Nabble.  No problem.  Finding the GET listname FILELIST and GET listname file1, GET listname file2, … commands was easy enough.  A quick search of Nabble support made it clear that I needed to send them mbox files.  So, I set out in search of a Listserv to mbox converter.  I found a couple scripts: one in perl and another in PHP.  But trying them out, made it clear that I was going to have to do some tweaking.  After a few near misses, I thought: “I could do this easier in Groovy.”  So, I ended up with this script.  Basically, it came down to leaving the messages and their headers alone and just adding a From_ line in front.  Otherwise, the only tricky part was getting the dates right (GMT time without timezone specified in the From_ line and a some reshuffling of the date format in the message header).

Both for future me and anyone else who might benefit, here’s the script I ended up with:

import java.text.SimpleDateFormat

delim = '=' * 73	// LISTSERV separates messages with a bar of equal signs
foundDelim = false	// we skip all content until first delimiter
inHeader = true		// true when processing header data
def header = ""		// holds current header data

dfListserv = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss z")
dfHeader = new SimpleDateFormat("E MMM dd HH:mm:ss yyyy z")
dfMbox = new SimpleDateFormat("E MMM dd HH:mm:ss yyyy")
dfMbox.timeZone = TimeZone.getTimeZone("GMT")	// for mbox, convert to GMT and drop timezone reference
cal = Calendar.instance

// Process input line by line from stdin
System.in.eachLine() { line ->
  if (!foundDelim)
    foundDelim = (line == delim)	// skip until we find first delim
  else if (inHeader) {
    // within header
    if (line =~ /^s*$/) {
      // empty line signals end of header

      // fetch Date from header and reformat it for output
      m1 = header =~ /(?ms)^Date:s+(.*?)s*$/
      date = dfListserv.parse(m1[0][1])
      cal.time = date
      mboxDate = dfMbox.format(cal.time)
      headerDate = dfHeader.format(cal.time)

      // fetch From from header
      m2 = header =~ /(?ms)^From:s+(.*?)s*$/
      fromHeader = m2[0][1]
      leftBracket = fromHeader.indexOf('<')
      rightBracket = fromHeader.indexOf('>')
      if (leftBracket > 0 && rightBracket > leftBracket)
        from = fromHeader.substring(leftBracket+1, rightBracket)
      else
        from = fromHeader

      // output header with mbox-required From_ line up front and reformatted date
      header = "From $from $mboxDaten" + header.replaceAll(/(?m)^Date:s+.*$/, "Date: $headerDate")
      println "$headern"

      inHeader = false	// no longer in header
      header = ""	// clear for next message
    } else {
      header += "$linen"	// accumulate full header data
    }
  } else if (line == delim) {
    // if we find a delim, begin processing next line as header
    print "nn"
    inHeader = true
  } else {
    // within a message, just send it through untouched
    println line
  }
}

Making a groovy module for OpenMRS

Thursday, December 13th, 2007

No, I’m not smoking anything and I’m not trying to do a Greg Brady impersonation. By “groovy” module…I mean a Groovy module. :P

Groovy has the potential to bring the fun and rapid prototyping benefits of languages like Ruby to the Java scene. But a big advantage of Groovy is that it’s built in Java and designed to both work with Java and give Java programmers a fairly easy introduction to the fun of higher level scripting.

So, this Groovy module is a just testing the waters. Groovy is incredibly easy to embed into any Java application (they make it ridiculously simple…a single JAR library is all it takes). So, I made a simple little module that embeds Groovy into OpenMRS and gives a single web page with a textarea where you can play with Groovy scripting. The module adds a “Groovy Scripting” privilege to OpenMRS that you could assign to users…but I wouldn’t recommend it. Currently, this is for testing only and shouldn’t be used in production until we have some more experience with it.

So, fire up a copy of OpenMRS, install the new Groovy module and let’s take it for a spin.

Groovy Scripting

Once the Groovy module is installed, you should see a link in the OpenMRS administration page under a new “Groovy Module” section. Clicking on that link should bring up a simple textarea dialog like the one shown above. Sorry…but that’s about as fancy as it gets for now.

There are several special variables automatically bound to the context for you: cohort, concept, encounter, form, locale, logic, obs, patient, person, and user. Most of these are bound to the corresponding service; locale is the locale of the current context, which is handy for some API calls.

So, type the following into the textarea and click the GO button:

p = patient.getPatient(2)
println p.givenName

That should display the given name of patient #2 from your database. Here are a few more examples of Groovy scripts you can copy and paste into the textarea:

Want to see a 100 concepts?

import groovy.xml.*
 
writer = new StringWriter()
b = new MarkupBuilder(writer)
 
b.table(border: 1) {
  for (i in 1..100) {
    c = concept.getConcept(i)
    tr { td(c.name, style:"font-weight:bold"); td(c.name.description) }
  }
}
 
println writer.toString()

How about some encounters?

p = patient.getPatient(2)
println "&lt;h2&gt;${p.givenName} ${p.familyName} Encounters&lt;/h2&gt;"
for (e in encounter.getEncounters(p)) {
  println "${String.format('%tF', e.encounterDatetime)} - ${e.creator}&lt;br /&gt;"
  println "&lt;ul&gt;"
  for (o in e.getObs()) {
    println "&lt;li&gt;${o.concept.name}&lt;/li&gt;"
  }
  println "&lt;/ul&gt;"
}

Or dump out some observations.

p = patient.getPatient(2)
println "&lt;h2&gt;${p.givenName} ${p.familyName}&lt;/h2&gt;"
for (o in obs.getObservations(p, false)) {
  println "${o.concept.name} &rarr; ${o.getValueAsString(locale)}&lt;br /&gt;"
}

Any patients with “nga” in their name?

s = "nga"
for (p in patient.getPatientsByName(s)) {
  n = "${p.givenName} ${p.familyName}".replaceAll("(?i)($s)", "&lt;b&gt;&#92;$1&lt;/b&gt;")
  println "${n}&lt;br /&gt;"
}

You can even manage modules…but don’t stop the Groovy module!

import org.openmrs.module.*
 
// Uncomment the next line to start the printing module
// ModuleFactory.startModule(ModuleFactory.getModuleById("printing"))
 
// list out your running modules
for (m in ModuleFactory.startedModules) {
  println "${m.name} : ${m.started}&lt;br /&gt;"
  // uncomment the next line to stop the printing module
  // if (m.name == "Printing") ModuleFactory.stopModule(m)
}

As you may gather from trying the examples above, I’m redirecting the stdout from the script into a <div> on the page as HTML, so you can play with formatted output. If you want to simply print some text within Groovy and preserve whitespace, then just put println “<pre>” and println “</pre>” around your println statements. Or use <textarea></textarea> instead.

Learning Groovy (especially for Java developers) is pretty easy. See the Groovy documentation for more about the language. Remember that you don’t need get and set — e.g., person.givenName will execute person.getGivenName() for you. And you can enjoy a break from the semicolons. :)

The real fun with Groovy is that you can throw in good ol’ import statements and directly reference java classes whenever you want.

What next?

While the ability to execute some scripts on the fly can be fun…maybe even handy for testing out code during development, my real hope is to evolve toward a Grails module that could facilitate rapid prototyping of web forms or quick & dirty report pages. The ultimate would be a Grails module that provides a quick and easy starting point, let’s you edit and extend it without any re-compile steps, and then provides a button to download a snapshot of the current state of the module as a new omod file to facilitate rapid prototyping of OpenMRS modules to target quick & dirty development needs and/or prototype new functionality.

Now that would be groovy!