commit a1ee3cf1b5bb317c40725266de827cb9547513b6 Author: Jens Date: Wed Feb 3 22:49:24 2021 +0100 Initial commit diff --git a/ShoppingList/.classpath b/ShoppingList/.classpath new file mode 100644 index 0000000..fb786d7 --- /dev/null +++ b/ShoppingList/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ShoppingList/.gitignore b/ShoppingList/.gitignore new file mode 100644 index 0000000..a917b76 --- /dev/null +++ b/ShoppingList/.gitignore @@ -0,0 +1,74 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/eclipse +# Edit at https://www.toptal.com/developers/gitignore?templates=eclipse + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +### Eclipse Patch ### +# Spring Boot Tooling +.sts4-cache/ + +# End of https://www.toptal.com/developers/gitignore/api/eclipse + +ShoppingListLogFile.txt +ShoppingList-settings.ini \ No newline at end of file diff --git a/ShoppingList/.project b/ShoppingList/.project new file mode 100644 index 0000000..00864f5 --- /dev/null +++ b/ShoppingList/.project @@ -0,0 +1,17 @@ + + + ShoppingList + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/ShoppingList/lib/commons-lang3-3.9.jar b/ShoppingList/lib/commons-lang3-3.9.jar new file mode 100644 index 0000000..0d89693 Binary files /dev/null and b/ShoppingList/lib/commons-lang3-3.9.jar differ diff --git a/ShoppingList/lib/javax.xml.bind.jar b/ShoppingList/lib/javax.xml.bind.jar new file mode 100644 index 0000000..2b5dc7e Binary files /dev/null and b/ShoppingList/lib/javax.xml.bind.jar differ diff --git a/ShoppingList/lib/mariadb-java-client-2.4.4.jar b/ShoppingList/lib/mariadb-java-client-2.4.4.jar new file mode 100644 index 0000000..9df5b8d Binary files /dev/null and b/ShoppingList/lib/mariadb-java-client-2.4.4.jar differ diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/DatabaseHandler.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/DatabaseHandler.java new file mode 100644 index 0000000..e3fe229 --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/DatabaseHandler.java @@ -0,0 +1,134 @@ +package com.jens.rhasspy.shoppinglist; + + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +public class DatabaseHandler implements Runnable +{ + private static DatabaseHandler instance = null; + static final String databaseConnectionEncoding = "utf8"; + + Connection conn = null; + + private DatabaseHandler() + { + } + + public static DatabaseHandler getInstance() + { + if(instance == null) + instance = new DatabaseHandler(); + + return instance; + } + + public Connection getConnection() + { +// if(isConnectedToDatabase()) +// { +// // It has occured that the connection was there, but dead due to timeout or whatever +// try +// { +// conn.getSchema(); +// } +// catch (SQLException e) +//// if(conn.isValid(5000)) +// { +// Miscellaneous.logEvent("DB connection probably dropped. Reestablishing..."); +// conn = null; +// establishConnection(); +// } +// } + + if(!isConnectedToDatabase()) + establishConnection(true); + + return this.conn; + } + + /** force means that connection is definitely reestablished, even if there seems to be an existing one **/ + private synchronized void establishConnection(boolean force) + { + if(conn == null | force) + { + for(String dbServer : Settings.databaseServerNames) + { + Miscellaneous.logEvent("Trying to connect to database " + Settings.databaseName + "@" + dbServer + " as " + Settings.databaseUsername + "...", 3); + +// String url = "jdbc:mysql://" + dbServer + ":" + Settings.databasePort + "/"; +// String driver = "com.mysql.jdbc.Driver"; + String url = "jdbc:mariadb://" + dbServer + ":" + Settings.databasePort + "/"; + String driver = "org.mariadb.jdbc.Driver"; + try + { + Class.forName(driver).newInstance(); + conn = DriverManager.getConnection(url + Settings.databaseName + "?characterEncoding=" + databaseConnectionEncoding, Settings.databaseUsername, Settings.databasePassword); + Miscellaneous.logEvent("Connected to database.", 3); + + break; + } + catch (ClassNotFoundException e) + { + Miscellaneous.logEvent(Settings.languageBlock.get("dbDriverNotFound"), 1); + } + catch (Exception e) + { + Miscellaneous.logEvent(Settings.languageBlock.get("dbCouldNotConnect"), 1); + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 2); + this.conn = null; + } + } + } + } + + public void disconnect() + { + // TODO: Timeout after which the DB connection is terminated automatically. + + if(conn != null) + { + Miscellaneous.logEvent("Disconnecting from database.", 3); + try + { + this.conn.close(); + } + catch (SQLException e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + } + else + Miscellaneous.logEvent("Not disconnecting from database because not connected.", 4); + + conn=null; + } + + @Override + protected void finalize() throws Throwable + { + disconnect(); + } + + @Override + public void run() + { + getConnection(); + } + + public boolean isConnectedToDatabase() + { + try + { + if(conn != null && conn.isValid(5000)) + return true; + } + catch (SQLException e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + + return false; + } +} \ No newline at end of file diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/Diverse.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Diverse.java new file mode 100644 index 0000000..21ad4d0 --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Diverse.java @@ -0,0 +1,611 @@ +package com.jens.rhasspy.shoppinglist; + + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.security.SecureRandom; +import java.sql.Time; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.TimeZone; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +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; + +public class Diverse +{ + public final static String networkSeparatorCommunication = ";commSep"; + public final static String networkSeparatorSettings = ";commSett"; + + public static enum cacheObjectsEnum { all, devices, commands, rooms, rules, users, houses, nodes, sensors, userDevices }; + + public enum SolarEvent {sunrise, sunset}; + + public static final String lineSeparator = System.getProperty("line.separator"); + + public static String intToOpenClosed(int value) + { + if(value == 1) + return "closed"; + else if(value == 0) + return "open"; + else + return "unknown"; + } + + public static String intToWaterYesNo(int value) + { + if(value == 1) + return "water"; + else if(value == 0) + return "dry"; + else + return "unknown"; + } + + public static String intToSmokeYesNo(int value) + { + if(value == 1) + return "smoke"; + else if(value == 0) + return "no smoke"; + else + return "unknown"; + } + + public static String getEnabledDisabledString(boolean value) + { + if(value) + return "enabled"; + else + return "disabled"; + } + + public static Calendar calendarFromLong(long source) + { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(source); + return cal; + } + + public static String getOnOffString(boolean value) + { + if(value) + return "on"; + else + return "off"; + } + + public static String getIniLikeValue(String fullText, String searchObject, String separator) + { + fullText = fullText.trim(); + + if (fullText.toLowerCase().contains(searchObject.toLowerCase())) + { + if (fullText.toLowerCase().contains(separator.toLowerCase())) // multiple values + { + int start = fullText.toLowerCase().indexOf(searchObject.toLowerCase() + "=") + searchObject.length() + 1; + int end = fullText.toLowerCase().indexOf(separator.toLowerCase(), start); + + if (end == -1) // if the last index in fullText + return fullText.substring(start); + else + return fullText.substring(start, end); + } + else // only one value + { + return fullText.substring(fullText.indexOf("=") + 1); + } + } + else + { + Miscellaneous.logEvent("Index " + searchObject + " cannot be found in full text.", 5); + return null; + } + } + + public static String addOrReplaceIniLikeValue(String fullText, String key, String value, String separator) + { + fullText = fullText.trim(); + + if (fullText.startsWith(key + "=") | fullText.contains(separator + key + "=")) + { + if (fullText.contains(separator)) // multiple values + { + int start = fullText.indexOf(key + "=") + key.length() + 1; + int end = fullText.indexOf(separator, start); + + String oldValue; + if (end == -1) // if the last index in fullText + oldValue = fullText.substring(start); + else + oldValue = fullText.substring(start, end); + + return fullText.replace(key + "=" + oldValue, key + "=" + value); + } + else // only one value + { + return key + "=" + value; + } + } + else + { + if(fullText.length() > 0) + return fullText + separator + key + "=" + value; + else + return key + "=" + value; + } + } + + public static String removeIniLikeValue(String fullText, String key, String separator) + { + fullText = fullText.trim(); + String toBeRemoved = getIniLikeValue(fullText, key, separator); + + if(toBeRemoved != null && fullText.contains(toBeRemoved)) + { + if(fullText.contains(";")) + { + if(fullText.contains(";" + toBeRemoved)) + return fullText.replace(";" + toBeRemoved, ""); + else + return fullText.replace(toBeRemoved + ";", ""); + } + else + return ""; + } + else + return fullText; + } + + public static String updateIniLikeValue(String fullText, String key, String value, String separator) + { + if (fullText.contains(key)) + { + if (fullText.contains(separator)) // multiple values + { + String[] lines = fullText.split(separator); + for(int i=0; i < lines.length; i++) + { + if(lines[i].startsWith(key)) + { + int equalsPosition = lines[i].indexOf(key + "=") + key.length() + 1; + lines[i] = lines[i].substring(0, equalsPosition) + value; + break; + } + } + + return Diverse.arrayImplode(separator, lines); + } + else // only one value + { + return fullText + separator + key + "=" + value; + } + } + else + { + return fullText + separator + key + "=" + value; + } + } + + public static int boolToInt(boolean in) + { + if (in) + return 1; + else + return 0; + } + + public static boolean intToBool(int in) + { + if (in > 0) + return true; + else + return false; + +// ClientServerSplit.logEvent("Error transforming int to bool.", 3); +// return false; + } + + public static boolean isNumeric(String stringToCheck) + { + String character; + + for(int i = 0; i < stringToCheck.length(); i++) + { + character = stringToCheck.substring(i, i + 1); + + if(!character.matches("[1234567890]") && !character.equals(".") && !character.equals(",")) + return false; + } + + return true; + } + + public static boolean arraySearch(String[] haystack, String needle, boolean caseSensitive, boolean matchFullLine) + { + if(matchFullLine) + { + if(caseSensitive) + { + for (String s : haystack) + { + if (s.equals(needle)) + return true; + } + } + else + { + for (String s : haystack) + { + if (s.toLowerCase().equals(needle.toLowerCase())) + return true; + } + } + } + else + { + if(caseSensitive) + { + for (String s : haystack) + { + if (s.contains(needle)) + return true; + } + } + else + { + for (String s : haystack) + { + if (s.toLowerCase().contains(needle.toLowerCase())) + return true; + } + } + } + + return false; + } + + public static boolean arraySearch(ArrayList requestList, String needle, boolean caseSensitive, boolean matchFullLine) + { + return arraySearch(requestList.toArray(new String[requestList.size()]), needle, caseSensitive, matchFullLine); + } + + public static boolean arraySearch(cacheObjectsEnum[] haystack, cacheObjectsEnum needle) + { + if (needle != null) + { + for (cacheObjectsEnum c : haystack) + { + if (c.equals(needle)) + return true; + } + } + else + Miscellaneous.logEvent("Needle should not be null in function arraySearch()", 5); + + return false; + } + + public static String arrayImplode(String glue, String... values) + { + String returnString = ""; + + for (String s : values) + returnString += s + glue; + + if (returnString.length() > 0) + returnString = returnString.substring(0, returnString.length() - glue.length()); + + return returnString; + } + + public static String arrayImplode(String glue, ArrayList arrayList) + { + String returnString = ""; + + for (Object s : arrayList) + returnString += s + glue; + + if (returnString.length() > 0) + returnString = returnString.substring(0, returnString.length() - glue.length()); + + return returnString; + } + + public static String arrayImplode(String glue, Object[] array) + { + String returnString = ""; + + for (Object s : array) + returnString += s.toString() + glue; + + if (returnString.length() > 0) + returnString = returnString.substring(0, returnString.length() - glue.length()); + + return returnString; + } + + public static String arrayImplode(String glue, HashMap map) + { + String returnString = ""; + + for (String key : map.keySet()) + returnString += map.get(key) + glue; + + if (returnString.length() > 0) + returnString = returnString.substring(0, returnString.length() - glue.length()); + + return returnString; + } + + public static String getSystemTimezone() + { +// https://coderanch.com/t/386398/java/System-Timezone + TimeZone tz = Calendar.getInstance().getTimeZone(); +// System.out.println(tz.getDisplayName());// (i.e. Moscow Standard Time) + return tz.getID(); + +// Should return something like this: Asia/Calcutta + } + + public static String createPassword(int length) + { + final String allowedChars = "0123456789abcdefghijklmnopqrstuvwABCDEFGHIJKLMNOP!§$%&?*+#"; + SecureRandom random = new SecureRandom(); + StringBuilder pass = new StringBuilder(length); + for (int i = 0; i < length; i++) + { + pass.append(allowedChars.charAt(random.nextInt(allowedChars.length()))); + } + return pass.toString(); + } + + public static Element getXmlTree(String inputString) throws SAXException, IOException, ParserConfigurationException + { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + +// Create a Document from a file or stream + /* + StringBuilder xmlStringBuilder = new StringBuilder(); + xmlStringBuilder.append(" "); + ByteArrayInputStream input = new ByteArrayInputStream(xmlStringBuilder.toString().getBytes("UTF-8")); + */ +// Document doc = builder.parse(input); + Document doc = builder.parse(new InputSource(new StringReader(inputString))); + + Element rootElement = doc.getDocumentElement(); + + return rootElement; + /* +// Examine attributes + + //returns specific attribute + root.getAttribute("attributeName"); + + //returns a Map (table) of names/values + root.getAttributes(); + +// Examine sub-elements + + //returns a list of subelements of specified name + root.getElementsByTagName("subelementName"); + + //returns a list of all child nodes + root.getChildNodes(); + */ + } + + public static String xmlToString(Node node, boolean omitXmlDeclaration, boolean prettyPrint) + { + if (node == null) + { + throw new IllegalArgumentException("node is null."); + } + + try + { + // Remove unwanted whitespaces + node.normalize(); + XPath xpath = XPathFactory.newInstance().newXPath(); + XPathExpression expr = xpath.compile("//text()[normalize-space()='']"); + NodeList nodeList = (NodeList) expr.evaluate(node, XPathConstants.NODESET); + + for (int i = 0; i < nodeList.getLength(); ++i) + { + Node nd = nodeList.item(i); + nd.getParentNode().removeChild(nd); + } + + // Create and setup transformer + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + + if (omitXmlDeclaration == true) + { + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + } + + if (prettyPrint == true) + { + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + } + + // Turn the node into a string + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(node), new StreamResult(writer)); + return writer.toString(); + } + catch (TransformerConfigurationException e) + { + e.printStackTrace(); + } + catch (TransformerException e) + { + throw new RuntimeException(e); + } + catch (XPathExpressionException e) + { + throw new RuntimeException(e); + } + + return null; + } + + + public static String getStackTrace() + { + StringBuilder trace = new StringBuilder(); + for (StackTraceElement ste : Thread.currentThread().getStackTrace()) + trace.append(ste + Diverse.lineSeparator); + + trace.delete(trace.length(), trace.length()); + + return trace.toString(); + } + + public static String getStackTraceAsString(Throwable aThrowable) + { + Writer result = new StringWriter(); + PrintWriter printWriter = new PrintWriter(result); + aThrowable.printStackTrace(printWriter); + return result.toString(); + } + + /** + * Defines a custom format for the stack trace as String. + */ + public static String getCustomStackTrace(Throwable aThrowable) + { + //add the class name and any message passed to constructor + StringBuilder result = new StringBuilder( "Stacktrace: " ); + result.append(aThrowable.toString()); + String NEW_LINE = System.getProperty("line.separator"); + result.append(NEW_LINE); + + //add each element of the stack trace + for (StackTraceElement element : aThrowable.getStackTrace()) + { + result.append(element); + result.append(NEW_LINE); + } + return result.toString(); + } + + public static ArrayList getSubElements(Node node, String parentName, String childName) + { + ArrayList returnList = new ArrayList(); + NodeList nodeElements = ((Element)node).getElementsByTagName("houses"); + for(int i = 0; i < nodeElements.getLength(); i++) + { + if (nodeElements.item(i).getNodeType() == Node.ELEMENT_NODE) + { + NodeList childElements = nodeElements.item(i).getChildNodes(); + for (int j = 0; j < childElements.getLength(); j++) + { + Element element = (Element) childElements.item(j); +// HouseTemplate house = HouseTemplate.fromXmlStringStatic(Diverse.getXmlFull(element)); + returnList.add(element); + } + } + } + + /*ArrayList returnList = new ArrayList<>(); + + NodeList children = ((Element)node).getElementsByTagName(parentName); + + for(int i=0; i < children.getLength(); i++) + { + returnList.add((Element)children.item(i)); + }*/ + + return returnList; + } + + public static double round(double value, int places) + { + if (places < 0) throw new IllegalArgumentException(); + + BigDecimal bd = new BigDecimal(Double.toString(value)); + bd = bd.setScale(places, RoundingMode.HALF_UP); + return bd.doubleValue(); + } + + public static Class getCallerClass() + { + StackTraceElement[] stElements = Thread.currentThread().getStackTrace(); + for (int i=1; i (maxSizeInBytes)) + { + File archivedLogFile = new File(logFile.getAbsolutePath() + "-old"); + logFile.renameTo(archivedLogFile); + Miscellaneous.logEvent("Log renamed to " + archivedLogFile.getAbsolutePath(), 3); + } + + Miscellaneous.logEvent("Cleaning up log file finished.", 3); + + logCleanerRunning = false; + } + } + } + + public static String getGCStats() + { + StringBuilder returnString = new StringBuilder(); + + long totalGarbageCollections = 0; + long garbageCollectionTime = 0; + + for(GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) + { + + long count = gc.getCollectionCount(); + + if(count >= 0) { + totalGarbageCollections += count; + } + + long time = gc.getCollectionTime(); + + if(time >= 0) + garbageCollectionTime += time; + } + + returnString.append("Total Garbage Collections: " + totalGarbageCollections + Diverse.lineSeparator); + returnString.append("Total Garbage Collection Time (ms): " + garbageCollectionTime); + + return returnString.toString(); + } + + public static class SmtpSimple + { + /** + * Send a single email. + */ + public boolean sendEmail(String mailServer, int mailServerPor, String encryptionType, boolean useAuthentication, final String username, final String password, String aFromEmailAddr, String aToEmailAddr, String aSubject, String aBody) + { + // Properties über die Systemeigenschaften anlegen + Properties properties = System.getProperties(); + + properties.setProperty("mail.smtp.host", mailServer); + properties.setProperty("mail.smtp.port", String.valueOf(mailServerPor)); + + properties.setProperty("mail.smtp.auth", String.valueOf(useAuthentication)); + + /* + * final Properties props = new Properties(); + * props.put("mail.smtp.host", "SMTPHOST"); + * props.put("mail.smtp.port", "PORTNUMBER"); + * props.put("mail.transport.protocol","smtp"); + * props.put("mail.smtp.auth", "true"); + * props.put("mail.smtp.starttls.enable", "true"); + * props.put("mail.smtp.tls", "true"); + * props.put("mail.smtp.ssl.checkserveridentity", "true"); + */ + + if(encryptionType.equalsIgnoreCase("STARTTLS")) + properties.setProperty("mail.smtp.starttls.enable", "true"); + else if(encryptionType.equalsIgnoreCase("TLS")) + properties.put("mail.smtp.tls", "true"); + else if(encryptionType.equalsIgnoreCase("SSL")) + properties.setProperty("mail.smtp.ssl.enable", "true"); + +// properties.put("mail.smtp.ssl.checkserveridentity", "false"); + + Session session; + + Authenticator auth = new Authenticator() + { + protected PasswordAuthentication getPasswordAuthentication() + { + return new PasswordAuthentication(username, password); + } + }; + + if(useAuthentication) + session = Session.getDefaultInstance(properties, auth); + else + session= Session.getDefaultInstance(properties, null); + +// session.setDebug(true); + + MimeMessage message = new MimeMessage(session); + try + { + //the "from" address may be set in code, or set in the + //config file under "mail.from" ; here, the latter style is used + message.setFrom(new InternetAddress(aFromEmailAddr)); + message.addRecipient(Message.RecipientType.TO, new InternetAddress(aToEmailAddr)); + message.setSubject(aSubject); + message.setText(aBody); + Transport.send(message); + return true; + } + catch (AddressException e) + { + System.err.println("Cannot send email. " + Diverse.getStackTraceAsString(e)); + } + catch (javax.mail.MessagingException e) + { + System.err.println("Cannot send email. " + Diverse.getStackTraceAsString(e)); + } + + return false; + } + } + + public static String readFile(File file) + { + String content = null; + try + { + FileReader reader = new FileReader(file); + char[] chars = new char[(int) file.length()]; + reader.read(chars); + content = new String(chars); + reader.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + return content; + } + + public static double convertCelsiusToFahrenheit(double celsius) + { + return (celsius * 1.8 + 32); + } + + public static double convertFahrenheitToCelsius(double fahrenheit) + { + return ((fahrenheit - 32)/1.8); + } + + public static String downloadWebpage(String urlAddress) + { + URL url; + InputStream is = null; + BufferedReader br = null; + String line; + + try + { + url = new URL(urlAddress); + is = url.openStream(); // throws an IOException + br = new BufferedReader(new InputStreamReader(is)); + + StringBuilder returnString = new StringBuilder(); + + while ((line = br.readLine()) != null) + { +// System.out.println(line); + returnString.append(line); + } + + if(br != null) + br.close(); + + if (is != null) + is.close(); + + Miscellaneous.logEvent("Webpage downloaded: " + returnString.toString(), 5); + + return returnString.toString(); + } + catch (MalformedURLException mue) + { + mue.printStackTrace(); + } + catch (IOException ioe) + { + ioe.printStackTrace(); + } + finally + { + try + { + if(br != null) + br.close(); + + if (is != null) + is.close(); + } + catch (IOException ioe) + { + // nothing to see here + } + } + + return genericErrorMessage; + } + + public static boolean isDevelopment() + { + Boolean desenv = null; + +// if (desenv != null) +// return desenv; + + try + { + desenv = new File(".").getCanonicalPath().contains("workspace"); + } + catch (IOException e) + { + e.printStackTrace(); + } + + return desenv; + } + + public static String getOnOffStringForBoolean(boolean state) + { + if(state) + return "on"; + else + return "off"; + } + +// public enum SolarEvent { dawn, sunrise, solarNoon, sunset, dusk }; + + /** + * + * @param commandToExecute + * @param timeout + * @return Returns an array: 0=exit code, 1=cmdline output + */ + public static Object[] runExternalApplication(String commandToExecute, long timeout) + { + /* + * Classes stolen from https://github.com/stleary/JSON-java + */ + + Miscellaneous.logEvent("Running external application " + commandToExecute + "...", 4); + + Object[] returnObject = new Object[2]; + + StringBuilder output = new StringBuilder(); + String line = null; + OutputStream stdin = null; + InputStream stderr = null; + InputStream stdout = null; + + try + { + Process process = null; + + process = Runtime.getRuntime().exec(commandToExecute); + stdin = process.getOutputStream (); + stderr = process.getErrorStream (); + stdout = process.getInputStream (); + + // "write" the parms into stdin + /*line = "param1" + "\n"; + stdin.write(line.getBytes() ); + stdin.flush(); + + line = "param2" + "\n"; + stdin.write(line.getBytes() ); + stdin.flush(); + + line = "param3" + "\n"; + stdin.write(line.getBytes() ); + stdin.flush(); + + stdin.close(); */ + + // clean up if any output in stdout + BufferedReader brCleanUp = new BufferedReader (new InputStreamReader (stdout)); + while ((line = brCleanUp.readLine ()) != null) + { + Miscellaneous.logEvent ("[Stdout] " + line, 4); + output.append(line); + } + brCleanUp.close(); + + // clean up if any output in stderr + brCleanUp = new BufferedReader (new InputStreamReader (stderr)); + while ((line = brCleanUp.readLine ()) != null) + { + Miscellaneous.logEvent ("[Stderr] " + line, 4); + output.append(line); + } + brCleanUp.close(); + + try + { + // Wait for the process to exit, we want the return code + if(timeout > 0) + { + try + { + if(!process.waitFor(timeout, TimeUnit.MILLISECONDS)) + { + Miscellaneous.logEvent("Timeout of " + String.valueOf(timeout) + " ms reached. Killing check attempt.", 3); + process.destroyForcibly(); + } + } + catch(NoSuchMethodError e) + { + process.waitFor(); + } + } + else + process.waitFor(); + } + catch (InterruptedException e) + { + Miscellaneous.logEvent("Waiting for process failed: " + Diverse.getStackTraceAsString(e), 4); + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + + Miscellaneous.logEvent("ReturnCode: " + String.valueOf(process.exitValue()), 4); + + returnObject[0] = process.exitValue(); + returnObject[1] = output.toString(); + + return returnObject; + } + catch (IOException e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + + Miscellaneous.logEvent("Error running external application.", 1); + + return null; + } + + public static boolean restartNode() + { +// return true; + return (boolean) runExternalApplication("sudo shutdown -r", 60000)[0]; + } + + public static boolean isLeapYear(int year) + { + boolean leap = false; + + if(year % 4 == 0) + { + if( year % 100 == 0) + { + // year is divisible by 400, hence the year is a leap year + if ( year % 400 == 0) + leap = true; + else + leap = false; + } + else + leap = true; + } + else + leap = false; + + return leap; + + /*if(leap) + System.out.println(year + " is a leap year."); + else + System.out.println(year + " is not a leap year.");*/ + } + + public static double getStarDate(Calendar when) + { + int y = when.get(Calendar.YEAR); + + int n = 0; + if(Miscellaneous.isLeapYear(y)) + n = 366; + else + n = 365; + + int b = 2005; + + long c = 58000; + + int d = when.get(Calendar.DAY_OF_MONTH); + + int m = 0; + switch(when.get(Calendar.MONTH)) + { + case Calendar.JANUARY: + m = 0; + break; + case Calendar.FEBRUARY: + m = 31; + break; + case Calendar.MARCH: + m = 59; + break; + case Calendar.APRIL: + m = 90; + break; + case Calendar.MAY: + m = 120; + break; + case Calendar.JUNE: + m = 151; + break; + case Calendar.JULY: + m = 181; + break; + case Calendar.AUGUST: + m = 212; + break; + case Calendar.SEPTEMBER: + m = 243; + break; + case Calendar.OCTOBER: + m = 273; + break; + case Calendar.NOVEMBER: + m = 304; + break; + case Calendar.DECEMBER: + m = 334; + break; + } + + double stardate = c + (1000 * (y-b)) + (1000/n * (m+d-1)); + + return stardate; + } +} \ No newline at end of file diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/Product.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Product.java new file mode 100644 index 0000000..7f1dc7e --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Product.java @@ -0,0 +1,194 @@ +package com.jens.rhasspy.shoppinglist; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.ArrayList; + +public class Product +{ + static ArrayList productCache = null; + + long id; + String name; + String synonyms; + StoreType storeType; + + public long getId() + { + return id; + } + public void setId(long id) + { + this.id = id; + } + public String getName() + { + return name; + } + public void setName(String name) + { + this.name = name; + } + + public String getSynonyms() + { + return synonyms; + } + public void setSynonyms(String synonyms) + { + this.synonyms = synonyms; + } + public static ArrayList readAllProducts() + { + if(productCache == null) + { + try + { + Connection conn = DatabaseHandler.getInstance().getConnection(); + + if(conn == null) + Start.exitWithError(Settings.languageBlock.get("dbCouldNotConnect")); + + PreparedStatement preparedStmt = null; + + String query = "SELECT * FROM products"; + + preparedStmt = conn.prepareStatement(query); + + Miscellaneous.logEvent(preparedStmt.toString(), 5); + + ResultSet res = preparedStmt.executeQuery(); + + productCache = new ArrayList(); + + while (res.next()) + { + Product p = new Product(); + + p.setId(res.getLong("id")); + p.setName(res.getString("name")); + p.setSynonyms(res.getString("synonyms")); + + StoreType st = StoreType.getById(res.getLong("storeTypeId")); + p.setStoreType(st); + + productCache.add(p); + } + + res.close(); + preparedStmt.close(); + } + catch(Exception e) + { + Start.exitWithError(Settings.languageBlock.get("dbCouldNotConnect")); + } + } + + return productCache; + } + + @Override + public boolean equals(Object obj) + { + return ((Product)obj).getName().equalsIgnoreCase(getName()); + } + + public static Product getByName(String productName) + { + for(Product p : readAllProducts()) + { + if(p.getName().equalsIgnoreCase(productName)) + return p; + else if(p.getName().equalsIgnoreCase(productName.replace("-", " "))) + return p; + } + + return null; + } + + @Override + public String toString() + { + return getName(); + } + + public static Product getById(long id) + { + for(Product p : readAllProducts()) + { + if(p.getId() == id) + return p; + } + + return null; + } + public StoreType getStoreType() + { + return storeType; + } + public void setStoreType(StoreType storeType) + { + this.storeType = storeType; + } + + public boolean create() + { + String query = "INSERT INTO nodes (name, synonyms, storeTypeId) VALUES (?, ?, ?)"; + Connection conn = DatabaseHandler.getInstance().getConnection(); + PreparedStatement preparedStmt = null; + try + { + preparedStmt = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS); + + preparedStmt.setString(1, this.getName()); + + if(this.getSynonyms() == null) + preparedStmt.setNull(2, Types.VARCHAR); + else + preparedStmt.setString(2, getSynonyms()); + + preparedStmt.setLong(3, getStoreType().getId()); + + preparedStmt.executeUpdate(); + ResultSet rs = preparedStmt.getGeneratedKeys(); + if (rs.next()) + { + this.setId(rs.getInt(1)); + Miscellaneous.logEvent("INSERT-ID: " + String.valueOf(this.getId()), 5); + + rs.close(); + preparedStmt.close(); + + Miscellaneous.logEvent("Product has been successfully created.", 2); + + return true; + } + else + { + rs.close(); + String error = "Insert new product failed."; + Miscellaneous.logEvent(error, 1); + } + } + catch (SQLException e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + finally + { + try + { + if(preparedStmt != null && !preparedStmt.isClosed()) + preparedStmt.close(); + } + catch (SQLException e) + { + } + } + + return false; + } +} diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/Settings.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Settings.java new file mode 100644 index 0000000..bc68db7 --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Settings.java @@ -0,0 +1,118 @@ +package com.jens.rhasspy.shoppinglist; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +public class Settings +{ + public static Map languageBlock = new HashMap<>(); + + // Settings from file + public static String databaseUsername; + public static String databasePassword; + public static String databaseName; + public static String[] databaseServerNames; + public static int databasePort; + public static String logFolderPath; + public static String notificationFromAddress; + public static String[] notificationToAddresses; + public static String notificationMailServer; + public static int notificationMailServerPort; + public static String notificationEncryptionType; + public static boolean notificationAuthenticate; + public static String notificationUsername; + public static String notificationPassword; + public static String language; + public static int logLevel = 1; // Set a default value as logging is performed before settings can be loaded. + + // Constants not user modifiable. + public static final String programName = "ShoppingList"; + public static final String logFileName = programName + "LogFile.txt"; + public static final String settingsFileName = programName + "-settings.ini"; + public static final String dateFormat = "dd.MM.yyyy HH:mm:ss:SSSS"; + public static final int logMaxSize = 5000; // Set a default value as logging is performed before settings can be loaded. + public static final boolean notificationsEnabled = true; + public static final int notificationVerbosity = 2; + + public static boolean readSettings() + { + File sFile = new File(settingsFileName); + Miscellaneous.logEvent("Loading settings from " + sFile.getAbsolutePath(), 3); + + Properties prop = new Properties(); + + try + { + // Local settings from settings file + prop.load(new FileInputStream(sFile)); + + databaseUsername = prop.getProperty("databaseUsername", "error"); + databasePassword = prop.getProperty("databasePassword", "error"); + databaseName = prop.getProperty("databaseName", "error"); + databaseServerNames = prop.getProperty("databaseServerNames", "error").split(","); + databasePort = Integer.parseInt(prop.getProperty("databasePort", "error")); + logFolderPath = prop.getProperty("logFolderPath", "error"); + notificationFromAddress = prop.getProperty("notificationFromAddress", "error"); + notificationToAddresses = prop.getProperty("notificationToAddresses", "error").split(","); + notificationMailServer = prop.getProperty("notificationMailServer", "error"); + notificationMailServerPort = Integer.parseInt(prop.getProperty("notificationMailServerPort", "error")); + notificationEncryptionType = prop.getProperty("notificationEncryptionType", "error"); + notificationAuthenticate = Boolean.parseBoolean(prop.getProperty("notificationEncryptionType", "error")); + notificationUsername = prop.getProperty("notificationUsername", "error"); + notificationPassword = prop.getProperty("notificationPassword", "error"); + language = prop.getProperty("language", "error"); + logLevel = Integer.parseInt(prop.getProperty("logLevel", "1")); + } + catch (FileNotFoundException e) + { + Start.exitWithError(Settings.languageBlock.get("settingsFileNotFound") + " " + settingsFileName); + } + catch (IOException e) + { + Start.exitWithError(Settings.languageBlock.get("settingsCouldNotBeRead") + " " + settingsFileName); + } + + fillLanguageVariable(); + + return true; + } + + static void fillLanguageVariable() + { + if(language != null && language.equalsIgnoreCase("de")) + { + languageBlock.put("dbCouldNotConnect", "Konnte nicht zur Datenbank verbinden."); + languageBlock.put("dbDriverNotFound", "Datenbanktreiber nicht gefunden."); + languageBlock.put("settingsFileNotFound", "Konfigurationsdatei nicht gefunden."); + languageBlock.put("settingsCouldNotBeRead", "Konfigurationsdatei konnte nicht gelesen werden."); + languageBlock.put("noActionDefined", "Keine Aktion angegeben."); + languageBlock.put("couldNotCreateList", "Konnte keine Liste anlegen."); + languageBlock.put("productNotFound", "Produkt nicht gefunden."); + languageBlock.put("couldNotAddProdToList", "Produkt konnte nicht auf die Liste gesetzt werden."); + languageBlock.put("noProdSpecified", "Kein Produkt angegeben."); + languageBlock.put("couldNotRemoveProdFromList", "Produkt konnte nicht von Liste entfernt werden."); + languageBlock.put("couldNotSendList", "Liste konnte nicht verschickt werden."); + languageBlock.put("couldNotCreateNewList", "Neue Liste konnte nicht erstellt werden."); + } + else + { + languageBlock.put("dbCouldNotConnect", "Could not connect to database."); + languageBlock.put("dbDriverNotFound", "Database driver not found."); + languageBlock.put("settingsFileNotFound", "Configuration file not found."); + languageBlock.put("settingsCouldNotBeRead", "Could not read configuration file."); + languageBlock.put("noActionDefined", "No action specified."); + languageBlock.put("couldNotCreateList", "Could not create list."); + languageBlock.put("productNotFound", "Product not found."); + languageBlock.put("couldNotAddProdToList", "Product could not be added to list."); + languageBlock.put("noProdSpecified", "No product specified."); + languageBlock.put("couldNotRemoveProdFromList", "Product could not be removed from list."); + languageBlock.put("couldNotSendList", "List could not be sent."); + languageBlock.put("couldNotCreateNewList", "New list could not be created."); + } + } +} diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/ShoppingList.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/ShoppingList.java new file mode 100644 index 0000000..612b447 --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/ShoppingList.java @@ -0,0 +1,254 @@ +package com.jens.rhasspy.shoppinglist; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Calendar; + +public class ShoppingList +{ + long id; + Calendar creationTime; + String comment; + ArrayList entries = new ArrayList<>(); + + public long getId() + { + return id; + } + public void setId(long id) + { + this.id = id; + } + public Calendar getCreationTime() + { + return creationTime; + } + public void setCreationTime(Calendar creationTime) + { + this.creationTime = creationTime; + } + public String getComment() + { + return comment; + } + public void setComment(String comment) + { + this.comment = comment; + } + + public boolean create() + { + PreparedStatement preparedStmt = null; + Connection conn = null; + try + { + conn = DatabaseHandler.getInstance().getConnection(); + + String parentQuery = "INSERT INTO lists (id, creationTime, comment) VALUES (?, ?, ?)"; + preparedStmt = conn.prepareStatement(parentQuery, Statement.RETURN_GENERATED_KEYS); + + preparedStmt.setLong(1, this.getId()); + preparedStmt.setLong(2, this.getCreationTime().getTimeInMillis()); + if(comment != null) + preparedStmt.setString(3, this.getComment()); + else + preparedStmt.setNull(3, java.sql.Types.VARCHAR); + + Miscellaneous.logEvent(preparedStmt.toString(), 5); + + long numAffectedRows = preparedStmt.executeUpdate(); + Miscellaneous.logEvent("AMOUNT OF UPDATED ROWS: " + numAffectedRows, 5); + ResultSet rs = preparedStmt.getGeneratedKeys(); + if (numAffectedRows > 0) + { + if (rs.next()) + { + this.setId(rs.getInt(1)); + rs.close(); + Miscellaneous.logEvent("INSERT-ID: " + String.valueOf(this.getId()), 5); + preparedStmt.close(); + return true; + } + } + } + catch(Exception e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + finally + { + try + { + if(preparedStmt != null && !preparedStmt.isClosed()) + preparedStmt.close(); + } + catch (SQLException e) + { + } + } + + return false; + } + + public static ShoppingList getMostRecentList() + { + ShoppingList resultList = null; + + PreparedStatement preparedStmt = null; + try + { + Connection conn = DatabaseHandler.getInstance().getConnection(); + + String query = "SELECT * FROM lists ORDER BY creationTime DESC LIMIT 0,1"; + + preparedStmt = conn.prepareStatement(query); + + Miscellaneous.logEvent(preparedStmt.toString(), 5); + + ResultSet res = preparedStmt.executeQuery(); + + if (res.next()) + { + resultList = new ShoppingList(); + resultList.setId(res.getLong("id")); + resultList.setCreationTime(Diverse.calendarFromLong(res.getLong("creationTime"))); + resultList.setComment(res.getString("comment")); + } + + res.close(); + preparedStmt.close(); + + if(resultList == null) + resultList = createNewList(); + + // Read entries + if(resultList.getEntries() == null) + resultList.setEntries(new ArrayList<>()); + resultList.getEntries().clear(); + + query = "SELECT * FROM listEntries WHERE listId=?"; + + preparedStmt = conn.prepareStatement(query); + preparedStmt.setLong(1, resultList.getId()); + + Miscellaneous.logEvent(preparedStmt.toString(), 5); + + res = preparedStmt.executeQuery(); + + while (res.next()) + { + ShoppingListEntry entry = new ShoppingListEntry(); + entry.setParentList(resultList); + entry.setProduct(Product.getById(res.getLong("productId"))); + resultList.getEntries().add(entry); + } + + res.close(); + preparedStmt.close(); + } + catch(Exception e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + finally + { + try + { + if(preparedStmt != null && !preparedStmt.isClosed()) + preparedStmt.close(); + } + catch (SQLException e) + { + } + } + + if(resultList == null) + resultList = createNewList(); + + return resultList; + } + + public boolean send() + { + StringBuilder shoppingListString = new StringBuilder(); + + if(comment != null) + shoppingListString.append("(" + comment + ")" + Diverse.lineSeparator); + + ArrayList storeTypesInUse = new ArrayList<>(); + for(ShoppingListEntry entry : this.entries) + { + if(!storeTypesInUse.contains(entry.getProduct().getStoreType())) + { + storeTypesInUse.add(entry.getProduct().getStoreType()); + } + } + + for(StoreType st : storeTypesInUse) + { + shoppingListString.append(st.getName() + Diverse.lineSeparator + "=======================" + Diverse.lineSeparator); + + for(ShoppingListEntry entry : this.entries) + { + if(entry.getProduct().getStoreType().equals(st)) + shoppingListString.append(entry.getProduct().getName() + Diverse.lineSeparator); + } + + shoppingListString.append(Diverse.lineSeparator); + } + + Miscellaneous.SmtpSimple smtp = new Miscellaneous.SmtpSimple(); + try + { + boolean result = true; + for(String address : Settings.notificationToAddresses) + { + if(!smtp.sendEmail(Settings.notificationMailServer, Settings.notificationMailServerPort, Settings.notificationEncryptionType, Settings.notificationAuthenticate, Settings.notificationUsername, Settings.notificationPassword, Settings.notificationFromAddress, address, "Einkaufsliste", shoppingListString.toString())) + { + result = false; + } + } + + if(result) + { + Miscellaneous.logEvent("Successfully sent shopping list to all recipients via server " + Settings.notificationMailServer, 2); + return true; + } + else + Miscellaneous.logEvent("Error sending shopping list.", 2); + } + catch (Exception e) + { + Miscellaneous.logEvent("Error sending shopping list: " + Diverse.getStackTraceAsString(e), 2); + } + + return false; + } + + public ArrayList getEntries() + { + return entries; + } + public void setEntries(ArrayList entries) + { + this.entries = entries; + } + + public static ShoppingList createNewList() + { + ShoppingList returnList = new ShoppingList(); + returnList.setCreationTime(Calendar.getInstance()); + if(returnList.create()) + return returnList; + else + return null; + } + @Override + public String toString() + { + return "Liste erstellt am " + Miscellaneous.formatDate(getCreationTime().getTime()); + } +} diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/ShoppingListEntry.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/ShoppingListEntry.java new file mode 100644 index 0000000..fd4a7bb --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/ShoppingListEntry.java @@ -0,0 +1,121 @@ +package com.jens.rhasspy.shoppinglist; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Calendar; + +public class ShoppingListEntry +{ + ShoppingList parentList; + Product product; + + public ShoppingList getParentList() + { + return parentList; + } + + public void setParentList(ShoppingList parentList) + { + this.parentList = parentList; + } + + public Product getProduct() + { + return product; + } + + public void setProduct(Product product) + { + this.product = product; + } + + public boolean create() + { + PreparedStatement preparedStmt = null; + Connection conn = null; + try + { + conn = DatabaseHandler.getInstance().getConnection(); + + String parentQuery = "INSERT IGNORE INTO listEntries (listId, productId) VALUES (?, ?)"; + preparedStmt = conn.prepareStatement(parentQuery, Statement.RETURN_GENERATED_KEYS); + + preparedStmt.setLong(1, this.getParentList().getId()); + preparedStmt.setLong(2, this.getProduct().getId()); + + Miscellaneous.logEvent(preparedStmt.toString(), 5); + + long numAffectedRows = preparedStmt.executeUpdate(); + Miscellaneous.logEvent("AMOUNT OF UPDATED ROWS: " + numAffectedRows, 5); + ResultSet rs = preparedStmt.getGeneratedKeys(); +// if (numAffectedRows > 0) +// { + preparedStmt.close(); + return true; +// } + } + catch(Exception e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + finally + { + try + { + if(preparedStmt != null && !preparedStmt.isClosed()) + preparedStmt.close(); + } + catch (SQLException e) + { + } + } + + return false; + } + + public boolean delete() + { + PreparedStatement preparedStmt = null; + Connection conn = null; + try + { + conn = DatabaseHandler.getInstance().getConnection(); + + String parentQuery = "DELETE FROM listEntries WHERE listId=? AND productId=?"; + preparedStmt = conn.prepareStatement(parentQuery, Statement.RETURN_GENERATED_KEYS); + + preparedStmt.setLong(1, this.getParentList().getId()); + preparedStmt.setLong(2, this.getProduct().getId()); + + Miscellaneous.logEvent(preparedStmt.toString(), 5); + + long numAffectedRows = preparedStmt.executeUpdate(); + Miscellaneous.logEvent("AMOUNT OF UPDATED ROWS: " + numAffectedRows, 5); + ResultSet rs = preparedStmt.getGeneratedKeys(); +// if (numAffectedRows > 0) +// { + preparedStmt.close(); + return true; +// } + } + catch(Exception e) + { + Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1); + } + finally + { + try + { + if(preparedStmt != null && !preparedStmt.isClosed()) + preparedStmt.close(); + } + catch (SQLException e) + { + } + } + + return false; + } +} diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/Start.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Start.java new file mode 100644 index 0000000..ce44f1a --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/Start.java @@ -0,0 +1,228 @@ +package com.jens.rhasspy.shoppinglist; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +public class Start +{ + public static void main(String[] args) + { + String productName = null; + String action = null; + String filePath = null; + + List argsList = new ArrayList(); + List optsList = new ArrayList(); + List doubleOptsList = new ArrayList(); + for (int i=0; i < args.length; i++) + { + switch (args[i].charAt(0)) + { + case '-': + if (args[i].charAt(1) == '-') + { + int len = 0; + String argstring = args[i].toString(); + len = argstring.length(); +// System.out.println("Found double dash with command " + argstring.substring(2, len) ); + String argName = argstring.substring(2, len); + doubleOptsList.add(argName); + if(argName.equalsIgnoreCase("shoppingProduct")) + productName = args[i+1].replace("\"", ""); + else if(argName.equalsIgnoreCase("action")) + action = args[i+1].replace("\"", ""); + else if(argName.equalsIgnoreCase("filePath")) + filePath = args[i+1].replace("\"", ""); + } + else + { +// System.out.println("Found dash with command " + args[i].charAt(1) + " and value " + args[i+1] ); + i= i+1; + optsList.add(args[i]); + } + break; + default: +// System.out.println("Add a default arg." ); + argsList.add(args[i]); + break; + } + } + + Settings.readSettings(); + + if(action == null) + { + System.out.println(Settings.languageBlock.get("noActionDefined")); + } + else + { + + switch(action) + { + case "addToList": + if(!StringUtils.isEmpty(productName)) + { + ShoppingList list = ShoppingList.getMostRecentList(); + Product p = Product.getByName(productName); + + if(list == null) + exitWithError(Settings.languageBlock.get("couldNotCreateList")); + + if(p == null) + exitWithError(Settings.languageBlock.get("productNotFound") + " " + productName); + + ShoppingListEntry entry = new ShoppingListEntry(); + entry.setParentList(list); + entry.setProduct(p); + + if(entry.create()) + { + DatabaseHandler.getInstance().disconnect(); + System.exit(0); + } + else + exitWithError(Settings.languageBlock.get("couldNotAddProdToList") + " " + productName); + } + else + System.out.println(Settings.languageBlock.get("noProdSpecified")); + break; + case "removeFromList": + if(!StringUtils.isEmpty(productName)) + { + ShoppingList list = ShoppingList.getMostRecentList(); + Product p = Product.getByName(productName); + + if(list == null) + exitWithError(Settings.languageBlock.get("couldNotCreateList")); + + if(p == null) + exitWithError(Settings.languageBlock.get("productNotFound") + " " + productName); + + for(ShoppingListEntry entry : list.getEntries()) + { + if(entry.getProduct().equals(p)) + { + if(entry.delete()) + { + DatabaseHandler.getInstance().disconnect(); + System.exit(0); + } + else + Miscellaneous.logEvent(Settings.languageBlock.get("couldNotRemoveProdFromList") + " " + productName, 2); + } + } + // If it wasn't on the list - why care? + DatabaseHandler.getInstance().disconnect(); + System.exit(0); + } + else + System.out.println(Settings.languageBlock.get("noProdSpecified")); + break; + case "sendList": + if(ShoppingList.getMostRecentList().send()) + { +// System.out.println("Liste wurde verschickt."); + DatabaseHandler.getInstance().disconnect(); + System.exit(0); + } + else + System.out.println(Settings.languageBlock.get("couldNotSendList")); + break; + case "resetList": + if(ShoppingList.createNewList() != null) + { +// System.out.println("Neue Liste erstellt"); + DatabaseHandler.getInstance().disconnect(); + System.exit(0); + } + else + System.out.println(Settings.languageBlock.get("couldNotCreateNewList")); + break; + case "importProducts": + File importFile = new File(filePath); + importFile(importFile); + break; + } + } + + exitWithError(null); + } + + static void exitWithError(String errorText) + { + if(!StringUtils.isEmpty(errorText)) + { + System.out.println(errorText); + Miscellaneous.logEvent("Exiting with error: " + errorText, 1); + } + else + Miscellaneous.logEvent("Exiting with empty error.", 1); + + DatabaseHandler.getInstance().disconnect(); + System.exit(1); + } + + static boolean importFile(File importFile) + { + try + { + if(!importFile.exists()) + exitWithError("File does not exist."); + + if(!importFile.canRead()) + exitWithError("Cannot read file."); + + String fileContent = Miscellaneous.readFile(importFile).trim(); + + if(StringUtils.isEmpty(fileContent)) + exitWithError("File is empty."); + + int errorCounter = 0; + + outerLoop: + for(String line : fileContent.split(Diverse.lineSeparator)) + { + String[] synonyms = line.split(":"); + String product = synonyms[synonyms.length -1]; + + for(Product existingProduct : Product.readAllProducts()) + { + if(existingProduct.getName().equalsIgnoreCase(product)) + continue outerLoop; + } + + Product newProduct = new Product(); + newProduct.setName(product); + newProduct.setStoreType(StoreType.readAllStoreTypes().get(0)); + + if(synonyms.length > 1) + { + String syns = synonyms[0].substring(1, synonyms[0].length()-1); + syns = syns.replace("|", ";"); + newProduct.setSynonyms(syns); + } + + if(!newProduct.create()) + { + Miscellaneous.logEvent("Failed to import product " + newProduct.getName(), 1); + errorCounter++; + } + } + + if(errorCounter > 0) + System.out.println("Import complete with " + String.valueOf(errorCounter) + "."); + else + System.out.println("Import complete without errors."); + + return true; + } + catch(Exception e) + { + + } + + return false; + } +} \ No newline at end of file diff --git a/ShoppingList/src/com/jens/rhasspy/shoppinglist/StoreType.java b/ShoppingList/src/com/jens/rhasspy/shoppinglist/StoreType.java new file mode 100644 index 0000000..c9b8581 --- /dev/null +++ b/ShoppingList/src/com/jens/rhasspy/shoppinglist/StoreType.java @@ -0,0 +1,97 @@ +package com.jens.rhasspy.shoppinglist; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; + +public class StoreType +{ + long id; + String name; + + static ArrayList storeTypeCache = null; + + public static ArrayList readAllStoreTypes() + { + if(storeTypeCache == null) + { + try + { + storeTypeCache = new ArrayList(); + + Connection conn = DatabaseHandler.getInstance().getConnection(); + PreparedStatement preparedStmt = null; + + String query = "SELECT id, name FROM storeTypes"; + + preparedStmt = conn.prepareStatement(query); + + Miscellaneous.logEvent(preparedStmt.toString(), 5); + + ResultSet res = preparedStmt.executeQuery(); + + while (res.next()) + { + StoreType st = new StoreType(); + + st.setId(res.getLong("id")); + st.setName(res.getString("name")); + + storeTypeCache.add(st); + } + + res.close(); + preparedStmt.close(); + } + catch(Exception e) + { + + } + } + + return storeTypeCache; + } + + public long getId() + { + return id; + } + + public void setId(long id) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + @Override + public boolean equals(Object obj) + { + return name.equalsIgnoreCase(((StoreType)obj).getName()); + } + + @Override + public String toString() + { + return this.getName(); + } + + public static StoreType getById(long id) + { + for(StoreType st : readAllStoreTypes()) + { + if(st.getId() == id) + return st; + } + + return null; + } +}