// PathVisio, // a tool for data visualization and analysis using Biological Pathways // Copyright 2006-2011 BiGCaT Bioinformatics // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package org.pathvisio.gui; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.bridgedb.AttributeMapper; import org.bridgedb.IDMapper; import org.bridgedb.IDMapperException; import org.bridgedb.Xref; import org.pathvisio.core.debug.Logger; import org.pathvisio.core.debug.WorkerThreadOnly; import org.pathvisio.core.model.ObjectType; import org.pathvisio.core.model.PathwayElement; import org.pathvisio.core.util.Resources; import org.pathvisio.core.util.Utils; /** * BackpageTextProvider knows how to generate a html "backpage" for a given PathwayElement. * The backpage consists of a template, and several sections. The sections are each * generated by an implementation of @link{BackpageHook}, and plugins can register * more backpage hooks to extend the information in the backpage. *

* Two basic BackpageHooks are defined here: @link{BackpageAttributes} and * {@link BackpageXrefs}. However, these are not automatically registered, that * is the responsibility of the instantiator. */ public class BackpageTextProvider { /** * Hook into the backpage text provider, * use this to generate a fragment of text for the backpage */ public static interface BackpageHook { /** * Return a fragment of html-formatted text. The returned fragment should not * contain <html> or <body> tags, but it can contain most other * html tags. *

* The function getHtml is normally called from a worker thread. */ @WorkerThreadOnly public String getHtml (PathwayElement e); } /** * A @{link BackpageHook} that generates a section with a description * and a few other attributes to the backpage panel. */ public static class BackpageAttributes implements BackpageHook { private final AttributeMapper attributeMapper; public BackpageAttributes (AttributeMapper attr) { attributeMapper = attr; } public String getHtml(PathwayElement e) { String text = ""; String type = e.getDataNodeType(); // type will be displayed in the header, make either "Metabolite" or "Gene"; text += "

" + type + " information

"; if (!type.equals("Metabolite")) { type = "Gene"; } if(e.getXref().getId() == null || "".equals(e.getXref().getId())) { text += "Invalid annotation: missing identifier."; return text; } try { StringBuilder bpInfo = new StringBuilder(""); Map> attributes = null; if(e.getXref().getDataSource() != null) { attributes = attributeMapper.getAttributes(e.getXref()); } else { attributes = new HashMap>(); } String[][] table; if (!type.equals ("Metabolite")) { table = new String[][] { {"Gene ID", e.getXref().getId()}, {"Gene Symbol", Utils.oneOf(attributes.get("Symbol"))}, {"Synonyms", Utils.oneOf (attributes.get("Synonyms"))}, {"Description", Utils.oneOf (attributes.get("Description"))}, {"Chr", Utils.oneOf (attributes.get("Chromosome"))}, }; } else { table = new String[][] { {"Metabolite", Utils.oneOf (attributes.get("Symbol"))}, {"Bruto Formula", Utils.oneOf (attributes.get("BrutoFormula"))}, {"Synonyms", Utils.oneOf (attributes.get("Synonym"))}, }; } for (String[] row : table) { if (!(row[1] == null)) { bpInfo.append ("
"); bpInfo.append (row[0]); bpInfo.append (":"); bpInfo.append (row[1]); } } bpInfo.append ("
"); text += bpInfo.toString(); } catch (IDMapperException ex) { text += "Exception occurred, see log for details
"; Logger.log.error ("Error fetching backpage info", ex); } return text; } } /** * A @{link BackpageHook} that adds a list of crossref links to * the backpage panel. */ public static class BackpageXrefs implements BackpageHook { private final IDMapper gdb; public BackpageXrefs (IDMapper mapper) { gdb = mapper; } public String getHtml(PathwayElement e) { try { if( e.getXref().getId() == null || "".equals(e.getXref().getId()) || e.getXref().getDataSource() == null ) { return ""; } Set crfs = gdb.mapID(e.getXref()); crfs.add(e.getXref()); if(crfs.size() == 0) return ""; List sortedRefs = new ArrayList(crfs); Collections.sort(sortedRefs); StringBuilder crt = new StringBuilder("

Cross references

"); for(Xref cr : sortedRefs) { String idtxt = cr.getId(); String url = cr.getUrl(); url = url.replace("&", "&"); // primitive HTML entity encoding. TODO: do it properly if(url != null) { idtxt = "" + idtxt + ""; } String dbName = cr.getDataSource().getFullName(); crt.append( idtxt + ", " + (dbName != null ? dbName : cr.getDataSource().getSystemCode()) + "
"); } return crt.toString(); } catch (IDMapperException ex) { return "Exception occured while getting cross-references
\n" + ex.getMessage() + "\n"; } } } /** * Register a BackpageHook with this text provider. Backpage fragments * are generated in the order that the hooks were registered. */ public void addBackpageHook(BackpageHook hook) { hooks.add (hook); } private final List hooks = new ArrayList(); public BackpageTextProvider() { initializeHeader(); } /** * generates html for a given PathwayElement. Combines the base * header with fragments from all BackpageHooks into one html String. */ public String getBackpageHTML(PathwayElement e) { if (e == null || e.getObjectType() != ObjectType.DATANODE || e.getDataSource() == null) return "

No data

"; StringBuilder builder = new StringBuilder(backpagePanelHeader); for (BackpageHook h : hooks) { builder.append(h.getHtml(e)); } builder.append (""); return builder.toString(); } /** * Header file, containing style information */ final private static String HEADERFILE = "header.html"; private String backpagePanelHeader; /** * Reads the header of the HTML content displayed in the browser. This header is displayed in the * file specified in the {@link HEADERFILE} field */ private void initializeHeader() { try { BufferedReader input = new BufferedReader(new InputStreamReader( Resources.getResourceURL(HEADERFILE).openStream())); String line; backpagePanelHeader = ""; while((line = input.readLine()) != null) { backpagePanelHeader += line.trim(); } } catch (Exception e) { Logger.log.error("Unable to read header file for backpage browser: " + e.getMessage(), e); } } }