From 77d5556d9e3e28d8a1d57f2e2a8d787a6e8928a4 Mon Sep 17 00:00:00 2001
From: Mark Driver <mdd31@alumni.cam.ac.uk>
Date: Mon, 3 Feb 2020 14:43:24 +0000
Subject: [PATCH] ad methods to write SystemCollection to file. Update to
 namespace and schema compliance.

Update to write lower case boolean expressions to conform to xsd:boolean type.

Update to schema namespace to: http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema
---
 phasecalculator/classes/outputinformation.py  |  17 +--
 phasecalculator/classes/xmlnamespacing.py     |   2 +-
 .../io/systemcollectionprocessor.py           |  71 ++++++++++
 .../test/classestest/moleculetest.py          |   2 +-
 .../test/classestest/outputinformationtest.py |  14 +-
 .../test/classestest/phasestest.py            |   2 +-
 phasecalculator/test/classestest/phasetest.py |   2 +-
 .../classestest/runtimeinformationtest.py     |   8 +-
 .../test/classestest/systemtest.py            |  16 +--
 .../test/classestest/temperaturetest.py       |   2 +-
 .../iotest/systemcollectionprocessortest.py   | 121 ++++++++++++++++++
 11 files changed, 225 insertions(+), 32 deletions(-)
 create mode 100755 phasecalculator/io/systemcollectionprocessor.py
 create mode 100755 phasecalculator/test/iotest/systemcollectionprocessortest.py

diff --git a/phasecalculator/classes/outputinformation.py b/phasecalculator/classes/outputinformation.py
index f804851..c66313f 100755
--- a/phasecalculator/classes/outputinformation.py
+++ b/phasecalculator/classes/outputinformation.py
@@ -65,23 +65,24 @@ class OutputInformation(object):
     @classmethod
     def parse_fgip_output(cls, output_xml):
         xpath_expression = "phasecalc:FGIPOutput/text()"
-        fgip_output = bool(output_xml.xpath(xpath_expression, namespaces=PHASE_CALC_NAMESPACE_DICT)[0])
-        return fgip_output
+        fgip_output = output_xml.xpath(xpath_expression, namespaces=PHASE_CALC_NAMESPACE_DICT)[0]
+        return True if fgip_output == "true" else False
     @classmethod
     def parse_similarity_output(cls, output_xml):
         xpath_expression = "phasecalc:SimilarityOutput/text()"
-        similarity_output = bool(output_xml.xpath(xpath_expression, namespaces=PHASE_CALC_NAMESPACE_DICT)[0])
+        similarity_output = output_xml.xpath(xpath_expression, namespaces=PHASE_CALC_NAMESPACE_DICT)[0]
         if similarity_output:
             type_xpath = "phasecalc:SimilarityOutput/@phasecalc:outputType"
             similarity_output_type = output_xml.xpath(type_xpath, namespaces=PHASE_CALC_NAMESPACE_DICT)[0]
         else:
             similarity_output_type = None
+        similarity_output = True if similarity_output  == "true" else False
         return similarity_output, similarity_output_type
     @classmethod
     def parse_vle_output(cls, output_xml):
         xpath_expression = "phasecalc:FGIPOutput/text()"
