
org.pathvisio.libgpml.model.GPML2021Writer Maven / Gradle / Ivy
/*******************************************************************************
* 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.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.Pathway.Author;
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.PathwayElement.EvidenceRef;
import org.pathvisio.libgpml.model.type.ArrowHeadType;
import org.pathvisio.libgpml.util.ColorUtils;
import org.pathvisio.libgpml.util.Utils;
import org.pathvisio.libgpml.util.XrefUtils;
/**
* This class writes a PathwayModel to an output (GPML 2021).
*
* NB:
*
* - GPML2021 is the current gpml format.
*
- In the GUI, Pathways are saved/written in the GPML2021 format.
*
*
* @author finterly
*/
public class GPML2021Writer extends GPML2021FormatAbstract implements GPMLFormatWriter {
public static final GPML2021Writer GPML2021WRITER = new GPML2021Writer("GPML2021.xsd",
Namespace.getNamespace("http://pathvisio.org/GPML/2021"));
/**
* Constructor for GPML writer.
*
* @param xsdFile the schema file.
* @param nsGPML the GPML namespace.
*/
protected GPML2021Writer(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);
writeInteractions(pathwayModel.getInteractions(), root);
writeGraphicalLines(pathwayModel.getGraphicalLines(), root);
writeLabels(pathwayModel.getLabels(), root);
writeShapes(pathwayModel.getShapes(), root);
writeGroups(pathwayModel.getGroups(), root);
writeAnnotations(pathwayModel.getAnnotations(), root);
writeCitations(pathwayModel.getCitations(), root);
writeEvidences(pathwayModel.getEvidences(), root);
}
return doc;
}
/**
* Writes pathway object {@link Pathway} information and authors list 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();
root.setAttribute("title", pathway.getTitle());
if (pathway.getOrganism() != null) {
root.setAttribute("organism", pathway.getOrganism());
}
if (pathway.getSource() != null) {
root.setAttribute("source", pathway.getSource());
}
if (pathway.getVersion() != null) {
root.setAttribute("version", pathway.getVersion());
}
if (pathway.getLicense() != null) {
root.setAttribute("license", pathway.getLicense());
}
if (pathway.getXref() != null) {
writeXref(pathway.getXref(), root, false);
}
String description = pathway.getDescription();
if (description != null) {
Element desc = new Element("Description", root.getNamespace());
desc.setText(description);
root.addContent(desc);
}
writeAuthors(pathway.getAuthors(), root);
writeComments(pathway.getComments(), root);
writeDynamicProperties(pathway.getDynamicProperties(), root);
writeAnnotationRefs(pathway.getAnnotationRefs(), root);
writeCitationRefs(pathway.getCitationRefs(), root);
writeEvidenceRefs(pathway.getEvidenceRefs(), root);
Element gfx = new Element("Graphics", root.getNamespace());
root.addContent(gfx);
gfx.setAttribute("boardWidth", String.valueOf(pathway.getBoardWidth()));
gfx.setAttribute("boardHeight", String.valueOf(pathway.getBoardHeight()));
}
/**
* Writes xref {@link Xref} information to new element. Xref is required for
* Evidences. Xref is optional for the Pathway, DataNodes, States, Interactions,
* Groups, and Annotations. For Citations, either Xref and/or Url are required.
*
* @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) {
if (xref == null && required) {
Element xrf = new Element("Xref", e.getNamespace());
xrf.setAttribute("identifier", "");
xrf.setAttribute("dataSource", "");
e.addContent(xrf);
}
if (xref != null) {
String identifier = xref.getId();
DataSource dataSource = xref.getDataSource();
String dataSourceStr = XrefUtils.getXrefDataSourceStr(dataSource);
if (dataSourceStr != null && !dataSourceStr.equals("")) {
Element xrf = new Element("Xref", e.getNamespace());
xrf.setAttribute("identifier", identifier == null ? "" : identifier);
xrf.setAttribute("dataSource", dataSourceStr);
e.addContent(xrf);
}
}
}
/**
* Writes url link information to new element. Url is optional for Annotations
* and Evidences. For Citations, either Xref and/or Url are required.
*
* @param urlLink the url link.
* @param e the jdom element.
*/
protected void writeUrl(String urlLink, Element e) {
if (urlLink != null && !Utils.stringEquals(urlLink, "")) {
Element u = new Element("Url", e.getNamespace());
u.setAttribute("link", urlLink);
e.addContent(u);
}
}
/**
* Writes author {@link Author} information.
*
* @param authors the list of authors.
* @param root the root element.
* @throws ConverterException
*/
protected void writeAuthors(List authors, Element root) throws ConverterException {
if (!authors.isEmpty()) {
Element aus = new Element("Authors", root.getNamespace());
List auList = new ArrayList();
for (Author author : authors) {
Element au = new Element("Author", root.getNamespace());
au.setAttribute("name", author.getName());
// sets optional properties
String username = author.getUsername();
int order = author.getOrder();
writeXref(author.getXref(), au, false);
if (username != null)
au.setAttribute("username", username);
if (order != 0)
au.setAttribute("order", String.valueOf(order));
if (au != null) {
auList.add(au);
}
}
if (auList != null && auList.isEmpty() == false) {
aus.addContent(auList);
root.addContent(aus);
}
}
}
/**
* 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 dynamic property information for pathway or pathway element.
* {@link PathwayElement#getDynamicProperty}
*
* @param dynamicProperties the list of dynamic properties.
* @param e the parent element.
* @throws ConverterException
*/
protected void writeDynamicProperties(Map dynamicProperties, Element e) throws ConverterException {
for (String key : dynamicProperties.keySet()) {
String value = dynamicProperties.get(key);
// warnings for conversion GPML2021 to GPML2013a
if (GPML2013aFormatAbstract.GPML2013A_KEY_SET.contains(key)) {
Logger.log.trace("Warning: Conversion GPML2013a to GPML2021: " + e.getName() + " dynamic property \""
+ key + "\" (key) and \"" + value + "\" (value) info lost.");
continue;
}
Element dp = new Element("Property", e.getNamespace());
dp.setAttribute("key", key);
dp.setAttribute("value", value);
if (dp != null) {
e.addContent(dp);
}
}
}
/**
* Writes annotation reference information for pathway or pathway element.
* {@link Pathway#getAnnotationRefs , ElementInfo#getAnnotationRefs}. In
* GPML2021, annotationRef can have citationRefs and/or evidenceRefs nested
* inside.
*
* @param annotationRefs the list of annotation references.
* @param e the parent element.
* @throws ConverterException
*/
protected void writeAnnotationRefs(List annotationRefs, Element e) throws ConverterException {
for (AnnotationRef annotationRef : annotationRefs) {
Element anntRef = new Element("AnnotationRef", e.getNamespace());
anntRef.setAttribute("elementRef", annotationRef.getAnnotation().getElementId());
writeCitationRefs(annotationRef.getCitationRefs(), anntRef);
writeEvidenceRefs(annotationRef.getEvidenceRefs(), anntRef);
if (anntRef != null) {
e.addContent(anntRef);
}
}
}
/**
* Writes citation reference information for pathway or pathway element.
* {@link Pathway#getCitationRefs , ElementInfo#getCitationRefs}.
*
* @param citationRefs the list of citation references.
* @param e the parent element.
* @throws ConverterException
*/
protected void writeCitationRefs(List citationRefs, Element e) throws ConverterException {
if (e != null) {
for (CitationRef citationRef : citationRefs) {
Element citRef = new Element("CitationRef", e.getNamespace());
citRef.setAttribute("elementRef", citationRef.getCitation().getElementId());
writeAnnotationRefs(citationRef.getAnnotationRefs(), citRef);
if (citRef != null) {
e.addContent(citRef);
}
}
}
}
/**
* Writes evidence reference information for pathway or pathway element
* {@link Pathway#getEvidenceRefs , ElementInfo#getEvidenceRefs}.
*
*
* @param evidenceRefs the list of evidence references.
* @param e the parent element.
* @throws ConverterException
*/
protected void writeEvidenceRefs(List evidenceRefs, Element e) throws ConverterException {
if (e != null) {
for (EvidenceRef evidenceRef : evidenceRefs) {
Element evidRef = new Element("EvidenceRef", e.getNamespace());
evidRef.setAttribute("elementRef", evidenceRef.getEvidence().getElementId());
if (evidRef != null) {
e.addContent(evidRef);
}
}
}
}
/**
* 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 {
if (!dataNodes.isEmpty()) {
Element dns = new Element("DataNodes", root.getNamespace());
List dnList = new ArrayList();
for (DataNode dataNode : dataNodes) {
Element dn = new Element("DataNode", root.getNamespace());
writeXref(dataNode.getXref(), dn, false);
writeStates(dataNode.getStates(), dn);
writeShapedElement(dataNode, dn);
// write jdom attributes
dn.setAttribute("textLabel", dataNode.getTextLabel());
dn.setAttribute("type", dataNode.getType().getName());
writeGroupRef(dataNode.getGroupRef(), dn);
writeAliasRef(dataNode.getAliasRef(), dn);
if (dn != null) {
dnList.add(dn);
}
}
if (dnList != null && dnList.isEmpty() == false) {
dns.addContent(dnList);
root.addContent(dns);
}
}
}
/**
* Writes aliasRef property information for a data node. Used in
* {@link #writeDataNodes}.
*
* @param aliasRef the group for which data node is an alias.
* @param e the parent jdom element.
*/
protected void writeAliasRef(Group aliasRef, Element e) {
if (aliasRef != null) {
String aliasRefStr = aliasRef.getElementId();
if (aliasRefStr != null && !aliasRefStr.equals("")) {
e.setAttribute("aliasRef", aliasRefStr);
}
}
}
/**
* Writes state {@link State} information.
*
* @param states the list of states.
* @param dn the parent data node element.
* @throws ConverterException
*/
protected void writeStates(List states, Element dn) throws ConverterException {
if (!states.isEmpty()) {
Element sts = new Element("States", dn.getNamespace());
List stList = new ArrayList();
for (State state : states) {
Element st = new Element("State", dn.getNamespace());
writeXref(state.getXref(), st, false);
writeShapedElement(state, st);
// write jdom attributes
st.setAttribute("textLabel", state.getTextLabel() == null ? "" : state.getTextLabel());
st.setAttribute("type", state.getType().getName());
if (st != null) {
stList.add(st);
}
}
if (stList != null && stList.isEmpty() == false) {
sts.addContent(stList);
dn.addContent(sts);
}
}
}
/**
* 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 {
if (!interactions.isEmpty()) {
Element ias = new Element("Interactions", root.getNamespace());
List iaList = new ArrayList();
for (Interaction interaction : interactions) {
Element ia = new Element("Interaction", root.getNamespace());
writeXref(interaction.getXref(), ia, false);
writeLineElement(interaction, ia);
if (ia != null) {
iaList.add(ia);
}
}
if (iaList != null && iaList.isEmpty() == false) {
ias.addContent(iaList);
root.addContent(ias);
}
}
}
/**
* 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 {
if (!graphicalLines.isEmpty()) {
Element glns = new Element("GraphicalLines", root.getNamespace());
List glnList = new ArrayList();
for (GraphicalLine graphicalLine : graphicalLines) {
Element gln = new Element("GraphicalLine", root.getNamespace());
writeLineElement(graphicalLine, gln);
if (gln != null) {
glnList.add(gln);
}
}
if (glnList != null && glnList.isEmpty() == false) {
glns.addContent(glnList);
root.addContent(glns);
}
}
}
/**
* 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 {
Element wyps = new Element("Waypoints", ln.getNamespace());
ln.addContent(wyps);
writePoints(lineElement, wyps);
writeAnchors(lineElement.getAnchors(), wyps);
Element gfx = new Element("Graphics", ln.getNamespace());
ln.addContent(gfx);
writeLineStyleProperty(lineElement, gfx);
writeElementInfo(lineElement, ln);
writeGroupRef(lineElement.getGroupRef(), ln);
}
/**
* Writes point {@link LinePoint} information.
*
* @param lineElement the line element.
* @param wyps the parent element.
* @throws ConverterException
*/
protected void writePoints(LineElement lineElement, Element wyps) 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", wyps.getNamespace());
writeElementId(point.getElementId(), pt);
// if start or end point, write arrowhead type.
if (i == 0) {
pt.setAttribute("arrowHead", lineElement.getStartArrowHeadType().getName());
} else if (i == points.size() - 1) {
pt.setAttribute("arrowHead", lineElement.getEndArrowHeadType().getName());
} else { // otherwise arrowHeadType = Undirected
pt.setAttribute("arrowHead", ArrowHeadType.UNDIRECTED.getName());
}
pt.setAttribute("x", Double.toString(point.getX()));
pt.setAttribute("y", Double.toString(point.getY()));
if (writeElementRef(point.getElementRef(), pt)) {
pt.setAttribute("relX", Double.toString(point.getRelX()));
pt.setAttribute("relY", Double.toString(point.getRelY()));
}
if (pt != null) {
ptList.add(pt);
}
}
if (ptList != null && ptList.isEmpty() == false) {
wyps.addContent(ptList);
}
}
/**
* Writes elementRef property information. Returns boolean if elementRef is
* written. Used in {@link #writePoints}.
*
* @param elementRef the elementRef.
* @param e the parent jdom element.
* @return true if elementRef exists and is successfully written.
*/
protected boolean writeElementRef(LinkableTo elementRef, Element e) {
if (elementRef != null) {
String elementRefStr = elementRef.getElementId();
if (elementRefStr != null && !elementRefStr.equals("")) {
e.setAttribute("elementRef", elementRefStr);
}
return true;
}
return false;
}
/**
* Writes anchor {@link Anchor} information.
*
* @param anchors the list of anchors.
* @param wyps the parent element.
* @throws ConverterException
*/
protected void writeAnchors(List anchors, Element wyps) throws ConverterException {
if (!anchors.isEmpty()) {
List anList = new ArrayList();
for (Anchor anchor : anchors) {
Element an = new Element("Anchor", wyps.getNamespace());
writeElementId(anchor.getElementId(), an);
an.setAttribute("position", Double.toString(anchor.getPosition()));
an.setAttribute("shapeType", anchor.getShapeType().getName());
if (an != null) {
anList.add(an);
}
}
if (anList != null && anList.isEmpty() == false) {
wyps.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