diff --git a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java index eefd44b8791b4c3e4a4142c891115de78e94cb28..7c8a5614e878b04ce342d07652280202eb2475bb 100644 --- a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java +++ b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java @@ -3,7 +3,6 @@ package lcsb.mapviewer.common; import java.awt.Color; import java.io.BufferedReader; import java.io.ByteArrayInputStream; -import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; @@ -414,7 +413,8 @@ final public class XmlParser { TransformerFactory factory = TransformerFactory.newInstance(); // Use the factory to create a template containing the xsl file - Templates template = factory.newTemplates(new StreamSource(ClassLoader.getSystemResourceAsStream("to_lowercase.xsl"))); + Templates template = factory + .newTemplates(new StreamSource(ClassLoader.getSystemResourceAsStream("to_lowercase.xsl"))); // Use the template to create a transformer Transformer xformer = template.newTransformer(); @@ -428,7 +428,7 @@ final public class XmlParser { // to the output file xformer.transform(source, result); return output.toString("UTF-8"); - } catch (Exception e ) { + } catch (Exception e) { throw new InvalidStateException("Problem with translating input xml", e); } } diff --git a/converter-CellDesigner/pom.xml b/converter-CellDesigner/pom.xml index 1a8111a55708a201ce456361729bda161fdc808e..641ecc14e374496def655b697e6db0f339b751ee 100644 --- a/converter-CellDesigner/pom.xml +++ b/converter-CellDesigner/pom.xml @@ -26,12 +26,6 @@ <version>1.0</version> </dependency> - <dependency> - <groupId>com.googlecode.ez-vcard</groupId> - <artifactId>ez-vcard</artifactId> - <version>${ez-vcard.version}</version> - </dependency> - <!-- Log4J --> <dependency> <groupId>log4j</groupId> diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParser.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParser.java index 2c0d2e35236f4f13838a0df6097a7f928bf160c0..e25ffdbe72a718117c4db66db0ccd1d3de1a7a94 100644 --- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParser.java +++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParser.java @@ -362,6 +362,9 @@ public class CellDesignerXmlParser extends Converter { } else if (node.getNodeName().equalsIgnoreCase("rdf:RDF")) { XmlAnnotationParser xmlAnnotationParser = new XmlAnnotationParser(); model.addMiriamData(xmlAnnotationParser.parseRdfNode(node)); + model.addAuthors(xmlAnnotationParser.getAuthorsFromRdf(node)); + model.setCreationDate(xmlAnnotationParser.getCreateDateFromRdf(node)); + model.addModificationDates(xmlAnnotationParser.getModificationDatesFromRdf(node)); } else { throw new InvalidXmlSchemaException("Unknown element of annotation: " + node.getNodeName()); } diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java index 4913b32ddb347dea70b0dbc49f41708767ae3f4f..3bd124a15a06835e66a5142163be4c28242fbd61 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java @@ -104,6 +104,21 @@ public class CellDesignerXmlParserTest extends CellDesignerTestFunctions { } } + @Test + public void testParseVcard() throws Exception { + try { + CellDesignerXmlParser parser = new CellDesignerXmlParser(); + Model model = parser.createModel(new ConverterParams().filename("testFiles/model_with_vcard.xml")); + assertEquals("There is one author defined", 1, model.getAuthors().size()); + assertNotNull("Author data cannot be null", model.getAuthors().get(0)); + assertEquals("Modification date is not defined", 1, model.getModificationDates().size()); + assertNotNull("Creation date is not defined", model.getCreationDate()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + @Test public void testOpenFromInvalidFile() throws Exception { try { diff --git a/converter-CellDesigner/testFiles/model_with_vcard.xml b/converter-CellDesigner/testFiles/model_with_vcard.xml new file mode 100644 index 0000000000000000000000000000000000000000..95201e411c46367fccf146f4fca6dc1e64042d5a --- /dev/null +++ b/converter-CellDesigner/testFiles/model_with_vcard.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<sbml xmlns="http://www.sbml.org/sbml/level2/version4" xmlns:celldesigner="http://www.sbml.org/2001/ns/celldesigner" level="2" version="4"> +<model metaid="untitled" id="untitled"> +<annotation> +<celldesigner:extension> +<celldesigner:modelVersion>4.0</celldesigner:modelVersion> +<celldesigner:modelDisplay sizeX="600" sizeY="400"/> +<celldesigner:listOfCompartmentAliases/> +<celldesigner:listOfComplexSpeciesAliases/> +<celldesigner:listOfSpeciesAliases/> +<celldesigner:listOfGroups/> +<celldesigner:listOfProteins/> +<celldesigner:listOfGenes/> +<celldesigner:listOfRNAs/> +<celldesigner:listOfAntisenseRNAs/> +<celldesigner:listOfLayers/> +<celldesigner:listOfBlockDiagrams/> +</celldesigner:extension> +<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:vCard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" xmlns:bqmodel="http://biomodels.net/model-qualifiers/"> +<rdf:Description rdf:about="#untitled"> +<dc:creator> +<rdf:Bag> +<rdf:li rdf:parseType="Resource"> +<vCard:N rdf:parseType="Resource"> +<vCard:Family>Gawron</vCard:Family> +<vCard:Given>Piotr</vCard:Given> +</vCard:N> +<vCard:EMAIL>piotr.gawron@uni.lu</vCard:EMAIL> +<vCard:ORG rdf:parseType="Resource"> +<vCard:Orgname>LCSB</vCard:Orgname> +</vCard:ORG> +</rdf:li> +</rdf:Bag> +</dc:creator> +<dcterms:created rdf:parseType="Resource"> +<dcterms:W3CDTF>2019-03-26T11:12:52Z</dcterms:W3CDTF> +</dcterms:created> +<dcterms:modified rdf:parseType="Resource"> +<dcterms:W3CDTF>2019-03-26T11:12:56Z</dcterms:W3CDTF> +</dcterms:modified> +</rdf:Description> +</rdf:RDF> +</annotation> +<listOfUnitDefinitions> +<unitDefinition metaid="substance" id="substance" name="substance"> +<listOfUnits> +<unit metaid="CDMT00001" kind="mole"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="volume" id="volume" name="volume"> +<listOfUnits> +<unit metaid="CDMT00002" kind="litre"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="area" id="area" name="area"> +<listOfUnits> +<unit metaid="CDMT00003" kind="metre" exponent="2"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="length" id="length" name="length"> +<listOfUnits> +<unit metaid="CDMT00004" kind="metre"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="time" id="time" name="time"> +<listOfUnits> +<unit metaid="CDMT00005" kind="second"/> +</listOfUnits> +</unitDefinition> +</listOfUnitDefinitions> +<listOfCompartments> +<compartment metaid="default" id="default" size="1" units="volume"/> +</listOfCompartments> +</model> +</sbml> diff --git a/converter/src/main/java/lcsb/mapviewer/converter/annotation/XmlAnnotationParser.java b/converter/src/main/java/lcsb/mapviewer/converter/annotation/XmlAnnotationParser.java index e1c24e81fa9ef5484b365ccbdb18c15e1ab91492..95b971649f01b8a3c7c15f3c282cae65f58df57c 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/annotation/XmlAnnotationParser.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/annotation/XmlAnnotationParser.java @@ -1,11 +1,17 @@ package lcsb.mapviewer.converter.annotation; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.log4j.Logger; +import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -16,6 +22,7 @@ import lcsb.mapviewer.common.exception.InvalidXmlSchemaException; import lcsb.mapviewer.model.map.MiriamData; import lcsb.mapviewer.model.map.MiriamRelationType; import lcsb.mapviewer.model.map.MiriamType; +import lcsb.mapviewer.model.map.model.Author; /** * This class allow to parse xml nodes responsible for species annotations in @@ -68,7 +75,7 @@ public class XmlAnnotationParser { * @throws InvalidXmlSchemaException * thrown when there is a problem with xml */ - public Set<MiriamData> parseRdfNode(NodeList root) throws InvalidXmlSchemaException { + private Set<MiriamData> parseRdfNode(NodeList root) throws InvalidXmlSchemaException { Node rdf = XmlParser.getNode("rdf:RDF", root); return parseRdfNode(rdf); } @@ -95,6 +102,9 @@ public class XmlAnnotationParser { MiriamRelationType relationType = MiriamRelationType.getTypeByStringRepresentation(relationTypeString); if (relationType != null) { miriamDataSet.addAll(parseMiriamNode(node)); + } else if (relationTypeString.equals("dc:creator")) { + } else if (relationTypeString.equals("dcterms:created")) { + } else if (relationTypeString.equals("dcterms:modified")) { } else { logger.warn("RDF relation type is not supported: " + relationTypeString); } @@ -109,6 +119,112 @@ public class XmlAnnotationParser { return miriamDataSet; } + public Set<Author> getAuthorsFromRdf(Node rdf) throws InvalidXmlSchemaException { + Set<Author> authors = new HashSet<>(); + + if (rdf != null) { + Node description = XmlParser.getNode("rdf:Description", rdf.getChildNodes()); + if (description != null) { + NodeList list = description.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + String relationTypeString = node.getNodeName(); + if (relationTypeString.equals("dc:creator")) { + Node bag = XmlParser.getNode("rdf:Bag", node.getChildNodes()); + if (bag == null) { + throw new InvalidXmlSchemaException("No rdf:Bag node found"); + } + list = bag.getChildNodes(); + List<Node> nodes = XmlParser.getNodes("rdf:li", list); + for (Node li : nodes) { + Author author = parseAuthor(li); + authors.add(author); + } + } + } + } + } else { + throw new InvalidXmlSchemaException("rdf:Description node not found"); + } + } else { + throw new InvalidXmlSchemaException("rdf:Rdf node not found"); + } + return authors; + } + + public Calendar getCreateDateFromRdf(Node rdf) throws InvalidXmlSchemaException { + if (rdf != null) { + Node description = XmlParser.getNode("rdf:Description", rdf.getChildNodes()); + if (description != null) { + NodeList list = description.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + String relationTypeString = node.getNodeName(); + if (relationTypeString.equals("dcterms:created")) { + Node dateNode = XmlParser.getNode("dcterms:W3CDTF", node); + if (dateNode != null) { + return getDateFromNode(dateNode); + } + } + } + } + } else { + throw new InvalidXmlSchemaException("rdf:Description node not found"); + } + } else { + throw new InvalidXmlSchemaException("rdf:Rdf node not found"); + } + return null; + } + + private Calendar getDateFromNode(Node dateNode) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + try { + Date date = dateFormat.parse(dateNode.getTextContent().replaceAll("[T]", " ")); + Calendar result = Calendar.getInstance(); + result.setTime(date); + return result; + } catch (ParseException | DOMException e) { + logger.warn("Problem with parsing date: ", e); + } + return null; + } + + private Author parseAuthor(Node li) { + NodeList list = li.getChildNodes(); + String firstName = null; + String lastName = null; + String organization = null; + String email = null; + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + if (node.getNodeName().equals("vCard:EMAIL")) { + email = node.getNodeValue(); + } else if (node.getNodeName().equals("vCard:ORG")) { + organization = node.getNodeValue(); + } else if (node.getNodeName().equals("vCard:N")) { + Node familyNode = XmlParser.getNode("vCard:Family", node); + if (familyNode != null) { + lastName = familyNode.getNodeValue(); + } + Node givenNode = XmlParser.getNode("vCard:Given", node); + if (givenNode != null) { + firstName = givenNode.getNodeValue(); + } + } else { + logger.warn("Unknown data node in vcard: " + node.getNodeName()); + } + } + } + Author author = new Author(firstName, lastName); + author.setEmail(email); + author.setOrganisation(organization); + return author; + } + /** * This method converts a xml node into MiriamData object (annotation of a * species). @@ -199,4 +315,32 @@ public class XmlAnnotationParser { return result.toString(); } + public List<Calendar> getModificationDatesFromRdf(Node rdf) throws InvalidXmlSchemaException { + List<Calendar> result = new ArrayList<>(); + + if (rdf != null) { + Node description = XmlParser.getNode("rdf:Description", rdf.getChildNodes()); + if (description != null) { + NodeList list = description.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + String relationTypeString = node.getNodeName(); + if (relationTypeString.equals("dcterms:modified")) { + for (Node dateNode : XmlParser.getNodes("dcterms:W3CDTF", node.getChildNodes())) { + result.add(getDateFromNode(dateNode)); + } + } + } + } + } else { + throw new InvalidXmlSchemaException("rdf:Description node not found"); + } + } else { + throw new InvalidXmlSchemaException("rdf:Rdf node not found"); + } + + return result; + } + } diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java b/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java index 74557fa936c06412b1778c53f8116d26839ef4d7..ff797ab9e935d907175f2bdfb61b7f81848fa744 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java @@ -549,7 +549,9 @@ public interface Model { void addMiriamData(Collection<MiriamData> parseRdfNode); public void addAuthor(Author author); - + + void addAuthors(Set<Author> authorsFromRdf); + public List<Author> getAuthors(); public Calendar getCreationDate(); @@ -560,4 +562,7 @@ public interface Model { public List<Calendar> getModificationDates(); + void addModificationDates(List<Calendar> modificationDatesFromRdf); + + } diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java index 5e9bc0ef741d6adf2cae4621caa15232eb5fb12e..2c9905f430b8469b698a5225d75bf6300276248d 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java @@ -719,4 +719,18 @@ public class ModelFullIndexed implements Model { public void addAuthor(Author author) { modelData.addAuthor(author); } + + @Override + public void addAuthors(Set<Author> authors) { + for (Author author : authors) { + addAuthor(author); + } + } + + @Override + public void addModificationDates(List<Calendar> modificationDates) { + for (Calendar calendar : modificationDates) { + addModificationDate(calendar); + } + } }