-        vle_output = bool(output_xml.xpath(xpath_expression, namespaces=PHASE_CALC_NAMESPACE_DICT)[0])
-        return vle_output
+        vle_output = output_xml.xpath(xpath_expression, namespaces=PHASE_CALC_NAMESPACE_DICT)[0]
+        return True if vle_output == "true" else False
     def write_to_xml(self):
         """Write information to Etree representation of XML.
 
@@ -98,15 +99,15 @@ class OutputInformation(object):
         return out_element
     def write_fgip_output(self):
         fgip_element = etree.Element(PHASE_CALCULATOR + "FGIPOutput", nsmap=PHASE_CALC_NAMESPACE_DICT)
-        fgip_element.text = str(self.fgip_output)
+        fgip_element.text = str(self.fgip_output).lower()
         return fgip_element
     def write_similarity_output(self):
         sim_element = etree.Element(PHASE_CALCULATOR + "SimilarityOutput", nsmap=PHASE_CALC_NAMESPACE_DICT)
-        sim_element.text = str(self.similarity_output)
+        sim_element.text = str(self.similarity_output).lower()
         if self.similarity_output_type is not None:
             sim_element.set(PHASE_CALCULATOR + "outputType", self.similarity_output_type)
         return sim_element
     def write_vle_output(self):
         vle_element = etree.Element(PHASE_CALCULATOR + "VLEOutput", nsmap=PHASE_CALC_NAMESPACE_DICT)
-        vle_element.text = str(self.vle_output)
+        vle_element.text = str(self.vle_output).lower()
         return vle_element
\ No newline at end of file
diff --git a/phasecalculator/classes/xmlnamespacing.py b/phasecalculator/classes/xmlnamespacing.py
index 6202a8d..82bfe41 100755
--- a/phasecalculator/classes/xmlnamespacing.py
+++ b/phasecalculator/classes/xmlnamespacing.py
@@ -26,6 +26,6 @@ logging.basicConfig()
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.WARN)
 
-PHASE_CALC_NAMESPACE_DICT = {"phasecalc": "http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema"}
+PHASE_CALC_NAMESPACE_DICT = {"phasecalc": "http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema"}
 
 PHASE_CALCULATOR = "{{{}}}".format(PHASE_CALC_NAMESPACE_DICT["phasecalc"])
diff --git a/phasecalculator/io/systemcollectionprocessor.py b/phasecalculator/io/systemcollectionprocessor.py
new file mode 100755
index 0000000..7084582
--- /dev/null
+++ b/phasecalculator/io/systemcollectionprocessor.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+#    phasecalculator calculates FGIPs, solvent similarity and VLE with SSIMPLE.
+#    Copyright (C) 2019  Mark D. Driver
+#
+#    phasecalculator is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+"""
+Script for IO handling of System Collection class.
+
+@author: Mark
+"""
+
+import logging
+from lxml import etree
+import xmlvalidator.xmlvalidation as xmlval
+from phasecalculator.classes.system import SystemCollection
+
+logging.basicConfig()
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.WARN)
+
+
+def read_system_collection_file(xml_filename):
+    """Read SystemCollection from file.
+
+    Parameters
+    ----------
+    xml_filename : str
+        XML filename.
+
+    Returns
+    -------
+    SystemCollection
+        SystemCollection for calculations.
+
+    """
+    system_collection_etree = xmlval.validate_and_read_xml_file(xml_filename, xmlval.PHASE_CALCULATOR_SCHEMA)
+    return SystemCollection.parse_xml(system_collection_etree)
+
+
+def write_system_collection_file(system_collection, xml_filename):
+    """Write SystemCollection to XML file.
+
+    Parameters
+    ----------
+    system_collection : SystemCollection
+        SystemCollection for calculations.
+    xml_filename : str
+        XML filename.
+
+    Returns
+    -------
+    None.
+
+    """
+    sys_coll_element = system_collection.write_to_xml()
+    system_coll_etree = etree.ElementTree(sys_coll_element)
+    xmlval.validate_xml(system_coll_etree, xmlval.PHASE_CALCULATOR_SCHEMA)
+    system_coll_etree.write(
+        xml_filename, encoding="UTF-8", xml_declaration=True, pretty_print=True
+    )
\ No newline at end of file
diff --git a/phasecalculator/test/classestest/moleculetest.py b/phasecalculator/test/classestest/moleculetest.py
index de00d8b..10a71aa 100755
--- a/phasecalculator/test/classestest/moleculetest.py
+++ b/phasecalculator/test/classestest/moleculetest.py
@@ -67,7 +67,7 @@ class MoleculeTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:Molecule xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema" phasecalc:name="water" phasecalc:inChIKey="XLYOFNOQVPJJNP-UHFFFAOYSA-N" phasecalc:ssipFileLocation="XLYOFNOQVPJJNP-UHFFFAOYSA-N_ssip.xml" phasecalc:molefraction="1.0000"/>
+        expected_xml = """<phasecalc:Molecule xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema" phasecalc:name="water" phasecalc:inChIKey="XLYOFNOQVPJJNP-UHFFFAOYSA-N" phasecalc:ssipFileLocation="XLYOFNOQVPJJNP-UHFFFAOYSA-N_ssip.xml" phasecalc:molefraction="1.0000"/>
 """
         actual_xml = self.molecule.write_to_xml()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
diff --git a/phasecalculator/test/classestest/outputinformationtest.py b/phasecalculator/test/classestest/outputinformationtest.py
index c8e27d6..7e93fcf 100755
--- a/phasecalculator/test/classestest/outputinformationtest.py
+++ b/phasecalculator/test/classestest/outputinformationtest.py
@@ -98,10 +98,10 @@ class OutputInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:OutputInformation xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">
-  <phasecalc:FGIPOutput>True</phasecalc:FGIPOutput>
-  <phasecalc:SimilarityOutput phasecalc:outputType="all">True</phasecalc:SimilarityOutput>
-  <phasecalc:VLEOutput>True</phasecalc:VLEOutput>
+        expected_xml = """<phasecalc:OutputInformation xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">
+  <phasecalc:FGIPOutput>true</phasecalc:FGIPOutput>
+  <phasecalc:SimilarityOutput phasecalc:outputType="all">true</phasecalc:SimilarityOutput>
+  <phasecalc:VLEOutput>true</phasecalc:VLEOutput>
 </phasecalc:OutputInformation>
 """
         actual_xml = self.out_inf.write_to_xml()
@@ -114,7 +114,7 @@ class OutputInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:FGIPOutput xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">True</phasecalc:FGIPOutput>
+        expected_xml = """<phasecalc:FGIPOutput xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">true</phasecalc:FGIPOutput>
 """
         actual_xml = self.out_inf.write_fgip_output()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
@@ -126,7 +126,7 @@ class OutputInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:SimilarityOutput xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema" phasecalc:outputType="all">True</phasecalc:SimilarityOutput>
+        expected_xml = """<phasecalc:SimilarityOutput xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema" phasecalc:outputType="all">true</phasecalc:SimilarityOutput>
 """
         actual_xml = self.out_inf.write_similarity_output()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
@@ -138,7 +138,7 @@ class OutputInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:VLEOutput xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">True</phasecalc:VLEOutput>
+        expected_xml = """<phasecalc:VLEOutput xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">true</phasecalc:VLEOutput>
 """
         actual_xml = self.out_inf.write_vle_output()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
diff --git a/phasecalculator/test/classestest/phasestest.py b/phasecalculator/test/classestest/phasestest.py
index 6b1f909..e088e48 100755
--- a/phasecalculator/test/classestest/phasestest.py
+++ b/phasecalculator/test/classestest/phasestest.py
@@ -76,7 +76,7 @@ class PhasesTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:Phases xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">
+        expected_xml = """<phasecalc:Phases xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">
   <phasecalc:Phase>
     <phasecalc:Molecule phasecalc:name="water" phasecalc:inChIKey="XLYOFNOQVPJJNP-UHFFFAOYSA-N" phasecalc:ssipFileLocation="XLYOFNOQVPJJNP-UHFFFAOYSA-N_ssip.xml" phasecalc:molefraction="1.0000"/>
     <phasecalc:Temperature phasecalc:value="298.0" phasecalc:unit="KELVIN"/>
