You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 11:38:20 UTC

[12/17] incubator-taverna-plugin-bioinformatics git commit: Revert "temporarily empty repository"

http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/a87b4151/taverna-biomart-martservice/src/main/java/org/biomart/martservice/config/ui/MartServiceQueryConfigUIFactory.java
----------------------------------------------------------------------
diff --git a/taverna-biomart-martservice/src/main/java/org/biomart/martservice/config/ui/MartServiceQueryConfigUIFactory.java b/taverna-biomart-martservice/src/main/java/org/biomart/martservice/config/ui/MartServiceQueryConfigUIFactory.java
new file mode 100644
index 0000000..3531539
--- /dev/null
+++ b/taverna-biomart-martservice/src/main/java/org/biomart/martservice/config/ui/MartServiceQueryConfigUIFactory.java
@@ -0,0 +1,3543 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename           $RCSfile: MartServiceQueryConfigUIFactory.java,v $
+ * Revision           $Revision: 1.6 $
+ * Release status     $State: Exp $
+ * Last modified on   $Date: 2008/03/04 16:46:53 $
+ *               by   $Author: davidwithers $
+ * Created on 21-Jun-2007
+ *****************************************************************/
+package org.biomart.martservice.config.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.AbstractButton;
+import javax.swing.AbstractListModel;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.ListModel;
+import javax.swing.SwingConstants;
+import javax.swing.border.AbstractBorder;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import org.apache.log4j.Logger;
+import org.biomart.martservice.DatasetLink;
+import org.biomart.martservice.MartDataset;
+import org.biomart.martservice.MartQuery;
+import org.biomart.martservice.MartService;
+import org.biomart.martservice.MartServiceException;
+import org.biomart.martservice.config.QueryConfigController;
+import org.biomart.martservice.config.QueryConfigUtils;
+import org.biomart.martservice.config.event.QueryComponentAdapter;
+import org.biomart.martservice.config.event.QueryComponentEvent;
+import org.biomart.martservice.query.Attribute;
+import org.biomart.martservice.query.Dataset;
+import org.biomart.martservice.query.Filter;
+import org.biomart.martservice.query.Query;
+import org.biomart.martservice.query.QueryListener;
+import org.ensembl.mart.lib.config.AttributeCollection;
+import org.ensembl.mart.lib.config.AttributeDescription;
+import org.ensembl.mart.lib.config.AttributeGroup;
+import org.ensembl.mart.lib.config.AttributeList;
+import org.ensembl.mart.lib.config.AttributePage;
+import org.ensembl.mart.lib.config.BaseNamedConfigurationObject;
+import org.ensembl.mart.lib.config.DatasetConfig;
+import org.ensembl.mart.lib.config.FilterCollection;
+import org.ensembl.mart.lib.config.FilterDescription;
+import org.ensembl.mart.lib.config.FilterGroup;
+import org.ensembl.mart.lib.config.FilterPage;
+import org.ensembl.mart.lib.config.Option;
+import org.ensembl.mart.lib.config.PushAction;
+
+/**
+ * Implementation of the <code>QueryConfigUIFactory</code> interface that
+ * creates a UI which looks like the Biomart web interface.
+ *
+ * @author David Withers
+ */
+public class MartServiceQueryConfigUIFactory implements QueryConfigUIFactory {
+
+	private static Logger logger = Logger
+	.getLogger(MartServiceQueryConfigUIFactory.class);
+
+	private String version;
+
+	private Color borderColor = new Color(202, 207, 213);
+
+	private Color backgroundColor = Color.WHITE;
+
+	private Color componentBackgroundColor = Color.WHITE;
+
+	private MartService martService;
+
+	private QueryConfigController controller;
+
+	private MartDataset martDataset;
+
+	private DatasetConfig datasetConfig;
+
+	private Map<String, Component> filterNameToComponentMap = new HashMap<String, Component>();
+
+	private Map<String, List<Component>> attributeNameToComponentMap = new HashMap<String, List<Component>>();
+
+	private Map<String, String> filterToDisplayName = new HashMap<String, String>();
+
+	private Map<String, String> attributeToDisplayName = new HashMap<String, String>();
+
+	private Map<String, Component> attributePageNameToComponent = new HashMap<String, Component>();
+
+	private Map<String, JRadioButton> attributePageNameToButton = new HashMap<String, JRadioButton>();
+
+	private boolean settingAttributeState = false;
+
+	private List<Component> componentRegister = new ArrayList<Component>();
+
+	private int datasetNumber;
+
+	public MartServiceQueryConfigUIFactory(MartService martService,
+			QueryConfigController controller, MartDataset martDataset)
+			throws MartServiceException {
+		this(martService, controller, martDataset, 1);
+	}
+
+	public MartServiceQueryConfigUIFactory(MartService martService,
+			QueryConfigController controller, MartDataset martDataset,
+			int datasetNumber) throws MartServiceException {
+		this.martService = martService;
+		this.controller = controller;
+		this.martDataset = martDataset;
+		this.datasetNumber = datasetNumber;
+		version = getConfigStyle();
+	}
+
+	private String getConfigStyle() {
+		String configStyle = "0.5";
+		String version = controller.getMartQuery().getQuery()
+				.getSoftwareVersion();
+		if (version == null || "0.4".equals(version)) {
+			configStyle = "0.4";
+		}
+		return configStyle;
+	}
+
+	/**
+	 * Returns the martDataset.
+	 *
+	 * @return the martDataset.
+	 */
+	public MartDataset getMartDataset() {
+		return martDataset;
+	}
+
+	/**
+	 * Returns the query configuration for the dataset.
+	 *
+	 * @return the query configuration for the dataset
+	 * @throws MartServiceException
+	 *             if the MartService returns an error or is unavailable
+	 */
+	public DatasetConfig getDatasetConfig() throws MartServiceException {
+		if (datasetConfig == null) {
+			datasetConfig = martService.getDatasetConfig(martDataset);
+		}
+		return datasetConfig;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getDatasetConfigUI(org.ensembl.mart.lib.config.DatasetConfig)
+	 */
+	public Component getDatasetConfigUI() throws MartServiceException {
+		JPanel panel = new JPanel(new BorderLayout());
+
+		final SummaryPanel summaryPanel = new SummaryPanel();
+
+		final JButton countButton = new JButton("Count");
+		countButton.setFont(countButton.getFont().deriveFont(Font.BOLD));
+		countButton.setOpaque(false);
+		countButton.addActionListener(new ActionListener() {
+
+			public void actionPerformed(ActionEvent e) {
+				countButton.setEnabled(false);
+				countButton.setText("Counting...");
+				new Thread("BiomartDatasetCount") {
+					public void run() {
+						try {
+							MartQuery martQuery = controller.getMartQuery();
+							Query query = martQuery.getQuery();
+							String datasetName = martQuery.getMartDataset()
+									.getName();
+
+							JLabel label1 = summaryPanel
+									.getDataset1CountLabel();
+							setSummaryCount(query, datasetName, label1);
+
+							Set<String> linkedDatasets = martQuery.getLinkedDatasets();
+							if (linkedDatasets.size() == 1) {
+								String linkedDatasetName = linkedDatasets
+										.iterator().next();
+								JLabel label2 = summaryPanel
+										.getDataset2CountLabel();
+								setSummaryCount(query, linkedDatasetName,
+										label2);
+							}
+
+						} catch (MartServiceException e) {
+						}
+						countButton.setText("Count");
+						countButton.setEnabled(true);
+					}
+				}.start();
+			}
+
+		});
+
+		final JCheckBox uniqueCheckBox = new JCheckBox("Unique results only");
+		uniqueCheckBox.setBackground(Color.BLACK);
+		uniqueCheckBox.setForeground(Color.WHITE);
+		uniqueCheckBox.setSelected(controller.getMartQuery().getQuery()
+				.getUniqueRows() == 1);
+
+		uniqueCheckBox.addItemListener(new ItemListener() {
+			public void itemStateChanged(ItemEvent e) {
+				if (e.getStateChange() == ItemEvent.SELECTED) {
+					controller.getMartQuery().getQuery().setUniqueRows(1);
+				} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+					controller.getMartQuery().getQuery().setUniqueRows(0);
+				}
+			}
+		});
+
+		JPanel buttonPanel = new JPanel(new BorderLayout());
+		buttonPanel.setBackground(Color.BLACK);
+		buttonPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
+		buttonPanel.add(countButton, BorderLayout.WEST);
+		buttonPanel.add(uniqueCheckBox, BorderLayout.EAST);
+		panel.add(buttonPanel, BorderLayout.NORTH);
+
+		JLabel label = new JLabel("biomart version 0.6");
+		label.setBackground(Color.BLACK);
+		label.setForeground(Color.WHITE);
+		label.setOpaque(true);
+		label.setBorder(new EmptyBorder(5, 5, 5, 5));
+		panel.add(label, BorderLayout.SOUTH);
+
+		JSplitPane splitPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+				true);
+		splitPanel.setBackground(backgroundColor);
+		splitPanel.setBorder(new EmptyBorder(10, 0, 10, 0));
+		splitPanel.setDividerLocation(250);
+
+		panel.add(splitPanel, BorderLayout.CENTER);
+
+		JScrollPane scrollPane1 = new JScrollPane(summaryPanel);
+		scrollPane1.getVerticalScrollBar().setUnitIncrement(10);
+		scrollPane1.setBorder(new LineBorder(Color.BLACK, 1));
+
+		splitPanel.setLeftComponent(scrollPane1);
+
+		final JComponent inputPanel = createVerticalBox(backgroundColor);
+		inputPanel.setBorder(new EmptyBorder(10, 5, 10, 5));
+
+		JScrollPane scrollPane = new JScrollPane(inputPanel);
+		scrollPane.getVerticalScrollBar().setUnitIncrement(10);
+		scrollPane.setBorder(new LineBorder(Color.BLACK, 1));
+
+		splitPanel.setRightComponent(scrollPane);
+
+		final JComponent datasetPanel = new DatasetPanel();
+		inputPanel.add(datasetPanel);
+
+//		final Component linkComponent = new DatasetLinkComponent(inputPanel,
+//				summaryPanel);
+//		componentRegister.add(linkComponent);
+
+		final JComponent attributePanel = createVerticalBox(backgroundColor);
+		attributePanel.setBorder(new EmptyBorder(10, 5, 10, 5));
+
+		final JComponent filterPanel = createVerticalBox(backgroundColor);
+		filterPanel.setBorder(new EmptyBorder(10, 5, 10, 5));
+
+		summaryPanel.getDataset1Button().addActionListener(
+				new ActionListener() {
+					public void actionPerformed(ActionEvent e) {
+						inputPanel.removeAll();
+						inputPanel.add(datasetPanel);
+						inputPanel.revalidate();
+						inputPanel.repaint();
+					}
+				});
+
+//		summaryPanel.getDataset2Button().addActionListener(
+//				new ActionListener() {
+//					public void actionPerformed(ActionEvent e) {
+//						inputPanel.removeAll();
+//						inputPanel.add(linkComponent);
+//						inputPanel.revalidate();
+//						inputPanel.repaint();
+//					}
+//				});
+
+		generateConfiguration(this, summaryPanel, inputPanel, attributePanel,
+				filterPanel);
+
+		summaryPanel.getFilters1Button().addActionListener(
+				new ActionListener() {
+					public void actionPerformed(ActionEvent e) {
+						inputPanel.removeAll();
+						inputPanel.add(filterPanel);
+						inputPanel.revalidate();
+						inputPanel.repaint();
+					}
+				});
+
+		summaryPanel.getAttributes1Button().addActionListener(
+				new ActionListener() {
+					public void actionPerformed(ActionEvent e) {
+						inputPanel.removeAll();
+						inputPanel.add(attributePanel);
+						inputPanel.revalidate();
+						inputPanel.repaint();
+					}
+				});
+
+		return panel;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributePagesUI(org.ensembl.mart.lib.config.AttributePage[])
+	 */
+	public Component getAttributePagesUI(AttributePage[] attributePages,
+			Object data) throws MartServiceException {
+		final JComponent box = createVerticalBox(backgroundColor);
+
+		final JComboBox formatList = new JComboBox();
+		formatList.setBackground(backgroundColor);
+
+		if (datasetNumber == 1) {
+			formatList.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					if (e.getStateChange() == ItemEvent.SELECTED) {
+						controller.getMartQuery().getQuery().setFormatter(
+								(String) e.getItem());
+					}
+				}
+			});
+
+			ButtonGroup outputButtons = new ButtonGroup();
+			JRadioButton multipleOutput = new JRadioButton(
+					"Multiple outputs (one per attribute)");
+			multipleOutput.setBackground(backgroundColor);
+			JRadioButton singleOutput = new JRadioButton(
+					"Single output formatted as");
+			singleOutput.setBackground(backgroundColor);
+			outputButtons.add(multipleOutput);
+			outputButtons.add(singleOutput);
+			if (controller.getMartQuery().getQuery().getFormatter() == null) {
+				multipleOutput.setSelected(true);
+				formatList.setEnabled(false);
+			} else {
+				singleOutput.setSelected(true);
+				formatList.setEnabled(true);
+			}
+
+			singleOutput.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					if (e.getStateChange() == ItemEvent.SELECTED) {
+						controller.getMartQuery().getQuery().setFormatter(
+								(String) formatList.getSelectedItem());
+						formatList.setEnabled(true);
+					} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+						controller.getMartQuery().getQuery().setFormatter(null);
+						formatList.setEnabled(false);
+					}
+				}
+			});
+
+			JPanel multipleOutputBox = new JPanel(new MinimalLayout());
+			multipleOutputBox.setBackground(componentBackgroundColor);
+			multipleOutputBox.add(multipleOutput);
+
+			JComponent formatBox = createHorizontalBox(backgroundColor);
+			formatBox.add(singleOutput);
+			formatBox.add(Box.createHorizontalStrut(10));
+			formatBox.add(formatList);
+			formatBox.add(Box.createHorizontalGlue());
+
+			JComponent outputBox = createVerticalBox(backgroundColor);
+			outputBox.setBorder(new CompoundBorder(new LineBorder(borderColor,
+					1), new EmptyBorder(10, 10, 10, 10)));
+			outputBox.add(multipleOutputBox);
+			outputBox.add(formatBox);
+
+			box.add(Box.createVerticalStrut(2));
+			box.add(outputBox);
+
+		}
+
+		if (attributePages.length > 1) {
+			ButtonGroup buttonGroup = new ButtonGroup();
+			final Map<String, Component> componentMap = new HashMap<String, Component>();
+			final Map<String, List<String>> formatMap = new HashMap<String, List<String>>();
+
+			final JComponent buttonBox = new JPanel(new GridLayout(0, 2));
+			buttonBox.setBorder(new CompoundBorder(new LineBorder(borderColor,
+					1), new EmptyBorder(10, 10, 10, 10)));
+			buttonBox.setBackground(backgroundColor);
+			box.add(buttonBox, 0);
+
+			final JComponent pagePanel = new JPanel(new BorderLayout());
+			pagePanel.setBackground(backgroundColor);
+			box.add(pagePanel);
+
+			ItemListener listener = new ItemListener() {
+				Component lastSelectedComponent;
+
+				JRadioButton lastSelectedButton;
+
+				public void itemStateChanged(ItemEvent e) {
+					JRadioButton button = (JRadioButton) e.getItem();
+					if (button != null) {
+						Component selectedComponent = componentMap.get(button
+								.getActionCommand());
+						if (e.getStateChange() == ItemEvent.SELECTED) {
+							boolean switchPage = true;
+							if (lastSelectedComponent != null) {
+								Map<String, AttributeComponent> selected = new HashMap<String, AttributeComponent>();
+								// find all attributes on the last page that
+								// were selected
+								List<AttributeComponent> oldChildren = getAttributeComponents(lastSelectedComponent);
+								for (AttributeComponent attributeComponent : oldChildren) {
+									if (attributeComponent.isSelected()) {
+										selected.put(attributeComponent
+												.getQualifiedName(),
+												attributeComponent);
+									}
+								}
+								// remove attributes that are already selected
+								// on
+								// the new page
+								List<AttributeComponent> newChildren = getAttributeComponents(selectedComponent);
+								for (AttributeComponent attributeComponent : newChildren) {
+									if (attributeComponent.isSelected()) {
+										selected.remove(attributeComponent
+												.getQualifiedName());
+									}
+								}
+								Collection<AttributeComponent> stillSelected = selected
+										.values();
+								if (stillSelected.size() > 0) {
+									List<String> attributeNames = new ArrayList<String>();
+									for (AttributeComponent component : stillSelected) {
+										attributeNames.add(component
+												.getButton().getText());
+									}
+									List<Object> message = new ArrayList<Object>();
+									message
+											.add("The "
+													+ button.getText()
+													+ " page does not contain the following attributes:");
+									JList jList = new JList(attributeNames
+											.toArray());
+									jList.setBorder(LineBorder
+											.createGrayLineBorder());
+									message.add(jList);
+									message
+											.add("These attributes will be removed. Do you wish to continue?");
+									switchPage = JOptionPane.showConfirmDialog(
+											buttonBox, message.toArray(),
+											"Confirm page change",
+											JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
+								}
+								if (switchPage) {
+									// deselect any attributes on the old page
+									// that are not on the new page
+									for (AttributeComponent attributeComponent : stillSelected) {
+										attributeComponent.setSelected(false);
+									}
+								}
+							}
+							if (switchPage) {
+								pagePanel.add(selectedComponent,
+										BorderLayout.NORTH);
+								if (datasetNumber == 1) {
+									List<String> formats = formatMap.get(button
+											.getActionCommand());
+									formatList
+											.setModel(new DefaultComboBoxModel(
+													formats.toArray()));
+									String formatter = controller
+											.getMartQuery().getQuery()
+											.getFormatter();
+									if (formatter != null) {
+										formatList.getModel().setSelectedItem(
+												null);
+										if (formats.contains(formatter)) {
+											formatList.getModel()
+													.setSelectedItem(formatter);
+										} else if (formats.size() > 0) {
+											formatList.getModel()
+													.setSelectedItem(
+															formats.get(0));
+										}
+									}
+								}
+							} else {
+								lastSelectedButton.setSelected(true);
+							}
+							box.revalidate();
+							box.repaint();
+						} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+							pagePanel.removeAll();
+							lastSelectedComponent = selectedComponent;
+							lastSelectedButton = button;
+						}
+					}
+				}
+
+			};
+
+			for (int i = 0; i < attributePages.length; i++) {
+				if (QueryConfigUtils.display(attributePages[i])) {
+					Component component = getAttributePageUI(attributePages[i],
+							data);
+					JRadioButton button = new JRadioButton(attributePages[i]
+							.getDisplayName());
+					String description = attributePages[i].getDescription();
+					if (description != null) {
+						button.setToolTipText(description);
+					}
+					button.setBackground(backgroundColor);
+					button.setFont(button.getFont().deriveFont(Font.BOLD));
+					button
+							.setActionCommand(attributePages[i]
+									.getInternalName());
+					button.addItemListener(listener);
+					buttonGroup.add(button);
+					buttonBox.add(button);
+					componentMap.put(attributePages[i].getInternalName(),
+							component);
+					formatMap.put(attributePages[i].getInternalName(), getFormatList(attributePages[i]));
+					attributePageNameToComponent.put(attributePages[i]
+							.getInternalName(), component);
+					attributePageNameToButton.put(attributePages[i]
+							.getInternalName(), button);
+				}
+			}
+
+		} else if (attributePages.length == 1) {
+			if (datasetNumber == 1) {
+				List<String> formats = Arrays.asList(attributePages[0]
+						.getOutFormats().toUpperCase().split(","));
+				formatList
+						.setModel(new DefaultComboBoxModel(formats.toArray()));
+				String formatter = controller.getMartQuery().getQuery()
+						.getFormatter();
+				if (formatter != null) {
+					formatList.getModel().setSelectedItem(null);
+					if (formats.contains(formatter)) {
+						formatList.getModel().setSelectedItem(formatter);
+					} else if (formats.size() > 0) {
+						formatList.getModel().setSelectedItem(formats.get(0));
+					}
+				}
+			}
+			box.add(getAttributePageUI(attributePages[0], data));
+
+		} else {
+			box.add(new JLabel("No attributes available"));
+		}
+
+		JPanel northPanel = new JPanel(new BorderLayout());
+		northPanel.setBackground(backgroundColor);
+		northPanel.add(box, BorderLayout.NORTH);
+
+		return northPanel;
+
+		// return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributePageUI(org.ensembl.mart.lib.config.AttributePage)
+	 */
+	public Component getAttributePageUI(AttributePage attributePage, Object data)
+			throws MartServiceException {
+		JComponent box = createVerticalBox(backgroundColor);
+
+		AttributeGroup[] attributeGroups = (AttributeGroup[]) attributePage
+				.getAttributeGroups().toArray(new AttributeGroup[0]);
+
+		box.add(getAttributeGroupsUI(attributeGroups, data));
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeGroupsUI(org.ensembl.mart.lib.config.AttributeGroup[])
+	 */
+	public Component getAttributeGroupsUI(AttributeGroup[] attributeGroups,
+			Object data) throws MartServiceException {
+		JComponent box = createVerticalBox(backgroundColor);
+
+		for (int i = 0; i < attributeGroups.length; i++) {
+			if (QueryConfigUtils.display(attributeGroups[i])) {
+				box.add(Box.createVerticalStrut(2));
+				box.add(getAttributeGroupUI(attributeGroups[i], data));
+			}
+		}
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeGroupUI(org.ensembl.mart.lib.config.AttributeGroup)
+	 */
+	public Component getAttributeGroupUI(AttributeGroup attributeGroup,
+			Object data) throws MartServiceException {
+		JLabel title = new JLabel(attributeGroup.getDisplayName());
+		title.setFont(title.getFont().deriveFont(Font.PLAIN));
+
+		String description = attributeGroup.getDescription();
+		if (description != null) {
+			title.setToolTipText(description);
+		}
+		ExpandableBox box = new ExpandableBox(title, componentBackgroundColor,
+				borderColor, new Insets(10, 10, 10, 10));
+
+		AttributeCollection[] attributeCollections = attributeGroup
+				.getAttributeCollections();
+		box.add(getAttributeCollectionsUI(attributeCollections, data));
+
+		box.setExpanded(false);
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeCollectionsUI(org.ensembl.mart.lib.config.AttributeCollection[])
+	 */
+	public Component getAttributeCollectionsUI(
+			AttributeCollection[] attributeCollections, Object data)
+			throws MartServiceException {
+		JComponent box = createVerticalBox(componentBackgroundColor);
+
+		for (int i = 0; i < attributeCollections.length; i++) {
+			if (QueryConfigUtils.display(attributeCollections[i])) {
+				box.add(Box.createVerticalStrut(10));
+				box
+						.add(getAttributeCollectionUI(attributeCollections[i],
+								data));
+			}
+		}
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeCollectionUI(org.ensembl.mart.lib.config.AttributeCollection)
+	 */
+	public Component getAttributeCollectionUI(
+			AttributeCollection attributeCollection, Object data)
+			throws MartServiceException {
+		JComponent box = null;
+
+		AttributeDescription[] attributeDescriptions = (AttributeDescription[]) attributeCollection
+				.getAttributeDescriptions()
+				.toArray(new AttributeDescription[0]);
+
+		AttributeList[] attributeLists = (AttributeList[]) attributeCollection
+				.getAttributeLists().toArray(new AttributeList[0]);
+
+		JLabel sequenceLabel = null;
+		if ("seq_scope_type".equals(attributeCollection.getInternalName())) {
+			sequenceLabel = new JLabel(MartServiceIcons
+					.getIcon("gene_schematic"));
+			box = createBox(sequenceLabel, false);
+		} else if (attributeDescriptions.length > 1
+				|| attributeLists.length > 1) {
+			// more than one attribute so create a box with the collection name
+			// as a header
+			JLabel title = new JLabel(attributeCollection.getDisplayName());
+			title.setFont(title.getFont().deriveFont(Font.BOLD));
+			String description = attributeCollection.getDescription();
+			if (description != null) {
+				title.setToolTipText(description);
+			}
+			box = createBox(title, false);
+		} else {
+			box = createBox(null, false);
+		}
+
+		int maxSelect = attributeCollection.getMaxSelect();
+		if (maxSelect == 1) {
+			if (attributeDescriptions.length > 0) {
+				box.add(getAttributeDescriptionsUI(attributeDescriptions,
+						new Object[] { SINGLE_SELECTION, sequenceLabel }));
+			} else {
+				box.add(getAttributeListsUI(attributeLists, new Object[] {
+						SINGLE_SELECTION, sequenceLabel }));
+			}
+		} else {
+			if (attributeDescriptions.length > 0) {
+				box.add(getAttributeDescriptionsUI(attributeDescriptions,
+						new Object[] { MULTIPLE_SELECTION, sequenceLabel }));
+			} else {
+				box.add(getAttributeListsUI(attributeLists, new Object[] {
+						MULTIPLE_SELECTION, sequenceLabel }));
+			}
+		}
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeDescriptionsUI(org.ensembl.mart.lib.config.AttributeDescription[],
+	 *      int)
+	 */
+	public Component getAttributeDescriptionsUI(
+			AttributeDescription[] attributeDescriptions, Object data)
+			throws MartServiceException {
+		Object[] dataArray = (Object[]) data;
+		JComponent box = new JPanel(new GridLayout(1, 2));
+		box.setBackground(componentBackgroundColor);
+		JComponent box1 = createVerticalBox(componentBackgroundColor);
+		JComponent box2 = createVerticalBox(componentBackgroundColor);
+		box.add(box1);
+		box.add(box2);
+
+		// button group used if the attribute collection is SINGLE_SELECTION
+		ButtonGroup buttonGroup = new ButtonGroup();
+		JRadioButton off = new JRadioButton("OFF");
+		buttonGroup.add(off);
+
+		JComponent currentBox = box1;
+
+		for (int i = 0; i < attributeDescriptions.length; i++) {
+			if (QueryConfigUtils.display(attributeDescriptions[i])) {
+				Component component = getAttributeDescriptionUI(
+						attributeDescriptions[i],
+						dataArray[0] == SINGLE_SELECTION ? new Object[] { off,
+								dataArray[1] } : new Object[] { null,
+								dataArray[1] });
+				if (component != null) {
+					currentBox.add(component);
+					if (dataArray[0] == SINGLE_SELECTION
+							&& component instanceof AttributeComponent) {
+						AttributeComponent attributeComponent = (AttributeComponent) component;
+						buttonGroup.add(attributeComponent.getButton());
+					}
+					if (QueryConfigUtils.isFilterReference(
+							attributeDescriptions[i], version)) {
+						FilterDescription filterDescription = QueryConfigUtils
+								.getReferencedFilterDescription(
+										attributeDescriptions[i], version);
+						Component filterComponent = getFilterDescriptionUI(
+								filterDescription, data);
+						if (filterComponent instanceof QueryComponent
+								&& component instanceof AttributeComponent) {
+							AttributeComponent attributeComponent = (AttributeComponent) component;
+							((QueryComponent) filterComponent)
+									.setSelectorButton(attributeComponent
+											.getButton());
+						}
+						componentRegister.add(filterComponent);
+						box2.add(filterComponent);
+						currentBox = box2;
+					}
+					if (currentBox == box1) {
+						currentBox = box2;
+					} else {
+						currentBox = box1;
+					}
+				}
+			}
+		}
+		currentBox.add(Box.createVerticalGlue());
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeDescriptionUI(org.ensembl.mart.lib.config.AttributeDescription,
+	 *      int)
+	 */
+	public Component getAttributeDescriptionUI(
+			AttributeDescription attributeDescription, Object data)
+			throws MartServiceException {
+		Object[] dataArray = (Object[]) data;
+		MartDataset dataset = martDataset;
+		AttributeDescription displayedAttribute;
+		if (QueryConfigUtils.isReference(attributeDescription, version)) {
+			dataset = QueryConfigUtils.getReferencedDataset(martService,
+					martDataset, attributeDescription, version);
+			if (dataset == null) {
+				return null;
+			}
+			if (QueryConfigUtils.isFilterReference(attributeDescription,
+					version)) {
+				FilterDescription filter = QueryConfigUtils
+						.getReferencedFilterDescription(martService, dataset,
+								attributeDescription, version);
+				if (filter == null) {
+					return null;
+				}
+				displayedAttribute = attributeDescription;
+				displayedAttribute.setDisplayName(filter.getDisplayName());
+				filterToDisplayName.put(filter.getInternalName(), filter
+						.getDisplayName());
+			} else {
+				displayedAttribute = QueryConfigUtils
+						.getReferencedAttributeDescription(martService,
+								dataset, attributeDescription, version);
+				if (displayedAttribute == null) {
+					// if the reference can't be resolved the the attribute just
+					// doesn't get displayed
+					return null;
+				}
+			}
+		} else {
+			displayedAttribute = attributeDescription;
+		}
+
+		final AttributeComponent component = new AttributeComponent(
+				displayedAttribute, martDataset, dataArray[0]);
+		component.setPointerDataset(attributeDescription
+				.getAttribute("pointerDataset"));
+		if (!QueryConfigUtils.isFilterReference(attributeDescription, version)) {
+			if (!attributeNameToComponentMap.containsKey(component
+					.getQualifiedName())) {
+				attributeNameToComponentMap.put(component.getQualifiedName(),
+						new ArrayList<Component>());
+			}
+			attributeNameToComponentMap.get(component
+					.getQualifiedName()).add(component);
+			componentRegister.add(component);
+			// nasty hard coded rules that aren't in the configs
+			// component.addQueryComponentListener(new QueryComponentAdapter() {
+			// public void attributeAdded(QueryComponentEvent event) {
+			// String name = component.getName();
+			// String dataset = component.getDataset().getName();
+			// if (name.equals("coding_gene_flank")
+			// || name.equals("coding_transcript_flank")
+			// || name.equals("transcript_flank")
+			// || name.equals("gene_flank")) {
+			// QueryComponent filterComponent = (QueryComponent)
+			// filterNameToComponentMap
+			// .get("upstream_flank");
+			// if (filterComponent != null) {
+			// filterComponent.setSelected(true);
+			// }
+			// filterComponent = (QueryComponent) filterNameToComponentMap
+			// .get("downstream_flank");
+			// if (filterComponent != null) {
+			// filterComponent.setSelected(true);
+			// }
+			// }
+			// }
+			//
+			// });
+		}
+		if (dataArray[1] instanceof JLabel) {
+			final JLabel sequenceLabel = (JLabel) dataArray[1];
+			component.addQueryComponentListener(new QueryComponentAdapter() {
+				public void attributeAdded(QueryComponentEvent event) {
+					String name = component.getName();
+					if ("3utr".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_3utr"));
+					} else if ("5utr".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_5utr"));
+					} else if ("cdna".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_cdna"));
+					} else if ("coding_gene_flank".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_coding_gene_flank"));
+					} else if ("coding_transcript_flank".equals(name)) {
+						sequenceLabel
+								.setIcon(MartServiceIcons
+										.getIcon("gene_schematic_coding_transcript_flank"));
+					} else if ("coding".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_coding"));
+					} else if ("gene_exon_intron".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_gene_exon_intron"));
+					} else if ("gene_exon".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_gene_exon"));
+					} else if ("gene_flank".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_gene_flank"));
+					} else if ("peptide".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_peptide"));
+					} else if ("transcript_exon_intron".equals(name)) {
+						sequenceLabel
+								.setIcon(MartServiceIcons
+										.getIcon("gene_schematic_transcript_exon_intron"));
+					} else if ("transcript_exon".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_transcript_exon"));
+					} else if ("transcript_flank".equals(name)) {
+						sequenceLabel.setIcon(MartServiceIcons
+								.getIcon("gene_schematic_transcript_flank"));
+					}
+				}
+
+			});
+		}
+		return component;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeListsUI(org.ensembl.mart.lib.config.AttributeList[],
+	 *      int)
+	 */
+	public Component getAttributeListsUI(AttributeList[] attributeLists,
+			Object data) throws MartServiceException {
+		Object[] dataArray = (Object[]) data;
+		JComponent box = new JPanel(new GridLayout(1, 2));
+		box.setBackground(componentBackgroundColor);
+		JComponent box1 = createVerticalBox(componentBackgroundColor);
+		JComponent box2 = createVerticalBox(componentBackgroundColor);
+		box.add(box1);
+		box.add(box2);
+
+		// button group used if the attribute collection is SINGLE_SELECTION
+		ButtonGroup buttonGroup = new ButtonGroup();
+		JRadioButton off = new JRadioButton("OFF");
+		buttonGroup.add(off);
+
+		JComponent currentBox = box1;
+
+		for (int i = 0; i < attributeLists.length; i++) {
+			if (QueryConfigUtils.display(attributeLists[i])) {
+				Component component = getAttributeListUI(attributeLists[i],
+						dataArray[0] == SINGLE_SELECTION ? new Object[] { off,
+								dataArray[1] } : new Object[] { null,
+								dataArray[1] });
+				if (component != null) {
+					currentBox.add(component);
+					if (dataArray[0] == SINGLE_SELECTION
+							&& component instanceof AttributeComponent) {
+						AttributeComponent attributeComponent = (AttributeComponent) component;
+						buttonGroup.add(attributeComponent.getButton());
+					}
+					if (currentBox == box1) {
+						currentBox = box2;
+					} else {
+						currentBox = box1;
+					}
+				}
+			}
+		}
+		currentBox.add(Box.createVerticalGlue());
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getAttributeListUI(org.ensembl.mart.lib.config.AttributeList,
+	 *      int)
+	 */
+	public Component getAttributeListUI(AttributeList attributeList, Object data)
+			throws MartServiceException {
+		Object[] dataArray = (Object[]) data;
+
+		AttributeComponent component = new AttributeComponent(attributeList,
+				martDataset, dataArray[0]);
+
+		if (!attributeNameToComponentMap.containsKey(component
+				.getQualifiedName())) {
+			attributeNameToComponentMap.put(component.getQualifiedName(),
+					new ArrayList<Component>());
+		}
+		attributeNameToComponentMap.get(component.getQualifiedName())
+				.add(component);
+		componentRegister.add(component);
+		/*
+		 * if (dataArray[1] instanceof JLabel) { final JLabel sequenceLabel =
+		 * (JLabel) dataArray[1]; component.addQueryComponentListener(new
+		 * QueryComponentAdapter() { public void
+		 * attributeAdded(QueryComponentEvent event) { String name =
+		 * component.getName(); if ("3utr".equals(name)) {
+		 * sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_3utr")); } else if ("5utr".equals(name)) {
+		 * sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_5utr")); } else if ("cdna".equals(name)) {
+		 * sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_cdna")); } else if
+		 * ("coding_gene_flank".equals(name)) {
+		 * sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_coding_gene_flank")); } else if
+		 * ("coding_transcript_flank".equals(name)) { sequenceLabel
+		 * .setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_coding_transcript_flank")); } else if
+		 * ("coding".equals(name)) { sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_coding")); } else if
+		 * ("gene_exon_intron".equals(name)) {
+		 * sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_gene_exon_intron")); } else if
+		 * ("gene_exon".equals(name)) { sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_gene_exon")); } else if
+		 * ("gene_flank".equals(name)) { sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_gene_flank")); } else if
+		 * ("peptide".equals(name)) { sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_peptide")); } else if
+		 * ("transcript_exon_intron".equals(name)) { sequenceLabel
+		 * .setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_transcript_exon_intron")); } else if
+		 * ("transcript_exon".equals(name)) {
+		 * sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_transcript_exon")); } else if
+		 * ("transcript_flank".equals(name)) {
+		 * sequenceLabel.setIcon(MartServiceIcons
+		 * .getIcon("gene_schematic_transcript_flank")); } }
+		 *
+		 * }); }
+		 */
+		return component;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterPagesUI(org.ensembl.mart.lib.config.FilterPage[])
+	 */
+	public Component getFilterPagesUI(FilterPage[] filterPages, Object data)
+			throws MartServiceException {
+		final JComponent box = createVerticalBox(backgroundColor);
+
+		for (int i = 0; i < filterPages.length; i++) {
+			if (QueryConfigUtils.display(filterPages[i])) {
+				box.add(getFilterPageUI(filterPages[i], data));
+			}
+		}
+
+		JPanel panel = new JPanel(new BorderLayout());
+		panel.setBackground(backgroundColor);
+		panel.add(box, BorderLayout.NORTH);
+
+		return panel;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterPageUI(org.ensembl.mart.lib.config.FilterPage)
+	 */
+	public Component getFilterPageUI(FilterPage filterPage, Object data)
+			throws MartServiceException {
+		JComponent box = createVerticalBox(backgroundColor);
+
+		FilterGroup[] filterGroups = (FilterGroup[]) filterPage
+				.getFilterGroups().toArray(new FilterGroup[0]);
+		box.add(getFilterGroupsUI(filterGroups, data));
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterGroupsUI(org.ensembl.mart.lib.config.FilterGroup[])
+	 */
+	public Component getFilterGroupsUI(FilterGroup[] filterGroups, Object data)
+			throws MartServiceException {
+		JComponent box = createVerticalBox(backgroundColor);
+
+		for (int i = 0; i < filterGroups.length; i++) {
+			if (QueryConfigUtils.display(filterGroups[i])) {
+				box.add(Box.createVerticalStrut(2));
+				box.add(getFilterGroupUI(filterGroups[i], data));
+			}
+		}
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterGroupUI(org.ensembl.mart.lib.config.FilterGroup)
+	 */
+	public Component getFilterGroupUI(FilterGroup filterGroup, Object data)
+			throws MartServiceException {
+		JLabel title = new JLabel(filterGroup.getDisplayName());
+		title.setFont(title.getFont().deriveFont(Font.PLAIN));
+		String description = filterGroup.getDescription();
+		if (description != null) {
+			title.setToolTipText(description);
+		}
+		ExpandableBox box = new ExpandableBox(title, componentBackgroundColor,
+				borderColor, new Insets(10, 10, 10, 10));
+
+		FilterCollection[] filterCollections = filterGroup
+				.getFilterCollections();
+		box.add(getFilterCollectionsUI(filterCollections, data));
+
+		box.setExpanded(false);
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterCollectionsUI(org.ensembl.mart.lib.config.FilterCollection[])
+	 */
+	public Component getFilterCollectionsUI(
+			FilterCollection[] filterCollections, Object data)
+			throws MartServiceException {
+		JComponent box = createVerticalBox(componentBackgroundColor);
+
+		for (int i = 0; i < filterCollections.length; i++) {
+			if (QueryConfigUtils.display(filterCollections[i])) {
+				Component component = getFilterCollectionUI(
+						filterCollections[i], data);
+				if (component != null) {
+					box.add(Box.createVerticalStrut(10));
+					box.add(component);
+				}
+			}
+		}
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterCollectionUI(org.ensembl.mart.lib.config.FilterCollection)
+	 */
+	public Component getFilterCollectionUI(FilterCollection filterCollection,
+			Object data) throws MartServiceException {
+		JComponent box = null;
+
+		String displayName = filterCollection.getDisplayName();
+		if (displayName == null) {
+			displayName = filterCollection.getInternalName();
+		}
+		AbstractButton selectorButton = new JCheckBox(QueryConfigUtils
+				.splitSentence(displayName));
+		selectorButton.setFont(selectorButton.getFont().deriveFont(Font.PLAIN));
+		selectorButton.setBackground(componentBackgroundColor);
+		String description = filterCollection.getDescription();
+		if (description != null) {
+			selectorButton.setToolTipText(description);
+		}
+
+		FilterDescription[] filterDescriptions = (FilterDescription[]) filterCollection
+				.getFilterDescriptions().toArray(new FilterDescription[0]);
+
+		if (filterDescriptions.length == 1) {
+			if (QueryConfigUtils.display(filterDescriptions[0])) {
+				Component filterComponent = getFilterDescriptionUI(
+						filterDescriptions[0], data);
+				if (filterComponent != null) {
+					filterToDisplayName.put(
+							filterDescriptions[0].getInternalName(), displayName);
+					if (QueryConfigUtils
+							.isReference(filterDescriptions[0], version)) {
+						MartDataset dataset = QueryConfigUtils
+						.getReferencedDataset(martService, martDataset,
+								filterDescriptions[0], version);
+						FilterDescription referencedFilter = QueryConfigUtils
+						.getReferencedFilterDescription(martService,
+								dataset, filterDescriptions[0], version);
+						filterToDisplayName.put(referencedFilter.getInternalName(),
+								displayName);
+					}
+
+					box = createBox(null, false);
+					JComponent grid = new JPanel(new GridLayout(1, 2));
+					grid.setBackground(componentBackgroundColor);
+					JPanel buttonPanel = new JPanel(new MinimalLayout());
+					buttonPanel.setBackground(componentBackgroundColor);
+					buttonPanel.add(selectorButton);
+					grid.add(buttonPanel);
+					if (filterComponent instanceof QueryComponent) {
+						((QueryComponent) filterComponent)
+						.setSelectorButton(selectorButton);
+					}
+					grid.add(filterComponent);
+					box.add(grid);
+				}
+			}
+		} else {
+			Component component = getFilterDescriptionsUI(filterDescriptions,
+					selectorButton);
+			if (component != null) {
+				box = createBox(selectorButton, false);
+				box.add(component);
+			}
+		}
+
+		return box;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterDescriptionsUI(org.ensembl.mart.lib.config.FilterDescription[],
+	 *      int)
+	 */
+	public Component getFilterDescriptionsUI(
+			FilterDescription[] filterDescriptions, Object data)
+			throws MartServiceException {
+		List<Component> components = new ArrayList<Component>();
+		for (int i = 0; i < filterDescriptions.length; i++) {
+			if (QueryConfigUtils.display(filterDescriptions[i])) {
+				Component component = getFilterDescriptionUI(
+						filterDescriptions[i], data);
+				if (component != null) {
+					if (component instanceof QueryComponent
+							&& data instanceof AbstractButton) {
+						((QueryComponent) component)
+						.setSelectorButton((AbstractButton) data);
+					}
+
+					String displayName = filterDescriptions[i].getDisplayName();
+					if (displayName == null) {
+						logger.info("Cant find a display name for filter '"
+								+ filterDescriptions[i].getInternalName() + "'");
+						displayName = filterDescriptions[i].getInternalName();
+					}
+					filterToDisplayName.put(
+							filterDescriptions[i].getInternalName(), displayName);
+					JLabel displayLabel = new JLabel(QueryConfigUtils
+							.splitSentence(displayName));
+					displayLabel.setFont(displayLabel.getFont().deriveFont(
+							Font.PLAIN));
+					String description = filterDescriptions[i].getDescription();
+					if (description != null) {
+						displayLabel.setToolTipText(description);
+					}
+					displayLabel.setBackground(componentBackgroundColor);
+					displayLabel.setBorder(new EmptyBorder(0, 22, 0, 0));
+
+					components.add(displayLabel);
+					components.add(component);
+				}
+			}
+		}
+
+		if (components.size() > 0) {
+			JComponent box = new JPanel(
+					new GridLayout(components.size() / 2, 2));
+			box.setBackground(componentBackgroundColor);
+			for (Component component : components) {
+				box.add(component);
+			}
+			return box;
+		} else {
+			return null;
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryConfigUIFactory#getFilterDescriptionUI(org.ensembl.mart.lib.config.FilterDescription,
+	 *      int)
+	 */
+	public Component getFilterDescriptionUI(
+			FilterDescription filterDescription, Object data)
+			throws MartServiceException {
+		QueryComponent component;
+
+		String pointerDataset = filterDescription
+				.getAttribute("pointerDataset");
+		MartDataset dataset = martDataset;
+		FilterDescription displayedFilter;
+		if (QueryConfigUtils.isReference(filterDescription, version)) {
+			dataset = QueryConfigUtils.getReferencedDataset(martService,
+					martDataset, filterDescription, version);
+			if (dataset == null) {
+				return null;
+			}
+			displayedFilter = QueryConfigUtils.getReferencedFilterDescription(
+					martService, dataset, filterDescription, version);
+			if (displayedFilter == null){
+				return null;
+			}
+			filterDescription.setDisplayName(displayedFilter.getDisplayName());
+		} else {
+			displayedFilter = filterDescription;
+		}
+		assert dataset != null;
+
+		String type = displayedFilter.getType();
+		if (type == null) {
+			type = "text";// default filter type
+		}
+
+		if (type.equals("boolean") || type.equals("boolean_num")) {
+			component = new BooleanFilterComponent(displayedFilter, martDataset);
+			component.setPointerDataset(pointerDataset);
+			componentRegister.add(component);
+		} else if (type.endsWith("list") || type.endsWith("basic_filter")
+				|| QueryConfigUtils.isList(displayedFilter)) {
+			if (type.equals("boolean_list")
+					|| QueryConfigUtils.isBooleanList(displayedFilter)) {
+				Option[] options = displayedFilter.getOptions();
+				List filters = new ArrayList();
+				for (int i = 0; i < options.length; i++) {
+					FilterDescription booleanFilterDescription = new FilterDescription(
+							options[i]);
+					QueryComponent queryComponent = new BooleanFilterComponent(
+							booleanFilterDescription, martDataset);
+					queryComponent.setPointerDataset(pointerDataset);
+					filters.add(queryComponent);
+					componentRegister.add(queryComponent);
+				}
+				component = new BooleanListFilterComponent(displayedFilter,
+						martDataset, filters);
+				component.setPointerDataset(pointerDataset);
+			} else if (type.equals("id_list")
+					|| QueryConfigUtils.isIdList(displayedFilter)) {
+				Option[] options = displayedFilter.getOptions();
+				List<TextFilterComponent> filters = new ArrayList<TextFilterComponent>();
+				for (int i = 0; i < options.length; i++) {
+					FilterDescription idFilterDescription = new FilterDescription(
+							options[i]);
+					idFilterDescription.setType("id_list");
+					TextFilterComponent queryComponent = new TextFilterComponent(
+							idFilterDescription, martDataset);
+					queryComponent.setPointerDataset(pointerDataset);
+					filters.add(queryComponent);
+					componentRegister.add(queryComponent);
+				}
+				component = new IdListFilterComponent(displayedFilter,
+						martDataset, filters);
+				component.setPointerDataset(pointerDataset);
+			} else if (QueryConfigUtils.isNestedList(displayedFilter)) {
+				TextFilterComponent filterComponent = new TextFilterComponent(
+						displayedFilter, martDataset);
+				filterComponent.setPointerDataset(pointerDataset);
+				filterComponent.add(QueryConfigUtils.getOptionButton(
+						displayedFilter, filterComponent));
+				component = filterComponent;
+				componentRegister.add(component);
+			} else {
+				ListFilterComponent filterComponent = new ListFilterComponent(
+						getDatasetConfig().getDataset(), displayedFilter,
+						martDataset, filterNameToComponentMap);
+				filterComponent.setPointerDataset(pointerDataset);
+				// map the component to a local dataset name as the 'ref' of a
+				// pushaction may be a local reference
+				filterNameToComponentMap.put(getDatasetConfig().getDataset()
+						+ "." + displayedFilter.getInternalName(),
+						filterComponent);
+				// if the filter is a reference then also map the component to
+				// its referenced dataset name as the 'ref' of a pushaction may
+				// be a non-local reference
+				if (QueryConfigUtils.isReference(filterDescription, version)) {
+					filterNameToComponentMap.put(filterDescription
+							.getInternalName(), filterComponent);
+				}
+				component = filterComponent;
+				componentRegister.add(component);
+			}
+		} else {
+			String multipleValues = displayedFilter.getMultipleValues();
+			if ("1".equals(multipleValues)) {
+				component = new MultipleTextFilterComponent(displayedFilter, martDataset);
+			} else {
+				component = new TextFilterComponent(displayedFilter, martDataset);
+			}
+			component.setPointerDataset(pointerDataset);
+			componentRegister.add(component);
+			// mapping for hard coded rules
+			filterNameToComponentMap.put(filterDescription.getInternalName(),
+					component);
+		}
+
+		return component;
+	}
+
+	private void registerComponents() {
+		for (Iterator iter = componentRegister.iterator(); iter.hasNext();) {
+			QueryComponent component = (QueryComponent) iter.next();
+			controller.register(component);
+		}
+	}
+
+	private void deregisterComponents() {
+		for (Iterator iter = componentRegister.iterator(); iter.hasNext();) {
+			QueryComponent component = (QueryComponent) iter.next();
+			controller.deregister(component);
+		}
+	}
+
+	/**
+	 *
+	 * @param inputPanel
+	 * @param attributePanel
+	 * @param filterPanel
+	 */
+	private void generateConfiguration(
+			final MartServiceQueryConfigUIFactory factory,
+			final SummaryPanel summaryPanel, final JComponent inputPanel,
+			final JComponent attributePanel, final JComponent filterPanel) {
+		final JProgressBar filterProgressBar = new JProgressBar();
+		filterProgressBar.setIndeterminate(true);
+		filterProgressBar.setStringPainted(true);
+		filterProgressBar.setString("Fetching filter configuration");
+		filterPanel.add(filterProgressBar);
+
+		final JProgressBar attributeProgressBar = new JProgressBar();
+		attributeProgressBar.setIndeterminate(true);
+		attributeProgressBar.setStringPainted(true);
+		attributeProgressBar.setString("Fetching attribute configuration");
+		attributePanel.add(attributeProgressBar);
+
+		new Thread("DatasetConfigUI") {
+			public void run() {
+				try {
+
+					FilterPage[] filterPages = factory.getDatasetConfig()
+							.getFilterPages();
+					AttributePage[] attributePages = factory.getDatasetConfig()
+							.getAttributePages();
+
+					final Component filterPagesComponent = factory
+							.getFilterPagesUI(filterPages, null);
+					final Component attributePagesComponent = factory
+							.getAttributePagesUI(attributePages, null);
+
+					filterPanel.remove(filterProgressBar);
+					filterPanel.add(filterPagesComponent);
+
+					attributePanel.remove(attributeProgressBar);
+					attributePanel.add(attributePagesComponent);
+
+					factory.registerComponents();
+
+					factory.selectAttributePage(attributePages);
+
+				} catch (MartServiceException e) {
+					logger.error("Error while fetching dataset configuration", e);
+					JTextArea textArea = new JTextArea();
+					textArea
+							.append("Error while fetching dataset configuration\n\n");
+					textArea.append(e.getMessage());
+					inputPanel.removeAll();
+					inputPanel.add(textArea);
+				} catch (Exception e) {
+					logger.error("Error while generating the Query Editor", e);
+					JTextArea textArea = new JTextArea();
+					textArea
+							.append("Error while generating the Query Editor\n\n");
+					textArea.append(e.toString());
+					inputPanel.removeAll();
+					inputPanel.add(textArea);
+				} finally {
+					inputPanel.revalidate();
+					inputPanel.repaint();
+					summaryPanel.updateDatasets();
+				}
+			}
+		}.start();
+	}
+
+	private List<AttributeComponent> getAttributeComponents(Component component) {
+		List<AttributeComponent> attributeComponents = new ArrayList<AttributeComponent>();
+		if (component instanceof AttributeComponent) {
+			attributeComponents.add((AttributeComponent) component);
+		} else if (component instanceof ExpandableBox) {
+			Component[] children = ((ExpandableBox) component).getComponents();
+			for (int i = 0; i < children.length; i++) {
+				attributeComponents.addAll(getAttributeComponents(children[i]));
+			}
+		} else if (component instanceof Container) {
+			Component[] children = ((Container) component).getComponents();
+			for (int i = 0; i < children.length; i++) {
+				attributeComponents.addAll(getAttributeComponents(children[i]));
+			}
+		}
+		return attributeComponents;
+	}
+
+	private List<AttributeComponent> getSelectedAttributeComponents(
+			Component component) {
+		List<AttributeComponent> attributeComponents = new ArrayList<AttributeComponent>();
+		if (component instanceof AttributeComponent) {
+			if (((AttributeComponent) component).isSelected()) {
+				attributeComponents.add((AttributeComponent) component);
+			}
+		} else if (component instanceof ExpandableBox) {
+			Component[] children = ((ExpandableBox) component).getComponents();
+			for (int i = 0; i < children.length; i++) {
+				attributeComponents
+						.addAll(getSelectedAttributeComponents(children[i]));
+			}
+		} else if (component instanceof Container) {
+			Component[] children = ((Container) component).getComponents();
+			for (int i = 0; i < children.length; i++) {
+				attributeComponents
+						.addAll(getSelectedAttributeComponents(children[i]));
+			}
+		}
+		return attributeComponents;
+	}
+
+	private void selectAttributePage(AttributePage[] attributePages) {
+		int selectedAttributes = -1;
+		JRadioButton selectedButton = null;
+		Component selectedComponent = null;
+
+		for (int i = 0; i < attributePages.length; i++) {
+			if (QueryConfigUtils.display(attributePages[i])) {
+				Component component = attributePageNameToComponent
+						.get(attributePages[i].getInternalName());
+				JRadioButton button = attributePageNameToButton
+						.get(attributePages[i].getInternalName());
+				if (component != null && button != null) {
+					int attributeCount = getSelectedAttributeComponents(
+							component).size();
+					if (attributeCount > selectedAttributes) {
+						selectedAttributes = attributeCount;
+						selectedButton = button;
+						selectedComponent = component;
+					}
+				}
+			}
+			if (selectedButton != null && selectedComponent != null) {
+				selectedButton.setSelected(true);
+			}
+		}
+	}
+
+	private List<String> getFormatList(AttributePage attributePage) {
+		List<String> formatList = new ArrayList<String>();
+		for (String format : attributePage.getOutFormats()
+				.toUpperCase().split(",")) {
+			if (!"".equals(format)) {
+				formatList.add(format);
+			}
+		}
+		return formatList;
+	}
+
+	private JComponent createHorizontalBox(Color background) {
+		// using a JPanel instead of a Box as a workaround for bug 4907674
+		JPanel box = new JPanel();
+		box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
+		box.setBackground(background);
+		return box;
+	}
+
+	private JComponent createVerticalBox(Color background) {
+		// using a JPanel instead of a Box as a workaround for bug 4907674
+		JPanel box = new JPanel();
+		box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
+		box.setBackground(background);
+		return box;
+	}
+
+	private JComponent createBox(Component titleComponent, boolean fullBorder) {
+		JComponent box = createVerticalBox(componentBackgroundColor);
+		box.add(Box.createHorizontalStrut(400));
+		if (fullBorder) {
+			box.setBorder(new CompoundBorder(new LineBorder(borderColor, 1),
+					new EmptyBorder(10, 10, 10, 10)));
+		} else {
+			box.setBorder(new CompoundBorder(new SideBorder06(
+					SwingConstants.TOP, borderColor), new EmptyBorder(5, 10, 0,
+					10)));
+		}
+		if (titleComponent != null) {
+			JComponent labelBox = createHorizontalBox(componentBackgroundColor);
+			labelBox.add(titleComponent);
+			labelBox.add(Box.createHorizontalGlue());
+			box.add(labelBox);
+		}
+		return box;
+	}
+
+	private void setSummaryCount(Query query, String datasetName, JLabel label)
+			throws MartServiceException {
+		if ("".equals(label.getText())) {
+			String count = null;
+			String total = null;
+			Query countQuery = new Query(query);
+			countQuery.removeAllDatasets();
+			countQuery.addDataset(new Dataset(datasetName));
+			countQuery.setCount(1);
+			countQuery.setFormatter(null);
+
+			Object[] results = martService.executeQuery(countQuery);
+			if (results.length == 1) {
+				if (results[0] instanceof List) {
+					List result = (List) results[0];
+					if (result.size() >= 1) {
+						total = (String) result.get(0);
+						// test for biomart's 'let add a random blank line'
+						// thing
+						if ("".equals(total) && result.size() > 1) {
+							total = (String) result.get(1);
+						}
+						try {
+							Integer.parseInt(total);
+						} catch (NumberFormatException e) {
+							total = "?";
+						}
+					}
+				}
+			}
+			Dataset dataset = query.getDataset(datasetName);
+			if (dataset != null && dataset.getFilters().size() > 0) {
+				Dataset countDataset = new Dataset(dataset);
+				countQuery.removeAllDatasets();
+				countQuery.addDataset(countDataset);
+				results = martService.executeQuery(countQuery);
+				if (results.length == 1) {
+					if (results[0] instanceof List) {
+						List result = (List) results[0];
+						if (result.size() >= 1) {
+							count = (String) result.get(0);
+							// test for biomart's 'let add a random blank
+							// line' thing
+							if ("".equals(count) && result.size() > 1) {
+								count = (String) result.get(1);
+							}
+							try {
+								Integer.parseInt(count);
+							} catch (NumberFormatException e) {
+								count = "";
+							}
+						}
+					}
+				}
+			} else {
+				count = total;
+			}
+
+			if (count != null && total != null) {
+				if (count.equals("")) {
+					label.setText("0 / " + total + " Genes");
+				} else {
+					label.setText(count + " / " + total + " Genes");
+				}
+			}
+
+		}
+	}
+
+	class TextFilterComponent extends QueryComponent {
+		private static final long serialVersionUID = 1L;
+
+		private JTextField textField;
+
+		public TextFilterComponent(FilterDescription filterDescription,
+				MartDataset dataset) {
+			setConfigObject(filterDescription);
+			setDataset(dataset);
+			setName(filterDescription.getInternalName());
+			setLayout(new MinimalLayout(MinimalLayout.HORIZONTAL));
+			setBackground(componentBackgroundColor);
+
+			textField = new JTextField();
+			textField.setBackground(componentBackgroundColor);
+			textField.setPreferredSize(new Dimension(200, textField
+					.getPreferredSize().height + 4));
+
+			textField.getDocument().addDocumentListener(new DocumentListener() {
+				public void changedUpdate(DocumentEvent e) {
+				}
+
+				public void insertUpdate(DocumentEvent e) {
+					fireFilterChanged(new QueryComponentEvent(this, getName(),
+							getDataset(), textField.getText()));
+				}
+
+				public void removeUpdate(DocumentEvent e) {
+					fireFilterChanged(new QueryComponentEvent(this, getName(),
+							getDataset(), textField.getText()));
+				}
+			});
+
+			add(textField);
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryComponent#getType()
+		 */
+		public int getType() {
+			return FILTER;
+		}
+
+		public void setValue(String value) {
+			textField.setText(value);
+		}
+
+		public String getValue() {
+			return textField.getText();
+		}
+
+	}
+
+	class MultipleTextFilterComponent extends QueryComponent {
+		private static final long serialVersionUID = 1L;
+
+		private JTextArea textArea;
+
+		public MultipleTextFilterComponent(FilterDescription filterDescription,
+				MartDataset dataset) {
+			setConfigObject(filterDescription);
+			setDataset(dataset);
+			setName(filterDescription.getInternalName());
+			setLayout(new MinimalLayout(MinimalLayout.HORIZONTAL));
+			setBackground(componentBackgroundColor);
+
+			textArea = new JTextArea();
+			textArea.getDocument().addDocumentListener(new DocumentListener() {
+				public void changedUpdate(DocumentEvent e) {
+				}
+
+				public void insertUpdate(DocumentEvent e) {
+					fireFilterChanged(new QueryComponentEvent(this, getName(),
+							getDataset(), getValue()));
+				}
+
+				public void removeUpdate(DocumentEvent e) {
+					fireFilterChanged(new QueryComponentEvent(this, getName(),
+							getDataset(), getValue()));
+				}
+			});
+
+			final JFileChooser chooser = new JFileChooser();
+			JButton chooserButton = new JButton("Browse...");
+			chooserButton.setBackground(componentBackgroundColor);
+			chooserButton.setFont(chooserButton.getFont()
+					.deriveFont(Font.PLAIN));
+			chooserButton.addActionListener(new ActionListener() {
+				public void actionPerformed(ActionEvent e) {
+					int returnVal = chooser
+							.showOpenDialog(MultipleTextFilterComponent.this);
+					if (returnVal == JFileChooser.APPROVE_OPTION) {
+						File file = chooser.getSelectedFile();
+						if (file != null && file.exists() && file.canRead()
+								&& !file.isDirectory()) {
+							StringBuffer buffer = new StringBuffer();
+							BufferedReader in = null;
+							try {
+								in = new BufferedReader(new FileReader(file));
+								String line = in.readLine();
+								while (line != null) {
+									buffer.append(line);
+									buffer.append(QueryConfigUtils.LINE_END);
+									line = in.readLine();
+								}
+							} catch (IOException e1) {
+								// no action
+							} finally {
+								if (in != null) {
+									try {
+										in.close();
+									} catch (IOException e1) {
+										// give up
+									}
+								}
+							}
+							setValue(buffer.toString());
+						}
+					}
+				}
+			});
+
+			JPanel buttonPanel = new JPanel(new BorderLayout());
+			buttonPanel.setBackground(componentBackgroundColor);
+			buttonPanel.add(chooserButton, BorderLayout.WEST);
+
+			JScrollPane textScrollPane = new JScrollPane(textArea);
+			textScrollPane.setBackground(componentBackgroundColor);
+			textScrollPane.setPreferredSize(new Dimension(200, 80));
+
+			add(textScrollPane, BorderLayout.CENTER);
+			add(buttonPanel, BorderLayout.SOUTH);
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryComponent#getType()
+		 */
+		public int getType() {
+			return FILTER;
+		}
+
+		public void setValue(String value) {
+			textArea.setText(QueryConfigUtils.csvToValuePerLine(value));
+		}
+
+		public String getValue() {
+			return QueryConfigUtils.valuePerLineToCsv(textArea.getText());
+		}
+
+	}
+
+	class ListFilterComponent extends QueryComponent {
+		private static final long serialVersionUID = 1L;
+
+		private DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel();
+
+		private JComboBox comboBox;
+
+		private JTextField textField;
+
+		private Map optionMap = new HashMap();
+
+		private List optionList = new ArrayList();
+
+		private String dataset;
+
+		private Map componentMap;
+
+		private String type;
+
+		public ListFilterComponent(String refDataset,
+				FilterDescription filterDescription, MartDataset dataset,
+				Map componentMap) {
+			this.dataset = refDataset;
+			this.componentMap = componentMap;
+			setConfigObject(filterDescription);
+			setDataset(dataset);
+			setName(filterDescription.getInternalName());
+			setLayout(new BorderLayout());
+			setBackground(componentBackgroundColor);
+
+			Option[] options = filterDescription.getOptions();
+			// if there are no options but there is a default value then use the
+			// default value as an option
+			if (options.length == 0) {
+				String defaultValue = filterDescription.getDefaultValue();
+				if (defaultValue != null) {
+					Option newOption = new Option();
+					newOption.setInternalName(defaultValue);
+					newOption.setDisplayName(defaultValue);
+					newOption.setValue(defaultValue);
+					newOption.setSelectable("true");
+					options = new Option[] { newOption };
+				}
+			}
+
+			textField = new JTextField();
+			textField.setBackground(componentBackgroundColor);
+			textField.setPreferredSize(new Dimension(200, textField
+					.getPreferredSize().height + 4));
+
+			textField.getDocument().addDocumentListener(new DocumentListener() {
+				public void changedUpdate(DocumentEvent e) {
+					fireFilterChanged(new QueryComponentEvent(this, getName(),
+							getDataset(), textField.getText()));
+				}
+
+				public void insertUpdate(DocumentEvent e) {
+					fireFilterChanged(new QueryComponentEvent(this, getName(),
+							getDataset(), textField.getText()));
+				}
+
+				public void removeUpdate(DocumentEvent e) {
+					fireFilterChanged(new QueryComponentEvent(this, getName(),
+							getDataset(), textField.getText()));
+				}
+			});
+
+			comboBox = new JComboBox();
+			comboBox.setFont(comboBox.getFont().deriveFont(Font.PLAIN));
+			comboBox.setBackground(componentBackgroundColor);
+			comboBox.setModel(comboBoxModel);
+
+			if (options.length == 0) {
+				add(textField, BorderLayout.WEST);
+				type = "text";
+			} else {
+				add(comboBox, BorderLayout.WEST);
+				type = "list";
+			}
+
+			setOptions(options);
+			// comboBox.setSelectedIndex(-1);
+
+			comboBox.addItemListener(new ItemListener() {
+
+				public void itemStateChanged(ItemEvent e) {
+					if (e.getStateChange() == ItemEvent.SELECTED) {
+						Option option = (Option) optionList.get(comboBox
+								.getSelectedIndex());
+						optionSelected(option);
+						ListFilterComponent.super.setValue(option.getValue());
+						fireFilterChanged(new QueryComponentEvent(this,
+								getName(), getDataset(), option.getValue()));
+					} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+						Option option = (Option) optionMap.get(getValue());
+						if (option != null) {
+							optionDeselected(option);
+						}
+						fireFilterChanged(new QueryComponentEvent(this,
+								getName(), getDataset(), ""));
+					}
+				}
+
+			});
+
+		}
+
+		public void setOptions(Option[] options) {
+			clearOptions();
+			for (int i = 0; i < options.length; i++) {
+				if (options[i].getHidden() == null
+						|| !options[i].getHidden().equals("true")) {
+					optionMap.put(options[i].getValue(), options[i]);
+					optionList.add(options[i]);
+					String displayName = options[i].getDisplayName();
+					if (displayName != null) {
+						comboBoxModel.addElement(QueryConfigUtils
+								.truncateName(displayName));
+					}
+				}
+			}
+			if (optionList.size() > 0) {
+				if ("text".equals(type)) {
+					removeAll();
+					add(comboBox, BorderLayout.WEST);
+					type = "list";
+					revalidate();
+					repaint();
+				}
+				setValue(((Option) optionList.get(0)).getValue());
+			} else {
+				if ("list".equals(type)) {
+					removeAll();
+					add(textField, BorderLayout.WEST);
+					type = "text";
+					revalidate();
+					repaint();
+				}
+			}
+		}
+
+		private void clearOptions() {
+			comboBox.setSelectedIndex(-1);
+			comboBoxModel.removeAllElements();
+			optionMap.clear();
+			optionList.clear();
+		}
+
+		public void setValue(String value) {
+			if ("list".equals(type)) {
+				if (value == null) {
+					if (getValue() != null) {
+						optionDeselected((Option) optionMap.get(getValue()));
+						comboBox.setSelectedIndex(-1);
+					}
+				} else {
+					if (getValue() != null) {
+						Option option = (Option) optionMap.get(getValue());
+						if (option != null) {
+							optionDeselected(option);
+						}
+					}
+					Option option = (Option) optionMap.get(value);
+					if (option != null) {
+						optionSelected(option);
+					}
+					int index = optionList.indexOf(option);
+					comboBox.setSelectedIndex(index);
+				}
+			} else if ("text".equals(type)) {
+				textField.setText(value);
+			}
+			super.setValue(value);
+		}
+
+		private void optionSelected(Option option) {
+			if (option == null) {
+				logger.info("null option for " + getName());
+			} else {
+				PushAction[] pushActions = option.getPushActions();
+				for (int i = 0; i < pushActions.length; i++) {
+					QueryComponent queryComponent = getReferencedComponent(pushActions[i]);
+					if (queryComponent instanceof ListFilterComponent) {
+						ListFilterComponent filterComponent = (ListFilterComponent) queryComponent;
+						if (filterComponent != null) {
+							filterComponent.setOptions(pushActions[i]
+									.getOptions());
+						}
+					}
+				}
+			}
+		}
+
+		private void optionDeselected(Option option) {
+			PushAction[] pushActions = option.getPushActions();
+			for (int i = 0; i < pushActions.length; i++) {
+				QueryComponent queryComponent = getReferencedComponent(pushActions[i]);
+				if (queryComponent instanceof ListFilterComponent) {
+					ListFilterComponent filterComponent = (ListFilterComponent) queryComponent;
+					if (filterComponent != null) {
+						filterComponent.clearOptions();
+					}
+				}
+			}
+		}
+
+		private QueryComponent getReferencedComponent(PushAction pushAction) {
+			String ref = pushAction.getRef();
+			if (ref.indexOf('.') == -1) {
+				return (QueryComponent) componentMap.get(dataset + "." + ref);
+			} else {
+				return (QueryComponent) componentMap.get(ref);
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.embl.ebi.escience.scuflworkers.biomartservice.config.QueryComponent#getType()
+		 */
+		public int getType() {
+			return FILTER;
+		}
+	}
+
+	class IdListFilterComponent extends QueryComponent {
+		private static final long serialVersionUID = 1L;
+
+		private DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel();
+
+		private JComboBox comboBox;
+
+		private JTextArea textArea;
+
+		private Map<String, QueryComponent> componentMap = new HashMap<String, QueryComponent>();
+
+		private List<String> filterList = new ArrayList<String>();
+
+		private int currentIndex;
+
+		private boolean valueChanging;
+
+		public IdListFilterComponent(FilterDescription description,
+				MartDataset dataset, List<TextFilterComponent> filterComponentList) {
+			setLayout(new MinimalLayout(MinimalLayout.VERTICAL));
+			setBackground(componentBackgroundColor);
+
+			comboBox = new JComboBox();
+			comboBox.setFont(comboBox.getFont().deriveFont(Font.PLAIN));
+			comboBox.setBackground(componentBackgroundColor);
+			comboBox.setModel(comboBoxModel);
+
+			for (TextFilterComponent filterComponent : filterComponentList) {
+				BaseNamedConfigurationObject filterDescription = filterComponent
+						.getConfigObject();
+				componentMap.put(filterDescription.getInternalName(),
+						filterComponent);
+				filterList.add(filterDescription.getInternalName());
+				comboBoxModel.addElement(filterDescription.getDisplayName());
+				filterToDisplayName.put(filterDescription.getInternalName(),
+						filterDescription.getDisplayName());
+				filterComponent
+						.addQueryComponentListener(new QueryComponentAdapter() {
+							public void filterAdded(QueryComponentEvent event) {
+								if (!valueChanging) {
+									valueChanging = true;
+									comboBox.setSelectedIndex(filterList
+											.indexOf(event.getName()));
+									selectorButton.setSelected(true);
+									valueChanging = false;
+								}
+							}
+
+							public void filterRemoved(QueryComponentEvent event) {
+								if (!valueChanging) {
+									valueChanging = true;
+									selectorButton.setSelected(false);
+									valueChanging = false;
+								}
+							}
+
+							public void filterChanged(QueryComponentEvent event) {
+								if (!valueChanging) {
+									valueChanging = true;
+									textArea
+											.setText(QueryConfigUtils
+													.csvToValuePerLine(event
+															.getValue()));
+									valueChanging = false;
+								}
+							}
+						});
+				filterComponent.setSelectorButton(new JCheckBox());
+			}
+
+			comboBox.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					int selectedIndex = comboBox.getSelectedIndex();
+					if (selectorButton.isSelected()) {
+						if (e.getStateChange() == ItemEvent.SELECTED) {
+							if (!valueChanging) {
+								valueChanging = true;
+								QueryComponent queryComponent = componentMap
+										.get(filterList.get(selectedIndex));
+								queryComponent.setValue(QueryConfigUtils
+										.valuePerLineToCsv(textArea.getText()));
+								queryComponent.setSelected(true);
+								valueChanging = false;
+							}
+						} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+							if (!valueChanging) {
+								valueChanging = true;
+								componentMap.get(filterList
+										.get(currentIndex)).setSelected(false);
+								valueChanging = false;
+							}
+						}
+					}
+					currentIndex = selectedIndex;
+				}
+			});
+
+			textArea = new JTextArea();
+			textArea.getDocument().addDocumentListener(new DocumentListener() {
+				public void changedUpdate(DocumentEvent e) {
+				}
+
+				public void insertUpdate(DocumentEvent e) {
+					updateValue();
+				}
+
+				public void removeUpdate(DocumentEvent e) {
+					updateValue();
+				}
+
+				private void updateValue() {
+					if (!valueChanging) {
+						valueChanging = true;
+						int selectedIndex = comboBox.getSelectedIndex();
+						String value = QueryConfigUtils
+								.valuePerLineToCsv(textArea.getText());
+						componentMap.get(filterList
+								.get(selectedIndex)).setValue(value);
+						valueChanging = false;
+					}
+				}
+			});
+
+			final JFileChooser chooser = new JFileChooser();
+			JButton chooserButton = new JButton("Browse...");
+			chooserButton.setBackground(componentBackgroundColor);
+			chooserButton.setFont(chooserButton.getFont()
+					.deriveFont(Font.PLAIN));
+			chooserButton.addActionListener(new ActionListener() {
+				public void actionPerformed(ActionEvent e) {
+					int returnVal = chooser
+							.showOpenDialog(IdListFilterComponent.this);
+					if (returnVal == JFileChooser.APPROVE_OPTION) {
+						File file = chooser.getSelectedFile();
+						if (file != null && file.exists() && file.canRead()
+								&& !file.isDirectory()) {
+							StringBuffer buffer = new StringBuffer();
+							BufferedReader in = null;
+							try {
+								in = new BufferedReader(new FileReader(file));
+								String line = in.readLine();
+								while (line != null) {
+									buffer.append(line);
+									buffer.append(QueryConfigUtils.LINE_END);
+									line = in.readLine();
+								}
+							} catch (IOException e1) {
+								// no action
+							} finally {
+								if (in != null) {
+									try {
+										in.close();
+									} catch (IOException e1) {
+										// give up
+									}
+								}
+							}
+							textArea.setText(buffer.toString());
+						}
+					}
+				}
+			});
+
+			JPanel buttonPanel = new JPanel(new BorderLayout());
+			buttonPanel.setBackground(componentBackgroundColor);
+			buttonPanel.add(chooserButton, BorderLayout.WEST);
+
+			JScrollPane textScrollPane = new JScrollPane(textArea);
+			textScrollPane.setBackground(componentBackgroundColor);
+			textScrollPane.setPreferredSize(new Dimension(200, 80));
+
+			add(comboBox, BorderLayout.NORTH);
+			add(textScrollPane, BorderLayout.CENTER);
+			add(buttonPanel, BorderLayout.SOUTH);
+
+		}
+
+		public void setSelectorButton(AbstractButton button) {
+			selectorButton = button;
+			button.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					int selectedIndex = comboBox.getSelectedIndex();
+					if (e.getStateChange() == ItemEvent.SELECTED) {
+						if (!valueChanging) {
+							valueChanging = true;
+							QueryComponent queryComponent = componentMap
+									.get(filterList.get(selectedIndex));
+							queryComponent.setValue(QueryConfigUtils
+									.valuePerLineToCsv(textArea.getText()));
+							queryComponent.setSelected(true);
+							valueChanging = false;
+						}
+					} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+						if (!valueChanging) {
+							valueChanging = true;
+							componentMap.get(filterList
+									.get(selectedIndex)).setSelected(false);
+							valueChanging = false;
+						}
+					}
+				}
+			});
+
+		}
+
+		public int getType() {
+			return FILTER;
+		}
+
+	}
+
+	class BooleanListFilterComponent extends QueryComponent {
+		private static final long serialVersionUID = 1L;
+
+		private DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel();
+
+		private JComboBox comboBox;
+
+		private BooleanFilterComponent booleanFilterComponent;
+
+		private Map componentMap = new HashMap();
+
+		private List<String> filterList = new ArrayList<String>();
+
+		private int currentIndex;
+
+		public BooleanListFilterComponent(FilterDescription description,
+				MartDataset dataset, List filterComponentList) {
+			setLayout(new MinimalLayout(MinimalLayout.HORIZONTAL));
+			setBackground(componentBackgroundColor);
+
+			comboBox = new JComboBox();
+			comboBox.setFont(comboBox.getFont().deriveFont(Font.PLAIN));
+			comboBox.setBackground(componentBackgroundColor);
+			comboBox.setModel(comboBoxModel);
+
+			for (Iterator iter = filterComponentList.iterator(); iter.hasNext();) {
+				BooleanFilterComponent filterComponent = (BooleanFilterComponent) iter
+						.next();
+				BaseNamedConfigurationObject filterDescription = filterComponent
+						.getConfigObject();
+				componentMap.put(filterDescription.getInternalName(),
+						filterComponent);
+				filterList.add(filterDescription.getInternalName());
+				comboBoxModel.addElement(filterDescription.getDisplayName());
+				filterToDisplayName.put(filterDescription.getInternalName(),
+						filterDescription.getDisplayName());
+				filterComponent
+						.addQueryComponentListener(new QueryComponentAdapter() {
+							public void filterAdded(QueryComponentEvent event) {
+								comboBox.setSelectedIndex(filterList
+										.indexOf(event.getName()));
+								selectorButton.setSelected(true);
+							}
+
+							public void filterChanged(QueryComponentEvent event) {
+								booleanFilterComponent.setValue(event
+										.getValue());
+							}
+						});
+				filterComponent.setSelectorButton(new JCheckBox());
+			}
+
+			comboBox.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					int selectedIndex = comboBox.getSelectedIndex();
+					if (selectorButton.isSelected()) {
+						if (e.getStateChange() == ItemEvent.SELECTED) {
+							QueryComponent queryComponent = (QueryComponent) componentMap
+									.get(filterList.get(selectedIndex));
+							queryComponent.setValue(booleanFilterComponent
+									.getValue());
+							queryComponent.setSelected(true);
+						} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+							((QueryComponent) componentMap.get(filterList
+									.get(currentIndex))).setSelected(false);
+						}
+					}
+					currentIndex = selectedIndex;
+				}
+			});
+
+			booleanFilterComponent = new BooleanFilterComponent(
+					new FilterDescription(), dataset);
+			booleanFilterComponent
+					.addQueryComponentListener(new QueryComponentAdapter() {
+						public void filterChanged(QueryComponentEvent event) {
+							int selectedIndex = comboBox.getSelectedIndex();
+							((QueryComponent) componentMap.get(filterList
+									.get(selectedIndex))).setValue(event
+									.getValue());
+						}
+					});
+
+			JPanel comboBoxPanel = new JPanel(new MinimalLayout());
+			comboBoxPanel.setBackground(componentBackgroundColor);
+			comboBoxPanel.setBorder(new EmptyBorder(5, 5, 0, 0));
+			add(comboBox);
+			add(booleanFilterComponent);
+		}
+
+		public void setSelectorButton(AbstractButton button) {
+			selectorButton = button;
+			button.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					int selectedIndex = comboBox.getSelectedIndex();
+					if (e.getStateChange() == ItemEvent.SELECTED) {
+						QueryComponent queryComponent = (QueryComponent) componentMap
+								.get(filterList.get(selectedIndex));
+						queryComponent.setValue(booleanFilterComponent
+								.getValue());
+						queryComponent.setSelected(true);
+					} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+						((QueryComponent) componentMap.get(filterList
+								.get(selectedIndex))).setSelected(false);
+					}
+				}
+			});
+		}
+
+		public int getType() {
+			return FILTER;
+		}
+
+	}
+
+	class BooleanFilterComponent extends QueryComponent {
+		private static final long serialVersionUID = 1L;
+
+		private static final String ONLY = "only";
+
+		private static final String EXCLUDED = "excluded";
+
+		private ButtonGroup buttonGroup = new ButtonGroup();
+
+		private JRadioButton only;
+
+		private JRadioButton excluded;
+
+		public BooleanFilterComponent(FilterDescription filterDescription,
+				MartDataset dataset) {
+			setConfigObject(filterDescription);
+			setDataset(dataset);
+			setName(filterDescription.getInternalName());
+			setBackground(componentBackgroundColor);
+
+			setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+			setBackground(componentBackgroundColor);
+
+			only = new JRadioButton("Only");
+			only.setFont(only.getFont().deriveFont(Font.PLAIN));
+			only.setBackground(componentBackgroundColor);
+			only.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					if (e.getStateChange() == ItemEvent.SELECTED) {
+						fireFilterChanged(new QueryComponentEvent(this,
+								getName(), getDataset(), ONLY));
+					}
+				}
+			});
+			buttonGroup.add(only);
+			add(only);
+
+			excluded = new JRadioButton("Excluded");
+			excluded.setFont(excluded.getFont().deriveFont(Font.PLAIN));
+			excluded.setBackground(componentBackgroundColor);
+			excluded.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					if (e.getStateChange() == ItemEvent.SELECTED) {
+						fireFilterChanged(new QueryComponentEvent(this,
+								getName(), getDataset(), EXCLUDED));
+					}
+				}
+			});
+			buttonGroup.add(excluded);
+			add(excluded);
+
+			setValue(filterDescription.getQualifier());
+		}
+
+		public int getType() {
+			return FILTER;
+		}
+
+		public String getValue() {
+			if (excluded.isSelected()) {
+				return EXCLUDED;
+			} else {
+				return ONLY;
+			}
+		}
+
+		public void setValue(String value) {
+			if (EXCLUDED.equals(value)) {
+				excluded.setSelected(true);
+			} else {
+				only.setSelected(true);
+			}
+		}
+
+	}
+
+	class AttributeComponent extends QueryComponent {
+		private static final long serialVersionUID = 1L;
+
+		private AbstractButton button;
+
+		private AbstractButton offButton;
+
+		public AttributeComponent(
+				BaseNamedConfigurationObject attributeDescription,
+				MartDataset dataset, Object offButton) {
+			this.offButton = (AbstractButton) offButton;
+			setConfigObject(attributeDescription);
+			setDataset(dataset);
+			setName(attributeDescription.getInternalName());
+			if (attributeDescription instanceof AttributeList) {
+				setValue(((AttributeList) attributeDescription).getAttributes());
+			}
+			setLayout(new BorderLayout());
+			setBackground(componentBackgroundColor);
+			// if there's no display name the attribute isn't displayed
+			String displayName = attributeDescription.getDisplayName();
+			if (displayName != null) {
+				attributeToDisplayName.put(attributeDescription
+						.getInternalName(), displayName);
+				if (offButton != null) {
+					button = new JRadioButton(QueryConfigUtils
+							.splitSentence(displayName));
+				} else {
+					button = new JCheckBox(QueryConfigUtils
+							.splitSentence(displayName));
+				}
+				button.setFont(button.getFont().deriveFont(Font.PLAIN));
+				button.setBackground(componentBackgroundColor);
+				setSelectorButton(button);
+
+				String description = attributeDescription.getDescription();
+				if (description != null) {
+					button.setToolTipText(description);
+				}
+
+				add(button, BorderLayout.WEST);
+
+				button.addItemListener(new ItemListener() {
+					public void itemStateChanged(ItemEvent e) {
+						if (!settingAttributeState) {
+							settingAttributeState = true;
+							List attributes = (List) attributeNameToComponentMap
+									.get(getQualifiedName());
+							if (attributes != null) {
+								for (Iterator iter = attributes.iterator(); iter
+										.hasNext();) {
+									AttributeComponent attribute = (AttributeComponent) iter
+											.next();
+									if (attribute != AttributeComponent.this) {
+										if (e.getStateChange() == ItemEvent.SELECTED) {
+											attribute.setSelected(true);
+										} else if (e.getStateChange() == ItemEvent.DESELECTED) {
+											attribute.setSelected(false);
+										}
+									}
+								}
+							}
+							settingAttributeState = false;
+						}
+					}
+				});
+			}
+		}
+
+		public int getType() {
+			return ATTRIBUTE;
+		}
+
+		public void setSelected(boolean selected) {
+			if (offButton != null) {
+				if (selected) {
+					button.setSelected(true);
+				} else {
+					offButton.setSelected(true);
+				}
+			} 

<TRUNCATED>