# The Data Adapter Cookbook

# Introduction

This guide aims to be a quick start to writing your own dataaapter for Apollo. It uses the `SampleAdapter` for illustration: the code for that adapter lies in the `apollo/dataadapter/sample` package. One way of getting going quickly would be to start by examining the code skeleton provided in the sample dataadapter, and then modify it for your own purposes. I assume in all the following that if you're reading this document then you have already obtained a developer's installation of apollo - for instance a cvs checkout of the fully source tree and supporting files, and are reasonably familiar with the location and basic function of the main supporting files (apollo.cfg, the style and tiers files for an adapter). If you haven't, then you can, via cvs or tarball, from `gmod.sourceforge.net` - this site has all the code and instructions for downloading etc.

# Run the sample! Get going now!

You should start by activating the sample dataadapter. Do this by adding the following lines to the `conf/apollo.cfg` file:

`DataAdapterInstall "apollo.dataadapter.sample.SampleAdapter" "sample.style"`

When apollo starts, it will try to create the sample adapter and its gui, and load them to the list of adapters available to the user. If the load fails, it will notify the user in a message sent to the console during startup. Start up Apollo and choose the Sample adapter from the list of available adapters. It should allow you to choose the number of features you want to display, and then display the chosen number in Apollo, along with a fake sequence.

# The classes and configuration files you need to write

Every data adapter in Apollo needs two main classes and two configuration files. In practice you may well have more than these two classes in the data adapter's design, but Apollo will rely on the presence of the two main classes, and their configuration files.

The data adapter (e.g. `apollo.dataadapter.sample.SampleAdapter`),

  This is responsible for gathering data (features and sequence) from a back end, and packaging the data in terms of Apollo's datamodel. The type of data gathered and where it's gathered from is specified as state information on the adapter.

The data adapter's gui (e.g. `apollo.dataadapter.sample.SampleAdapterGUI`),

  This is responsible for gathering the user's preferences (via a gui) for where the data should be loaded from, and what sort to gather, and setting all this information on the data adapter.

The data adapter's style file (e.g. `conf/sample.style`)

  This keeps the user's visual preferences specific to the SampleAdapter.

The data adapter's tier file (e.g. `conf/sample.tiers`)``

  This keeps the list of possible data "tiers" (tracks) which we expect the SampleAdapter to provide, along with their visual appearance.

  When you are displaying the results of many independent analyses of a particular genome, you will need to group results of the same analysis together visually, and distinguish them from results from other analyses. You do this by putting your results in tiers (visual groupings). Tiers (visual groupings) are tied to the logical data groups via the type of the Features your adapter creates. You specify how a tier looks (data colours and glyphs) in the tiers file, and lots of other visual properties besides.

## Writing a DataAdapterGUI

The DataAgapterGUI is just a glorified JPanel which is created by the your DataAdapter class (several times actually) during Apollo's startup, and then placed - when the user chooses to use it - into the central panel of the DataAdapterChooser. You should have two main goals when writing one -

1. Write a nice constructor. This amounts to writing the code that creates widgets and adding them to the JPanel. Everyone has their own taste as to how to do this - the sample has a suggested style. I have a few other suggestions based on experience:

   - Minimise the use of direct access to instance variables in the class (the rule I use is to only directly refer to the instance when the object is created). This is generally wise rule to brutally enforce, but I think I've seen the most flagrant violations in gui-related code. So, for instance, say

     `getMyFavouriteDropDown().setSelectedItem(...);`

     instead of

     `myFavouriteDropDown().setSelectedItem(...)` .

     Generations in the future will thank you.

   - If you want to remain sane, use GridBagLayout to lay your components out: Box is seductive but has weird side effects, and is basically impossible for normal humans to alter post-hoc.

2. Implement doOperation. This is forced on you by the DataAdapterUI interface in org.bdgp.io, and it's the call made by the DataAdapterChooser on your dataadapter when the user hits "OK". It's traditional here to have the adapter do three things in this operation:

   - Derive a summary of the user's choices - the "state information" - based on the GUI's current state. This summary is placed into a Properties object

   - Transmit this information to the DataAdapter by passing the Properties object

   - Call a method on the DataAdapter to fetch the CurationSet. This is where all the data gets read. Pass the CurationSet you obtain out as the return from the doOperation method.

     If you intend your adapter to read and write data then you have to make a decision in the doOperation method as to what to do: each GUI instance is created with only one operation in mind, so you must check the operation inside the GUI instance, and branch based on that. See the BaseGFFAdapter or the GAMEAdapter for an example of how to do this.

You also should implement a few lesser methods (such as `get/setProperties`). These are explained and demonstrated in the SampleAdapter.

## DataAdapter.

Implement (mainly) getCurationSet.

## Style file.

Copy someone elses - for the moment you needn't change anything.

## Tiers file.

The type of the features and feature sets you create is the point here: you will need to define tiers and types within tiers for all your input feature types.

# 3. Notes on practice:

## The Apollo datamodel

The relationship between what you specify and what you see (feature names, holders and tiers files):

### What is a CurationSet?

DataAdapter.getCurationSet() returns an apollo.datamodel.CurationSet object. A CurationSet holds both results and annotations. Results are set with setResults(StrandedFeatureSetI), and annots are set with setAnnots(StrandedFeatureSetI). This determines what gets displayed in the annotation and result views in apollo. A StrandedFeatureSetI has a forward and reverse FeatureSetI for the 2 strands.

### Creating annotations

The StrandedFeatureSetI for the annots (in CurationSet) should contain GenericAnnotationIs for apollos AnnotationView and its AnnotationMenu to function properly. Gene, Transcript, Exon, and GenericAnnotation all implement the GenericAnnotationI interface. (More needs to be written about this. For now you can look at a code example of Gene models being built in apollo.dataadapter.GAMEAdapter's getGene, getTranscript, and getExon methods.)

### How to create a simple analysis result

..eg a repeatmasked area..Create a SeqFeature with the appropriate start/stop/name and type.

### How to creat a hit to another feature

..eg a blast hit ..Create a FeaturePair, with the visible SeqFeature as the first feature, and the hit feature as the second feature.

### How to creat a group of features visibly linked together

.. a set of exons grouped into a transcript ..create a FeatureSet, adding in the individual SeqFeatures into the set.

### Why you'd want to create holders

## Exception handling.

What do you do when things go wrong, for instance when the user enters "cat" into a chromosome start field? Or when the database you're examining has changed schema? --Why, you throw an apollo.dataadapter.DataAdapterException, of course. But what if you're overriding a method which is specified to have no such exception? Is the game over? Is it time to

`catch(Exception e) { e.printStackTrace();}` ?

Well, no, there is a better way: throw a run-time exception, and catch it yourself from the entry points. See the NonFatalDataAdapterException as an example.

## What runs when

1. ApolloRunner starts
2. Config loads
3. Each dataadapter is created and loaded into registry, along with its chosen Style
4. User chooses a dataadapter from dropdown
5. Dataadapter has its setProperties() invoked with history passed in
6. User populates fields on data adapter's gui and hits "OK"
7. DataAdapterGUI.doOperation method runs
8. DataAdapter's getCurationSet method is invoked
9. DataAdapterGUI.getProperties() invoked to grab the properties written to history
10. ApolloRunner receives the created curation set, creates the ApolloFrame, sets the data into it.
11. DrawableSeqFeatures are created for each of the SeqFeatures in the results/annotations. These are rendered by the various views resident inside the StrandedZoomableApolloPanels