diff --git a/phasecalculator/test/classestest/phasetest.py b/phasecalculator/test/classestest/phasetest.py
index 0e28f72..3bd1764 100755
--- a/phasecalculator/test/classestest/phasetest.py
+++ b/phasecalculator/test/classestest/phasetest.py
@@ -93,7 +93,7 @@ class PhaseTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:Phase xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">
+        expected_xml = """<phasecalc:Phase xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">
   <phasecalc:Molecule phasecalc:name="water" phasecalc:inChIKey="XLYOFNOQVPJJNP-UHFFFAOYSA-N" phasecalc:ssipFileLocation="XLYOFNOQVPJJNP-UHFFFAOYSA-N_ssip.xml" phasecalc:molefraction="1.0000"/>
   <phasecalc:Temperature phasecalc:value="298.0" phasecalc:unit="KELVIN"/>
 </phasecalc:Phase>
diff --git a/phasecalculator/test/classestest/runtimeinformationtest.py b/phasecalculator/test/classestest/runtimeinformationtest.py
index 10f3045..06f2e86 100755
--- a/phasecalculator/test/classestest/runtimeinformationtest.py
+++ b/phasecalculator/test/classestest/runtimeinformationtest.py
@@ -103,7 +103,7 @@ class RuntimeInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:RuntimeInformation xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">
+        expected_xml = """<phasecalc:RuntimeInformation xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">
   <phasecalc:PhaseTransferJar>resources/example.jar</phasecalc:PhaseTransferJar>
   <phasecalc:ScratchDirectory>scratch</phasecalc:ScratchDirectory>
   <phasecalc:OutputDirectory>fgip</phasecalc:OutputDirectory>
@@ -119,7 +119,7 @@ class RuntimeInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:PhaseTransferJar xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">resources/example.jar</phasecalc:PhaseTransferJar>
+        expected_xml = """<phasecalc:PhaseTransferJar xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">resources/example.jar</phasecalc:PhaseTransferJar>
 """
         actual_xml = self.runtime_inf.write_phasetransfer_jar_xml()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
@@ -131,7 +131,7 @@ class RuntimeInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:ScratchDirectory xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">scratch</phasecalc:ScratchDirectory>
+        expected_xml = """<phasecalc:ScratchDirectory xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">scratch</phasecalc:ScratchDirectory>
 """
         actual_xml = self.runtime_inf.write_scratch_dir_xml()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
@@ -143,7 +143,7 @@ class RuntimeInformationTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:OutputDirectory xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">fgip</phasecalc:OutputDirectory>
+        expected_xml = """<phasecalc:OutputDirectory xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">fgip</phasecalc:OutputDirectory>
 """
         actual_xml = self.runtime_inf.write_output_dir_xml()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
\ No newline at end of file
diff --git a/phasecalculator/test/classestest/systemtest.py b/phasecalculator/test/classestest/systemtest.py
index 1c74366..ce47480 100755
--- a/phasecalculator/test/classestest/systemtest.py
+++ b/phasecalculator/test/classestest/systemtest.py
@@ -90,7 +90,7 @@ class SystemTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:SystemCollection xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">
+        expected_xml = """<phasecalc:SystemCollection xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">
   <phasecalc:System>
     <phasecalc:Phases>
       <phasecalc:Phase>
@@ -104,9 +104,9 @@ class SystemTestCase(unittest.TestCase):
       <phasecalc:OutputDirectory>fgip</phasecalc:OutputDirectory>
     </phasecalc:RuntimeInformation>
     <phasecalc:OutputInformation>
-      <phasecalc:FGIPOutput>True</phasecalc:FGIPOutput>
-      <phasecalc:SimilarityOutput phasecalc:outputType="all">True</phasecalc:SimilarityOutput>
-      <phasecalc:VLEOutput>True</phasecalc:VLEOutput>
+      <phasecalc:FGIPOutput>true</phasecalc:FGIPOutput>
+      <phasecalc:SimilarityOutput phasecalc:outputType="all">true</phasecalc:SimilarityOutput>
+      <phasecalc:VLEOutput>true</phasecalc:VLEOutput>
     </phasecalc:OutputInformation>
   </phasecalc:System>
 </phasecalc:SystemCollection>
@@ -131,7 +131,7 @@ class SystemTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:System xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema">
+        expected_xml = """<phasecalc:System xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">
   <phasecalc:Phases>
     <phasecalc:Phase>
       <phasecalc:Molecule phasecalc:name="water" phasecalc:inChIKey="XLYOFNOQVPJJNP-UHFFFAOYSA-N" phasecalc:ssipFileLocation="XLYOFNOQVPJJNP-UHFFFAOYSA-N_ssip.xml" phasecalc:molefraction="1.0000"/>
@@ -144,9 +144,9 @@ class SystemTestCase(unittest.TestCase):
     <phasecalc:OutputDirectory>fgip</phasecalc:OutputDirectory>
   </phasecalc:RuntimeInformation>
   <phasecalc:OutputInformation>
-    <phasecalc:FGIPOutput>True</phasecalc:FGIPOutput>
-    <phasecalc:SimilarityOutput phasecalc:outputType="all">True</phasecalc:SimilarityOutput>
-    <phasecalc:VLEOutput>True</phasecalc:VLEOutput>
+    <phasecalc:FGIPOutput>true</phasecalc:FGIPOutput>
+    <phasecalc:SimilarityOutput phasecalc:outputType="all">true</phasecalc:SimilarityOutput>
+    <phasecalc:VLEOutput>true</phasecalc:VLEOutput>
   </phasecalc:OutputInformation>
 </phasecalc:System>
 """
diff --git a/phasecalculator/test/classestest/temperaturetest.py b/phasecalculator/test/classestest/temperaturetest.py
index 36b85c8..7effef7 100755
--- a/phasecalculator/test/classestest/temperaturetest.py
+++ b/phasecalculator/test/classestest/temperaturetest.py
@@ -67,7 +67,7 @@ class TemperatureTestCase(unittest.TestCase):
         None.
 
         """
-        expected_xml = """<phasecalc:Temperature xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/schema/PhaseCalculatorSchema" phasecalc:value="298.0" phasecalc:unit="KELVIN"/>
+        expected_xml = """<phasecalc:Temperature xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema" phasecalc:value="298.0" phasecalc:unit="KELVIN"/>
 """
         actual_xml = self.temperature.write_to_xml()
         self.assertMultiLineEqual(expected_xml, etree.tounicode(actual_xml, pretty_print=True))
diff --git a/phasecalculator/test/iotest/systemcollectionprocessortest.py b/phasecalculator/test/iotest/systemcollectionprocessortest.py
new file mode 100755
index 0000000..201380b
--- /dev/null
+++ b/phasecalculator/test/iotest/systemcollectionprocessortest.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+#    phasecalculator calculates FGIPs, solvent similarity and VLE with SSIMPLE.
+#    Copyright (C) 2019  Mark D. Driver
+#
+#    phasecalculator is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+"""
+Test case for System Collection Processor methods.
+
+@author: Mark
+"""
+
+import logging
+import unittest
+from lxml import etree
+from phasecalculator.classes.temperature import Temperature
+from phasecalculator.classes.molecule import Molecule
+from phasecalculator.classes.phase import Phase
+from phasecalculator.classes.phases import Phases
+from phasecalculator.classes.runtimeinformation import RuntimeInformation
+from phasecalculator.classes.outputinformation import OutputInformation
+from phasecalculator.classes.system import System, SystemCollection
+import phasecalculator.io.systemcollectionprocessor as sysproc
+
+
+logging.basicConfig()
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.WARN)
+
+class SystemCollectionProcessorTestCase(unittest.TestCase):
+    """Test case for  System Collection Processor methods."""
+    def setUp(self):
+        """Set up before tests.
+
+        Returns
+        -------
+        None.
+
+        """
+        self.maxDiff = None
+        self.temperature = Temperature(298.0, "KELVIN")
+        self.molecule = Molecule("water", "XLYOFNOQVPJJNP-UHFFFAOYSA-N", "XLYOFNOQVPJJNP-UHFFFAOYSA-N_ssip.xml", 1.0)
+        self.phase = Phase([self.molecule], self.temperature)
+        self.phases = Phases([self.phase])
+        self.example_jar = "resources/example.jar"
+        self.runtime_inf = RuntimeInformation(self.example_jar, "scratch", "fgip")
+        self.out_inf = OutputInformation(True, True, "all", True)
+        self.system = System(self.phases, self.runtime_inf, self.out_inf)
+        self.system_collection = SystemCollection([self.system])
+        self.xml_filename = "syscollection.xml"
+        sysproc.write_system_collection_file(self.system_collection, self.xml_filename)
+    def tearDown(self):
+        """Clean up after tests.
+
+        Returns
+        -------
+        None.
+
+        """
+        del self.phase
+        del self.molecule
+        del self.temperature
+        del self.phases
+        del self.runtime_inf
+        del self.out_inf
+        del self.system
+        del self.system_collection
+    def test_read_system_collection_file(self):
+        """Test
+
+        Returns
+        -------
+        None.
+
+        """
+        actual_sys_collection = sysproc.read_system_collection_file(self.xml_filename)
+        self.assertEqual(self.system_collection, actual_sys_collection)
+    def test_write_system_collection_file(self):
+        """Test
+
+        Returns
+        -------
+        None.
+
+        """
+        expected_contents = """<?xml version='1.0' encoding='UTF-8'?>
+<phasecalc:SystemCollection xmlns:phasecalc="http://www-hunter.ch.cam.ac.uk/PhaseCalculatorSchema">
+  <phasecalc:System>
+    <phasecalc:Phases>
+      <phasecalc:Phase>
+        <phasecalc:Molecule phasecalc:name="water" phasecalc:inChIKey="XLYOFNOQVPJJNP-UHFFFAOYSA-N" phasecalc:ssipFileLocation="XLYOFNOQVPJJNP-UHFFFAOYSA-N_ssip.xml" phasecalc:molefraction="1.0000"/>
+        <phasecalc:Temperature phasecalc:value="298.0" phasecalc:unit="KELVIN"/>
+      </phasecalc:Phase>
+    </phasecalc:Phases>
+    <phasecalc:RuntimeInformation>
+      <phasecalc:PhaseTransferJar>resources/example.jar</phasecalc:PhaseTransferJar>
+      <phasecalc:ScratchDirectory>scratch</phasecalc:ScratchDirectory>
+      <phasecalc:OutputDirectory>fgip</phasecalc:OutputDirectory>
+    </phasecalc:RuntimeInformation>
+    <phasecalc:OutputInformation>
+      <phasecalc:FGIPOutput>true</phasecalc:FGIPOutput>
+      <phasecalc:SimilarityOutput phasecalc:outputType="all">true</phasecalc:SimilarityOutput>
+      <phasecalc:VLEOutput>true</phasecalc:VLEOutput>
+    </phasecalc:OutputInformation>
+  </phasecalc:System>
+</phasecalc:SystemCollection>
+"""
+        with open(self.xml_filename, "r") as actual_file:
+            actual_contents = actual_file.read()
+            self.assertMultiLineEqual(expected_contents, actual_contents)
+        
-- 
GitLab