Skip to content

Analyzer plugins

Paul Schwartz edited this page Feb 5, 2015 · 28 revisions

Background

We support two models of importing analyzer results. The older model, which we are phasing out, has the code for importing analyzer results as part of the core of OpenELIS. The newer model which all new analyzers should use is a plugin model.

Basics

There is a directory /plugin in OpenElis. Any jar file in this directory will be processed and if it is a valid analyzer plugin it will be added to the application. If the plugin is later removed any imported data will be retained but the analyzer will no longer appear in the menu and openELIS will not accept analyzer files meant for that analyzer.

The plugins are loaded during the application startup. A future feature will be to enable/disable them during runtime.

Working with plugins

Plugins can be developed completely independently of OpenELIS or they can be checked into https://github.com/openelisglobal/openelisglobal-plugins. Currently we are only supporting plugins for analyzers but we expect to also support plugins for electronic and paper reports. The analyzer plugins should be added under "analyzer". There is an example called WeberAnalyzer which can be used as a template. Note that it also includes a SMALL input file sample as well as contact information.

Good manners

If you want to modify an existing analyzer written by a different organization please contact the creator of the analyzer and work with them to make sure that your changes do not break their imports. You should also include the core group with confirmation that you have the right to modify the work from a different organization or else we will not allow the change to be made in repository. An alternative is to make a copy of the other persons work. Note that you should honor the copyright notice and name yourself as a contributor, not as the creator.

If you no longer are using a particular analyzer and do not care if the work is modified please note that in the contact file.

Working with git

The plugins are in a separate repository from the core but the IDE is only tracking the core repository. When you do a commit from within the IDE you are only committing what is in openelisglobal-core, not anything from openelisglobal-plugin. To maintain that repository you will need to either work from the command line or use a tool such as SourceTree.

Setting up for Eclipse

Creation Steps

  1. Create a new Java project. Accept all of the defaults. The name of the project should match the name of the analyzer.
  2. Open up the properties for the project
  3. Select the Java build path (left hand side of the dialog)
  4. Select projects tab and add (right hand side of the dialog) openElisGlobal
  5. Click ok

Jar'ing Steps

  1. Select project
  2. Right click and select export
  3. Select type java->jar
  4. Select next
  5. Select the project as the resources to export
  6. Select the destination as tomcatRoot/webapps/openElisGlobal/plugin/.jar

Setting up for IntelliJ

The overarching unit of work in IntelliJ is a project. Each project is made up of one or more modules and each module is made up of one or more artifacts.

We are assuming that openelis-global is already a project in IntelliJ and just the analyzer part needs to be set up.

Steps:

  1. If you have not done so already clone the repository with the analyzer you want to work on.
  2. From the project view open Module Settings (F4)
  3. On the left hand side click on modules
  4. Click on the green plus button
  5. Click new module
  6. On the New module dialog box select Java as the module type
  7. On the second widget down select the content root. As an example for the Weber analyzer select ...\openelisglobal-plugins\analyzers\weberAnalyzer
  8. This should automatically create the correct name
  9. Uncheck "create source root" at the bottom of the dialog
  10. Click on next and then finish.
  11. You now have the module set up.
  12. On the left hand side now click on artifacts
  13. Click on the green plus button
  14. Click on add jar -> with modules and dependencies
  15. On the module dropdown select the new module name
  16. Leave everything else as is and click ok
  17. The output layout will include a huge number of jar files and app compile and the analyzer compile listing.
  18. Delete everything accept the analyzer compile listing
  19. Set the output to the output of the app module, it should be something like ...\openelisglobal-core\app\out\artifacts\app_war_exploded\plugin
  20. Make sure the build on make checkbox is selected
  21. Change to the app artifact
  22. Select the Output layout tab
  23. Select the green plus button
  24. Select the artifact icon
  25. Select the analyzer jar file
  26. Highlight the jar file in the list
  27. Select the green plus button
  28. Select module output
  29. Select the analyzer module

The next time you do a complete build the analyzer jar file should be in the ...\openelisglobal-core\app\out\artifacts\app_war_exploded\plugin directory and it should be loaded into the application

Setting up for NetBeans

It is assumed that openelisglobal-core is already a project in NetBeans.

Steps:

  1. Fork https://github.com/openelisglobal/openelisglobal-plugins to your own github account
  2. Clone openelisglobal-plugins from your github account to your local machine
  3. Add the plugins at the level of the analyzer, not at the level of the project. In other words: if you are working on the WeberAnalayzer then the location of the plugin-project should be openelisglobal-plugins\analyzers\weberAnalyzer. There will be one project per analyzer
  4. The project for openelisglobal-core should be built. Right click on the project and on the pop-up menu select "clean and build"
  5. Change to the output directory openelisglobal-core\app\build\web\WEB-INF\classes
  6. jar the classes "c:\Program Files\Java\jdk1.7.0_13\bin\jar.exe" cf oe.jar .\us* (note the path to your jdk may differ)
  7. copy the oe.jar file to the root of your plugin project or some well known place on your file system
  8. DO NOT ADD THE JAR FILE TO THE REPOSITORY
  9. Add the oe.jar file to the library of the plugin directory
    1. Right click the plugin project
    2. Select "Properties" at the bottom of the pop-up
    3. Select "Libraries" from the dialog
    4. Select "Add JAR/Folders"
    5. Find the oe.jar file and add it
    6. Click OK
    7. At this point the

