![JAR search and dependency download from the Maven repository](/logo.png)
org.pathvisio.libgpml.model.GPML2013aWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.pathvisio.libgpml Show documentation
Show all versions of org.pathvisio.libgpml Show documentation
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:
*
* - If writing (converting) GPML2021 to GPML2013a, warning messages are
* thrown.
*
- 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