From f1fbf171c63fce59360e3bf24151dc271ef8eb27 Mon Sep 17 00:00:00 2001 From: Martin Goik <goik@hdm-stuttgart.de> Date: Fri, 19 Jun 2015 10:05:14 +0200 Subject: [PATCH] New exercises --- P/Sd1/NonsenseGenerator/.gitignore | 5 + P/Sd1/NonsenseGenerator/pom.xml | 22 +++ .../mi/nonsense/BoundedRandomGenerator.java | 20 +++ .../de/hdm_stuttgart/mi/nonsense/Driver.java | 18 +++ .../mi/nonsense/MyRandomGenerator.java | 19 +++ .../mi/nonsense/NonsenseGenerator.java | 64 ++++++++ .../src/main/resources/log4j2.xml | 21 +++ .../mi/sd1/nonsenseGenerator/AppTest.java | 15 ++ P/Sda1/catalog2rdbmsPrepare/.gitignore | 5 + .../catalog2rdbmsPrepare/Schema/catalog.xsd | 27 ++++ P/Sda1/catalog2rdbmsPrepare/Schema/schema.sql | 27 ++++ P/Sda1/catalog2rdbmsPrepare/pom.xml | 50 +++++++ P/Sda1/catalog2rdbmsPrepare/products.xml | 17 +++ .../mi/sda1/catalog2sql/DataInsert.java | 86 +++++++++++ .../mi/sda1/catalog2sql/Helper.java | 18 +++ .../mi/sda1/catalog2sql/Messages.java | 22 +++ .../mi/sda1/catalog2sql/Xml2Rdbms.java | 87 +++++++++++ .../handler/CatalogContentHandler.java | 137 ++++++++++++++++++ .../mi/sda1/catalog2sql/messages.properties | 17 +++ .../src/main/resources/log4j2.xml | 21 +++ P/pom.xml | 2 + 21 files changed, 700 insertions(+) create mode 100644 P/Sd1/NonsenseGenerator/.gitignore create mode 100644 P/Sd1/NonsenseGenerator/pom.xml create mode 100644 P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/BoundedRandomGenerator.java create mode 100644 P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/Driver.java create mode 100644 P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/MyRandomGenerator.java create mode 100644 P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/NonsenseGenerator.java create mode 100644 P/Sd1/NonsenseGenerator/src/main/resources/log4j2.xml create mode 100644 P/Sd1/NonsenseGenerator/src/test/java/de/hdm_stuttgart/mi/sd1/nonsenseGenerator/AppTest.java create mode 100644 P/Sda1/catalog2rdbmsPrepare/.gitignore create mode 100644 P/Sda1/catalog2rdbmsPrepare/Schema/catalog.xsd create mode 100644 P/Sda1/catalog2rdbmsPrepare/Schema/schema.sql create mode 100644 P/Sda1/catalog2rdbmsPrepare/pom.xml create mode 100644 P/Sda1/catalog2rdbmsPrepare/products.xml create mode 100644 P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/DataInsert.java create mode 100644 P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Helper.java create mode 100644 P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Messages.java create mode 100644 P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Xml2Rdbms.java create mode 100644 P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/handler/CatalogContentHandler.java create mode 100644 P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/messages.properties create mode 100644 P/Sda1/catalog2rdbmsPrepare/src/main/resources/log4j2.xml diff --git a/P/Sd1/NonsenseGenerator/.gitignore b/P/Sd1/NonsenseGenerator/.gitignore new file mode 100644 index 000000000..60016e96d --- /dev/null +++ b/P/Sd1/NonsenseGenerator/.gitignore @@ -0,0 +1,5 @@ +/target/ +/.settings/ +.classpath +.project +A1.log diff --git a/P/Sd1/NonsenseGenerator/pom.xml b/P/Sd1/NonsenseGenerator/pom.xml new file mode 100644 index 000000000..c3b6e8464 --- /dev/null +++ b/P/Sd1/NonsenseGenerator/pom.xml @@ -0,0 +1,22 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>de.hdm-stuttgart.mi</groupId> + <artifactId>lecturenotes-pom</artifactId> + <version>1.0</version> + + <relativePath>../../pom.xml</relativePath> + </parent> + + <groupId>de.hdm-stuttgart.mi.sd1</groupId> + <artifactId>nonsensegenerator</artifactId> + <version>0.9</version> + <packaging>jar</packaging> + + <name>Nonsensegenerator</name> + + <url>http://www.mi.hdm-stuttgart.de/freedocs</url> + +</project> diff --git a/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/BoundedRandomGenerator.java b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/BoundedRandomGenerator.java new file mode 100644 index 000000000..4da2c78ca --- /dev/null +++ b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/BoundedRandomGenerator.java @@ -0,0 +1,20 @@ +package de.hdm_stuttgart.mi.nonsense; + +/** + * A random generator providing values within a specified bound + * + */ +public interface BoundedRandomGenerator { + /** + * Create a (pseudo) random number X within the following range: + * + * 0 <= X < bound + * + * Thus specifying bound=3 will return a random value being either 0, 1 or 2. + * + * @param bound The desired upper bound (exclusive) + * + * @return A random value being limited by the bound argument. + */ + public int getRandomValue(int bound); +} diff --git a/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/Driver.java b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/Driver.java new file mode 100644 index 000000000..8bd7be887 --- /dev/null +++ b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/Driver.java @@ -0,0 +1,18 @@ +package de.hdm_stuttgart.mi.nonsense; + +/** + * A driver class for generating random sentences + * + */ +public class Driver { + + /** + * @param args unused + */ + public static void main(String[] args) { + NonsenseGenerator ng = new NonsenseGenerator(new MyRandomGenerator()); + for (int i = 1; i < 5; i++) { + System.out.println(ng.generateRandomSentence()); + } + } +} diff --git a/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/MyRandomGenerator.java b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/MyRandomGenerator.java new file mode 100644 index 000000000..6224bcbaf --- /dev/null +++ b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/MyRandomGenerator.java @@ -0,0 +1,19 @@ +package de.hdm_stuttgart.mi.nonsense; + +import java.util.Random; + +/** + * Wrapping Java's standard random generator. The purpose is just providing + * a flexible means to supply a different implementation. + * + */ +public class MyRandomGenerator implements BoundedRandomGenerator { + + final Random randomGenerator = new Random(); + + @Override + public int getRandomValue(int bound) { + return randomGenerator.nextInt(bound); + } + +} diff --git a/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/NonsenseGenerator.java b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/NonsenseGenerator.java new file mode 100644 index 000000000..8650dc705 --- /dev/null +++ b/P/Sd1/NonsenseGenerator/src/main/java/de/hdm_stuttgart/mi/nonsense/NonsenseGenerator.java @@ -0,0 +1,64 @@ +package de.hdm_stuttgart.mi.nonsense; + +/** + * + * + */ +public class NonsenseGenerator { + + /** + * Using a specified random number generator implementation. + * + * @param boundedRandomGenerator + */ + public NonsenseGenerator(final BoundedRandomGenerator boundedRandomGenerator) { + this.boundedRandomGenerator = boundedRandomGenerator; + } + + final BoundedRandomGenerator boundedRandomGenerator; + + + + private static final String[] THINGS = { "bottle", "bowl", "brick", "building", "bunny", "cake", "car", "cat", "cup", + "desk", "dog", "duck", "elephant", "engineer", "fork", "glass", "griffon", "hat", "key", "knife", "lawyer", + "llama", "manual", "meat", "monitor", "mouse", "tangerine", "paper", "pear", "pen", "pencil", "phone", + "physicist", "planet", "potato", "road", "salad", "shoe", "slipper", "soup", "spoon", "star", "steak", "table", + "terminal", "treehouse", "truck", "watermelon", "window" }; + + private static final String[] ADJECTIVES = { "red", "green", "yellow", "gray", "solid", "fierce", "friendly", + "cowardly", "convenient", "foreign", "national", "tall", "short", "metallic", "golden", "silver", "sweet", + "nationwide", "competitive", "stable", "municipal", "famous" }; + + private static final String[] VERBS_PRESENT = { "accuses", "threatens", "warns", "speaks to", "meets with", "seen with", + "advances towards", "collapses on", "signs partnership with", "converts into", "becomes", + "is authorized to sell", "sells", "buys", "rents", "allegedly speaks to", "leases", "invests on", + "expected to buy", "expected to sell", "reported to have met with", "works together with", + "plans cease fire against", "starts war with", "signs truce with", "now manages" }; + + /** + * Randomly creating a (typically nonsense) sentence. + * @return The random string. + */ + public String generateRandomSentence() { + + final StringBuffer buffer = new StringBuffer(); + buffer.append("The "); + buffer.append(choose(ADJECTIVES)); + buffer.append(" "); + buffer.append(choose(THINGS)); + buffer.append(" "); + buffer.append(choose(VERBS_PRESENT)); + buffer.append(" a "); + buffer.append(choose(THINGS)); + buffer.append("."); + + return buffer.toString(); + } + + String choose(final String[] strings) { + + return strings[boundedRandomGenerator.getRandomValue(strings.length)]; + + } + +} diff --git a/P/Sd1/NonsenseGenerator/src/main/resources/log4j2.xml b/P/Sd1/NonsenseGenerator/src/main/resources/log4j2.xml new file mode 100644 index 000000000..f149b1b40 --- /dev/null +++ b/P/Sd1/NonsenseGenerator/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.sd1.plot.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="info"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/P/Sd1/NonsenseGenerator/src/test/java/de/hdm_stuttgart/mi/sd1/nonsenseGenerator/AppTest.java b/P/Sd1/NonsenseGenerator/src/test/java/de/hdm_stuttgart/mi/sd1/nonsenseGenerator/AppTest.java new file mode 100644 index 000000000..8b1c55bdc --- /dev/null +++ b/P/Sd1/NonsenseGenerator/src/test/java/de/hdm_stuttgart/mi/sd1/nonsenseGenerator/AppTest.java @@ -0,0 +1,15 @@ +package de.hdm_stuttgart.mi.sd1.nonsenseGenerator; + +import org.junit.Assert; +import org.junit.Test; + +/** + */ +public class AppTest { + /** + */ + @Test + public void testApp() { + Assert.assertTrue( true ); + } +} diff --git a/P/Sda1/catalog2rdbmsPrepare/.gitignore b/P/Sda1/catalog2rdbmsPrepare/.gitignore new file mode 100644 index 000000000..660be2a5f --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/.gitignore @@ -0,0 +1,5 @@ +.project +.classpath +/.settings/ +/target/ +A1.log \ No newline at end of file diff --git a/P/Sda1/catalog2rdbmsPrepare/Schema/catalog.xsd b/P/Sda1/catalog2rdbmsPrepare/Schema/catalog.xsd new file mode 100644 index 000000000..9df8b8626 --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/Schema/catalog.xsd @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + + <xs:element name="catalog"> + <xs:complexType> + <xs:sequence> + <xs:element ref="product" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + <xs:key name="uniqueProductId"> + <xs:selector xpath="product"/> + <xs:field xpath="@id"/> + </xs:key> + </xs:element> + + <xs:element name="product"> + <xs:complexType> + <xs:sequence> + <xs:element name="name" type="xs:string"/> + <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="age" type="xs:int" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + <xs:attribute name="id" type="xs:int" use="required"/> + </xs:complexType> + </xs:element> + +</xs:schema> diff --git a/P/Sda1/catalog2rdbmsPrepare/Schema/schema.sql b/P/Sda1/catalog2rdbmsPrepare/Schema/schema.sql new file mode 100644 index 000000000..b4c82d7c2 --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/Schema/schema.sql @@ -0,0 +1,27 @@ +DROP TABLE IF EXISTS Description; +DROP TABLE IF EXISTS Product; + +CREATE TABLE Product ( + id INTEGER NOT NULL PRIMARY KEY + ,name VARCHAR(255) NOT NULL + ,age SMALLINT +); + +CREATE TABLE Description ( + product INTEGER NOT NULL REFERENCES Product + ,orderIndex int NOT NULL -- preserving the order of descriptions belonging to a given product + ,text VARCHAR(255) NOT NULL + ,UNIQUE(product, orderIndex) +); + +-- example data corresponding to products.xml -- + +-- Product lacking age property -- +INSERT INTO Product (id, name) VALUES (1, 'Monkey Picked Tea'); +INSERT INTO Description VALUES(1, 1, 'Picked only by specially trained monkeys'); +INSERT INTO Description VALUES(1, 2, 'Rare wild Chinese tea'); + +INSERT INTO Product VALUES (2, '4-Person Instant Tent', 15); +INSERT INTO Description VALUES(2, 0, 'Exclusive WeatherTec system.'); +INSERT INTO Description VALUES(2, 1, '4-person, 1-room tent'); +INSERT INTO Description VALUES(2, 2, 'Pre-attached tent poles'); diff --git a/P/Sda1/catalog2rdbmsPrepare/pom.xml b/P/Sda1/catalog2rdbmsPrepare/pom.xml new file mode 100644 index 000000000..b0303e6ed --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/pom.xml @@ -0,0 +1,50 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>de.hdm-stuttgart.mi</groupId> + <artifactId>lecturenotes-pom</artifactId> + <version>1.0</version> + + <relativePath>../../pom.xml</relativePath> + </parent> + + <groupId>de.hdm-stuttgart.mi.sda1</groupId> + <artifactId>catalog2rdbms</artifactId> + <version>0.8</version> + <packaging>jar</packaging> + + <name>catalog2rdbms</name> + + <url>http://www.mi.hdm-stuttgart.de/freedocs</url> + + <dependencies> + + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + <version>2.1</version> + </dependency> + + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>2.1</version> + </dependency> + + <dependency> + <groupId>de.hdm-stuttgart.mi.sda1</groupId> + <artifactId>saxerrorhandler</artifactId> + <version>0.8</version> + </dependency> + + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>5.1.34</version> + </dependency> + + </dependencies> + +</project> diff --git a/P/Sda1/catalog2rdbmsPrepare/products.xml b/P/Sda1/catalog2rdbmsPrepare/products.xml new file mode 100644 index 000000000..15000ab5d --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/products.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="Schema/catalog.xsd"> + <product id="17"> + <name>Monkey Picked Tea</name> + <description>Rare wild Chinese tea</description> + <description>Picked only by specially trained monkeys</description> + </product> + <product id="42"> + <name>4-Person Instant Tent</name> + <description>4-person, 1-room tent</description> + <description>Pre-attached tent poles</description> + <description>Exclusive WeatherTec system.</description> + <age>15</age> + </product> +</catalog> \ No newline at end of file diff --git a/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/DataInsert.java b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/DataInsert.java new file mode 100644 index 000000000..41c4a28db --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/DataInsert.java @@ -0,0 +1,86 @@ +package de.hdm_stuttgart.mi.sda1.catalog2sql; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +/** + * Formatting product related INSERT statements + * + */ +public class DataInsert { + + final Statement stmt; + + /** + * @param conn Destination RDBMS + * @throws SQLException + */ + public DataInsert(final Connection conn) throws SQLException { + conn.setAutoCommit(false); + stmt = conn.createStatement(); + } + + /** + * Create an SQL INSERT statement corresponding to a <product id='...' > entry + * lacking age specification. + * @param productId See {@link #insertproduct(String, String, int)} + * @param productName See {@link #insertproduct(String, String, int)} + */ + public void insertproduct(final String productId, final String productName) { + final String sqlInsertStmt = "INSERT INTO Product (id, name) VALUES (" + productId + ", '" + productName + "');"; + try { + stmt.executeUpdate(sqlInsertStmt); + } catch (SQLException e) { + Helper.exitWithErrorMessage("Unable to insert product without age property", 1); + + } + } + + /** + * Insert dataset corresponding to a <product id='...' > entry + * @param productId The product's unique id property + * @param productName The product's end user readable name. + * @param age The product's age + */ + public void insertproduct(final String productId, final String productName, final int age) { + + // A PreparedStatement is preferable but not yet introduced in lecture + // + final String sqlInsertStmt = "INSERT INTO Product VALUES (" + productId + ", '" + productName + "', " + age + ");"; + try { + stmt.executeUpdate(sqlInsertStmt); + } catch (SQLException e) { + Helper.exitWithErrorMessage("Unable to insert product including age property", 1); + } + } + + + /** + * Adding a description to a given product. + * + * @param productId The description belongs to this product + * @param descriptions All descriptions belonging to productId + */ + public void insertDescription(final String productId, final List<String> descriptions) { + + for (int i = 0; i < descriptions.size(); i++) { + final String sqlInsertStmt = "INSERT INTO Description VALUES('" + productId + "', " + i + ", '" + + descriptions.get(i) + "');"; + try { + stmt.executeUpdate(sqlInsertStmt); + } catch (SQLException e) { + Helper.exitWithErrorMessage("Unable to insert product description", 1); + } + } + } + /** + * Closing internal Statement instance + * @throws SQLException + */ + public void commit() throws SQLException { + stmt.getConnection().commit(); + } + +} diff --git a/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Helper.java b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Helper.java new file mode 100644 index 000000000..b59d33d53 --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Helper.java @@ -0,0 +1,18 @@ +package de.hdm_stuttgart.mi.sda1.catalog2sql; + +/** + * Project wide helper methods + * + */ +public class Helper { + /** + * Write message to stderr and exit with given error code + * @param errMsg + * @param errorCode + */ + public static void exitWithErrorMessage(final String errMsg, int errorCode) { + System.err.println(errMsg); + System.exit(errorCode); + } + +} diff --git a/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Messages.java b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Messages.java new file mode 100644 index 000000000..e68812cee --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Messages.java @@ -0,0 +1,22 @@ +package de.hdm_stuttgart.mi.sda1.catalog2sql; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class Messages { + private static final String BUNDLE_NAME = "de.hdm_stuttgart.mi.sda1.catalog2sql.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private Messages() { + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} diff --git a/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Xml2Rdbms.java b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Xml2Rdbms.java new file mode 100644 index 000000000..126cf9b59 --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/Xml2Rdbms.java @@ -0,0 +1,87 @@ +package de.hdm_stuttgart.mi.sda1.catalog2sql; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +import de.hdm_stuttgart.mi.sda1.catalog2sql.handler.CatalogContentHandler; +import de.hdm_stuttgart.mi.sda1.saxerrorhandler.handler.SaxErrorHandler; + +/** + * A simple SAX parser demo + * + */ +public class Xml2Rdbms { + private static final Logger log = LogManager.getLogger(Xml2Rdbms.class); + + /** + * @param args Unused + * @throws SAXException + * @throws ParserConfigurationException + * @throws IOException + */ + public static void main(String[] args) throws ParserConfigurationException, + SAXException, IOException { + + log.info(Messages.getString("Xml2Rdbms.0")); + final SAXParserFactory saxPf = SAXParserFactory.newInstance(); + final SAXParser saxParser = saxPf.newSAXParser(); + final XMLReader xmlReader = saxParser.getXMLReader(); + + + // Register Driver + final String sqlDriverClassName = Messages.getString("Xml2Rdbms.jdbcDriverName"); + try { + Class.forName(sqlDriverClassName); + } catch (ClassNotFoundException e) { + Helper.exitWithErrorMessage(Messages.getString("Xml2Rdbms.errMsgUnableRegisterDriverClass") + sqlDriverClassName + Messages.getString("Xml2Rdbms.3"), 1); + } + + + // Opening a JDBC connection + // + Connection conn = null; + + final String jdbcConnectionUrl = Messages.getString("Xml2Rdbms.jdbcUrl"); + final String userName = Messages.getString("Xml2Rdbms.jdbcUser"); + try { + conn = DriverManager.getConnection(jdbcConnectionUrl, userName, Messages.getString("Xml2Rdbms.jdbcPasswd")); + } catch (SQLException e) { + Helper.exitWithErrorMessage(Messages.getString("Xml2Rdbms.errMsgUnableToConnect") + userName + Messages.getString("Xml2Rdbms.8") + + jdbcConnectionUrl + Messages.getString("Xml2Rdbms.9"), 1); + } + + DataInsert dataInsert = null; + try { + dataInsert = new DataInsert(conn); + } catch (SQLException e) { + Helper.exitWithErrorMessage(Messages.getString("Xml2Rdbms.errMsgUnableInitDataInsert"), 1); + } + + log.info(Messages.getString("Xml2Rdbms.11")); + xmlReader.setContentHandler(new CatalogContentHandler(dataInsert)); + xmlReader.setErrorHandler(new SaxErrorHandler(System.err)); + + final String xmlDocumentInstanceFilename = Messages.getString("Xml2Rdbms.xmlSourceFileName"); + log.info(Messages.getString("Xml2Rdbms.13") + xmlDocumentInstanceFilename + Messages.getString("Xml2Rdbms.14")); + xmlReader.parse(xmlDocumentInstanceFilename); + + // Closing + try { + conn.close(); // Closing Connection + } catch (SQLException e) { + Helper.exitWithErrorMessage(Messages.getString("Xml2Rdbms.errMsgUnableCloseRdbms"), 1); + } + } + +} diff --git a/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/handler/CatalogContentHandler.java b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/handler/CatalogContentHandler.java new file mode 100644 index 000000000..6f1236a9d --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/handler/CatalogContentHandler.java @@ -0,0 +1,137 @@ +package de.hdm_stuttgart.mi.sda1.catalog2sql.handler; + +import java.sql.SQLException; +import java.util.List; +import java.util.Vector; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +import de.hdm_stuttgart.mi.sda1.catalog2sql.DataInsert; +import de.hdm_stuttgart.mi.sda1.catalog2sql.Helper; +import de.hdm_stuttgart.mi.sda1.catalog2sql.Messages; + +/** + * Turning XML data into SQL INSERT statements + * + */ +public class CatalogContentHandler implements ContentHandler { + private static final Logger log = LogManager.getLogger(CatalogContentHandler.class); + Locator locator = null; + + final DataInsert sqlInserter; + + private final List<String> currentDescriptions = new Vector<String>(); + + final StringBuffer currentElementContent = new StringBuffer(); + + String productId, productName, productAgeString; + + /** + * @param sqlFormatter SQL INSERT statement formatter + */ + public CatalogContentHandler(final DataInsert sqlFormatter) { + this.sqlInserter = sqlFormatter; + } + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + // Convenience Method + String displayWithLocatio(final String saxMsg) { + if (null == locator) { + return saxMsg; + } else { + return "File position (" + locator.getLineNumber() + ", " + locator.getColumnNumber() + "): " + saxMsg; + } + } + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + currentElementContent.setLength(0); + switch(qName) { + case "product": + productAgeString = null; // Value will be altered if <age> is present + productId = attributes.getValue("id"); + log.info(displayWithLocatio("Product id=" + productId)); + break; + } + } + + @Override + public void endElement(final String uri, final String localName, final String qName) + throws SAXException { + switch(qName) { + case "product": + if (null == productAgeString) { + sqlInserter.insertproduct(productId, productName); + } else { + try { + sqlInserter.insertproduct(productId, productName, Integer.parseInt(productAgeString)); + } catch (NumberFormatException ex) { + log.error("Property <age> is not of integer value:" + productAgeString); + } + } + flushDescriptionEntries(); + break; + case "name": + productName = currentElementContent.toString(); + break; + + case "description": + // Do not interfere with the current INSERT INTO Product ... + // statement. Instead postpone related INSERT INTO Description ... + // operations, see flushDescriptionEntries(). + currentDescriptions.add(currentElementContent.toString()); + break; + case "age": + productAgeString = currentElementContent.toString(); + break; + } + } + + @Override public void endDocument() throws SAXException { + try { + sqlInserter.commit(); + } catch (SQLException e) { + Helper.exitWithErrorMessage(Messages.getString("Xml2Rdbms.errMsgUnableCommitTransaction"), 1); + } + } + + private void flushDescriptionEntries() { + // Add <description> related INSERTs + sqlInserter.insertDescription(productId, currentDescriptions); + + // Next <product> may be yet to come, so + // clear the current set of descriptions. + currentDescriptions.clear(); + } + + @Override + public void characters(final char[] ch, final int start, final int length) + throws SAXException { + currentElementContent.append(new String(ch, start,length)); + } + + // We don't need these remaining callbacks + + @Override public void startDocument() throws SAXException {} + @Override public void startPrefixMapping(String prefix, String uri) + throws SAXException {} + @Override public void endPrefixMapping(String prefix) + throws SAXException {} + @Override public void ignorableWhitespace(char[] ch, int start, int length) + throws SAXException {} + + @Override public void processingInstruction(String target, String data) + throws SAXException {} + + @Override public void skippedEntity(String name) throws SAXException {} + +} \ No newline at end of file diff --git a/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/messages.properties b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/messages.properties new file mode 100644 index 000000000..1d5308c65 --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/src/main/java/de/hdm_stuttgart/mi/sda1/catalog2sql/messages.properties @@ -0,0 +1,17 @@ +Xml2Rdbms.0=Creating SAX parser +Xml2Rdbms.11=Registering content- and error handler instances +Xml2Rdbms.13=Start parsing file ' +Xml2Rdbms.14=' +Xml2Rdbms.3=' +Xml2Rdbms.8=' to ' +Xml2Rdbms.9=' +Xml2Rdbms.errMsgUnableCloseRdbms=Unable to close RDBMS access +Xml2Rdbms.errMsgUnableInitDataInsert=Unable to initialize data inserter +Xml2Rdbms.errMsgUnableRegisterDriverClass=Unable to register driver class ' +Xml2Rdbms.errMsgUnableToConnect=Unable to connect as user ' +Xml2Rdbms.jdbcDriverName=com.mysql.jdbc.Driver +Xml2Rdbms.jdbcPasswd=XYZ +Xml2Rdbms.jdbcUrl=jdbc:mysql://localhost:3306/hdm +Xml2Rdbms.jdbcUser=hdmuser +Xml2Rdbms.xmlSourceFileName=products.xml +Xml2Rdbms.errMsgUnableCommitTransaction=Unable to commit transaction \ No newline at end of file diff --git a/P/Sda1/catalog2rdbmsPrepare/src/main/resources/log4j2.xml b/P/Sda1/catalog2rdbmsPrepare/src/main/resources/log4j2.xml new file mode 100644 index 000000000..eda4f3b0d --- /dev/null +++ b/P/Sda1/catalog2rdbmsPrepare/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.sda1.catalog2sax.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="debug"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/P/pom.xml b/P/pom.xml index 63d45f4e3..062b964b2 100644 --- a/P/pom.xml +++ b/P/pom.xml @@ -75,6 +75,8 @@ <module>Sd1/Navigation/V2</module> + <module>Sd1/NonsenseGenerator</module> + <module>Sd1/plot</module> <module>Sd1/Prime/V1</module> -- GitLab