All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pathvisio.libgpml.model.GPML2013aWriter Maven / Gradle / Ivy

Go to download

libGPML is a library for reading, writing, manipulation, and conversion of files and data streams in the GPML (Graphical Pathway Markup Language) format.

The newest version!
/*******************************************************************************
 * PathVisio, a tool for data visualization and analysis using biological pathways
 * Copyright 2006-2022 BiGCaT Bioinformatics, WikiPathways
 *
 * 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.libgpml.model;

import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.bridgedb.DataSource;
import org.bridgedb.Xref;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.pathvisio.libgpml.debug.Logger;
import org.pathvisio.libgpml.io.ConverterException;
import org.pathvisio.libgpml.model.DataNode.State;
import org.pathvisio.libgpml.model.GraphLink.LinkableTo;
import org.pathvisio.libgpml.model.LineElement.Anchor;
import org.pathvisio.libgpml.model.LineElement.LinePoint;
import org.pathvisio.libgpml.model.PathwayElement.AnnotationRef;
import org.pathvisio.libgpml.model.PathwayElement.CitationRef;
import org.pathvisio.libgpml.model.PathwayElement.Comment;
import org.pathvisio.libgpml.model.shape.IShape;
import org.pathvisio.libgpml.model.type.ArrowHeadType;
import org.pathvisio.libgpml.model.type.LineStyleType;
import org.pathvisio.libgpml.util.ColorUtils;
import org.pathvisio.libgpml.util.XrefUtils;

/**
 * This class writes a PathwayModel to an output (GPML 2013a).
 * 

* NB: *

    *
  1. If writing (converting) GPML2021 to GPML2013a, warning messages are * thrown. *
  2. In the GUI, export allows writing to the GPML2013a format. *
* * @author finterly */ public class GPML2013aWriter extends GPML2013aFormatAbstract implements GPMLFormatWriter { public static final GPML2013aWriter GPML2013aWRITER = new GPML2013aWriter("GPML2013a.xsd", Namespace.getNamespace("http://pathvisio.org/GPML/2013a")); /** * Constructor for GPML2013aWriter. * * @param xsdFile the GPML schema file. * @param nsGPML the GPML namespace. */ protected GPML2013aWriter(String xsdFile, Namespace nsGPML) { super(xsdFile, nsGPML); } /** * Writes the JDOM {@link Document} document to the outputstream specified. * * @param pathwayModel the pathway model. * @param output the outputstream to which the JDOM document should be * written * @param validate if true, validate the dom structure before writing. If * there is a validation error, or the xsd is not in the * classpath, an exception will be thrown. * @throws ConverterException */ @Override public void writeToXml(PathwayModel pathwayModel, OutputStream output, boolean validate) throws ConverterException { Document doc = createJdom(pathwayModel); if (validate) { validateDocument(doc); } // Get the XML code XMLOutputter xmlOutput = new XMLOutputter(Format.getPrettyFormat()); Format xmlformat = xmlOutput.getFormat(); xmlformat.setEncoding("UTF-8"); // xmlformat.setTextMode(Format.TextMode.NORMALIZE); // for now, use default to preserve spaces TODO xmlOutput.setFormat(xmlformat); try { // Send XML code to the outputstream xmlOutput.output(doc, output); // new FileOutputStream(new File("fileName.gpml") // Create a new file and write XML to it Logger.log.trace("Wrote pathway model successfully to gpml file"); } catch (IOException e) { throw new ConverterException(e); } } /** * Writes the JDOM document to the file specified. * * @param pathwayModel the pathway model. * @param file the file to which the JDOM document should be saved. * @param validate if true, validate the dom structure before writing to * file. * @throws ConverterException */ @Override public void writeToXml(PathwayModel pathwayModel, File file, boolean validate) throws ConverterException { OutputStream out; try { out = new FileOutputStream(file); } catch (IOException ex) { throw new ConverterException(ex); } writeToXml(pathwayModel, out, true); } /** * Creates and returns the JDOM document {@link Document} written from given * pathwayModel {@link PathwayModel} data. * * @param pathwayModel the pathway model to be written. * @throws ConverterException */ @Override public Document createJdom(PathwayModel pathwayModel) throws ConverterException { // removes empty groups and updates group dimensions updateGroups(pathwayModel); Document doc = new Document(); Element root = new Element("Pathway", getGpmlNamespace()); doc.setRootElement(root); if (root != null) { writePathwayInfo(pathwayModel, root); writeDataNodes(pathwayModel.getDataNodes(), root); writeStates(pathwayModel.getDataNodes(), root); writeInteractions(pathwayModel.getInteractions(), root); writeGraphicalLines(pathwayModel.getGraphicalLines(), root); writeLabels(pathwayModel.getLabels(), root); writeShapes(pathwayModel.getShapes(), root); writeGroups(pathwayModel.getGroups(), root); writeInfoBox(pathwayModel.getPathway(), root); writeLegend(pathwayModel.getPathway(), root); writeBiopax(pathwayModel, root); } return doc; } /** * Writes pathway object {@link Pathway} information to root element. * * @param pathwayModel the pathway model. * @param root the root element. * @throws ConverterException */ protected void writePathwayInfo(PathwayModel pathwayModel, Element root) throws ConverterException { Pathway pathway = pathwayModel.getPathway(); setAttr("Pathway", "Name", root, pathway.getTitle()); // sets optional properties, in the order written in GPML2013a String description = pathway.getDescription(); if (description != null) { Element cmt = new Element("Comment", root.getNamespace()); cmt.setAttribute("Source", WP_DESCRIPTION); cmt.setText(description); root.addContent(cmt); } setAttr("Pathway", "Data-Source", root, pathway.getSource()); setAttr("Pathway", "Version", root, pathway.getVersion()); setAttr("Pathway", "Author", root, pathway.getDynamicProperty(PATHWAY_AUTHOR)); setAttr("Pathway", "Maintainer", root, pathway.getDynamicProperty(PATHWAY_MAINTAINER)); setAttr("Pathway", "Email", root, pathway.getDynamicProperty(PATHWAY_EMAIL)); setAttr("Pathway", "Last-Modified", root, pathway.getDynamicProperty(PATHWAY_LASTMODIFIED)); setAttr("Pathway", "Organism", root, pathway.getOrganism()); setAttr("Pathway", "License", root, pathway.getLicense()); // writes comments, biopaxRefs/citationRefs, dynamic properties writeComments(pathway.getComments(), root); writeBiopaxRefs(pathway.getCitationRefs(), root); writePathwayDynamicProperties(pathway, root); // sets graphics properties Element gfx = new Element("Graphics", root.getNamespace()); root.addContent(gfx); setAttr("Pathway.Graphics", "BoardWidth", gfx, String.valueOf(pathway.getBoardWidth())); setAttr("Pathway.Graphics", "BoardHeight", gfx, String.valueOf(pathway.getBoardHeight())); // warnings for conversion GPML2021 to GPML2013a if (!pathway.getAuthors().isEmpty()) Logger.log.trace("Warning: Conversion GPML2021 to GPML2013a: Pathway authors info lost."); if (!pathway.getAnnotationRefs().isEmpty()) Logger.log.trace("Warning: Conversion GPML2021 to GPML2013a: Pathway annotationRef info lost."); if (!pathwayModel.getEvidences().isEmpty()) Logger.log.trace("Warning: Conversion GPML2021 to GPML2013a: Pathway evidences info lost."); if (pathway.getXref() != null) Logger.log.trace("Warning: Conversion GPML2021 to GPML2013a: Pathway xref info lost."); if (!pathway.getBackgroundColor().equals(Color.decode("#ffffff"))) Logger.log.trace("Warning: Conversion GPML2021 to GPML2013a: Pathway backgroundColor info lost."); } /** * Writes xref {@link Xref} information to new element. In GPML2013a, Xref is * required for DataNodes, Interactions, and optional for States. * * @param xref the xref of the pathway or pathway element. * @param e the parent element. * @param required if true, xref is a required property. */ protected void writeXref(Xref xref, Element e, boolean required) throws ConverterException { // if xref null and required, writes out "" if (xref == null && required) { Element xrf = new Element("Xref", e.getNamespace()); xrf.setAttribute("Database", ""); xrf.setAttribute("ID", ""); e.addContent(xrf); } if (xref != null) { String identifier = xref.getId(); DataSource dataSource = xref.getDataSource(); String dataSourceStr = XrefUtils.getXrefDataSourceStrGPML2013a(dataSource); if (dataSourceStr != null && !dataSourceStr.equals("")) { Element xrf = new Element("Xref", e.getNamespace()); String base = e.getName(); setAttr(base + ".Xref", "Database", xrf, dataSourceStr); setAttr(base + ".Xref", "ID", xrf, identifier == null ? "" : identifier); e.addContent(xrf); } } } /** * Writes comments {@link Comment} information for pathway or pathway element. * * @param comments the list of comments of pathway or pathway element. * @param e the parent element. * @throws ConverterException */ protected void writeComments(List comments, Element e) throws ConverterException { for (Comment comment : comments) { if (comment != null) { // write comment only if comment has text String commentText = comment.getCommentText(); if (commentText != null && !commentText.equals("")) { Element cmt = new Element("Comment", e.getNamespace()); cmt.setText(commentText); String source = comment.getSource(); if (source != null && !source.equals("")) cmt.setAttribute("Source", source); if (cmt != null) e.addContent(cmt); } } } } /** * Writes BiopaxRef information from {@link PathwayElement#getCitationRefs} for * pathway or pathway element. BiopaxRefs are equivalent to citationRefs in * GPML2013a. * * @param citationRefs the list of citation references. * @param e the parent element. * @throws ConverterException */ protected void writeBiopaxRefs(List citationRefs, Element e) throws ConverterException { if (e != null) { for (CitationRef citationRef : citationRefs) { Element bpRef = new Element("BiopaxRef", e.getNamespace()); bpRef.setText(citationRef.getCitation().getElementId()); if (bpRef != null) e.addContent(bpRef); } } } /** * Writes dynamic property information for pathway or pathway element. * {@link PathwayElement#getDynamicProperty}. * * @param pathway the pathway. * @param root the jdom root element. * @throws ConverterException */ protected void writePathwayDynamicProperties(Pathway pathway, Element root) throws ConverterException { Map dynamicProperties = pathway.getDynamicProperties(); for (String key : dynamicProperties.keySet()) { // if key is in static key set, do not write to GPML2013a if (GPML2013A_KEY_SET.contains(key)) continue; Element dp = new Element("Attribute", root.getNamespace()); setAttr("Attribute", "Key", dp, key); setAttr("Attribute", "Value", dp, dynamicProperties.get(key)); if (dp != null) { root.addContent(dp); } } } /** * Writes datanode {@link DataNode} information. * * @param dataNodes the list of datanodes. * @param root the root element. * @throws ConverterException */ protected void writeDataNodes(List dataNodes, Element root) throws ConverterException { for (DataNode dataNode : dataNodes) { Element dn = new Element("DataNode", root.getNamespace()); setAttr("DataNode", "TextLabel", dn, dataNode.getTextLabel()); writeShapedElement(dataNode, dn); String typeStr = dataNode.getType().getName(); // in GPML2013a, "Undefined" type is written as "Unknown" if (typeStr.equalsIgnoreCase("Undefined")) { typeStr = "Unknown"; } setAttr("DataNode", "Type", dn, typeStr); writeGroupRef(dataNode.getGroupRef(), dn); // writes xref (required) writeXref(dataNode.getXref(), dn, true); if (dn != null) { root.addContent(dn); } // warnings for conversion GPML2021 to GPML2013a if (dataNode.getAliasRef() != null) { Logger.log.trace("Warning: Conversion GPML2021 to GPML2013a: DataNode " + dataNode.getElementId() + " aliasRef info lost."); } } } /** * Writes state {@link State} information. * * @param dataNodes the parent dataNode. * @param root the root element. * @throws ConverterException */ protected void writeStates(List dataNodes, Element root) throws ConverterException { for (DataNode dataNode : dataNodes) { List states = dataNode.getStates(); for (State state : states) { Element st = new Element("State", root.getNamespace()); // NB: StateType was not fully implemented in GPML2013a String typeStr = state.getType().getName(); // in GPML2013a, "Undefined" type is written as "Unknown" if (typeStr.equalsIgnoreCase("Undefined")) { typeStr = "Unknown"; } setAttr("State", "StateType", st, typeStr); setAttr("State", "GraphRef", st, dataNode.getElementId()); setAttr("State", "TextLabel", st, state.getTextLabel() == null ? "" : state.getTextLabel()); // if there are annotationRefs, writes this information to comment convertStateRefToComments(state, st); writeElementInfo(state, st); writeShapedOrStateDynamicProperties(state.getDynamicProperties(), state, st); // sets graphics properties Element gfx = new Element("Graphics", st.getNamespace()); st.addContent(gfx); setAttr("State.Graphics", "RelX", gfx, Double.toString(state.getRelX())); setAttr("State.Graphics", "RelY", gfx, Double.toString(state.getRelY())); setAttr("State.Graphics", "Width", gfx, Double.toString(state.getWidth())); setAttr("State.Graphics", "Height", gfx, Double.toString(state.getHeight())); // state does not have custom font properties in GPML2013a // z-order for state is not written to GPML2013a setAttr("State.Graphics", "FillColor", gfx, ColorUtils.colorToHex2013(state.getFillColor(), false)); writeShapeStyleProperty(state, gfx); writeColor(state, gfx); // writes xref (write even if empty) writeXref(state.getXref(), st, true); if (st != null) { root.addContent(st); } } } } /** * This method handles converting {@link State} phosphosite * {@link AnnotationRef} and {@link Xref} information back to {@link Comment} * for writing to GPML2013a. * * NB: "ptm" and "direction" are specially handled. * * @param state * @param st * @throws ConverterException */ protected void convertStateRefToComments(State state, Element st) throws ConverterException { // linked hash map to maintain order of input Map annotationsMap = new LinkedHashMap(); for (AnnotationRef annotationRef : state.getAnnotationRefs()) { String value = annotationRef.getAnnotation().getValue(); String type = annotationRef.getAnnotation().getType().getName(); // specially handle ptm for (String key : STATE_PTM_MAP.keySet()) { if (value.equals(STATE_PTM_MAP.get(key).get(0))) { value = key; type = PTM; } } // specially handle direction for (String key : STATE_DIRECTION_MAP.keySet()) { if (value.equals(STATE_DIRECTION_MAP.get(key).get(0))) { value = key; type = DIRECTION; } } annotationsMap.put(type, value); } // if sitegrpid from xref, also add to comment if (state.getXref() != null) { if (XrefUtils.getXrefDataSourceStr(state.getXref().getDataSource()).equalsIgnoreCase(SITEGRPID_DB)) { String type = SITEGRPID; String value = state.getXref().getId(); annotationsMap.put(type, value); } } // create commentText string from annotations map. if (!annotationsMap.isEmpty()) { String commentText = annotationsMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()) .collect(Collectors.joining("; ")); Element cmt = new Element("Comment", st.getNamespace()); cmt.setText(commentText); if (cmt != null) { st.addContent(cmt); } } } /** * Writes interaction {@link Interaction} information. * * @param interactions the list of interactions. * @param root the root element; * @throws ConverterException */ protected void writeInteractions(List interactions, Element root) throws ConverterException { for (Interaction interaction : interactions) { Element ia = new Element("Interaction", root.getNamespace()); writeLineElement(interaction, ia); writeXref(interaction.getXref(), ia, true); if (ia != null) { root.addContent(ia); } } } /** * Writes graphical line {@link GraphicalLine} information. * * @param graphicalLines the list of graphical lines. * @param root the root element. * @throws ConverterException */ protected void writeGraphicalLines(List graphicalLines, Element root) throws ConverterException { for (GraphicalLine graphicalLine : graphicalLines) { Element gln = new Element("GraphicalLine", root.getNamespace()); writeLineElement(graphicalLine, gln); if (gln != null) { root.addContent(gln); } } } /** * Writes line element {@link LineElement} information for interactions or * graphicalLines. * * @param lineElement the interaction or graphicalLine. * @param ln the line element. * @throws ConverterException */ protected void writeLineElement(LineElement lineElement, Element ln) throws ConverterException { // writes comments, biopaxRefs/citationRefs, dynamic properties writeElementInfo(lineElement, ln); writeLineDynamicProperties(lineElement.getDynamicProperties(), lineElement, ln); // sets graphics properties Element gfx = new Element("Graphics", ln.getNamespace()); ln.addContent(gfx); writeLineStyleProperty(lineElement, gfx); // writes points writePoints(lineElement, gfx); // writes anchors writeAnchors(lineElement.getAnchors(), gfx); writeGroupRef(lineElement.getGroupRef(), ln); } /** * Writes point {@link LinePoint} information. * * @param lineElement the line element. * @param gfx the parent graphics element. * @throws ConverterException */ protected void writePoints(LineElement lineElement, Element gfx) throws ConverterException { List ptList = new ArrayList(); List points = lineElement.getLinePoints(); for (int i = 0; i < points.size(); i++) { LinePoint point = points.get(i); Element pt = new Element("Point", gfx.getNamespace()); writeElementId(point.getElementId(), pt); String base = ((Element) gfx.getParent()).getName(); setAttr(base + ".Graphics.Point", "X", pt, Double.toString(point.getX())); setAttr(base + ".Graphics.Point", "Y", pt, Double.toString(point.getY())); // sets optional properties elementRef, relX, and relY if (writePointElementRef(point.getElementRef(), pt)) { setAttr(base + ".Graphics.Point", "RelX", pt, Double.toString(point.getRelX())); setAttr(base + ".Graphics.Point", "RelY", pt, Double.toString(point.getRelY())); } // if start or end point, write arrowhead type. if (i == 0) { writeArrowHeadType(lineElement.getStartArrowHeadType(), base, pt); } else if (i == points.size() - 1) { writeArrowHeadType(lineElement.getEndArrowHeadType(), base, pt); } else { // otherwise arrowHeadType = Line setAttr(base + ".Graphics.Point", "ArrowHead", pt, "Line"); } // add point jdom element to list if (pt != null) { ptList.add(pt); } } if (ptList != null && ptList.isEmpty() == false) { gfx.addContent(ptList); } } /** * Writes the arrowHead for point jdom element. // TODO arrowhead sub types * Handling? * * @param arrowHead the arrow head. * @param base the string for either "Interaction" or "GraphicalLine" * @param pt the point jdom element to write to. * @throws ConverterException */ protected void writeArrowHeadType(ArrowHeadType arrowHead, String base, Element pt) throws ConverterException { String arrowHeadStr = getArrowHeadTypeStr(arrowHead); if (arrowHeadStr == null) { arrowHeadStr = arrowHead.getName(); } setAttr(base + ".Graphics.Point", "ArrowHead", pt, arrowHeadStr); } /** * Writes anchor {@link Anchor} information. * * @param anchors the list of anchors. * @param gfx the jdom graphics element. * @throws ConverterException */ protected void writeAnchors(List anchors, Element gfx) throws ConverterException { if (!anchors.isEmpty()) { List anList = new ArrayList(); for (Anchor anchor : anchors) { Element an = new Element("Anchor", gfx.getNamespace()); String base = ((Element) gfx.getParent()).getName(); setAttr(base + ".Graphics.Anchor", "Position", an, Double.toString(anchor.getPosition())); setAttr(base + ".Graphics.Anchor", "Shape", an, anchor.getShapeType().getName()); writeElementId(anchor.getElementId(), an); if (an != null) { anList.add(an); } } if (anList != null && anList.isEmpty() == false) { gfx.addContent(anList); } } } /** * Writes label {@link Label} information. * * @param labels the list of labels. * @param root the root element. * @throws ConverterException */ protected void writeLabels(List




© 2015 - 2025 Weber Informatics LLC | Privacy Policy