Skip to content
Snippets Groups Projects
Commit f1fbf171 authored by Goik Martin's avatar Goik Martin
Browse files

New exercises

parent 80344b6a
No related branches found
No related tags found
No related merge requests found
Showing
with 698 additions and 0 deletions
/target/
/.settings/
.classpath
.project
A1.log
<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>
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);
}
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());
}
}
}
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);
}
}
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)];
}
}
<?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
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 );
}
}
.project
.classpath
/.settings/
/target/
A1.log
\ No newline at end of file
<?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>
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');
<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>
<?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
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();
}
}
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);
}
}
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 + '!';
}
}
}
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);
}
}
}
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
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
<?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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment