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 &lt;product id='...' &gt; 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 &lt;product id='...' &gt; 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 &lt;age&gt; 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