diff --git a/APED/app/src/main/AndroidManifest.xml b/APED/app/src/main/AndroidManifest.xml index 54b771e..71a046f 100644 --- a/APED/app/src/main/AndroidManifest.xml +++ b/APED/app/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + + ActivityCompat.requestPermissions( + MainActivity.this, + new String[]{ + Manifest.permission.WRITE_EXTERNAL_STORAGE}, + STORAGE_PERMISSION_CODE)) + .setNegativeButton("cancel", (dialog, which) -> + System.exit(1)) + .create() + .show(); + + } else { + ActivityCompat.requestPermissions( + this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + STORAGE_PERMISSION_CODE); + } + } + } + + /** + * handles request permission results. + * @param requestCode the code of the requested + * @param permissions the permissions requested + * @param grantResults the result of the permission request + */ + @Override + public void onRequestPermissionsResult( + final int requestCode, + @NonNull final String[] permissions, + @NonNull final int[] grantResults) { + if (requestCode == STORAGE_PERMISSION_CODE) { + if (grantResults.length > 0 + && grantResults[0] == PERMISSION_GRANTED) { + Toast.makeText( + this, + "Permission GRANTED", + Toast.LENGTH_LONG) + .show(); + } else { + System.exit(1); + } + } } } diff --git a/APED/app/src/main/java/com/example/aped/communication/IXML.java b/APED/app/src/main/java/com/example/aped/utils/IXML.java similarity index 96% rename from APED/app/src/main/java/com/example/aped/communication/IXML.java rename to APED/app/src/main/java/com/example/aped/utils/IXML.java index 0c2b4a0..725a6c8 100644 --- a/APED/app/src/main/java/com/example/aped/communication/IXML.java +++ b/APED/app/src/main/java/com/example/aped/utils/IXML.java @@ -1,4 +1,4 @@ -package com.example.aped.communication; +package com.example.aped.utils; import java.util.Dictionary; import java.util.List; diff --git a/APED/app/src/main/java/com/example/aped/communication/TestXML.java b/APED/app/src/main/java/com/example/aped/utils/TestXML.java similarity index 96% rename from APED/app/src/main/java/com/example/aped/communication/TestXML.java rename to APED/app/src/main/java/com/example/aped/utils/TestXML.java index 3e043d4..723f494 100644 --- a/APED/app/src/main/java/com/example/aped/communication/TestXML.java +++ b/APED/app/src/main/java/com/example/aped/utils/TestXML.java @@ -1,4 +1,4 @@ -package com.example.aped.communication; +package com.example.aped.utils; import java.util.ArrayList; diff --git a/APED/app/src/main/java/com/example/aped/utils/XMLHandler.java b/APED/app/src/main/java/com/example/aped/utils/XMLHandler.java new file mode 100644 index 0000000..1ac657b --- /dev/null +++ b/APED/app/src/main/java/com/example/aped/utils/XMLHandler.java @@ -0,0 +1,185 @@ +package com.example.aped.utils; + +import android.util.Log; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import kotlin.NotImplementedError; + +public class XMLHandler implements IXML { + + /** the root of the XMl file. **/ + private Document root; + + /** + * constructor for the XMLHandler. + * @param xmlPath the path to the XML file + * @param xsdPath the path to the XSD file + * @throws ParserConfigurationException the XML parser configuration failed + * @throws IOException the XML file could not be accessed + * @throws SAXException the XML parse failed + */ + public XMLHandler(final String xmlPath, final String xsdPath) + throws ParserConfigurationException, IOException, SAXException { + if (!validate(xmlPath, xsdPath)) { + throw new VerifyError("the XML file is invalid"); + } + //parse the root document fromt the XML file + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + root = builder.parse(new File(xmlPath)); + } + + /** + * validates a XML file against a XSD file. + * @param xmlPath the path to the XML file + * @param xsdPath the path to the XSD file + * @return true if XML is valid + */ + private boolean validate(final String xmlPath, final String xsdPath) { + try { + SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI + ); + Schema schema = factory.newSchema(new File(xsdPath)); + Validator validator = schema.newValidator(); + validator.validate(new StreamSource(new File(xmlPath))); + } catch (IOException | SAXException e) { + Log.e("XMLHandler", + "Error while validating the XML file" + + e.getMessage()); + return false; + } + return true; + } + + @Override + public int download() { + throw new NotImplementedError(); + } + + @Override + public int upload() { + throw new NotImplementedError(); + } + + /** + * reads the device names from the XML file. + * @return the device names as a list of strings + */ + @Override + public List getDeviceNames() { + List returnList = new ArrayList<>(); + NodeList devices = root.getElementsByTagName("Device"); + for (int i = 0; i < devices.getLength(); i++) { + returnList.add(((Element) devices.item(i)).getAttribute("name")); + } + return returnList; + } + + /** + * reads the value info from the XML file. + * @param deviceName the name of the relevant device + * @return the value info as a dictionary {'unit','type','Offset','Factor'} + */ + @Override + public Dictionary getValueInfo(final String deviceName) { + Dictionary returnDictionary = new Hashtable<>(); + XPathFactory xPathFactory = XPathFactory.newInstance(); + XPath xPath = xPathFactory.newXPath(); + try { + XPathExpression xPathExpression = xPath.compile( + "//Device[@name='" + deviceName + "']/ValueInfo"); + Element result = (Element) xPathExpression.evaluate( + root, XPathConstants.NODE); + returnDictionary.put("type", result.getAttribute("type")); + returnDictionary.put("unit", result.getAttribute("unit")); + NodeList childNodes = result.getChildNodes(); + float offset = 0.0f; + float factor = 1.0f; + for (int i = 0; i < childNodes.getLength(); i++) { + switch (childNodes.item(i).getNodeName()) { + case "Offset": + offset = Float.parseFloat(childNodes.item(i) + .getTextContent()); + break; + case "Factor": + factor = Float.parseFloat(childNodes.item(i) + .getTextContent()); + break; + default: + break; + } + } + returnDictionary.put("offset", offset); + returnDictionary.put("factor", factor); + } catch (XPathExpressionException e) { + Log.e( + "XMLHandler", + "the XPath for getting the value info has errors:" + + e.getMessage() + ); + } + return returnDictionary; + } + + /** + * reads the port information from the XML file. + * @param deviceName the name of the relevant device + * @return the port information as a dictionary {'protocol','pins'} + */ + @Override + public Dictionary getPort(final String deviceName) { + Dictionary returnDictionary = new Hashtable<>(); + XPathFactory xPathFactory = XPathFactory.newInstance(); + XPath xPath = xPathFactory.newXPath(); + try { + XPathExpression xPathExpression = xPath.compile( + "//Device[@name='" + deviceName + "']/Port"); + Element result = (Element) xPathExpression.evaluate( + root, XPathConstants.NODE); + returnDictionary.put("protocol", result.getAttribute("protocol")); + NodeList childNodes = result.getChildNodes(); + List pins = new ArrayList<>(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + if (childNode.getNodeName().equals("Pin")) { + pins.add(childNode.getTextContent()); + } + } + returnDictionary.put("pins", pins); + } catch (XPathExpressionException e) { + Log.e( + "XMLHandler", + "the XPath for getting the value info has errors:" + + e.getMessage() + ); + } + return returnDictionary; + } +} diff --git a/APED/app/src/main/java/com/example/aped/utils/XML_files/config.xml b/APED/app/src/main/java/com/example/aped/utils/XML_files/config.xml new file mode 100644 index 0000000..244ae6b --- /dev/null +++ b/APED/app/src/main/java/com/example/aped/utils/XML_files/config.xml @@ -0,0 +1,23 @@ + + + + + + GPIO_2 + + + + + 1.2 + 2.5 + + + GPIO_3 + GPIO_4 + GPIO_5 + GPIO_6 + + + + \ No newline at end of file diff --git a/APED/app/src/main/java/com/example/aped/utils/XML_files/config.xsd b/APED/app/src/main/java/com/example/aped/utils/XML_files/config.xsd new file mode 100644 index 0000000..800b53e --- /dev/null +++ b/APED/app/src/main/java/com/example/aped/utils/XML_files/config.xsd @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/APED/app/src/main/java/com/example/aped/utils/XML_files/package-info.java b/APED/app/src/main/java/com/example/aped/utils/XML_files/package-info.java new file mode 100644 index 0000000..8411944 --- /dev/null +++ b/APED/app/src/main/java/com/example/aped/utils/XML_files/package-info.java @@ -0,0 +1,4 @@ +/** + * package for the storage of the XML files. + * */ +package com.example.aped.utils.XML_files; diff --git a/APED/app/src/main/java/com/example/aped/utils/package-info.java b/APED/app/src/main/java/com/example/aped/utils/package-info.java new file mode 100644 index 0000000..66a280a --- /dev/null +++ b/APED/app/src/main/java/com/example/aped/utils/package-info.java @@ -0,0 +1,4 @@ +/** + * package for utilities. + * */ +package com.example.aped.utils; diff --git a/APED/app/src/test/java/com/example/aped/Test.xml b/APED/app/src/test/java/com/example/aped/Test.xml new file mode 100644 index 0000000..244ae6b --- /dev/null +++ b/APED/app/src/test/java/com/example/aped/Test.xml @@ -0,0 +1,23 @@ + + + + + + GPIO_2 + + + + + 1.2 + 2.5 + + + GPIO_3 + GPIO_4 + GPIO_5 + GPIO_6 + + + + \ No newline at end of file diff --git a/APED/app/src/test/java/com/example/aped/Test.xsd b/APED/app/src/test/java/com/example/aped/Test.xsd new file mode 100644 index 0000000..800b53e --- /dev/null +++ b/APED/app/src/test/java/com/example/aped/Test.xsd @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/APED/app/src/test/java/com/example/aped/XMLHandlerUnitTest.java b/APED/app/src/test/java/com/example/aped/XMLHandlerUnitTest.java new file mode 100644 index 0000000..ea98a9c --- /dev/null +++ b/APED/app/src/test/java/com/example/aped/XMLHandlerUnitTest.java @@ -0,0 +1,92 @@ +package com.example.aped; + +import com.example.aped.utils.XMLHandler; + +import org.junit.Test; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; + +import static org.junit.Assert.*; + +public class XMLHandlerUnitTest { + private String xmlPath="src/test/java/com/example/aped/Test.xml"; + private String xsdPath="src/test/java/com/example/aped/Test.xsd"; + + @Test + public void TestFiles_AreValid(){ + try{ + XMLHandler xmlHandler = new XMLHandler(xmlPath,xsdPath); + }catch(IOException | ParserConfigurationException | SAXException e){ + System.out.println("XMLHandler failed"); + assert(false); + }catch(VerifyError e){ + System.out.println("XML not valid"); + assert(false); + } + } + + @Test + public void Test_getDeviceNames(){ + try{ + XMLHandler xmlHandler = new XMLHandler(xmlPath,xsdPath); + List deviceNames = xmlHandler.getDeviceNames(); + assertArrayEquals(new String[]{"example","sensorarray"},deviceNames.toArray()); + }catch(IOException | ParserConfigurationException | SAXException e){ + System.out.println("XMLHandler failed"); + assert(false); + } + } + + @Test + public void TestInput_SimpleValueInfo(){ + try{ + XMLHandler xmlHandler = new XMLHandler(xmlPath,xsdPath); + Dictionary valueInfo = xmlHandler.getValueInfo("example"); + assertEquals("{factor=1.0, type=boolean, unit=, offset=0.0}",valueInfo.toString()); + }catch(IOException | ParserConfigurationException | SAXException e){ + System.out.println("XMLHandler failed"); + assert(false); + } + } + + @Test + public void TestInput_ComplexValueInfo(){ + try{ + XMLHandler xmlHandler = new XMLHandler(xmlPath,xsdPath); + Dictionary valueInfo = xmlHandler.getValueInfo("sensorarray"); + assertEquals("{factor=2.5, type=int, unit=°C, offset=1.2}",valueInfo.toString()); + }catch(IOException | ParserConfigurationException | SAXException e){ + System.out.println("XMLHandler failed"); + assert(false); + } + } + + @Test + public void TestInput_SimplePort(){ + try{ + XMLHandler xmlHandler = new XMLHandler(xmlPath,xsdPath); + Dictionary port = xmlHandler.getPort("example"); + assertEquals("{pins=[GPIO_2], protocol=DI}",port.toString()); + }catch(IOException | ParserConfigurationException | SAXException e){ + System.out.println("XMLHandler failed"); + assert(false); + } + } + + @Test + public void TestInput_ComplexPort(){ + try{ + XMLHandler xmlHandler = new XMLHandler(xmlPath,xsdPath); + Dictionary port = xmlHandler.getPort("sensorarray"); + assertEquals("{pins=[GPIO_3, GPIO_4, GPIO_5, GPIO_6], protocol=DI}",port.toString()); + }catch(IOException | ParserConfigurationException | SAXException e){ + System.out.println("XMLHandler failed"); + assert(false); + } + } +} diff --git a/APED/app/src/test/java/com/example/aped/java/android/util/Log.java b/APED/app/src/test/java/com/example/aped/java/android/util/Log.java new file mode 100644 index 0000000..fe992ba --- /dev/null +++ b/APED/app/src/test/java/com/example/aped/java/android/util/Log.java @@ -0,0 +1,29 @@ +package android.util; + +public class Log { + public static int d(String tag, String msg) { + System.out.println("DEBUG: " + tag + ": " + msg); + return 0; + } + + public static int i(String tag, String msg) { + System.out.println("INFO: " + tag + ": " + msg); + return 0; + } + + public static int w(String tag, String msg) { + System.out.println("WARN: " + tag + ": " + msg); + return 0; + } + + public static int e(String tag, String msg) { + System.out.println("ERROR: " + tag + ": " + msg); + return 0; + } + + public static int v(String tag, String msg) { + System.out.println("ERROR: " + tag + ": " + msg); + return 0; + } + // add other methods if required... +}