Well after some work and crunching I have managed to get the new UI Idea up onto the live link (http://www.forxdesign.co.za/ox-designer/). Due to some recent changes in the GWT-dnd library there seems to be the possibility to removet the bottom "pallet" where the widgets are dropped on creation. I will be looking at changing this as well as refining the click-properties panel of each widget. I will either be adding an "edit" link or a context menu tag (right click - my preference)
OK so saying "its been a while" is a mild statement. I think raising the titanic took less time than the time between these blogs ;op
Onto business.. OX-Designer (XForms Designer) is back into the coding playing field thanks to the OpenMRS Internship Program. Keeping this short: I've finally managed to find a working version of my source..go figure you change computers a few times and have a few hard-drive crashes and what do you know..remembering where you backed up your work gets kinda tough!
I have updated my current dev environment to include the latest libraries from GWT, GWT-dnd and GWText (still using legacy version at this point). I will be working to upgrade the old source to the new libraries which include a few of the features I had to code myself (pallet). Stay tuned for posts on this.
When the code is up to date i will focus my attention on the properties dialog boxes (where i left off last) and the problem of only loading one instance and not creating multiple objects for each ui widget.
The link to the old code still works but I will be updating it with a new version ASAP! even the current old version is an option at this point!
Here's to the future.
I'm out here in Boston visiting the PIH offices and meeting all of the OpenMRS guys from the Boston and Indianapolis offices (more on that later).
Burke and I have been trying to figure out why the forms in OpenOffice.org aren't actually HTTP POSTing the XML data to the OpenMRS server. After scratching our heads and checking the server logs, he suggested I use tcpmon to capture the data from OpenOffice to see what was going wrong.
tcpmon is pretty cool. It works by creating a sort of proxy between your localhost and another server. You give tcpmon a local port and a server and port to connect to, and it relays all of the information sent to localhost:port to server:port, capturing all of the data in between. I tried it out with my OpenMRS installation at home, and here's the result of submitting a form:
HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=AFD3B8B163899870591929C471BEE8B7; Path=/openmrs
Location: http://localhost:8084/openmrs/logout
Content-Length: 0
Date: Wed, 15 Aug 2007 13:46:45 GMT
HTTP/1.1 405 HTTP method POST is not supported by this URL
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=104147D9161F0663F217CC856D2056FE; Path=/openmrs
Content-Type: text/html;charset=utf-8
Content-Length: 1115
Date: Wed, 15 Aug 2007 13:46:45 GMTHTTP Status 405 - HTTP method POST is not supported by this URL
type Status report
message HTTP method POST is not supported by this URL
description The specified HTTP method is not allowed for the requested resource (HTTP method POST is not supported by this URL).
Apache Tomcat/6.0.13
This seems to indicate that there's a problem with authentication. I'm given a JSESSIONID and immediately sent to the logout page. I'm also given an HTTP error 405.
The forms in InfoPath use the taskpane combined with some JavaScript trickery to capture the JSESSIONID for an authenticated session so the form is free to communicate with the server and the server thinks this is just a regular Internet Explorer session. I'm thinking that if I can somehow capture this JSESSIONID in OpenOffice, I can use it the same way that InfoPath does. How I'm going to do this, I don't know. It may finally be time to crack into my Macro book and see if I can do some similar HTTP trickery. When I return home and have access to InfoPath, I'll sic tcpmon on it and see what's happening.
While working on a form in OpenOffice.org, I noticed something quite annoying.
When you create a form element and bind it to the XML, you can choose what data type you want; date, decimal, string, boolean, etc. On certain data types, such as a decimal, you can define a minimum and maximum range for the data entered:
One would expect you to be able to define a separate range for each different control with type Decimal, right? Wrong. Apparently, if you define a range for ANY control that's type Decimal, it applies to ALL controls of type Decimal. I can't imagine why this is implemented as such because I don't see why you'd want the same range for all different controls. Needless to say, it's problematic.
I'm trying to find the best way to limit the range of values entered for controls such as obs/pulse/value in the OpenMRS forms. In InfoPath, this control (and others like it) have a custom data type, pulse_type_restricted_type, limited to a range of 0-230, inclusive. The entry from the XML schema looks like this:
<xs:simpleType name="pulse_type_restricted_type">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="230"/>
</xs:restriction>
</xs:simpleType>
OpenOffice.org doesn't seem to have this feature. While I can add a custom data type named
pulse_type_restricted_type, there doesn't appear to be a way to define a valid range for it. There's an option to add a "Constraint", but I'm not sure how this works. As you can see here, the help files on this are somewhat less than useful:
I'll post some questions to mailing lists and update this post when I've found a solution.
It's hard to believe, but it's already time for the middle-of-the-term progress report for Summer of Code, and that applies to us OpenMRS interns as well. So, here goes.
I'm back from Florida (pictures at http://pics.discosoup.net/FL.html for anyone interested) and back to work. The question I've been asking myself this past week is "How can I make things simpler?" in terms of form creation in OpenOffice.org. OpenOffice's XForms component is much less polished than Microsoft InfoPath so it requires a few more manual steps that the user needs to do to create forms. While the steps aren't difficult, they're tedious and time consuming and I felt that they seemed daunting to OpenMRS implementors and developers that may be converting forms to OOo and I wanted to see if I could cut them out.
Data Types
The first tedious step involves manually entering the data type for each XML element in the form when you create a binding. While InfoPath reads in the XML schema directly and does this for you, OOo does not. Users are required to specify the data type for each binding, and this requires either looking at the schema or at InfoPath to find out if a control should be a simpleType, simpleContent, Integer (decimal in OOo), _infopath_boolean, etc.
My first thought was that I could either write a Python script or some sort of XSLT trickery to manipulate the XML of the .ODT files to associate entries in the form with the proper data type from the schema (.odt files contain a content.xml which has both the styles that define the appearance of the document and the XML template + bindings), but this was too complicated. I looked at the output of submitting an OOo form to an XML file and noticed that none of the data type information (simpleContent, simpleType, etc) was saved. I compared this with the output from an InfoPath form, and it was the same there as well - no data type information saved. So I asked my mentor about this and we came to the conclusion that it's only necessary for data validation in the form itself (user input) and doesn't need to be kept track of in the bindings. While it's a good idea to make sure certain fields are restricted to integers or dates, it's not necessary for OpenOffice to keep track of whether checkboxes or radio buttons are simpleContent or simpleType - the output will be the same. This successfully cuts a lot of tedium from the form creation process.
Binding Names
Another tedious part of form creation is having to rename each binding after you create it in OOo. Creating new bindings results in bindings called "Binding 1", "Binding 2", etc. These names are somewhat less than descriptive, and I had been renaming them to their XPath expression equivalent - so "Binding 1" becomes "patient/patient.sex", etc. This is functionally irrelevant mind you - OOo doesn't care what it's named, it's just for user reference. Still, I prefer to have meaningful names so they can be easily referred to later.
I opened content.xml in jEdit to see how binding names were handled, and here's what I found:
<xforms:bind nodeset='patient/patient.sex' type='simpleContent' id='Binding 1'/>is an example of a binding with the default name. This is later referenced in the definition of a control style:
<form:radio form:control-implementation='ooo:com.sun.star.form.component.RadioButton' form:label='M' form:name='nameOfRadioButton' form:image-position='center' form:id='control19' form:value='M' xforms:bind='Binding 1'>It should be fairly easy to write a script that replaces every instance of 'Binding X' with the "nodeset" value, so that cuts this step out of form creation in OOo as well. All that's left now is to drag elements from the XML tree to the document, change the control type and label/properties, then position them to fit where you want them to - pretty easy stuff.
template.xml and FormEntry.xsd extraction
Each OpenMRS InfoPath form contains two important files: template.xml and FormEntry.xsd. Template.xml has the actual XML data that's edited by InfoPath. When a form is published, form data entered in the UI is written to the appropriate XML tag in this file. FormEntry.xsd is InfoPath's version of XML schema (one of the reasons OOo doesn't read this in - it's not quite a proper schema, but MS's own version). This contains all of the data type values for each element as well as valid HL7 values.
It's necessary to get both of these files for the form you want to convert to OOo. InfoPath's .xsn files are CAB files, so you need a CAB extractor to get at them. I've found that WinRAR works for Windows, Unarchiver on OS X, and cabextract on Linux. You can find links to these on my wiki instructions, and I'll soon be modifying the instructions to include a section on extracting these files.
What's Next
After I finish the wiki instructions on form creating in OOo, there are two big tasks to tackle: loading patient data from the webapp and recreating InfoPath's taskpane.
I've been thinking about loading patient data a lot these past few days. Currently, when a user loads a patient's form from the webapp, it sends an .infopathxml file which is a filled-out version of template.xml with instructions at the top so InfoPath knows which form to open. Paul is very adamant that OOo also has this functionality so it fits in with the FormEntry workflow just like InfoPath. I'm confident it can be done, and I've been thinking about several solutions:
As mentioned in a previous post, you can add local or remote instance data to a form in OOo. This can load patient data into your form, but it involves manually clicking "Add instance data" and selection the XML file containing patient data. Doable, but not at all an elegant, easy solution. I thought perhaps I could write a macro that automatically does this, but that would require users to have a local copy of the form they wish to do this with, and that's not very good either (currently forms are stored on a server and InfoPath opens them remotely).
After a discussion with Justin Miranda on the IRC, an idea popped into my head. Since OOo's .odt files are just zip files containing several XML files, and since all template data is saved in content.xml, why not have a script on the server that grabs the appropriate form, replaces the blank template data in content.xml with the filled-out .infopathxml files containing patient data, and send this to the user? Should be quite doable in Python, and from the user's perspective, the only thing that changes is that OOo opens instead of InfoPath. OOo can also open files from remote URLs, making this even easier.
Justin also mentioned the idea of having one form for everything and one XML file per patient. That way, every patient would have one form and one XML file. While this would simplify things IMMENSELY, it would require a lot of refactoring of the way OpenMRS works, and you could run into problems caused by adding/removing fields from the forms and would have several different versions of the form running around. Also, both the form and XML would be quite large, and this could be an issue for users who only need to edit a small section of data.
As far as InfoPath's taskpane is concerned, I'm not quite there yet. The taskpane is a tab in InfoPath that executes some javascript to pull in remote data via http. This allows users to select information (such as the location of a patient encounter) from a remote URL, all from within InfoPath. While all of this can be accessed via a regular web browser, it's convenient to have everything in one application. The quickest and dirtiest solution would be to connect macros to buttons that open the target URL in the user's $browser, but this loses the "all-in-one-place" appeal. Other options include using small web browsers (via a script) in a floating window in OOo and/or pestering the OOo developers to add this functionality. I welcome any suggestions on this issue.
I hope my progress thus far has been sufficient (I've gotten pretty good feedback from both OpenMRS and OpenOffice.org, so that's good), and I look forwarding to continuing for the rest of the summer and hopefully beyond as well. I truly enjoy doing this.
The OpenOffice.org Community
In order to work on this project, I've had to involve myself in the OpenOffice.org community. I've been reading and posting to the Users mailing list as well as the XML developer's list and hanging out on the IRC. This has all been immensely helpful and rewarding to me because I'm learning about OpenOffice by reading and answering other users' questions. You learn a lot about a subject when you're helping others because you're forced to really get in there and figure out how something works.
Andrew Pitonyak, author of the previously mentioned book, "OpenOffice.org Macros Explained", has noticed my work with XForms on my blog and the OpenMRS wiki and dealt some flattery my way by suggesting that I write the XForms documentation for the OpenOffice manual at OOoAuthors. I look forwarding to contributing to this as much as I can. There's quite the lack of OOo XForms documentation out there, and I'd very much like to share what I've learned with others.
All in all, this has been a very exciting and enjoyable summer, and I look forward to what lies (lays?) ahead.
(Note: After you've read this, see my follow-up post.)
This past week I've been working with InfoPath and OpenOffice.org side-by-side to compare what InfoPath can do vs. what OpenOffice can do. I've started creating the Adult Initial Encounter form in OpenOffice, and so far I've been quite pleased with the results (as have the rest of the OpenMRS gang). Here's a screenshot of part of the form:
I'm noticing that while InfoPath has a lot of drag-and-drop functionality, OpenOffice leaves much of it for the user to do. For example, in order to create a binding in InfoPath, you simply drag an element from the schema over to the document. You can then change what type of control it is (text field, radio button, date field, etc) and it will be nice and bound to your schema:
In OpenOffice, this isn't quite as easy. While you can drag an element from the data navigator directly to the document, you don't seem to have much control over what type of form control gets added. As you can see from the picture, it defaults to a simple text field with a label that I can't seem to change. While it allows you to replace the control with other controls, your choices are very limited. Hopefully this will be further developed in future versions:
In order to bind everything in OpenOffice, I've been selecting the binding from a drop-down list in the data tab of the control properties window. While this is perfectly doable, it's a bit tedious. I've posed a question to the OpenOffice Users mailing list about this, so hopefully I'll have an answer soon.
If there's no better way to do this in the GUI, it's possible that I may be able to write a script that edits the XML files in the .odt file that OpenOffice generates that fills in all of the bindings and default values. Both the InfoPath .xsn files and OpenOffice .odt files are zip files that contain XML and style sheets defining how the forms look and behave.
When the forms are submitted, they send an XML file to a remote server which then has some XSLT which translates the data to HL7. Here's an example of what this looks like, taken from the first screenshot, question 11a, "Is the patient or their partner currently using any form of family planning?":
If the user of the form checks the "Oral Contraceptive Pills" box, the <oral_contraception/> element is set to true, and 780^ORAL CONTRACEPTION^99DCT is the HL7 that is submitted.
I'm currently working on the rest of this form, and I'll start work on the others once it's finished. While the Adult Initial Visit form is rather large and tedious, I figure it's a good place to start because it will have a lot of reusable elements that I can copy and paste into other forms.
I'm pretty pleased with progress so far - I think things are going along quite nicely. Comments?
I'm going to use this post to collect useful resources that I find regarding XForms and OpenOffice (and general OpenMRS info). I'll update it as I find more, and I encourage anyone that has anything to add to leave comments.
Using XForms in Office Applications
The OpenOffice.org XML Project
OpenOffice.org module xforms
Wordpress search for "XForms" tag
W3C's XForms Specification
OpenMRS - Administering FormEntry
OpenMRS - InfoPath Notes
OpenMRS Data Model
GUI Architectures (useful MVC info)
OpenMRS - HL7
Office 2003 XML Reference Schemas
- a fully browser based Xforms editor that will allow the associating of XForm controls to the model associated with the XForm.
The initial User Interface ideas include the following:
- A light weight Layout, More of a hybrid of a GMAIL and Outlook appearance.
- A drag and drop layout manager for the XForm (this is under review)
With the initial front-end progress it is time to bring the server side up to speed. The server will run various JAVA based services that will allow the manipulation of the XForm structure. The first pass at the server side XForm structure includes an XForm object which holds the Model object, the Controls object and the Logic object.
The Model Object consists of a collection of model elements, these will be the data elements that are to be collected, which are obtained from the XML.I have decided to cater for XForm models that have attributes associated with the data elements to be collected, e.g:
The thinking behind allowing for attributes is to allow for a more hands-off generation of the forms from the meta-data associated to the model. There is no predefined attribute list as of yet, but rather I have chosen to leave it open for any developer should they wish to extend it to suit their needs.
Current design issues that are being considered are the following:
Should the model (xml) be parsed on the client side or on the server side. At this point in time the client side is slowly becoming heavier with various UI tasks and the server is fairly light. The current train of thought is that the Model should be parsed to the server (i.e. upload the file) to extract the model components and then return what is needed to the User. This should reduce the initial load time of the application while still giving the server the power and possibility to automatically generate a first pass of the form.
Second design issues that is being investigated is the representation of the XForms controls to the user in the editor, currently the controls are being displayed using GWT widgets and standard HTML controls. The decision that is being faced is that of making use of a RichText component that allows for a more WYSIWYG editor with a more flowing layout, or to maintain the idea of a fully absolute layout manager and the addition of text to the form be done using "Labels". Other issues being considered are the use of tables and how to represent these in the various methods described above.
With that said it leaves me with the task of investigating the issues and hopefully coming to the correct conclusion. Until next time
The idea of OX-Designer (Open Source XForms Designer) originated from a need brought up at the OpenMRS Implementors meeting 2006. OpenMRS is an open source medical record system which currently makes use of Microsoft InfoPath as the method to collect patient data. In the light of providing an alternative data collection method I proposed an XForms alternative.
XForms, for those not familiar with the technology, is a W3C specification for creating a form. It is essentially a form mark-up language that is build on a Model-View-Controller architecture. For more information regarding XForms the XForms site provides an in-depth description.
The project is to create an open source browser based XForms designer/editor. This will allow the user to upload an XForms model (stage 2 will hopefully include a model designer) and design the visual aspect of the form by making use of a WYSIWYG editor. The XForms model is an XML definition of the data that the form collects. The application will be an AJAX based web application and hence has no platform dependencies and the only condition to using the application would be that the user make use of a web browser.






