diff --git a/WK6/ORM_Example/ORM_Example.iml b/WK6/ORM_Example/ORM_Example.iml
new file mode 100644
index 0000000..e8eb938
--- /dev/null
+++ b/WK6/ORM_Example/ORM_Example.iml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WK6/ORM_Example/pom.xml b/WK6/ORM_Example/pom.xml
new file mode 100644
index 0000000..633d071
--- /dev/null
+++ b/WK6/ORM_Example/pom.xml
@@ -0,0 +1,87 @@
+
+ 4.0.0
+ com.origamisoftware.teach.effective
+ ORM_Example
+ jar
+ 1.0-SNAPSHOT
+ starter-app
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ -Xlint
+ ${project.build.sourceEncoding}
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+
+
+ junit
+ junit
+ 4.10
+ jar
+
+
+
+ mysql
+ mysql-connector-java
+ 5.1.6
+
+
+
+ javax.validation
+ validation-api
+ 1.0.0.GA
+
+
+
+ org.mockito
+ mockito-all
+ 1.9.5
+
+
+
+ org.apache.httpcomponents
+ httpcore
+ 4.4
+
+
+
+ org.apache.ibatis
+ ibatis-sqlmap
+ 2.3.4.726
+
+
+
+ org.hibernate
+ hibernate-core
+ 4.2.6.Final
+
+
+
+ org.hibernate.javax.persistence
+ hibernate-jpa-2.0-api
+ 1.0.1.Final
+
+
+
+
+
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/Hobby.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/Hobby.java
new file mode 100644
index 0000000..17c0f02
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/Hobby.java
@@ -0,0 +1,129 @@
+package com.origamisoftware.teach.advanced.model;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * Models the Hobby table
+ */
+@Entity
+public class Hobby {
+
+ private int id;
+ private String name;
+ private String description;
+ private int minimumAge;
+
+ /**
+ * Primary Key - Unique ID for a particular row in the hobby table.
+ *
+ * @return an integer value
+ */
+ @Id
+ @Column(name = "ID", nullable = false, insertable = true, updatable = true)
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the unique ID for a particular row in the hobby table.
+ * This method should not be called by client code. The value is managed in internally.
+ *
+ * @param id a unique value.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the name column as a String
+ */
+ @Basic
+ @Column(name = "name", nullable = false, insertable = true, updatable = true, length = 256)
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Specify the person's name
+ *
+ * @param name a String value
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ *
+ * @return the value of the description column as a String
+ */
+ @Basic
+ @Column(name = "description", nullable = false, insertable = true, updatable = true, length = 2056)
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Specify the Hobby's description
+ *
+ * @param description a String value
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * The recommended age for the hobby, an int value
+ * @return the value of the minimum_age column as an int value
+ */
+ @Basic
+ @Column(name = "minimum_age", nullable = false, insertable = true, updatable = true)
+ public int getMinimumAge() {
+ return minimumAge;
+ }
+
+ /**
+ * Specify the recommended age for the hobby
+ * @param minimumAge an int value
+ */
+ public void setMinimumAge(int minimumAge) {
+ this.minimumAge = minimumAge;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Hobby hobby = (Hobby) o;
+
+ if (id != hobby.id) return false;
+ if (minimumAge != hobby.minimumAge) return false;
+ if (description != null ? !description.equals(hobby.description) : hobby.description != null)
+ return false;
+ if (name != null ? !name.equals(hobby.name) : hobby.name != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (description != null ? description.hashCode() : 0);
+ result = 31 * result + minimumAge;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Hobby{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ ", description='" + description + '\'' +
+ ", minimumAge=" + minimumAge +
+ '}';
+ }
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/Person.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/Person.java
new file mode 100644
index 0000000..69bd94e
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/Person.java
@@ -0,0 +1,133 @@
+package com.origamisoftware.teach.advanced.model;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.sql.Timestamp;
+
+/**
+ * Models the Person table
+ */
+@Entity
+@Table(name="person")
+public class Person {
+
+ private int id;
+ private String firstName;
+ private String lastName;
+ private Timestamp birthDate;
+
+ /**
+ * Primary Key - Unique ID for a particular row in the person table.
+ *
+ * @return an integer value
+ */
+ @Id
+ @Column(name = "ID", nullable = false, insertable = true, updatable = true)
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the unique ID for a particular row in the person table.
+ * This method should not be called by client code. The value is managed in internally.
+ *
+ * @param id a unique value.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return the person's first name
+ */
+ @Basic
+ @Column(name = "first_name", nullable = false, insertable = true, updatable = true, length = 256)
+ public String getFirstName() {
+ return firstName;
+ }
+
+ /**
+ * Specify the person's first name
+ * @param firstName a String value
+ */
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ /**
+ *
+ * @return the person's last name
+ */
+ @Basic
+ @Column(name = "last_name", nullable = false, insertable = true, updatable = true, length = 256)
+ public String getLastName() {
+ return lastName;
+ }
+
+ /**
+ * Specify the person's last name
+ * @param lastName a String value
+ */
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ /**
+ *
+ * @return the person's birthdate.
+ */
+ @Basic
+ @Column(name = "birth_date", nullable = false, insertable = true, updatable = true)
+ public Timestamp getBirthDate() {
+ return birthDate;
+ }
+
+ /**
+ * Specify the person's date of birth.
+ * @param birthDate the time the person was born.
+ */
+ public void setBirthDate(Timestamp birthDate) {
+ this.birthDate = birthDate;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Person person = (Person) o;
+
+ if (id != person.id) return false;
+ if (birthDate != null ? !birthDate.equals(person.birthDate) : person.birthDate != null)
+ return false;
+ if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null)
+ return false;
+ if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id;
+ result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
+ result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
+ result = 31 * result + (birthDate != null ? birthDate.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Person{" +
+ "id=" + id +
+ ", firstName='" + firstName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", birthDate=" + birthDate +
+ '}';
+ }
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/PersonHobby.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/PersonHobby.java
new file mode 100644
index 0000000..cc4a84b
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/model/PersonHobby.java
@@ -0,0 +1,126 @@
+package com.origamisoftware.teach.advanced.model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * Models a table the combines person with their hobbies.
+ */
+@Entity
+@Table(name = "person_hobby", catalog = "activities")
+public class PersonHobby {
+ private int id;
+ private Person person;
+ private Hobby hobby;
+
+ /**
+ * Create a PersonHobby that needs to be initialized
+ */
+ public PersonHobby() {
+ // this empty constructor is required by hibernate framework
+
+ }
+
+ /**
+ * Create a valid PersonHobby
+ *
+ * @param person the person to assign the hobby to
+ * @param hobby the hobby to associate the person with
+ */
+ public PersonHobby(Person person, Hobby hobby) {
+ setHobby(hobby);
+ setPerson(person);
+ }
+
+ /**
+ * Primary Key - Unique ID for a particular row in the person_hobby table.
+ *
+ * @return an integer value
+ */
+ @Id
+ @Column(name = "ID", nullable = false, insertable = true, updatable = true)
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the unique ID for a particular row in the person_hobby table.
+ * This method should not be called by client code. The value is managed in internally.
+ *
+ * @param id a unique value.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return get the Person associated with this hobby
+ */
+ @ManyToOne
+ @JoinColumn(name = "person_id", referencedColumnName = "ID", nullable = false)
+ public Person getPerson() {
+ return person;
+ }
+
+ /**
+ * Specify the Person associated with the hobby.
+ *
+ * @param person a person instance
+ */
+ public void setPerson(Person person) {
+ this.person = person;
+ }
+
+ /**
+ *
+ * @return get the Hobby associated with this Person
+ */
+ @ManyToOne
+ @JoinColumn(name = "hobby_id", referencedColumnName = "ID", nullable = false)
+ public Hobby getHobby() {
+ return hobby;
+ }
+
+ /**
+ * Specify the Hobby associated with the Person.
+ *
+ * @param hobby a person instance
+ */
+ public void setHobby(Hobby hobby) {
+ this.hobby = hobby;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ PersonHobby that = (PersonHobby) o;
+
+ if (id != that.id) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id;
+ result = 31 * result + person.hashCode();
+ result = 31 * result + hobby.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "PersonHobby{" +
+ "id=" + id +
+ ", person=" + person +
+ ", hobby=" + hobby +
+ '}';
+ }
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesService.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesService.java
new file mode 100644
index 0000000..f25f614
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesService.java
@@ -0,0 +1,50 @@
+package com.origamisoftware.teach.advanced.service;
+
+import com.origamisoftware.teach.advanced.model.Hobby;
+import com.origamisoftware.teach.advanced.model.Person;
+
+import java.util.List;
+
+/**
+ *
+ */
+public interface ActivitiesService {
+
+ /**
+ * Get a list of all people
+ *
+ * @return a list of Person instances
+ * @throws ActivitiesServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ List getPerson() throws ActivitiesServiceException;
+
+ /**
+ * Add a new person or update an existing Person's data
+ *
+ * @param person a person object to either update or create
+ * @throws ActivitiesServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ void addOrUpdatePerson(Person person) throws ActivitiesServiceException;
+
+ /**
+ * Get a list of all a person's hobbies.
+ *
+ * @return a list of hobby instances
+ * @throws ActivitiesServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ List getHobbies(Person person) throws ActivitiesServiceException;
+
+ /**
+ * Assign a hobby to a person.
+ *
+ * @param hobby The hobby to assign
+ * @param person The person to assign the hobby too.
+ * @throws ActivitiesServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ public void addHobbyToPerson(Hobby hobby, Person person) throws ActivitiesServiceException;
+
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesServiceException.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesServiceException.java
new file mode 100644
index 0000000..216ec83
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesServiceException.java
@@ -0,0 +1,25 @@
+package com.origamisoftware.teach.advanced.service;
+
+/**
+ * Used to signal an issue with ActivitiesService
+ */
+public class ActivitiesServiceException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public ActivitiesServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesServiceFactory.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesServiceFactory.java
new file mode 100644
index 0000000..d9ac28e
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/ActivitiesServiceFactory.java
@@ -0,0 +1,21 @@
+package com.origamisoftware.teach.advanced.service;
+
+/**
+ * A factory that returns a ActivitiesService instance.
+ */
+public class ActivitiesServiceFactory {
+
+ /**
+ * Prevent instantiations
+ */
+ private ActivitiesServiceFactory() {}
+
+ /**
+ *
+ * @return get a StockService instance
+ */
+ public static ActivitiesService getInstance() {
+ return new DatabaseActivitiesService();
+ }
+
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/DatabaseActivitiesService.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/DatabaseActivitiesService.java
new file mode 100644
index 0000000..7ef016f
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/service/DatabaseActivitiesService.java
@@ -0,0 +1,152 @@
+package com.origamisoftware.teach.advanced.service;
+
+import com.origamisoftware.teach.advanced.model.Hobby;
+import com.origamisoftware.teach.advanced.model.Person;
+import com.origamisoftware.teach.advanced.model.PersonHobby;
+import com.origamisoftware.teach.advanced.util.DatabaseUtils;
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.criterion.Restrictions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ */
+public class DatabaseActivitiesService implements ActivitiesService {
+
+
+
+
+
+ /**
+ * Get a list of all people
+ *
+ * @return a list of Person instances
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public List getPerson() throws ActivitiesServiceException{
+ Session session = DatabaseUtils.getSessionFactory().openSession();
+ List returnValue = null;
+ Transaction transaction = null;
+ try {
+ transaction = session.beginTransaction();
+ Criteria criteria = session.createCriteria(Person.class);
+
+ /**
+ * NOTE criteria.list(); generates unchecked warning so SuppressWarnings
+ * is used - HOWEVER, this about the only @SuppressWarnings I think it is OK
+ * to suppress them - in almost all other cases they should be fixed not suppressed
+ */
+ returnValue = criteria.list();
+
+ } catch (HibernateException e) {
+ if (transaction != null && transaction.isActive()) {
+ transaction.rollback(); // close transaction
+ }
+ throw new ActivitiesServiceException("Could not get Person data. " + e.getMessage(), e);
+ } finally {
+ if (transaction != null && transaction.isActive()) {
+ transaction.commit();
+ }
+ }
+
+ return returnValue;
+
+ }
+
+ /**
+ * Add a new person or update an existing Person's data
+ *
+ * @param person a person object to either update or create
+ */
+ @Override
+ public void addOrUpdatePerson(Person person) {
+ Session session = DatabaseUtils.getSessionFactory().openSession();
+ Transaction transaction = null;
+ try {
+ transaction = session.beginTransaction();
+ session.saveOrUpdate(person);
+ transaction.commit();
+ } catch (HibernateException e) {
+ if (transaction != null && transaction.isActive()) {
+ transaction.rollback(); // close transaction
+ }
+ } finally {
+ if (transaction != null && transaction.isActive()) {
+ transaction.commit();
+ }
+ }
+ }
+
+ /**
+ * Get a list of all a person's hobbies.
+ *
+ * @param person the person
+ * @return a list of hobby instances
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public List getHobbies(Person person) {
+ Session session = DatabaseUtils.getSessionFactory().openSession();
+ Transaction transaction = null;
+ List hobbies = new ArrayList<>();
+ try {
+ transaction = session.beginTransaction();
+ Criteria criteria = session.createCriteria(PersonHobby.class);
+ criteria.add(Restrictions.eq("person", person));
+ /**
+ * NOTE criteria.list(); generates unchecked warning so SuppressWarnings
+ * is used - HOWEVER, this about the only @SuppressWarnings I think it is OK
+ * to suppress them - in almost all other cases they should be fixed not suppressed
+ */
+ List list = criteria.list();
+ for (PersonHobby personHobby : list) {
+ hobbies.add(personHobby.getHobby());
+ }
+ transaction.commit();
+ } catch (HibernateException e) {
+ if (transaction != null && transaction.isActive()) {
+ transaction.rollback(); // close transaction
+ }
+ } finally {
+ if (transaction != null && transaction.isActive()) {
+ transaction.commit();
+ }
+ }
+ return hobbies;
+
+ }
+
+ /**
+ * Assign a hobby to a person.
+ *
+ * @param hobby The hobby to assign
+ * @param person The person to assign the hobby too.
+ */
+ @Override
+ public void addHobbyToPerson(Hobby hobby, Person person) {
+ Session session = DatabaseUtils.getSessionFactory().openSession();
+ Transaction transaction = null;
+ try {
+ transaction = session.beginTransaction();
+ PersonHobby personHobby = new PersonHobby();
+ personHobby.setHobby(hobby);
+ personHobby.setPerson(person);
+ session.saveOrUpdate(personHobby);
+ transaction.commit();
+ } catch (HibernateException e) {
+ if (transaction != null && transaction.isActive()) {
+ transaction.rollback(); // close transaction
+ }
+ } finally {
+ if (transaction != null && transaction.isActive()) {
+ transaction.commit();
+ }
+ }
+ }
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java
new file mode 100644
index 0000000..ea8d91e
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java
@@ -0,0 +1,25 @@
+package com.origamisoftware.teach.advanced.util;
+
+/**
+ * This class is used to signal a problem connecting to a database.
+ */
+public class DatabaseConnectionException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public DatabaseConnectionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java
new file mode 100644
index 0000000..bc09f7d
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java
@@ -0,0 +1,25 @@
+package com.origamisoftware.teach.advanced.util;
+
+/**
+ * This class is used to signal a problem initializing to a database.
+ */
+public class DatabaseInitializationException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public DatabaseInitializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java
new file mode 100644
index 0000000..03f34b9
--- /dev/null
+++ b/WK6/ORM_Example/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java
@@ -0,0 +1,112 @@
+package com.origamisoftware.teach.advanced.util;
+
+import com.ibatis.common.jdbc.ScriptRunner;
+import com.origamisoftware.teach.advanced.service.DatabaseActivitiesService;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.service.ServiceRegistry;
+import org.hibernate.service.ServiceRegistryBuilder;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * A class that contains database related utility methods.
+ */
+public class DatabaseUtils {
+
+ public static final String initializationFile = "./src/main/sql/db_initialization.sql";
+
+ private static SessionFactory sessionFactory;
+ private static Configuration configuration;
+
+ /*
+ * @return SessionFactory for use with database transactions
+ */
+ public static SessionFactory getSessionFactory() {
+
+ // singleton pattern
+ synchronized (DatabaseActivitiesService.class) {
+ if (sessionFactory == null) {
+
+ Configuration configuration = getConfiguration();
+
+ ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
+ .applySettings(configuration.getProperties())
+ .buildServiceRegistry();
+
+ sessionFactory = configuration.buildSessionFactory(serviceRegistry);
+
+ }
+ }
+ return sessionFactory;
+ }
+
+ /**
+ * Create a new or return an existing database configuration object.
+ *
+ * @return a Hibernate Configuration instance.
+ */
+ private static Configuration getConfiguration() {
+
+ synchronized (DatabaseUtils.class) {
+ if (configuration == null) {
+ configuration = new Configuration();
+ configuration.configure("hibernate.cfg.xml");
+ }
+ }
+ return configuration;
+ }
+
+ public static Connection getConnection() throws DatabaseConnectionException {
+ Connection connection = null;
+ Configuration configuration = getConfiguration();
+ try {
+
+ Class.forName("com.mysql.jdbc.Driver");
+ String databaseUrl = configuration.getProperty("connection.url");
+ String username = configuration.getProperty("hibernate.connection.username");
+ String password = configuration.getProperty("hibernate.connection.password");
+ connection = DriverManager.getConnection(databaseUrl, username, password);
+
+ // an example of throwing an exception appropriate to the abstraction.
+ } catch (ClassNotFoundException | SQLException e) {
+ throw new DatabaseConnectionException("Could not connect to the database." + e.getMessage(), e);
+ }
+ return connection;
+ }
+
+ /**
+ * A utility method that runs a db initialize script.
+ *
+ * @param initializationScript full path to the script to run to create the schema
+ * @throws DatabaseInitializationException
+ */
+ public static void initializeDatabase(String initializationScript) throws DatabaseInitializationException {
+
+ Connection connection = null;
+ try {
+ connection = getConnection();
+ connection.setAutoCommit(false);
+ ScriptRunner runner = new ScriptRunner(connection, false, false);
+ InputStream inputStream = new FileInputStream(initializationScript);
+
+ InputStreamReader reader = new InputStreamReader(inputStream);
+
+ runner.runScript(reader);
+ reader.close();
+ connection.commit();
+ connection.close();
+
+ } catch (DatabaseConnectionException | SQLException | IOException e) {
+ throw new DatabaseInitializationException("Could not initialize db because of:"
+ + e.getMessage(), e);
+ }
+
+ }
+}
diff --git a/WK6/ORM_Example/src/main/resources/hibernate.cfg.xml b/WK6/ORM_Example/src/main/resources/hibernate.cfg.xml
new file mode 100644
index 0000000..c327342
--- /dev/null
+++ b/WK6/ORM_Example/src/main/resources/hibernate.cfg.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+ jdbc:mysql://localhost:3306/activities
+ com.mysql.jdbc.Driver
+ org.hibernate.dialect.MySQLDialect
+
+ monty
+ some_pass
+
+
+
+
+
+
+
+
diff --git a/WK6/ORM_Example/src/main/sql/db_initialization.sql b/WK6/ORM_Example/src/main/sql/db_initialization.sql
new file mode 100644
index 0000000..80aac40
--- /dev/null
+++ b/WK6/ORM_Example/src/main/sql/db_initialization.sql
@@ -0,0 +1,59 @@
+
+/* delete tables if they exist already - ensuring a clean db*/
+DROP TABLE IF EXISTS activities.person_hobby CASCADE;
+DROP TABLE IF EXISTS activities.hobbies CASCADE;
+DROP TABLE IF EXISTS activities.person CASCADE;
+
+
+/* creates a table to store a list of hobbies and their recommended ages */
+CREATE TABLE activities.hobbies
+(
+ ID INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ name VARCHAR(256) NOT NULL,
+ description VARCHAR(2056) NOT NULL,
+ minimum_age INT NOT NULL
+);
+
+/** creates a table to store a list of people */
+CREATE TABLE activities.person
+(
+ ID INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ first_name VARCHAR(256) NOT NULL,
+ last_name VARCHAR(256) NOT NULL,
+ birth_date DATETIME NOT NULL
+);
+
+/** A list of people and their hobbies */
+CREATE TABLE activities.person_hobby
+(
+ ID INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ person_id INT NOT NULL,
+ hobbie_id INT NOT NULL,
+ FOREIGN KEY (person_id) REFERENCES person (ID),
+ FOREIGN KEY (hobbie_id) REFERENCES hobbies (ID)
+);
+
+/** now add some sample data */
+
+INSERT INTO activities.hobbies (name,description,minimum_age) VALUES ('board games', 'assorted board games like monopoly', 8);
+INSERT INTO activities.hobbies (name,description,minimum_age) VALUES ('chess', 'ancient strategy game', 5);
+INSERT INTO activities.hobbies (name,description,minimum_age) VALUES ('go', 'ancient strategy game', 5);
+INSERT INTO activities.hobbies (name,description,minimum_age) VALUES ('archery', 'shot arrows with a bow', 12);
+INSERT INTO activities.hobbies (name,description,minimum_age) VALUES ('alpine skiing', 'recreation of sliding down snow-covered hills on skis with fixed-heel bindings', 2);
+INSERT INTO activities.hobbies (name,description,minimum_age) VALUES ('snow shoeing', 'traverse snow wearing large funny shoes', 6);
+INSERT INTO activities.hobbies (name,description,minimum_age) VALUES ('stamp collecting', 'collect rare and unusual postage stamps', 6);
+
+INSERT INTO activities.person (first_name,last_name,birth_date) VALUES ('Drew', 'Hope', '1999/10/10');
+INSERT INTO activities.person (first_name,last_name,birth_date) VALUES ('Lang', 'Heckman', '1959/11/11');
+INSERT INTO activities.person (first_name,last_name,birth_date) VALUES ('Lucy', 'Jones', '2010/1/1');
+INSERT INTO activities.person (first_name,last_name,birth_date) VALUES ('Stew', 'Hammer', '1990/3/28');
+INSERT INTO activities.person (first_name,last_name,birth_date) VALUES ('Dan', 'Lane', '1986/4/18');
+
+INSERT INTO activities.person_hobby (ID, person_id, hobbie_id) VALUES (1, 1, 2);
+INSERT INTO activities.person_hobby (ID, person_id, hobbie_id) VALUES (2, 1, 1);
+INSERT INTO activities.person_hobby (ID, person_id, hobbie_id) VALUES (3, 2, 1);
+INSERT INTO activities.person_hobby (ID, person_id, hobbie_id) VALUES (4, 3, 1);
+INSERT INTO activities.person_hobby (ID, person_id, hobbie_id) VALUES (5, 3, 3);
+INSERT INTO activities.person_hobby (ID, person_id, hobbie_id) VALUES (6, 3, 4);
+INSERT INTO activities.person_hobby (ID, person_id, hobbie_id) VALUES (7, 4, 7);
+
diff --git a/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/HobbyTest.java b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/HobbyTest.java
new file mode 100644
index 0000000..0b6b406
--- /dev/null
+++ b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/HobbyTest.java
@@ -0,0 +1,41 @@
+package com.origamisoftware.teach.advanced.model;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit test for Hobby class
+ */
+public class HobbyTest {
+
+ final static String description = "ride on a skateboard";
+ final static int minimumAge = 10;
+ final static String hobbyName = "SkateBoarding";
+
+ /**
+ * Testing helper method for generating Hobby test data
+ *
+ * @return a Hobby object that uses static constants for data.
+ */
+ public static Hobby createHobby() {
+ Hobby hobby = new Hobby();
+ hobby.setDescription(description);
+ hobby.setMinimumAge(minimumAge);
+ hobby.setName(hobbyName);
+ return hobby;
+ }
+
+ @Test
+ public void testHobbySettersAndGetters() {
+ Hobby hobby = createHobby();
+ int id = 10;
+ hobby.setId(id);
+ assertEquals("Minimum age", minimumAge, hobby.getMinimumAge());
+ assertEquals("Description", description, hobby.getDescription());
+ assertEquals("Name", hobbyName, hobby.getName());
+ assertEquals("id", id, hobby.getId());
+
+ }
+
+}
diff --git a/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/PersonHobbyTest.java b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/PersonHobbyTest.java
new file mode 100644
index 0000000..b8e7223
--- /dev/null
+++ b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/PersonHobbyTest.java
@@ -0,0 +1,72 @@
+package com.origamisoftware.teach.advanced.model;
+
+import org.junit.Test;
+
+import java.sql.Timestamp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit test for PersonHobby class
+ */
+public class PersonHobbyTest {
+
+ /**
+ * Testing helper method for generating PersonHobby test data
+ *
+ * @return a PersonHobby object that uses Person and Hobby
+ * return from their respective create method.
+ */
+ public static PersonHobby createPersonHobby() {
+ Person person = PersonTest.createPerson();
+ Hobby hobby = HobbyTest.createHobby();
+ return new PersonHobby(person, hobby);
+ }
+
+ @Test
+ public void testPersonHobbiesGetterAndSetters() {
+ Hobby hobby = HobbyTest.createHobby();
+ Person person = PersonTest.createPerson();
+ PersonHobby personHobby = new PersonHobby();
+ int id = 10;
+ personHobby.setId(id);
+ personHobby.setPerson(person);
+ personHobby.setHobby(hobby);
+ assertEquals("person matches", person, personHobby.getPerson());
+ assertEquals("hobby matches", hobby, personHobby.getHobby());
+ assertEquals("id matches", id, personHobby.getId());
+ }
+
+ @Test
+ public void testEqualsNegativeDifferentPerson() {
+ PersonHobby personHobby = createPersonHobby();
+ personHobby.setId(10);
+ Hobby hobby = HobbyTest.createHobby();
+ Person person = new Person();
+ Timestamp birthDate = new Timestamp(PersonTest.birthDayCalendar.getTimeInMillis() + 10000);
+ person.setBirthDate(birthDate);
+ person.setFirstName(PersonTest.firstName);
+ person.setLastName(PersonTest.lastName);
+ PersonHobby personHobby2 = new PersonHobby(person, hobby);
+ assertFalse("Different person", personHobby.equals(personHobby2));
+ }
+
+ @Test
+ public void testEquals() {
+ PersonHobby personHobby = createPersonHobby();
+ assertTrue("Same objects are equal", personHobby.equals(createPersonHobby()));
+ }
+
+ @Test
+ public void testToString() {
+ PersonHobby personHobby = createPersonHobby();
+ assertTrue("toString has lastName", personHobby.toString().contains(PersonTest.lastName));
+ assertTrue("toString has person", personHobby.toString().contains(PersonTest.firstName));
+ assertTrue("toString has hobby description", personHobby.toString().contains(HobbyTest.description));
+ assertTrue("toString has hobby name", personHobby.toString().contains(HobbyTest.hobbyName));
+ assertTrue("toString has hobby min age", personHobby.toString().contains(Integer.toString(HobbyTest.minimumAge)));
+ }
+
+}
diff --git a/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/PersonTest.java b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/PersonTest.java
new file mode 100644
index 0000000..6ec0aaa
--- /dev/null
+++ b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/model/PersonTest.java
@@ -0,0 +1,50 @@
+package com.origamisoftware.teach.advanced.model;
+
+import org.junit.Test;
+
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit test for the Person class
+ */
+public class PersonTest {
+
+ public static final Calendar birthDayCalendar = Calendar.getInstance();
+
+ static {
+ birthDayCalendar.set(1990, Calendar.JANUARY, 12);
+ }
+
+ public static final String firstName = "Spencer";
+ public static final String lastName = "Marks";
+ public static final Timestamp birthDate = new Timestamp(birthDayCalendar.getTimeInMillis());
+
+ /**
+ * Testing helper method for generating Person test data
+ *
+ * @return a Person object that uses static constants for data.
+ */
+ public static Person createPerson() {
+ Person person = new Person();
+ person.setBirthDate(birthDate);
+ person.setFirstName(firstName);
+ person.setLastName(lastName);
+ return person;
+ }
+
+ @Test
+ public void testPersonGettersAndSetters() {
+ Person person = createPerson();
+ int id = 10;
+ person.setId(id);
+ assertEquals("first name matches", firstName, person.getFirstName());
+ assertEquals("last name matches", lastName, person.getLastName());
+ assertEquals("birthday matches", birthDate, person.getBirthDate());
+ assertEquals("id matches", id, person.getId());
+
+ }
+
+}
diff --git a/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/services/ActivitiesServiceFactoryTest.java b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/services/ActivitiesServiceFactoryTest.java
new file mode 100644
index 0000000..5807920
--- /dev/null
+++ b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/services/ActivitiesServiceFactoryTest.java
@@ -0,0 +1,19 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.service.ActivitiesService;
+import com.origamisoftware.teach.advanced.service.ActivitiesServiceFactory;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * JUnit test for activitiesService
+ */
+public class ActivitiesServiceFactoryTest {
+
+ @Test
+ public void testFactory() {
+ ActivitiesService instance = ActivitiesServiceFactory.getInstance();
+ assertNotNull("Make sure factory works", instance);
+ }
+}
diff --git a/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseActivitiesServiceTest.java b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseActivitiesServiceTest.java
new file mode 100644
index 0000000..1e50efb
--- /dev/null
+++ b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseActivitiesServiceTest.java
@@ -0,0 +1,103 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.Hobby;
+import com.origamisoftware.teach.advanced.model.Person;
+import com.origamisoftware.teach.advanced.model.PersonTest;
+import com.origamisoftware.teach.advanced.service.ActivitiesService;
+import com.origamisoftware.teach.advanced.service.ActivitiesServiceException;
+import com.origamisoftware.teach.advanced.service.ActivitiesServiceFactory;
+import com.origamisoftware.teach.advanced.util.DatabaseUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests for the DatabaseActivitiesService
+ */
+public class DatabaseActivitiesServiceTest {
+
+ private ActivitiesService activitiesService;
+
+ private void initDb() throws Exception {
+ DatabaseUtils.initializeDatabase(DatabaseUtils.initializationFile);
+ }
+
+ // do not assume db is correct
+ @Before
+ public void setUp() throws Exception {
+ // we could also copy db state here for later restore before initializing
+ initDb();
+ activitiesService = ActivitiesServiceFactory.getInstance();
+ }
+
+ // clean up after ourselves. (this could also restore db from initial state
+ @After
+ public void tearDown() throws Exception {
+ initDb();
+ }
+
+ @Test
+ public void testGetInstance() {
+ assertNotNull("Make sure activitiesService is available", activitiesService);
+ }
+
+ @Test
+ public void testGetPerson() throws ActivitiesServiceException {
+ List personList = activitiesService.getPerson();
+ assertFalse("Make sure we get some Person objects from service", personList.isEmpty());
+ }
+
+ @Test
+ public void testAddOrUpdatePerson()throws ActivitiesServiceException {
+ Person newPerson = PersonTest.createPerson();
+ activitiesService.addOrUpdatePerson(newPerson);
+ List personList = activitiesService.getPerson();
+ boolean found = false;
+ for (Person person : personList) {
+ Timestamp returnedBirthDate = person.getBirthDate();
+ Calendar returnCalendar = Calendar.getInstance();
+ returnCalendar.setTimeInMillis(returnedBirthDate.getTime());
+ if (returnCalendar.get(Calendar.MONTH) == PersonTest.birthDayCalendar.get(Calendar.MONTH)
+ &&
+ returnCalendar.get(Calendar.YEAR) == PersonTest.birthDayCalendar.get(Calendar.YEAR)
+ &&
+ returnCalendar.get(Calendar.DAY_OF_MONTH) == PersonTest.birthDayCalendar.get(Calendar.DAY_OF_MONTH)
+ &&
+ person.getLastName().equals(PersonTest.lastName)
+ &&
+ person.getFirstName().equals(PersonTest.firstName)) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue("Found the person we added", found);
+ }
+
+ @Test
+ public void testGetHobbiesByPerson() throws ActivitiesServiceException {
+ Person person = PersonTest.createPerson();
+ List hobbies = activitiesService.getHobbies(person);
+ // make the person have all the hobbies
+ for (Hobby hobby : hobbies) {
+ activitiesService.addHobbyToPerson(hobby, person);
+ }
+ List hobbyList = activitiesService.getHobbies(person);
+ for (Hobby hobby : hobbies) {
+ boolean removed = hobbyList.remove(hobby);
+ assertTrue("Verify that the hobby was found on the list", removed);
+ }
+ // if hobbyList is empty then we know the lists matched.
+ assertTrue("Verify the list of returned hobbies match what was expected ", hobbyList.isEmpty());
+
+ }
+
+
+}
diff --git a/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java
new file mode 100644
index 0000000..06e08d2
--- /dev/null
+++ b/WK6/ORM_Example/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java
@@ -0,0 +1,39 @@
+package com.origamisoftware.teach.advanced.util;
+
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.Statement;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for the DatabaseUtils class
+ */
+public class DatabaseUtilsTest {
+
+ @Test
+ public void testGoodInitFile() throws Exception {
+ DatabaseUtils.initializeDatabase(DatabaseUtils.initializationFile);
+ }
+
+ @Test(expected = DatabaseInitializationException.class)
+ public void testBadInitFile() throws Exception {
+ DatabaseUtils.initializeDatabase("bogus");
+ }
+
+ @Test
+ public void testGetConnection() throws Exception{
+ Connection connection = DatabaseUtils.getConnection();
+ assertNotNull("verify that we can get a connection ok",connection);
+ }
+
+ @Test
+ public void testGetConnectionWorks() throws Exception{
+ Connection connection = DatabaseUtils.getConnection();
+ Statement statement = connection.createStatement();
+ boolean execute = statement.execute("select * from person");
+ assertTrue("verify that we can execute a statement",execute);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/lib/antlr-2.7.7.jar b/WK6/stockquote-week5-solved/lib/antlr-2.7.7.jar
new file mode 100644
index 0000000..5e5f14b
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/antlr-2.7.7.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/byte-buddy-1.8.17.jar b/WK6/stockquote-week5-solved/lib/byte-buddy-1.8.17.jar
new file mode 100644
index 0000000..45d3a29
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/byte-buddy-1.8.17.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/classmate-1.3.4.jar b/WK6/stockquote-week5-solved/lib/classmate-1.3.4.jar
new file mode 100644
index 0000000..5be6d99
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/classmate-1.3.4.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/dom4j-1.6.1.jar b/WK6/stockquote-week5-solved/lib/dom4j-1.6.1.jar
new file mode 100644
index 0000000..c8c4dbb
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/dom4j-1.6.1.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/hibernate-commons-annotations-5.0.4.Final.jar b/WK6/stockquote-week5-solved/lib/hibernate-commons-annotations-5.0.4.Final.jar
new file mode 100644
index 0000000..4fa4af3
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/hibernate-commons-annotations-5.0.4.Final.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/hibernate-core-5.3.6.Final.jar b/WK6/stockquote-week5-solved/lib/hibernate-core-5.3.6.Final.jar
new file mode 100644
index 0000000..df45bf4
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/hibernate-core-5.3.6.Final.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/jandex-2.0.5.Final.jar b/WK6/stockquote-week5-solved/lib/jandex-2.0.5.Final.jar
new file mode 100644
index 0000000..fb9c235
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/jandex-2.0.5.Final.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javassist-3.23.1-GA.jar b/WK6/stockquote-week5-solved/lib/javassist-3.23.1-GA.jar
new file mode 100644
index 0000000..fe85fd1
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javassist-3.23.1-GA.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.activation-api-1.2.0.jar b/WK6/stockquote-week5-solved/lib/javax.activation-api-1.2.0.jar
new file mode 100644
index 0000000..986c365
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.activation-api-1.2.0.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.annotation.jar b/WK6/stockquote-week5-solved/lib/javax.annotation.jar
new file mode 100644
index 0000000..52dca7f
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.annotation.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.ejb.jar b/WK6/stockquote-week5-solved/lib/javax.ejb.jar
new file mode 100644
index 0000000..4ebf5ec
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.ejb.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.jms.jar b/WK6/stockquote-week5-solved/lib/javax.jms.jar
new file mode 100644
index 0000000..d31451a
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.jms.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.persistence-api-2.2.jar b/WK6/stockquote-week5-solved/lib/javax.persistence-api-2.2.jar
new file mode 100644
index 0000000..164ef3a
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.persistence-api-2.2.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.persistence.jar b/WK6/stockquote-week5-solved/lib/javax.persistence.jar
new file mode 100644
index 0000000..21d80e0
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.persistence.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.resource.jar b/WK6/stockquote-week5-solved/lib/javax.resource.jar
new file mode 100644
index 0000000..696a234
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.resource.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.servlet.jar b/WK6/stockquote-week5-solved/lib/javax.servlet.jar
new file mode 100644
index 0000000..0519e4a
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.servlet.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.servlet.jsp.jar b/WK6/stockquote-week5-solved/lib/javax.servlet.jsp.jar
new file mode 100644
index 0000000..9c0631c
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.servlet.jsp.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.servlet.jsp.jstl.jar b/WK6/stockquote-week5-solved/lib/javax.servlet.jsp.jstl.jar
new file mode 100644
index 0000000..7be17cc
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.servlet.jsp.jstl.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/javax.transaction.jar b/WK6/stockquote-week5-solved/lib/javax.transaction.jar
new file mode 100644
index 0000000..729c695
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/javax.transaction.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/jboss-logging-3.3.2.Final.jar b/WK6/stockquote-week5-solved/lib/jboss-logging-3.3.2.Final.jar
new file mode 100644
index 0000000..67cde71
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/jboss-logging-3.3.2.Final.jar differ
diff --git a/WK6/stockquote-week5-solved/lib/jboss-transaction-api_1.2_spec-1.1.1.Final.jar b/WK6/stockquote-week5-solved/lib/jboss-transaction-api_1.2_spec-1.1.1.Final.jar
new file mode 100644
index 0000000..627f7ce
Binary files /dev/null and b/WK6/stockquote-week5-solved/lib/jboss-transaction-api_1.2_spec-1.1.1.Final.jar differ
diff --git a/WK6/stockquote-week5-solved/pom.xml b/WK6/stockquote-week5-solved/pom.xml
new file mode 100644
index 0000000..ed7ce3c
--- /dev/null
+++ b/WK6/stockquote-week5-solved/pom.xml
@@ -0,0 +1,88 @@
+
+ 4.0.0
+ com.origamisoftware.teach.effective
+ week-5-stock-ticker
+ jar
+ 1.0-SNAPSHOT
+ starter-app
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ -Xlint
+ ${project.build.sourceEncoding}
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+
+
+ junit
+ junit
+ 4.10
+ jar
+
+
+
+ mysql
+ mysql-connector-java
+ 5.1.6
+
+
+
+ javax.validation
+ validation-api
+ 1.0.0.GA
+
+
+
+ org.mockito
+ mockito-all
+ 1.9.5
+
+
+
+ org.apache.httpcomponents
+ httpcore
+ 4.4
+
+
+
+ org.apache.ibatis
+ ibatis-sqlmap
+ 2.3.4.726
+
+
+ org.jboss.shrinkwrap
+ shrinkwrap-api
+ 1.2.6
+
+
+ org.codehaus.plexus
+ plexus-component-annotations
+ 1.6
+
+
+ org.jboss.arquillian.config
+ arquillian-config-api
+ 1.4.0.Final
+
+
+
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.java
new file mode 100644
index 0000000..c1bb4c2
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.java
@@ -0,0 +1,150 @@
+package com.origamisoftware.teach.advanced.apps.stockquote;
+
+import com.origamisoftware.teach.advanced.model.StockQuery;
+import com.origamisoftware.teach.advanced.model.StockQuote;
+import com.origamisoftware.teach.advanced.services.StockService;
+import com.origamisoftware.teach.advanced.services.StockServiceException;
+import com.origamisoftware.teach.advanced.services.ServiceFactory;
+import com.origamisoftware.teach.advanced.util.Interval;
+
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * A simple application that shows the StockService in action.
+ */
+public class BasicStockQuoteApplication {
+
+ private StockService stockService;
+
+ // an example of how to use enum - not part of assignment 3 but useful for assignment 4
+
+ /**
+ * An enumeration that indicates how the program terminates (ends)
+ */
+ private enum ProgramTerminationStatusEnum {
+
+ // for now, we just have normal or abnormal but could more specific ones as needed.
+ NORMAL(0),
+ ABNORMAL(-1);
+
+ // when the program exits, this value will be reported to underlying OS
+ private int statusCode;
+
+ /**
+ * Create a new ProgramTerminationStatusEnum
+ *
+ * @param statusCodeValue the value to return the OS. A value of 0
+ * indicates success or normal termination.
+ * non 0 numbers indicate abnormal termination.
+ */
+ private ProgramTerminationStatusEnum(int statusCodeValue) {
+ this.statusCode = statusCodeValue;
+ }
+
+ /**
+ * @return The value sent to OS when the program ends.
+ */
+ private int getStatusCode() {
+ return statusCode;
+ }
+ }
+
+ /**
+ * Create a new Application.
+ *
+ * @param stockService the StockService this application instance should use for
+ * stock queries.
+ *
+ * NOTE: this is a example of Dependency Injection in action.
+ */
+ public BasicStockQuoteApplication(StockService stockService) {
+ this.stockService = stockService;
+ }
+
+ /**
+ * Given a stockQuery get back a the info about the stock to display to th user.
+ *
+ * @param stockQuery the stock to get data for.
+ * @return a String with the stock data in it.
+ * @throws StockServiceException If data about the stock can't be retrieved. This is a
+ * fatal error.
+ */
+ public String displayStockQuotes(StockQuery stockQuery) throws StockServiceException {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ List stockQuotes =
+ stockService.getQuote(stockQuery.getSymbol(),
+ stockQuery.getFrom(),
+ stockQuery.getUntil(),
+ Interval.DAY); // get one quote for each day in the from until date range.
+
+ stringBuilder.append("Stock quotes for: " + stockQuery.getSymbol() + "\n");
+ for (StockQuote stockQuote : stockQuotes) {
+ stringBuilder.append(stockQuote.toString());
+ }
+
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Terminate the application.
+ *
+ * @param statusCode an enum value that indicates if the program terminated ok or not.
+ * @param diagnosticMessage A message to display to the user when the program ends.
+ * This should be an error message in the case of abnormal termination
+ *
+ * NOTE: This is an example of DRY in action.
+ * A program should only have one exit point. This makes it easy to do any clean up
+ * operations before a program quits from just one place in the code.
+ * It also makes for a consistent user experience.
+ */
+ private static void exit(ProgramTerminationStatusEnum statusCode, String diagnosticMessage) {
+ if (statusCode == ProgramTerminationStatusEnum.NORMAL) {
+ System.out.println(diagnosticMessage);
+ } else if (statusCode == ProgramTerminationStatusEnum.ABNORMAL) {
+ System.err.println(diagnosticMessage);
+ } else {
+ throw new IllegalStateException("Unknown ProgramTerminationStatusEnum.");
+ }
+ System.exit(statusCode.getStatusCode());
+ }
+
+ /**
+ * Run the StockTicker application.
+ *
+ *
+ * @param args one or more stock symbols
+ */
+ public static void main(String[] args) {
+
+ // be optimistic init to positive values
+ ProgramTerminationStatusEnum exitStatus = ProgramTerminationStatusEnum.NORMAL;
+ String programTerminationMessage = "Normal program termination.";
+ if (args.length != 3) {
+ exit(ProgramTerminationStatusEnum.ABNORMAL,
+ "Please supply 3 arguments a stock symbol, a start date (MM/DD/YYYY) and end date (MM/DD/YYYY)");
+ }
+ try {
+
+ StockQuery stockQuery = new StockQuery(args[0], args[1], args[2]);
+ StockService stockService = ServiceFactory.getStockServiceInstance();
+ BasicStockQuoteApplication basicStockQuoteApplication =
+ new BasicStockQuoteApplication(stockService);
+ basicStockQuoteApplication.displayStockQuotes(stockQuery);
+
+ } catch (ParseException e) {
+ exitStatus = ProgramTerminationStatusEnum.ABNORMAL;
+ programTerminationMessage = "Invalid date data: " + e.getMessage();
+ } catch (StockServiceException e) {
+ exitStatus = ProgramTerminationStatusEnum.ABNORMAL;
+ programTerminationMessage = "StockService failed: " + e.getMessage();
+ } catch (Throwable t) {
+ exitStatus = ProgramTerminationStatusEnum.ABNORMAL;
+ programTerminationMessage = "General application error: " + t.getMessage();
+ }
+
+ exit(exitStatus, programTerminationMessage);
+ System.out.println("Oops could not parse a date");
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Person.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Person.java
new file mode 100644
index 0000000..fd1d977
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Person.java
@@ -0,0 +1,140 @@
+package com.origamisoftware.teach.advanced.model;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.sql.Timestamp;
+
+/**
+ * Models the Person table
+ */
+@Entity
+@Table(name="person")
+public class Person {
+
+ private int id;
+ private String firstName;
+ private String lastName;
+ private Timestamp birthDate;
+
+ public Person(String firstName, String lastName, Timestamp birthDay) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.birthDate = birthDay;
+ }
+ public Person(){}
+
+ /**
+ * Primary Key - Unique ID for a particular row in the person table.
+ *
+ * @return an integer value
+ */
+ @Id
+ @Column(name = "ID", nullable = false, insertable = true, updatable = true)
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the unique ID for a particular row in the person table.
+ * This method should not be called by client code. The value is managed in internally.
+ *
+ * @param id a unique value.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return the person's first name
+ */
+ @Basic
+ @Column(name = "first_name", nullable = false, insertable = true, updatable = true, length = 256)
+ public String getFirstName() {
+ return firstName;
+ }
+
+ /**
+ * Specify the person's first name
+ * @param firstName a String value
+ */
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ /**
+ *
+ * @return the person's last name
+ */
+ @Basic
+ @Column(name = "last_name", nullable = false, insertable = true, updatable = true, length = 256)
+ public String getLastName() {
+ return lastName;
+ }
+
+ /**
+ * Specify the person's last name
+ * @param lastName a String value
+ */
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ /**
+ *
+ * @return the person's birthdate.
+ */
+ @Basic
+ @Column(name = "birth_date", nullable = false, insertable = true, updatable = true)
+ public Timestamp getBirthDate() {
+ return birthDate;
+ }
+
+ /**
+ * Specify the person's date of birth.
+ * @param birthDate the time the person was born.
+ */
+ public void setBirthDate(Timestamp birthDate) {
+ this.birthDate = birthDate;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Person person = (Person) o;
+
+ if (id != person.id) return false;
+ if (birthDate != null ? !birthDate.equals(person.birthDate) : person.birthDate != null)
+ return false;
+ if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null)
+ return false;
+ if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id;
+ result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
+ result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
+ result = 31 * result + (birthDate != null ? birthDate.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Person{" +
+ "id=" + id +
+ ", firstName='" + firstName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", birthDate=" + birthDate +
+ '}';
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Person_Quotes.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Person_Quotes.java
new file mode 100644
index 0000000..2d00e4c
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Person_Quotes.java
@@ -0,0 +1,127 @@
+package com.origamisoftware.teach.advanced.model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * Models a table that combines person with their quotes.
+ */
+@Entity
+@Table(name = "person_quotes", catalog = "stocks")
+public class Person_Quotes {
+ private int id;
+ private Person person;
+ private Quotes quotes;
+
+ /**
+ * Create a Person_Quotes that needs to be initialized
+ */
+ public Person_Quotes() {
+ // this empty constructor is required by hibernate framework
+
+ }
+
+ /**
+ * Create a valid Person_Quotes
+ *
+ * @param person the person to assign the quotes to
+ * @param quotes the quotes to associate the person with
+ */
+ public Person_Quotes(Person person, Quotes quotes) {
+ setQuotes(quotes);
+ setPerson(person);
+ }
+
+ /**
+ * Primary Key - Unique ID for a particular row in the person_hobby table.
+ *
+ * @return an integer value
+ */
+ @Id
+ @Column(name = "ID", nullable = false, insertable = true, updatable = true)
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the unique ID for a particular row in the person_hobby table.
+ * This method should not be called by client code. The value is managed in internally.
+ *
+ * @param id a unique value.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return get the Person associated with this hobby
+ */
+ @ManyToOne
+ @JoinColumn(name = "person_id", referencedColumnName = "ID", nullable = false)
+ public Person getPerson() {
+ return person;
+ }
+
+ /**
+ * Specify the Person associated with the hobby.
+ *
+ * @param person a person instance
+ */
+ public void setPerson(Person person) {
+ this.person = person;
+ }
+
+ /**
+ *
+ * @return get the quotes associated with this Person
+ */
+ @ManyToOne
+ @JoinColumn(name = "quotes_id", referencedColumnName = "ID", nullable = false)
+ public Quotes getQuotes() {
+ return quotes;
+ }
+
+ /**
+ * Specify the quotes associated with the Person.
+ *
+ * @param quotes a person instance
+ */
+ public void setQuotes(Quotes quotes) {
+ this.quotes = quotes;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Person_Quotes that = (Person_Quotes) o;
+
+ if (id != that.id) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id;
+ result = 31 * result + person.hashCode();
+ result = 31 * result + quotes.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Person_Quotes{" +
+ "id=" + id +
+ ", person=" + person +
+ ", quotes=" + quotes +
+ '}';
+ }
+}
+
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Quotes.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Quotes.java
new file mode 100644
index 0000000..038a3e9
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/Quotes.java
@@ -0,0 +1,127 @@
+package com.origamisoftware.teach.advanced.model;
+
+import javax.persistence.*;
+import java.sql.Timestamp;
+
+/**
+ * Models the quotes table
+ */
+@Entity
+@Table(name="quotes")
+public class Quotes {
+
+ private int id;
+ private String symbol;
+ private Timestamp time;
+ private int price;
+
+ public Quotes(String symbol, int price, Timestamp time) {
+ }
+ public Quotes(){}
+ /**
+ * Primary Key - Unique ID for a particular row in the quotes table.
+ *
+ * @return an integer value
+ */
+ @Id
+ @Column(name = "ID", nullable = false, insertable = true, updatable = true)
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the unique ID for a particular row in the quotes table.
+ * This method should not be called by client code. The value is managed in internally.
+ *
+ * @param id a unique value.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the symbol column as a String
+ */
+ @Basic
+ @Column(name = "symbol", nullable = false, insertable = true, updatable = true, length = 256)
+ public String getSymbol() {
+ return symbol;
+ }
+
+ /**
+ * Specify the stocks symbol
+ *
+ * @param name a String value
+ */
+ public void setSymbol(String name) {
+ this.symbol = name;
+ }
+
+ @Basic
+ @Column(name = "time", nullable = false, insertable = true, updatable = true)
+ public Timestamp getTime() {
+ return time;
+ }
+
+ /**
+ * Specify the stocks date range.
+ * @param time the time the person was born.
+ */
+ public void setTime(Timestamp time) {
+ this.time = time;
+ }
+
+ /**
+ * The price for the stock, an int value
+ * @return the value of the price column as an int value
+ */
+ @Basic
+ @Column(name = "price", nullable = false, insertable = true, updatable = true)
+ public int getPrice() {
+ return price;
+ }
+
+ /**
+ * Specify the recommended $ amount for the price
+ * @param price an int value
+ */
+ public void setPrice(int price) {
+ this.price = price;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Quotes quotes = (Quotes) o;
+
+ if (id != quotes.id) return false;
+ if (time != null ? !time.equals(quotes.time) : quotes.time != null)
+ return false;
+ if (symbol != null ? !symbol.equals(quotes.symbol) : quotes.symbol != null)
+ return false;
+ if (price != quotes.price) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id;
+ result = 31 * result + (symbol != null ? symbol.hashCode() : 0);
+ result = 31 * result + (time != null ? time.hashCode() : 0);
+ result = 31 * result + price;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Quotes{" +
+ "id=" + id +
+ ", symbol='" + symbol + '\'' +
+ ", time='" + time + '\'' +
+ ", price=" + price +
+ '}';
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockData.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockData.java
new file mode 100644
index 0000000..9d94f5b
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockData.java
@@ -0,0 +1,27 @@
+package com.origamisoftware.teach.advanced.model;
+
+import java.text.SimpleDateFormat;
+
+/**
+ * Abstract Base class for classes that hold Stock data.
+ * Provides common code for such classes including date formatting.
+ */
+public abstract class StockData {
+
+ /**
+ * Provide a single SimpleDateFormat for consistency
+ * and to avoid duplicated code.
+ */
+ protected SimpleDateFormat simpleDateFormat;
+
+ public static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
+
+ /**
+ * Base constructor for StockData classes.
+ * Initialize member data that is shared with sub classes.
+ */
+ public StockData() {
+ simpleDateFormat = new SimpleDateFormat(dateFormat);
+ }
+
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockQuery.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockQuery.java
new file mode 100644
index 0000000..750eb9f
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockQuery.java
@@ -0,0 +1,58 @@
+package com.origamisoftware.teach.advanced.model;
+
+
+import org.apache.http.annotation.Immutable;
+
+import javax.validation.constraints.NotNull;
+import java.text.ParseException;
+import java.util.Calendar;
+
+/**
+ * This class is used to a single query to stock service.
+ */
+@Immutable
+public class StockQuery extends StockData{
+
+ private final String symbol;
+ private final Calendar from;
+ private final Calendar until;
+
+ /**
+ * Create a new instance from string data. This constructor will convert
+ * dates described as a String to Date objects.
+ *
+ * @param symbol the stock symbol
+ * @param from the start date as a string in the form of yyyy/MM/dd
+ * @throws ParseException if the format of the date String is incorrect. If this happens
+ * the only recourse is to try again with a correctly formatted String.
+ */
+ public StockQuery(@NotNull String symbol, @NotNull String from, @NotNull String until) throws ParseException {
+ super();
+ this.symbol = symbol;
+ this.from = Calendar.getInstance();
+ this.until = Calendar.getInstance();
+ this.from.setTime(simpleDateFormat.parse(from));
+ this.until.setTime(simpleDateFormat.parse(until));
+ }
+
+ /**
+ * @return get the stock symbol associated with this query
+ */
+ public String getSymbol() {
+ return symbol;
+ }
+
+ /**
+ * @return get the start Calendar associated with this query
+ */
+ public Calendar getFrom() {
+ return from;
+ }
+
+ /**
+ * @return get the end Calendar associated with this query
+ */
+ public Calendar getUntil() {
+ return until;
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockQuote.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockQuote.java
new file mode 100644
index 0000000..85e7847
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/model/StockQuote.java
@@ -0,0 +1,59 @@
+package com.origamisoftware.teach.advanced.model;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * A container class that contains stock data.
+ */
+public class StockQuote extends StockData {
+
+ private BigDecimal price;
+ private Date date;
+ private String symbol;
+
+ /**
+ * Create a new instance of a StockQuote.
+ *
+ * @param price the share price for the given date
+ * @param date the date of the share price
+ * @param symbol the stock symbol.
+ */
+ public StockQuote(BigDecimal price, Date date, String symbol) {
+ super();
+ this.price = price;
+ this.date = date;
+ this.symbol = symbol;
+ }
+
+ /**
+ * @return Get the share price for the given date.
+ */
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ /**
+ * @return The date of the share price
+ */
+ public Date getDate() {
+ return date;
+ }
+
+ /**
+ * @return The stock symbol.
+ */
+ public String getSymbol() {
+ return symbol;
+ }
+
+ @Override
+ public String toString() {
+ String dateString = simpleDateFormat.format(date);
+ return "StockQuote{" +
+ "price=" + price +
+ ", date=" + dateString +
+ ", symbol='" + symbol + '\'' +
+ '}';
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/DatabasePersonService.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/DatabasePersonService.java
new file mode 100644
index 0000000..a554890
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/DatabasePersonService.java
@@ -0,0 +1,114 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.Person;
+import com.origamisoftware.teach.advanced.model.Quotes;
+import com.origamisoftware.teach.advanced.util.DatabaseConnectionException;
+import com.origamisoftware.teach.advanced.util.DatabaseUtils;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An implementation of the PersonService interface that gets
+ * Person/Quote data from a database.
+ */
+class DatabasePersonService implements PersonService {
+
+ /**accesses database to retrieve person information
+ *
+ * @return a new person populated with database information
+ * @throws PersonServiceException
+ */
+
+ @Override
+ public List getPerson() throws PersonServiceException {
+ List personList = null;
+ Person person = new Person();
+ String firstName, lastName;
+ Timestamp birthDay;
+
+ firstName = person.getFirstName();
+ lastName = person.getLastName();
+ birthDay = person.getBirthDate();
+
+ try {
+ Connection connection = DatabaseUtils.getConnection();
+ Statement statement = connection.createStatement();
+ String queryString = "select * from person where first_name = '" + firstName + "' and last_name = '" + lastName + "'" +
+ "and birth_date = '" + birthDay + "'";
+
+ ResultSet resultSet = statement.executeQuery(queryString);
+ personList = new ArrayList<>(resultSet.getFetchSize());
+ while (resultSet.next()) {
+ firstName = resultSet.getString("first_name");
+ lastName = resultSet.getString("last_name");
+ birthDay = resultSet.getTimestamp("time");
+
+ personList.add(new Person(firstName, lastName, birthDay));
+ }
+
+ } catch (DatabaseConnectionException | SQLException exception) {
+ throw new PersonServiceException(exception.getMessage(), exception);
+ }
+ if (personList.isEmpty()) {
+ throw new PersonServiceException("There is no person data for:" + firstName + lastName + birthDay, null);
+ }
+ return personList;
+ }
+ //seems redundant with what list getPerson does? If i delete i get an error for not using all of the
+ //interfaces methods, should they be left blank?
+ @Override
+ public void addOrUpdatePerson(Person person) throws PersonServiceException {
+
+ }
+
+ /**accesses database to get quote information for use with PersonQuote
+ *
+ * @param person
+ * @return new list of quote information from the database
+ * @throws PersonServiceException
+ */
+ @Override
+ public List getQuotes(Person person) throws PersonServiceException {
+ List quotesList = null;
+ Quotes quotes = new Quotes();
+ String symbol;
+ int price = 0;
+ Timestamp time;
+
+ symbol = quotes.getSymbol();
+ price = quotes.getPrice();
+ time = quotes.getTime();
+
+ try {
+ Connection connection = DatabaseUtils.getConnection();
+ Statement statement = connection.createStatement();
+ String queryString = "select * from quotes where symbol = '" + symbol + "' and time = '" + time + "'" +
+ "and price = '" + price + "'";
+
+ ResultSet resultSet = statement.executeQuery(queryString);
+ quotesList = new ArrayList<>(resultSet.getFetchSize());
+ while (resultSet.next()) {
+ symbol = resultSet.getString("symbol");
+ price = resultSet.getInt("price");
+ time = resultSet.getTimestamp("time");
+
+ quotesList.add(new Quotes(symbol, price, time));
+ }
+
+ } catch (DatabaseConnectionException | SQLException exception) {
+ throw new PersonServiceException(exception.getMessage(), exception);
+ }
+ if (quotesList.isEmpty()) {
+ throw new PersonServiceException("There is no stock data for:" + symbol + price + time, null);
+ }
+
+ return quotesList;
+ }
+ //may not need to interact with the database? Information is aggregated in another method?
+ @Override
+ public void addQuotesToPerson(Quotes quotes, Person person) throws PersonServiceException {
+
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/DatabaseStockService.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/DatabaseStockService.java
new file mode 100644
index 0000000..309ba28
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/DatabaseStockService.java
@@ -0,0 +1,175 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.StockData;
+import com.origamisoftware.teach.advanced.model.StockQuote;
+import com.origamisoftware.teach.advanced.util.DatabaseConnectionException;
+import com.origamisoftware.teach.advanced.util.DatabaseUtils;
+import com.origamisoftware.teach.advanced.util.Interval;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+/**
+ * An implementation of the StockService interface that gets
+ * stock data from a database.
+ */
+class DatabaseStockService implements StockService {
+
+ /**
+ * Return the current price for a share of stock for the given symbol
+ *
+ * @param symbol the stock symbol of the company you want a quote for.
+ * e.g. APPL for APPLE
+ * @return a BigDecimal instance
+ * @throws StockServiceException if using the service generates an exception.
+ * If this happens, trying the service may work, depending on the actual cause of the
+ * error.
+ */
+ @Override
+ public StockQuote getQuote(String symbol) throws StockServiceException {
+ // todo - this is a pretty lame implementation why?
+ List stockQuotes = null;
+ try {
+ Connection connection = DatabaseUtils.getConnection();
+ Statement statement = connection.createStatement();
+ String queryString = "select * from quotes where symbol = '" + symbol + "'";
+
+ ResultSet resultSet = statement.executeQuery(queryString);
+ stockQuotes = new ArrayList<>(resultSet.getFetchSize());
+ while (resultSet.next()) {
+ String symbolValue = resultSet.getString("symbol");
+ Date time = resultSet.getDate("time");
+ BigDecimal price = resultSet.getBigDecimal("price");
+ stockQuotes.add(new StockQuote(price, time, symbolValue));
+ }
+
+ } catch (DatabaseConnectionException | SQLException exception) {
+ throw new StockServiceException(exception.getMessage(), exception);
+ }
+ if (stockQuotes.isEmpty()) {
+ throw new StockServiceException("There is no stock data for:" + symbol);
+ }
+ return stockQuotes.get(0);
+ }
+
+ /**
+ * Get a historical list of stock quotes for the provide symbol
+ *
+ * @param symbol the stock symbol to search for
+ * @param from the date of the first stock quote
+ * @param until the date of the last stock quote
+ * @param interval the number of stockquotes to get per a 24 hour period.
+ * @return a list of StockQuote instances
+ * @throws StockServiceException if using the service generates an exception.
+ * If this happens, trying the service may work, depending on the actual cause of the
+ * error.
+ */
+ @Override
+ public List getQuote(String symbol, Calendar from, Calendar until, Interval interval) throws StockServiceException {
+ List stockQuotes = null;
+ try {
+ Connection connection = DatabaseUtils.getConnection();
+ Statement statement = connection.createStatement();
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat(StockData.dateFormat);
+
+ String fromString = simpleDateFormat.format(from.getTime());
+ String untilString = simpleDateFormat.format(until.getTime());
+
+ String queryString = "select * from quotes where symbol = '" + symbol + "'"
+ + "and time BETWEEN '" + fromString + "' and '" + untilString + "'";
+
+ ResultSet resultSet = statement.executeQuery(queryString);
+ stockQuotes = new ArrayList<>();
+ StockQuote previousStockQuote = null;
+
+ /**
+ *
+ * Here is the general idea behind filtering on interval.
+ * It is not perfect, it would be better to filter using SQL and let the DBMS to it,
+ * but this way will work OK for small or medium data sets, and since this class
+ * (90.303 - not this actual Java class) is focused on Java and not SQL
+ * I thought this approach was appropriate.
+ *
+ * SIDE BAR:
+ *
+ * It also highlights a consistent tension which is the question of what should the
+ * DBMS be responsible for and what should the Java code be responsible. There is
+ * no one answer here as there are lots of factors to consider including:
+ *
+ * SQL compatibility (complex logic in the DBMS might not be portable to another DBMS)
+ *
+ * Where do you want your application's business logic to exist?
+ * In the DBMS only, in the Java code only? Spread out between the two?
+ * Keeping it in one place makes a lot more sense than spreading it out? But where is
+ * best - that depends on your application design, and capacity requirements, your teams'
+ * skill set (Do you have a lot of db experts on staff?) and whether or not DBMS vendor
+ * lock in is a concern or not.
+ *
+ * Performance and scalability
+ * DBMS intensive application will benefit from having the DBMS do the heavy data
+ * sorting.
+ *
+ * Ease of maintenance and test
+ * This questions really relates to your teams' skill set.
+ *
+ */
+ Calendar calendar = Calendar.getInstance();
+ while (resultSet.next()) {
+ String symbolValue = resultSet.getString("symbol");
+ Timestamp timeStamp = resultSet.getTimestamp("time");
+ calendar.setTimeInMillis(timeStamp.getTime());
+ BigDecimal price = resultSet.getBigDecimal("price");
+ java.util.Date time = calendar.getTime();
+ StockQuote currentStockQuote = new StockQuote(price, time, symbolValue);
+
+ if (previousStockQuote == null) { // first time through always add stockquote
+
+ stockQuotes.add(currentStockQuote);
+
+ } else if (isInterval(currentStockQuote.getDate(),
+ interval,
+ previousStockQuote.getDate())) {
+
+ stockQuotes.add(currentStockQuote);
+ }
+
+ previousStockQuote = currentStockQuote;
+ }
+
+ } catch (DatabaseConnectionException | SQLException exception) {
+ throw new StockServiceException(exception.getMessage(), exception);
+ }
+ if (stockQuotes.isEmpty()) {
+ throw new StockServiceException("There is no stock data for:" + symbol);
+ }
+
+ return stockQuotes;
+ }
+
+
+ /**
+ * Returns true of the currentStockQuote has a date that is later by the time
+ * specified in the interval value from the previousStockQuote time.
+ *
+ * @param endDate the end time
+ * @param interval the period of time that must exist between previousStockQuote and currentStockQuote
+ * in order for this method to return true.
+ * @param startDate the starting date
+ * @return
+ */
+ private boolean isInterval(java.util.Date endDate, Interval interval, java.util.Date startDate) {
+ Calendar startDatePlusInterval = Calendar.getInstance();
+ startDatePlusInterval.setTime(startDate);
+ startDatePlusInterval.add(Calendar.MINUTE, interval.getMinutes());
+ return endDate.after(startDatePlusInterval.getTime());
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/PersonService.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/PersonService.java
new file mode 100644
index 0000000..0c7b5df
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/PersonService.java
@@ -0,0 +1,50 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.Quotes;
+import com.origamisoftware.teach.advanced.model.Person;
+
+import java.util.List;
+
+/**
+ *
+ */
+public interface PersonService {
+
+ /**
+ * Get a list of all people
+ *
+ * @return a list of Person instances
+ * @throws PersonServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ List getPerson() throws PersonServiceException;
+
+ /**
+ * Add a new person or update an existing Person's data
+ *
+ * @param person a person object to either update or create
+ * @throws PersonServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ void addOrUpdatePerson(Person person) throws PersonServiceException;
+
+ /**
+ * Get a list of all a person's quotes.
+ *
+ * @return a list of quote instances
+ * @throws PersonServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ List getQuotes(Person person) throws PersonServiceException;
+
+ /**
+ * Assign quotes to a person.
+ *
+ * @param quotes The quotes to assign
+ * @param person The person to assign the quotes too.
+ * @throws PersonServiceException if a service can not read or write the requested data
+ * or otherwise perform the requested operation.
+ */
+ public void addQuotesToPerson(Quotes quotes, Person person) throws PersonServiceException;
+
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/PersonServiceException.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/PersonServiceException.java
new file mode 100644
index 0000000..8be7290
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/PersonServiceException.java
@@ -0,0 +1,25 @@
+package com.origamisoftware.teach.advanced.services;
+
+/**
+ * Used to signal an issue with ActivitiesService
+ */
+public class PersonServiceException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public PersonServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/ServiceFactory.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/ServiceFactory.java
new file mode 100644
index 0000000..c737678
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/ServiceFactory.java
@@ -0,0 +1,23 @@
+package com.origamisoftware.teach.advanced.services;
+
+/**
+ * A factory that returns a StockService instance.
+ */
+public class ServiceFactory {
+
+ /**
+ * Prevent instantiations
+ */
+ private ServiceFactory() {}
+
+ /**
+ *
+ * @return get a StockService instance
+ */
+ public static StockService getStockServiceInstance() {
+ return new SimpleStockService();
+ }
+ public static PersonService getPersonServiceInstance() {
+ return new SimplePersonService();
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/SimplePersonService.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/SimplePersonService.java
new file mode 100644
index 0000000..65b7152
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/SimplePersonService.java
@@ -0,0 +1,70 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.Person;
+import com.origamisoftware.teach.advanced.model.Person_Quotes;
+import com.origamisoftware.teach.advanced.model.Quotes;
+import com.sun.xml.internal.fastinfoset.util.StringArray;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An implementation of the PersonService that returns hard coded data.
+ */
+class SimplePersonService implements PersonService {
+
+ @Override
+ public List getPerson() throws PersonServiceException {
+ List personList = new ArrayList<>();
+ Person_Quotes person_quotes = new Person_Quotes();
+
+ Person person = person_quotes.getPerson();
+
+ personList.add(person);
+
+ return personList;
+ }
+
+ @Override
+ public void addOrUpdatePerson(Person person) throws PersonServiceException {
+ String firstName, lastName;
+ int id;
+ Timestamp birthDate;
+
+ if (person == null)
+ getPerson();
+ else{
+ firstName = person.getFirstName();
+ person.setFirstName(firstName);
+
+ lastName = person.getLastName();
+ person.setLastName(lastName);
+
+ id = person.getId();
+ person.setId(id);
+
+ birthDate = person.getBirthDate();
+ person.setBirthDate(birthDate);}
+ }
+
+ @Override
+ public List getQuotes(Person person) throws PersonServiceException {
+ List quotesList = new ArrayList<>();
+ Person_Quotes person_quotes = new Person_Quotes();
+
+ Quotes quotes = person_quotes.getQuotes();
+
+ quotesList.add(quotes);
+
+ return quotesList;
+ }
+
+ @Override
+ public void addQuotesToPerson(Quotes quotes, Person person) throws PersonServiceException {
+ StringArray personQuotes = new StringArray();
+ personQuotes.add(person.toString());
+ personQuotes.add(quotes.toString());
+
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/SimpleStockService.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/SimpleStockService.java
new file mode 100644
index 0000000..28649ca
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/SimpleStockService.java
@@ -0,0 +1,56 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.StockQuote;
+import com.origamisoftware.teach.advanced.util.Interval;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * An implementation of the StockService that returns hard coded data.
+ */
+ class SimpleStockService implements StockService {
+
+ /**
+ * Return the current price for a share of stock for the given symbol
+ *
+ * @param symbol the stock symbol of the company you want a quote for.
+ * e.g. APPL for APPLE
+ * @return a BigDecimal instance
+ * @throws StockServiceException if using the service generates an exception.
+ * If this happens, trying the service may work, depending on the actual cause of the
+ * error.
+ */
+ @Override
+ public StockQuote getQuote(String symbol) {
+ // a dead simple implementation.
+ return new StockQuote(new BigDecimal(100), Calendar.getInstance().getTime(), symbol);
+ }
+
+ /**
+ * Get a historical list of stock quotes for the provide symbol
+ *
+ * @param symbol the stock symbol to search for
+ * @param from the date of the first stock quote
+ * @param until the date of the last stock quote
+ * @return a list of StockQuote instances
+ * @throws StockServiceException if using the service generates an exception.
+ * If this happens, trying the service may work, depending on the actual cause of the
+ * error.
+ */
+ @Override
+ public List getQuote(String symbol, Calendar from, Calendar until, Interval interval) {
+ // a dead simple implementation.
+ List stockQuotes = new ArrayList<>();
+ Date aDay = from.getTime();
+ while (until.after(aDay)) {
+ stockQuotes.add(new StockQuote(new BigDecimal(100), aDay, symbol));
+ from.add(Calendar.DAY_OF_YEAR, 1);
+ aDay = from.getTime();
+ }
+ return stockQuotes;
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/StockService.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/StockService.java
new file mode 100644
index 0000000..73860ae
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/StockService.java
@@ -0,0 +1,42 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.StockQuote;
+import com.origamisoftware.teach.advanced.util.Interval;
+
+import java.util.Calendar;
+import java.util.List;
+
+/**
+ * This API describes how to get stock data from an external resource.
+ */
+public interface StockService {
+
+
+ /**
+ * Return the current price for a share of stock for the given symbol
+ *
+ * @param symbol the stock symbol of the company you want a quote for.
+ * e.g. APPL for APPLE
+ * @return a BigDecimal instance
+ * @throws StockServiceException if using the service generates an exception.
+ * If this happens, trying the service may work, depending on the actual cause of the
+ * error.
+ */
+ StockQuote getQuote(String symbol) throws StockServiceException;
+
+ /**
+ * Get a historical list of stock quotes for the provide symbol
+ *
+ * @param symbol the stock symbol to search for
+ * @param from the date of the first stock quote
+ * @param until the date of the last stock quote
+ * @param interval the number of stockquotes to get per a 24 hour period.
+ * @return a list of StockQuote instances
+ * @throws StockServiceException if using the service generates an exception.
+ * If this happens, trying the service may work, depending on the actual cause of the
+ * error.
+ */
+ List getQuote(String symbol, Calendar from, Calendar until, Interval interval) throws StockServiceException;
+
+}
+
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceException.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceException.java
new file mode 100644
index 0000000..efcfa21
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceException.java
@@ -0,0 +1,37 @@
+package com.origamisoftware.teach.advanced.services;
+
+/**
+ * Used to signal a problem with the StockService.
+ */
+public class StockServiceException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message. The
+ * cause is not initialized, and may subsequently be initialized by
+ * a call to {@link #initCause}.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public StockServiceException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public StockServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java
new file mode 100644
index 0000000..ea8d91e
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java
@@ -0,0 +1,25 @@
+package com.origamisoftware.teach.advanced.util;
+
+/**
+ * This class is used to signal a problem connecting to a database.
+ */
+public class DatabaseConnectionException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public DatabaseConnectionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseException.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseException.java
new file mode 100644
index 0000000..912397b
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseException.java
@@ -0,0 +1,25 @@
+package com.origamisoftware.teach.advanced.util;
+
+/**
+ * A higher level exception that tells the client accessing the database failed. .
+ */
+public class DatabaseException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public DatabaseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java
new file mode 100644
index 0000000..bc09f7d
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java
@@ -0,0 +1,25 @@
+package com.origamisoftware.teach.advanced.util;
+
+/**
+ * This class is used to signal a problem initializing to a database.
+ */
+public class DatabaseInitializationException extends Exception {
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
Note that the detail message associated with
+ * {@code cause} is not automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public DatabaseInitializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java
new file mode 100644
index 0000000..0ca0409
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java
@@ -0,0 +1,107 @@
+package com.origamisoftware.teach.advanced.util;
+
+import com.ibatis.common.jdbc.ScriptRunner;
+import org.hibernate.cfg.Configuration;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+
+/**
+ * A class that contains database related utility methods.
+ */
+public class DatabaseUtils {
+
+ public static final String initializationFile = "./src/main/sql/stocks_db_initialization.sql" ;
+
+ private static Configuration configuration;
+
+ /**
+ * Create a new or return an existing database configuration object.
+ *
+ * @return a Hibernate Configuration instance.
+ */
+ private static Configuration getConfiguration() {
+
+ synchronized (DatabaseUtils.class) {
+ if (configuration == null) {
+ configuration = new Configuration();
+ configuration.configure("hibernate.cfg.xml");
+ }
+ }
+ return configuration;
+ }
+
+ public static Connection getConnection() throws DatabaseConnectionException {
+ Connection connection = null;
+ Configuration configuration = getConfiguration();
+ try {
+
+ Class.forName("com.mysql.jdbc.Driver");
+ String databaseUrl = configuration.getProperty("connection.url");
+ String username = configuration.getProperty("hibernate.connection.username");
+ String password = configuration.getProperty("hibernate.connection.password");
+ connection = DriverManager.getConnection(databaseUrl, username, password);
+
+ // an example of throwing an exception appropriate to the abstraction.
+ } catch (ClassNotFoundException | SQLException e) {
+ throw new DatabaseConnectionException("Could not connect to the database." + e.getMessage(), e);
+ }
+ return connection;
+ }
+
+ /**
+ * A utility method that runs a db initialize script.
+ *
+ * @param initializationScript full path to the script to run to create the schema
+ * @throws DatabaseInitializationException
+ */
+ public static void initializeDatabase(String initializationScript) throws DatabaseInitializationException {
+
+ Connection connection = null;
+ try {
+ connection = getConnection();
+ connection.setAutoCommit(false);
+ ScriptRunner runner = new ScriptRunner(connection, false, false);
+ InputStream inputStream = new FileInputStream(initializationScript);
+
+ InputStreamReader reader = new InputStreamReader(inputStream);
+
+ runner.runScript(reader);
+ reader.close();
+ connection.commit();
+ connection.close();
+
+ } catch (DatabaseConnectionException | SQLException | IOException e) {
+ throw new DatabaseInitializationException("Could not initialize db because of:"
+ + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Execute SQL code
+ * @param someSQL the code to execute
+ * @return true if the operation succeeded.
+ * @throws DatabaseException if accessing and executing the sql failed in an unexpected way.
+ *
+ */
+ public static boolean executeSQL(String someSQL) throws DatabaseException {
+ Connection connection = null;
+ boolean returnValue = false;
+ try {
+ connection = DatabaseUtils.getConnection();
+ Statement statement = connection.createStatement();
+ returnValue = statement.execute(someSQL);
+ } catch (DatabaseConnectionException | SQLException e) {
+ throw new DatabaseException(e.getMessage(), e);
+ }
+ return returnValue;
+ }
+
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/Interval.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/Interval.java
new file mode 100644
index 0000000..b814914
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/Interval.java
@@ -0,0 +1,27 @@
+package com.origamisoftware.teach.advanced.util;
+
+/**
+ * An enumeration that represents a of unit of time
+ */
+public enum Interval {
+
+ MINUTE(1), HOUR(60), HALF_DAY(60 * 6), DAY(60 * 24);
+
+ private int minutes;
+
+ /**
+ * Create a new Interval enumeration.
+ * @param minutes the number of minutes in the interval
+ */
+ private Interval(int minutes) {
+ this.minutes = minutes;
+ }
+
+ /**
+ *
+ * @return the number of minutes in the interval
+ */
+ public int getMinutes() {
+ return minutes;
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/ProgramConfiguration.java b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/ProgramConfiguration.java
new file mode 100644
index 0000000..0b03a55
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/java/com/origamisoftware/teach/advanced/util/ProgramConfiguration.java
@@ -0,0 +1,15 @@
+package com.origamisoftware.teach.advanced.util;
+
+import java.util.Properties;
+
+/**
+ * A Utility class that provides application properties and
+ * configuration settings.
+ */
+public class ProgramConfiguration {
+
+ public static Properties getApplicationProperties() {
+ return null;
+ }
+
+}
diff --git a/WK6/stockquote-week5-solved/src/main/sql/stocks_db_initialization.sql b/WK6/stockquote-week5-solved/src/main/sql/stocks_db_initialization.sql
new file mode 100644
index 0000000..64022fb
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/main/sql/stocks_db_initialization.sql
@@ -0,0 +1,9 @@
+CREATE TABLE stocks.person_quotes
+(ID INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ person_id INT NOT NULL,
+ quotes_id INT NOT NULL,
+ FOREIGN KEY (person_id) REFERENCES person (ID),
+ FOREIGN KEY (quotes_id) REFERENCES quotes (ID)
+);
+
+
diff --git a/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.java b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.java
new file mode 100644
index 0000000..6a92157
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.java
@@ -0,0 +1,72 @@
+package com.origamisoftware.teach.advanced.apps.stockquote;
+
+import com.origamisoftware.teach.advanced.model.StockQuery;
+import com.origamisoftware.teach.advanced.model.StockQuote;
+import com.origamisoftware.teach.advanced.services.StockService;
+import com.origamisoftware.teach.advanced.services.StockServiceException;
+import com.origamisoftware.teach.advanced.util.Interval;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for BasicStockQuoteApplication
+ */
+public class BasicStockQuoteApplicationTest {
+
+ private BasicStockQuoteApplication basicStockQuoteApplication;
+ private StockService stockServiceMock;
+
+ @Before
+ public void setUp() {
+ stockServiceMock = mock(StockService.class);
+ }
+
+ @Test
+ public void testValidConstruction() {
+ basicStockQuoteApplication = new BasicStockQuoteApplication(stockServiceMock);
+ assertNotNull("Basic construction works");
+ }
+
+ @Test
+ public void testDisplayResults() throws ParseException, StockServiceException {
+ basicStockQuoteApplication = new BasicStockQuoteApplication(stockServiceMock);
+ String symbol = "APPL";
+ String from = "2011-10-29 12:12:12"; //yyyy-MM-dd HH:mm:ss
+ String until = "2014-11-29 12:12:12";
+ StockQuery stockQuery = new StockQuery(symbol, from, until);
+
+ List stockQuotes = new ArrayList<>();
+ StockQuote stockQuoteFromDate = new StockQuote(new BigDecimal(100), stockQuery.getFrom().getTime(), stockQuery.getSymbol());
+ stockQuotes.add(stockQuoteFromDate);
+ StockQuote stockQuoteUntilDate = new StockQuote(new BigDecimal(100), stockQuery.getUntil().getTime(), stockQuery.getSymbol());
+ stockQuotes.add(stockQuoteUntilDate);
+
+ when(stockServiceMock.getQuote(any(String.class),
+ any(Calendar.class),
+ any(Calendar.class),
+ any(Interval.class))).thenReturn(stockQuotes);
+
+ String output = basicStockQuoteApplication.displayStockQuotes(stockQuery);
+ assertTrue("make sure symbol appears in output", output.contains(symbol));
+ assertTrue("make sure from date appears in output", output.contains(from));
+ assertTrue("make sure until date in output", output.contains(until));
+
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testMainNegative() {
+ BasicStockQuoteApplication.main(null);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/model/StockQueryTest.java b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/model/StockQueryTest.java
new file mode 100644
index 0000000..2294ca4
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/model/StockQueryTest.java
@@ -0,0 +1,19 @@
+package com.origamisoftware.teach.advanced.model;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit test for StockQuery Class
+ */
+public class StockQueryTest {
+
+ @Test
+ public void testBasicConstruction() throws Exception{
+ String symbol = "APPL";
+ StockQuery stockQuery = new StockQuery(symbol,"2011-10-29 12:12:1","2014-10-29 12:12:1");
+ assertEquals("Verify construction", symbol, stockQuery.getSymbol());
+ }
+
+}
diff --git a/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/model/StockQuoteTest.java b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/model/StockQuoteTest.java
new file mode 100644
index 0000000..ad47fb1
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/model/StockQuoteTest.java
@@ -0,0 +1,44 @@
+package com.origamisoftware.teach.advanced.model;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * JUnit test for StockQuote class
+ */
+public class StockQuoteTest {
+
+ private BigDecimal price;
+ private Date date;
+ private String symbol;
+ private StockQuote stockQuote;
+
+ @Before
+ public void setUp() {
+ price = new BigDecimal(100);
+ date = Calendar.getInstance().getTime();
+ symbol = "APPL";
+ stockQuote = new StockQuote(price, date, symbol);
+ }
+
+ @Test
+ public void testGetPrice() {
+ assertEquals("Share price is correct", price, stockQuote.getPrice());
+ }
+
+ @Test
+ public void testGetDate() {
+ assertEquals("Share date is correct", date, stockQuote.getDate());
+ }
+
+ @Test
+ public void testGetSymbol() {
+ assertEquals("Symbol is correct", symbol, stockQuote.getSymbol());
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.java b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.java
new file mode 100644
index 0000000..6ba3c94
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.java
@@ -0,0 +1,105 @@
+package com.origamisoftware.teach.advanced.services;
+
+import com.origamisoftware.teach.advanced.model.StockData;
+import com.origamisoftware.teach.advanced.model.StockQuote;
+import com.origamisoftware.teach.advanced.util.DatabaseInitializationException;
+import com.origamisoftware.teach.advanced.util.DatabaseUtils;
+import com.origamisoftware.teach.advanced.util.Interval;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Unit tests for the DatabaseStockService
+ */
+public class DatabaseStockServiceTest {
+
+ private DatabaseStockService databaseStockService;
+
+ @Before
+ public void setUp() throws DatabaseInitializationException {
+ DatabaseUtils.initializeDatabase(DatabaseUtils.initializationFile);
+ databaseStockService = new DatabaseStockService();
+
+ }
+
+ @Test
+ public void testGetQuote() throws Exception {
+ String symbol = "APPL";
+ StockQuote stockQuote = databaseStockService.getQuote(symbol);
+ assertNotNull("Verify we can get a stock quote from the db", stockQuote);
+ assertEquals("Make sure the symbols match", symbol, stockQuote.getSymbol());
+ }
+
+ @Test
+ public void testGetQuoteWithIntervalBasic() throws Exception {
+ String symbol = "GOOG";
+ String fromStringDate = "2000-02-10 00:00:01";
+ String untilStringDate = "2015-02-03 00:00:01";
+
+ Calendar fromCalendar = makeCalendarFromString(fromStringDate);
+ Calendar untilCalendar = makeCalendarFromString(untilStringDate);
+
+ List stockQuotes = databaseStockService.getQuote(symbol, fromCalendar, untilCalendar, Interval.DAY);
+ assertFalse("verify stock quotes where returned", stockQuotes.isEmpty());
+ }
+
+ @Test
+ public void testGetQuoteWithinRange() throws Exception {
+
+ String fromDateString = "2015-02-10 00:01:01";
+ String endDateString = "2015-02-10 00:08:01";
+ String symbol = "AMZN";
+
+ String sql = "INSERT INTO quotes (symbol,time,price) VALUES ('AMZN','" + fromDateString + "','363.21');";
+ DatabaseUtils.executeSQL(sql);
+
+ sql = "INSERT INTO quotes (symbol,time,price) VALUES ('AMZN','2015-02-10 00:04:01','250.21');";
+ DatabaseUtils.executeSQL(sql);
+
+ sql = "INSERT INTO quotes (symbol,time,price) VALUES ('AMZN','2015-02-10 00:06:01','251.21');";
+ DatabaseUtils.executeSQL(sql);
+
+ sql = "INSERT INTO quotes (symbol,time,price) VALUES ('AMZN','" + endDateString + "','253.21');";
+ DatabaseUtils.executeSQL(sql);
+
+ Calendar fromCalendar = makeCalendarFromString(fromDateString);
+ Calendar untilCalendar = makeCalendarFromString(endDateString);
+
+ List stockQuotes = databaseStockService.getQuote(symbol, fromCalendar, untilCalendar, Interval.DAY);
+ assertEquals("got back expected number of stockquotes for one day interval", 1, stockQuotes.size());
+
+ stockQuotes = databaseStockService.getQuote(symbol, fromCalendar, untilCalendar, Interval.MINUTE);
+ assertEquals("got back expected number of stockquotes for one minute interval", 4, stockQuotes.size());
+ }
+
+ /**
+ * Handy dandy helper method that converts Strings in the format of StockData.dateFormat
+ * to Calendar instances set to the date expressed in the string.
+ *
+ * @param dateString a data and time in this format: StockData.dateFormat
+ * @return a calendar instance set to the time in the string.
+ * @throws ParseException if the string is not in the correct format, we can't tell what
+ * time it is, and therefore can't make a calender set to that time.
+ */
+ private Calendar makeCalendarFromString(String dateString) throws ParseException {
+ DateFormat format = new SimpleDateFormat(StockData.dateFormat, Locale.ENGLISH);
+ Date date = format.parse(dateString);
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ return calendar;
+
+ }
+
+}
diff --git a/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.java b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.java
new file mode 100644
index 0000000..fd605e9
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.java
@@ -0,0 +1,17 @@
+package com.origamisoftware.teach.advanced.services;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * JUnit test for StockServiceFactory
+ */
+public class StockServiceFactoryTest {
+
+ @Test
+ public void testGetInstance() {
+ StockService stockService = StockServiceFactory.getInstance();
+ assertNotNull(stockService);
+ }
+}
diff --git a/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java
new file mode 100644
index 0000000..3e2dc9d
--- /dev/null
+++ b/WK6/stockquote-week5-solved/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java
@@ -0,0 +1,40 @@
+package com.origamisoftware.teach.advanced.util;
+
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.Statement;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for the DatabaseUtils class
+ */
+public class DatabaseUtilsTest {
+
+ @Test
+ public void testGoodInitFile() throws Exception {
+ DatabaseUtils.initializeDatabase(DatabaseUtils.initializationFile);
+ }
+
+ @Test(expected = DatabaseInitializationException.class)
+ public void testBadInitFile() throws Exception {
+ DatabaseUtils.initializeDatabase("bogus");
+ }
+
+ @Test
+ public void testGetConnection() throws Exception{
+ Connection connection = DatabaseUtils.getConnection();
+ assertNotNull("verify that we can get a connection ok",connection);
+ }
+
+ @Test
+ public void testGetConnectionWorks() throws Exception{
+ Connection connection = DatabaseUtils.getConnection();
+ Statement statement = connection.createStatement();
+ boolean execute = statement.execute("select * from quotes");
+ assertTrue("verify that we can execute a statement",execute);
+ }
+
+}
diff --git a/WK6/stockquote-week5-solved/week-5-stock-ticker.iml b/WK6/stockquote-week5-solved/week-5-stock-ticker.iml
new file mode 100644
index 0000000..e61a793
--- /dev/null
+++ b/WK6/stockquote-week5-solved/week-5-stock-ticker.iml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file