Creating the plugin

configuration file

This file configures the plugin parts to be added to OpenElis Under src create a xml file. Name it something meaningful

Contents

<?xml version="1.0" encoding="UTF-8"?>
<openElisGlobalPlugin>
<version>1.0</version>
<analyzerImporter>
<extension_point path="us.mn.state.health.lims.plugin.AnalyzerImporterPlugin" >
	<extension path="<fully qualified path i.e. oe.plugin.analyzer.WeberAnalyzer>" />	
	<description value="<description of Analyzer" />
</extention_point>
</analyzerImporter>
<menu>
    <extension_point path="us.mn.state.health.lims.plugin.MenuPlugin" >
	<extension path="<fully qualified path i.e. oe.plugin.analyzer.WeberMenu>" />	
	<description value="Menu for Weber Analyzer" />
</extention_point>
</menu>
<permission>
    <extension_point path="us.mn.state.health.lims.plugin.PermissionPlugin" >
        <extension path="<fully qualified path i.e. oe.plugin.analyzer.WeberPermission>" />
        <description value="Weber Analyzer permission" />
    </extension_point>
</permission>
</openElisGlobalPlugin>

Analyzer import file

This file adds the needed elements to the database and registers itself to create the runtime objects needed This should be in the source in the package indicated in analyzerImporter section in xml file

public class <Name>Analyzer implements AnalyzerImporterPlugin {

    public boolean connect(){
        List<PluginAnalyzerService.TestMapping> nameMappinng = new ArrayList<PluginAnalyzerService.TestMapping>();
		//Mappings between the name in the analyzer results file and the test name as known to OpenElis
        nameMappinng.add(new PluginAnalyzerService.TestMapping("CD4_PER", "CD4 Compte en %"));
        nameMappinng.add(new PluginAnalyzerService.TestMapping("CD3_PER", "CD4 Compte Absolu"));
		//The name of the analyzer as it will appear in the database, the description of the analyzer and the name mappings
        getInstance().addAnalyzerDatabaseParts("WeberAnalyzer", "Plugin for weber analyzer",nameMappinng);
        getInstance().registerAnalyzer(this);
        return true;
    }

    @Override
    public boolean isTargetAnalyzer(List<String> lines) {
		//This will depend on finding a unique identifier in the analyzer results file which will be found in that file and for no other analyzer
        return lines.get(1) != null && lines.get(1).contains("MugelSET");
    }

    @Override
    public AnalyzerLineInserter getAnalyzerLineInserter() {
		//The object which will actually interpret the contents of the results file. 
        return new WeberAnalyzerImplementation();
    }
}

Menu import file

This file adds the elements needed to add the analyzer to the menu and provide for localization of the name. This should be in the source in the package indicated in menu section in xml file

public class <Name>Menu extends MenuPlugin {

	@Override
	protected void insertMenu() {
        PluginMenuService service = PluginMenuService.getInstance();
        Menu menu = new Menu();
	
		menu.setParent(PluginMenuService.getInstance().getKnownMenu(KnownMenu.ANALYZER, "menu_results"));
		//The order this analyzer will show on the menu relative to other analyzers
		menu.setPresentationOrder(5);
		//The id needs to be unique in the system
		menu.setElementId("weber_analyzer_plugin");
		//This will always be "/AnalyzerResults.do?type=<The name of the analyzer in the database as specified in then Analyzer class call to addAnalyzerDatabaseParts(....) 
		menu.setActionURL("/AnalyzerResults.do?type=WeberAnalyzer");
		//The key used for the name of the analyzer on the menu.  Should not already exist in MessageResource.properties.
 		menu.setDisplayKey("banner.menu.results.weber");
		menu.setOpenInNewWindow(false);

        service.addMenu(menu);
		//Analyzer name in English
        service.insertLanguageKeyValue("banner.menu.results.weber","Weber 4000", ConfigurationProperties.LOCALE.ENGLISH.getRepresentation());
		//Analyzer name in French
        service.insertLanguageKeyValue("banner.menu.results.weber","La Weber 4000", ConfigurationProperties.LOCALE.FRENCH.getRepresentation());
	}
}

##Permission File public class extends PermissionPlugin{ @Override protected boolean insertPermission(){ PluginPermissionService service = new PluginPermissionService(); //The name of the action followed by the action type followed by the description of the module SystemModule module = service.getOrCreateSystemModule( "AnalyzerResults", "WeberAnalyzer", "Results->Analyzer->WeberAnalyzer" ); //The name of role. If it does not exist it will be created. Note: the hierarchical permissions such as at RetroCI are currently not supported Role role = service.getSystemRole( "Results entry" ); return service.bindRoleToModule( role, module ); } }

Analyzer interpreter

This file does the heavy lifting of parsing the results file and adding the tests to the database. However because of the variety of the results files there is more variation than can be handled here. There are some interpreters which were added before we changed to a plugin model and they can be seen in the us.mn.state.health.lims.analyzerimport.analyzerreaders package to get a sense of how they will work.

Clone this wiki locally