From 1b947c81a99d8aaf162bdc19cf602bb71c2eb769 Mon Sep 17 00:00:00 2001 From: ivanmaker <43081738+ivanmaker@users.noreply.github.com> Date: Sun, 7 Oct 2018 18:37:24 -0700 Subject: [PATCH] WK5 So, obviously this is mostly the files from the Week 5 folder on BB. I've spent the last few evening studying your work and adding the requested elements from this weeks assignment. I couldn't quite figure out how to pass arguments to so I used an Intelij feature to pass command line arguments to main? --- stockquote-week5/pom.xml | 73 +++++++++ .../BasicStockQuoteApplication.java | 144 ++++++++++++++++++ .../teach/advanced/model/StockData.java | 25 +++ .../teach/advanced/model/StockQuery.java | 60 ++++++++ .../teach/advanced/model/StockQuote.java | 61 ++++++++ .../services/DatabaseStockService.java | 97 ++++++++++++ .../advanced/services/SimpleStockService.java | 55 +++++++ .../teach/advanced/services/StockService.java | 40 +++++ .../services/StockServiceException.java | 37 +++++ .../services/StockServiceFactory.java | 45 ++++++ .../util/DatabaseConnectionException.java | 25 +++ .../util/DatabaseInitializationException.java | 25 +++ .../teach/advanced/util/DatabaseUtils.java | 65 ++++++++ .../advanced/util/ProgramConfiguration.java | 15 ++ .../src/main/sql/stocks_db_initialization.sql | 15 ++ .../BasicStockQuoteApplicationTest.java | 68 +++++++++ .../teach/advanced/model/StockQueryTest.java | 19 +++ .../teach/advanced/model/StockQuoteTest.java | 44 ++++++ .../services/DatabaseStockServiceTest.java | 22 +++ .../services/StockServiceFactoryTest.java | 17 +++ .../advanced/util/DatabaseUtilsTest.java | 38 +++++ ...ication$ProgramTerminationStatusEnum.class | Bin 0 -> 2021 bytes .../BasicStockQuoteApplication.class | Bin 0 -> 4317 bytes .../teach/advanced/model/StockData.class | Bin 0 -> 505 bytes .../teach/advanced/model/StockQuery.class | Bin 0 -> 1543 bytes .../teach/advanced/model/StockQuote.class | Bin 0 -> 1550 bytes .../services/DatabaseStockService.class | Bin 0 -> 3836 bytes .../services/SimpleStockService.class | Bin 0 -> 1751 bytes .../advanced/services/StockService.class | Bin 0 -> 589 bytes .../services/StockServiceException.class | Bin 0 -> 617 bytes .../services/StockServiceFactory$1.class | Bin 0 -> 2050 bytes .../services/StockServiceFactory.class | Bin 0 -> 608 bytes .../util/DatabaseConnectionException.class | Bin 0 -> 517 bytes .../DatabaseInitializationException.class | Bin 0 -> 529 bytes .../teach/advanced/util/DatabaseUtils.class | Bin 0 -> 2512 bytes .../advanced/util/ProgramConfiguration.class | Bin 0 -> 459 bytes .../BasicStockQuoteApplicationTest.class | Bin 0 -> 3700 bytes .../teach/advanced/model/StockQueryTest.class | Bin 0 -> 1040 bytes .../teach/advanced/model/StockQuoteTest.class | Bin 0 -> 1699 bytes .../services/DatabaseStockServiceTest.class | Bin 0 -> 1379 bytes .../services/StockServiceFactoryTest.class | Bin 0 -> 854 bytes .../advanced/util/DatabaseUtilsTest.class | Bin 0 -> 1694 bytes stockquote-week5/week-5-stock-ticker.iml | 21 +++ 43 files changed, 1011 insertions(+) create mode 100644 stockquote-week5/pom.xml create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockData.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuery.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuote.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/DatabaseStockService.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/SimpleStockService.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockService.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceException.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceFactory.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java create mode 100644 stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/ProgramConfiguration.java create mode 100644 stockquote-week5/src/main/sql/stocks_db_initialization.sql create mode 100644 stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.java create mode 100644 stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/model/StockQueryTest.java create mode 100644 stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/model/StockQuoteTest.java create mode 100644 stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.java create mode 100644 stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.java create mode 100644 stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication$ProgramTerminationStatusEnum.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/model/StockData.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/model/StockQuery.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/model/StockQuote.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/DatabaseStockService.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/SimpleStockService.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockService.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceException.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceFactory$1.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceFactory.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/DatabaseUtils.class create mode 100644 stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/ProgramConfiguration.class create mode 100644 stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.class create mode 100644 stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/model/StockQueryTest.class create mode 100644 stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/model/StockQuoteTest.class create mode 100644 stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.class create mode 100644 stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.class create mode 100644 stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.class create mode 100644 stockquote-week5/week-5-stock-ticker.iml diff --git a/stockquote-week5/pom.xml b/stockquote-week5/pom.xml new file mode 100644 index 0000000..ec2af0f --- /dev/null +++ b/stockquote-week5/pom.xml @@ -0,0 +1,73 @@ + + 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 + + + diff --git a/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.java new file mode 100644 index 0000000..571f075 --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.java @@ -0,0 +1,144 @@ +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.StockServiceFactory; + +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()); + + 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. + *

+ * When invoking the program supply one ore more stock symbols. + * + * @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 = StockServiceFactory.getInstance(); + 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(); + } + + exit(exitStatus, programTerminationMessage); + System.out.println("Oops could not parse a date"); + } +} diff --git a/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockData.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockData.java new file mode 100644 index 0000000..2ee6c88 --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockData.java @@ -0,0 +1,25 @@ +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; + + /** + * Base constructor for StockData classes. + * Initialize member data that is shared with sub classes. + */ + public StockData() { + simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd"); + } + +} diff --git a/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuery.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuery.java new file mode 100644 index 0000000..37ddaba --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuery.java @@ -0,0 +1,60 @@ +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 String symbol; + private Calendar from; + private 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 + * @param from the end 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(); + System.out.println(simpleDateFormat); + 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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuote.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuote.java new file mode 100644 index 0000000..e19c713 --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/model/StockQuote.java @@ -0,0 +1,61 @@ +package com.origamisoftware.teach.advanced.model; + +import java.math.BigDecimal; +import java.util.Calendar; +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; + private Calendar from; + private Calendar until; + + /** + * 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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/DatabaseStockService.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/DatabaseStockService.java new file mode 100644 index 0000000..5f44614 --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/DatabaseStockService.java @@ -0,0 +1,97 @@ +package com.origamisoftware.teach.advanced.services; + +import com.origamisoftware.teach.advanced.model.StockQuote; +import com.origamisoftware.teach.advanced.util.DatabaseConnectionException; +import com.origamisoftware.teach.advanced.util.DatabaseUtils; + +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.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * An implementation of the StockService interface that gets + * stock data from a database. + */ +public 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 + * @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) throws StockServiceException { + + List stockQuotes = null; + try { + Connection connection = DatabaseUtils.getConnection(); + Statement statement = connection.createStatement(); + String queryString = "select * from quotes where symbol = '" + symbol + "' and DATE between '" + from + "' '" + until + "'"; + + 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; + } +} diff --git a/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/SimpleStockService.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/SimpleStockService.java new file mode 100644 index 0000000..1cc89c6 --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/SimpleStockService.java @@ -0,0 +1,55 @@ +package com.origamisoftware.teach.advanced.services; + +import com.origamisoftware.teach.advanced.model.StockQuote; + +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. + */ +public 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) { + // 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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockService.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockService.java new file mode 100644 index 0000000..d702731 --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockService.java @@ -0,0 +1,40 @@ +package com.origamisoftware.teach.advanced.services; + +import com.origamisoftware.teach.advanced.model.StockQuote; + +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 + * @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) throws StockServiceException; + +} + diff --git a/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceException.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceException.java new file mode 100644 index 0000000..efcfa21 --- /dev/null +++ b/stockquote-week5/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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceFactory.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceFactory.java new file mode 100644 index 0000000..1bc4e47 --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/services/StockServiceFactory.java @@ -0,0 +1,45 @@ +package com.origamisoftware.teach.advanced.services; + +import com.origamisoftware.teach.advanced.model.StockQuote; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * A factory that returns a StockService instance. + */ +public class StockServiceFactory { + + /** + * Prevent instantiations + */ + private StockServiceFactory() {} + + /** + * + * @return get a StockService instance + */ + public static DatabaseStockService getInstance() { + return new DatabaseStockService() { + @Override + public StockQuote getQuote(String symbol) throws StockServiceException { + return new StockQuote(new BigDecimal(100), Calendar.getInstance().getTime(), symbol); + } + + @Override + public List getQuote(String symbol, Calendar from, Calendar until) throws StockServiceException { + 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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseConnectionException.java new file mode 100644 index 0000000..ea8d91e --- /dev/null +++ b/stockquote-week5/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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.java new file mode 100644 index 0000000..bc09f7d --- /dev/null +++ b/stockquote-week5/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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java new file mode 100644 index 0000000..708b52a --- /dev/null +++ b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/DatabaseUtils.java @@ -0,0 +1,65 @@ +package com.origamisoftware.teach.advanced.util; + +import com.ibatis.common.jdbc.ScriptRunner; + +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 { + + // in a real program these values would be a configurable property and not hard coded. + // JDBC driver name and database URL + private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; + private static final String DB_URL = "jdbc:mysql://localhost:3306/stocks"; + + // Database credentials + private static final String USER = "monty"; + private static final String PASS = "some_pass"; + + public static Connection getConnection() throws DatabaseConnectionException{ + Connection connection = null; + try { + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection(DB_URL, USER, PASS); + } catch (ClassNotFoundException | SQLException e) { + throw new DatabaseConnectionException("Could not connection to 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(); + 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/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/ProgramConfiguration.java b/stockquote-week5/src/main/java/com/origamisoftware/teach/advanced/util/ProgramConfiguration.java new file mode 100644 index 0000000..0b03a55 --- /dev/null +++ b/stockquote-week5/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/stockquote-week5/src/main/sql/stocks_db_initialization.sql b/stockquote-week5/src/main/sql/stocks_db_initialization.sql new file mode 100644 index 0000000..3437e25 --- /dev/null +++ b/stockquote-week5/src/main/sql/stocks_db_initialization.sql @@ -0,0 +1,15 @@ +/** create the stocks database */ + +DROP TABLE IF EXISTS quotes CASCADE; +CREATE TABLE quotes( + id INT NOT NULL AUTO_INCREMENT, + symbol VARCHAR(4) NOT NULL, + time DATETIME NOT NULL, + price DECIMAL NOT NULL, + PRIMARY KEY ( id ) +); + +INSERT INTO quotes (symbol,time,price) VALUES ('GOOG','2004-08-19 00:00:01','85.00'); +INSERT INTO quotes (symbol,time,price) VALUES ('GOOG','2015-02-03 00:00:01','527.35'); +INSERT INTO quotes (symbol,time,price) VALUES ('APPL','2000-01-01 00:00:01','118.27'); +INSERT INTO quotes (symbol,time,price) VALUES ('AMZN','2015-02-03 00:00:01','363.21'); diff --git a/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.java b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.java new file mode 100644 index 0000000..fa3e3f2 --- /dev/null +++ b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.java @@ -0,0 +1,68 @@ +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 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"; + String until = "2011/11/29"; + 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))).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/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/model/StockQueryTest.java b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/model/StockQueryTest.java new file mode 100644 index 0000000..6574e84 --- /dev/null +++ b/stockquote-week5/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,"2010/11/11","2011/11/11"); + assertEquals("Verify construction", symbol, stockQuery.getSymbol()); + } + +} diff --git a/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/model/StockQuoteTest.java b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/model/StockQuoteTest.java new file mode 100644 index 0000000..ad47fb1 --- /dev/null +++ b/stockquote-week5/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/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.java b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.java new file mode 100644 index 0000000..ae2a556 --- /dev/null +++ b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.java @@ -0,0 +1,22 @@ +package com.origamisoftware.teach.advanced.services; + +import com.origamisoftware.teach.advanced.model.StockQuote; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Unit tests for the DatabaseStockService + */ +public class DatabaseStockServiceTest { + + @Test + public void testGetQuote() throws Exception { + DatabaseStockService databaseStockService = new DatabaseStockService(); + 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()); + } +} diff --git a/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.java b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.java new file mode 100644 index 0000000..fd605e9 --- /dev/null +++ b/stockquote-week5/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/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java new file mode 100644 index 0000000..f775571 --- /dev/null +++ b/stockquote-week5/src/test/java/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.java @@ -0,0 +1,38 @@ +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 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); + } + + @Test + public void testInitializeDatabaseWorks(String initializeDatabase) throws Exception{ + Connection connection = DatabaseUtils.getConnection(); + Statement statement = connection.createStatement(); + boolean execute = statement.execute("select * from quotes"); + assertNotNull("verify that the DB is NotNull",execute); + } + +} diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication$ProgramTerminationStatusEnum.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication$ProgramTerminationStatusEnum.class new file mode 100644 index 0000000000000000000000000000000000000000..7a13f96d86b02d8a8ff8eb79fd98fe2c36cf72a3 GIT binary patch literal 2021 zcmcgsTT|0O6#lkN+7iOWf?SIzqP9gzRqzHPg~72i<)X#TFg`6Ilwg`*lA=$JKgb6K z6-P(MXMdFA*`z`d^~q^E-QBbMoju=o_UwND@#!mo3Ct^yakYh-YYMJoB97iTZYXHS zP0`#EE4LHq5U@MKm`b2a^wV+NWr!^;KU&Ne8B!~*Q*n89)o`n(&3)6cOFs8&-hy4L zGN=XHHr#oOd!FGjSVi5bYL07Gc-8crP5(J}4b3;WzNPVvU2f~fhQ@bxJk9eR{pqus z;~Ux>_e{Mc?1#e6@9bEn9z+`bSMVu@M1JlUPsIyZ%{v6WMUmnI?ypLj4^@(>9iB)pf&Nu z=@2(=x|y_Q=!z*Nr{?O$eN$A?@ZYcMxF{+WmylM`Bi@=`6*IUO$1KBk^Bx5iDdbh0 z!<>q4oED=I6&*;b=t7dA{iycC2Tay2$0ljr=}beam)Exq-6#2r|CKt!WMcsb&*oG^ z*u(31oF(z-Y4oeZsFr7Q^kTQugD=hY3zY!%B$Q?%LO;+sAdZ9V7+TPWelQG>HA21k zls!Z~Ao>l`8?qP%sf`6|eS}Y8sE(hY{e*{-l(QcZ`vzIyBggP(XhscD7{=LPozhPz z5%B?{kOU$-mO4N@JM OMZH338I$Oo9ry{N_!|iT literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplication.class new file mode 100644 index 0000000000000000000000000000000000000000..161fe9df3e52886d2ed21fddf60fc90828e88c67 GIT binary patch literal 4317 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 W_w_p8JH)xf?l^vz*`0#nRp1+ro@ literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/model/StockQuote.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/model/StockQuote.class new file mode 100644 index 0000000000000000000000000000000000000000..b4359c2a15091b4fb4f10242c3fd16ec3aa9c3f7 GIT binary patch literal 1550 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 literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/SimpleStockService.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/SimpleStockService.class new file mode 100644 index 0000000000000000000000000000000000000000..da1d221a8752de990ad59aa8f920c36119f8505d GIT binary patch literal 1751 zcmb_c+foxj5IvJ@vJfI53K$id1fm#DAc+w* z+)f~ZQ5|;@Xu_bf+-<=v+|x0pHsd<(>zL4yWr$A-SI8VgG@W_Dpv`$Di=nL`T{et^K?Q2F&u8Io7biwo-!}CR%JEG#P$k*Jr3~6z5)!?N~?wVG~ zs964{Fs+JF6wZci6{Tmc7egD-XewLsS=E!2X)#?`k4ahp5|h zf`9`kb-T)zv+UW5{t--u!ZDe`xT+MkF~@DoEpb14oGnvlEQpGvWZH`FISgm(Jo^v~ zv8qd;3@w#?f>gTpy5Kz+KF_xrJ@Z^zl%T7z2U{C^eONezGWk#C%2A3_Maj+e$9yB` zu#QO`Qw+^TQFghk`qZ8`|FLNQ&NET;s=jIEh0sv}w zJhb3mz0hergl4*U8-^+42u5)m6Ex1@Zon@WX5QzQukj-`=s|D5K95VZiW1HgE>n3m qLL0+XT%(FyrwpoQq3;IyZU&af547pHr6WCx3|S)Rqp1F1HSinw|H|9| literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockService.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockService.class new file mode 100644 index 0000000000000000000000000000000000000000..b387788568f58545547b0f44ddd9511c3b586aee GIT binary patch literal 589 zcmb_aK~BRk5FD4%v;_+Mf?n{215ywYLR3PEgiv0vI7@IzY~(nBJHO(<19%j|Nl@X? z1FAULJL{R_^y*uqQCi+27XIv%vLHvZRJ&K_-`}ciQCfJW;lk*6Ex| zUDq1^q!6qXY zufyiQz(iL*$WKz88}hXaZNL7b^w~z^p0@+1wswjax(F>Dc3!0H8m;)aHC5pB4@Oo! zqw2l<<_jGBtmWoz$;t~{Y^t`}%Sb?A5IzGi7z%7*7~<^^wdbfqqL5!97`HDm3E63P G+xY^&N4Tf} literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceException.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceException.class new file mode 100644 index 0000000000000000000000000000000000000000..0aa546a1cfc431e58aba78b8647dcda4277bf7c4 GIT binary patch literal 617 zcmbtR%TB^T6g^WORYVaGOk8Pnp)q++tEYGQ1VqI?8QovhBA(Mkb3>e#?V-k_(zA{$mp4k zme$A#K8Z=GwwA$A=<10P@>bbu2Wt~u*bGJFkhf!p;ribt8LHpKR@HHY484*4958E0 z(+jcW(Avs>kAg`w+Im*MQoFX)!JEV-H}Iz&fG@xd=BTg d*fCu?NyQEqw3V2<6r-ysVVA5J$|U5V@&%NDkyQWy literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceFactory$1.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceFactory$1.class new file mode 100644 index 0000000000000000000000000000000000000000..f2d7453601b6f157b66542f8a9ab5420583a749d GIT binary patch literal 2050 zcmb_d-Evb^6#jN{lGCQ4t^8DifI z%pi$RGsxmI^K&bM1U|R%MFwNIVK@sDD4=9x(OhoZSh8_PAie1Nu3i#I<_k{+ta8v& z0#kL@R}Z_LrV5|Prbo{4df-U!sSI6nA22Pw;YI@4n(wQy?8zunyq4=u&?yF?+m;EGE_yaq_a_!tu5(0s#T0sxaB%3DmHZBylC`qRq5y;>|MBC5*TYM{kR)w+OFm6 z&*hdZdeU!GKXm>Gw@76|H2f=tbFUJP3;DLWaF+t{SeFj zcU|pz#j^C2-;!bJFkWGZS$88%06?SV+}2x7prnJ?g1OiHtq?GH{7-_bvI`6 zz15L=qj=A4SCr#+q-PMT2K#;%U!rEN4+Kucs&P9lhoS758fWnp>RGI!&OY6j@Ait3 zJQP?yf@}XhW&(F#2ZK!}n=(?v$^0K~?9H0M$;zFtU zkv98Bpprk*2HDHsVX>Qu&ezP^oFUqN2)lKn+@{edZifbskEjghwKN!&1D!IwPh!nJ z_{jdF)s$SNELYso~bL_ z5I>Pf-~@luG4l*glFs%Oa0>78#%V&1TIO*bDN?}c9VFIvkX)N?ZNvH*sh3D!-G==m zWy5%9W4xLEn*knQ;|$&-?)%iXc%F@IoTH=0#-H>h&9l0Lv9)cCFIclgUr1fc(Mslf z%;l^R>$#M%{0k-$cs4towqD{`|G^J`|B#yHM1F&F5?Ma<(87H}D5 z{#BaDm-?3XJgp8qr8oG1DK)WI@e!#cac&dsJkh6ci+C5An@g0N?Db`rDa*&4#9x@Q kQLu4kekkgzlqE1rtZOkf$Kn`oKf!g(kjfBgk|#g^0Oyq`uK)l5 literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceFactory.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/services/StockServiceFactory.class new file mode 100644 index 0000000000000000000000000000000000000000..37855d009c754381c99b7ae760bce58b39648c5e GIT binary patch literal 608 zcmbtRO-lnY5PjKxZ>z1Xig;4+(0VWk-V{Yz3WcJFO2K0`jcsbXfh4W?uk=(<@CW## z#97-zuhIlE^WMz7%p~7GA7212upc6WY7Vs!L1K4v*kdSl;#k?{L^!7$L-tC?+FvuI z>Ww}_x@iWAq1@H6x|>ZSWgkQ|A*R|jQcU{7>IARIv>$2Gxa~?a<;Lovm}+O9{EM)P zdnM$Ei@{vPQVqCMcCMvzyyuO4?k!PUNN?=xB|~wjd?$83NoHu(8~@U52`?hy)Vel_ zhCMU0Qnht5!NGcPb@AC)%tZ+~$Po5aMJR+05wz?ENns(wY4uYbcUmS|*U)B2>UO%ETnaM7OJs;CL{|3SJy`%CWUhp>wZA0(LI$J^M~IlE*w@KN{R r@B!kUVFeNU21j62C9VXEu#6@T31|hY+|8Hbtb+AdOmK>B literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/DatabaseInitializationException.class new file mode 100644 index 0000000000000000000000000000000000000000..3f8091cb2eda1db06dc933bc6cf8349572a75842 GIT binary patch literal 529 zcmb_ZO-lnY5Phj_S8M%h6+J3=&?@HQZN-aU6c#Tny-(A)jqGk@H`|K;%9G&1AK;G? zCn_o^cyR*Bn>Rz=8|L}t@d>~oRvVbXN`O{?wm|*JWX2r}batX^nvhH=i)GK{CX2&w zOn;o)DGd`H?hXX1Cw8O-mLiks%Q7A6yzgrQt;i}$29z70e~?u-HibYpQZ|(~H!-EA zuvczMxt30o8cP~YC{ubQOJ@>!N{)t9=q_6`l$bkm#%5=?O5b=83IwSx3X0zpf7lkN zDJlytuKhZJK%-~NT^2P$Op}_V__9A}XW!-* z&~eWEzCUW)bJMg9M|O7H>B+shzt`vYa)0TcfBpUkfQ$H9!x`L8!F{k2g8u!vD zrZKN!0ryorQ1MX3qKcA+jFfyN_azNiu`J&nYv{rg4N0u1c&gzTeo*nFhF&~V@m#}k ztV-ff@=bK%3d(X3Dhw5sG)xTxc%ouWLD${cnZoMq;@tABMFrX7rq~j?Eu3||6nK`i zKBeGb!FBvVIKi^8>!yO#?9A%YVo^bIsU($>4{nx9Bww=}E0|W$F+8$NYQe2g_;As3 z%!PWjYUj!wPlBKWMwKWVOwv_CQv#Zj(Lr;D>Iey>cs6S zI2T55l|^9rIulWK9euM>HuRF=S+!s>6eG$m%c<1^S};Ym6^rHSb8RxEQe;=8*^>>o zdj%FlCdH1mpwg}DG+e2$7*WZsdxm-23ai$PBTV?DY?BN|FiQVKI$3?gG)+pdle3<+ zWqK+$Gk5`8!KMFIQUzzEwR~teuj{sKnhn4je-NdTQyf} z!uM5FGdK^nK(5`(1)H1&H@NNAol2`v#2$*s3YQ)hWAwu3Vs3X>%t~JyK%?9F9A+^mG4)1OIHcMZ!%k74uDRZVsB%=C z+wa!KE^?^AT=s@GB!tEVm=}&%m)CE89|JM{Xb^l#`M3F%61AG?R1{3?V>nWZ4e+Sv zh*0B*oHu=+uz2m8^D!n$nRMVblQO!G`54Ma8=m`0PVgx?!}=rPy(O4>`cyKHN6ftw zDAYT^+1D63ELU4Bnod%=)39BifK%+Usuf_6AH6gDiYC#IA)Ey(#8ZO5eta1_ck=vI z?406xICfUiL0wKTu4A;Ib62=`j_yEt7n&UBnhJ^CnBaS+A%IB=0|(@7q+6-{E8!%# zUs3L56YtUSINO;`W!3jc-}?na#a(o*>>{(WgM-;a+c-S7jc#t+I5M__?8njHLi}0u z&}ag3*N9HKKMj@ZDN;`(&5w4LvG*Xy5B(r6F@6cFm)u_RzQF|oOptz&4{(`JHxhqS zK~een=W=xb-;$c7To--iF-3U>pybfWAF!$v-{U9&A6psg=-5He{4RP|n3BGQT^wJT z*ujZ>a{NSc8~t)QIragkn7AtaR(SAA# zIFCbwF+r-%+@Hr0=D44Mon=U)3`u7om-shm3g6L69@qKy0N3ywH^O90Q|kyNuaPfX zVvthTY5OetC~=daUyo8H>$Qp*a%B5F3zMdVNjoZ&HjRXe!l!u~VD4r^m0SM+Tnd0m literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/ProgramConfiguration.class b/stockquote-week5/target/classes/com/origamisoftware/teach/advanced/util/ProgramConfiguration.class new file mode 100644 index 0000000000000000000000000000000000000000..7d57f7c61f44d5dc72ba8b8f31b8901dcabc7b9b GIT binary patch literal 459 zcmbtQJx>Bb5Pi$1APQ2UogG-Xjh%$VkXT*RL_9Jtp*D33tI&-&vp0D;=3!Mi}^qqIHr*!JF zCC9m^z%IK~7{oSQZ8iy;l98>A^?|K;4~C;?O*{J0e@{f!zIVAd_L_@)$A4L$7s?K5 zs4I;BlTo2phDa!j_3eCZO~5HCa>(LUAcsR;YD18guB6w`UZ9@KaZ_reBwN^%f9Gof dEwlx-uwOET_@tbOrFs&i@T)8|2f|fw_zC>0akKyc literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.class b/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/apps/stockquote/BasicStockQuoteApplicationTest.class new file mode 100644 index 0000000000000000000000000000000000000000..3a2e06c99b607fe1659645d606157e6e60a8981d GIT binary patch literal 3700 zcmb7HS#uOs6#hDyq=!id;y{o=)M3*Q2u(l~5=4_Ah)zOaLNvH`dM=ZOneL&NKwNR( zaNqak)hDZz1XE>US>=P}yZ#!>?{-fzosd)wMKO2jbH1~mbMx1Kzy1c`4*ZZp2ZmJ~ zPvHdeD{wnTRGdtq38V7xP!bQPFosh}Jd(ttNj#?F@f2F|go-CqSS48v72_$SVaoeL z3L7Bg?sN(_pxA;5Sn_yA#n}`}D66nr&;UmYthC@9Tq(^K9&g7xEuXPJ55G0z?k9AETRDkaM_e9N&F9Lt$bS$ABkXp}9_Iqjb}T%r5IFeh}Q zFlpGPDCkC|;_03QI41%0{$&As6|{wfdEri4rWhoTf}VPWcoB!EhniOTiPwCJ7SENc$3aKrcoL-TuYv-mkEEu@)YFjQJ{V+M}+57 zvnEgYCo2jvCj#5I%3{>=EQ;>4ZO0GYOUcyAE$U|inxOZK(~c|1*zOZx)F@en0mt@y zH!!1Mw8e<4GSZUtkmXfM#?%Sn1tp)L&E8ab+$l-)GsdK$mkhf|x4D*GBzoes>y)XT zREjjIFdoMP;Z7;oTaP2k^l&K(L&!$VmMRFNPx)<;*ns$Y&I)~zt`Quj_(O)zkX*ks z;#1n{8rVr`M18Z+Gw2v&(>%eteE9D=g2C4fln4%)1;;DE>#j`Y8 zMq<#g>>*KPbSG(FQe3DA(-#E=*;piof>LSNv20(s^Dq)K?*y(X4qGx?H!oj9GV(iR zTs3rIr-FTTROph$qvAOY&*P$o?bxAUunwI1Yd|XZf`)DARIn~ICTqr$IeXr5&(e1< zYIq4RGb#IqhjaA7?p@v8diO4U_x|}qcX-%Shjxn-Q|j;v(jf@)jT+iBx34-rZ48|5#F$UOB4TYOTM|BN@$Zr7&)W9A7pGPJ*~9Rl$;VfBe4M*<&g$ zdlOE`j-zr>i^7+!nEkS&YF=0(bLmF|CCLZ}7t?bAiR`!hyn>(e)k(8vj$q-e>8x*tNP#6<5}ZBC6R&qrhIeq*G3@-BO=$97S8Uul=J*xe4OK0KV}y>35xmZnO@xz zSA97;HbhbM*a@|^^g%)MMCb8Bb1VFry?(eMir zHINiP16cxWi~+S)f%fv76mut61$WJZ9zh}mZSR~#(^%)vNKB*o7pUpv3|7>@SE7-O zTlvbr4Qps@P1E*80``Rh_ESKk)LQwDE?B|4e-{f#<Dj0tz+AFbWLMrPhu9U z#-`EM(=>}4#%7ToYb#7+btZ8cYc8W*u4|`pV^4FYDbsuf>l*OTHH4Wsp-MtEB9x}3 z*U#Xlt5~1j5Uv~M)+@L2Ak7cGRYm)?bb}P zE80pQH9|(QA8q{IP9N>ypFmw`rw`WA2V3Z^E_x})h>kLz0rv6{a~FQZeq2TmerII= z#sU0;gP~s^jr>*hYZ`x&rk6o##~-AUS+EXQaW{93#QvFF_b`ZE#Jd-L^mY!HsLKGu z9l*pP?o`Uzg!{;m#9`_vb1b4iLi+o8(@fN(cz~KkX%a>8!TB`VLyj{800cU{01ERANubL^8f$< literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/model/StockQueryTest.class b/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/model/StockQueryTest.class new file mode 100644 index 0000000000000000000000000000000000000000..d49fa9875ecf5c15e132e28a31535aa401d8001a GIT binary patch literal 1040 zcmbVLYj4vq6g}=MUC7pwZLl#O9nW?hOUpwD4I!0j`xIc%sS+RE)azW581fkOXYqw0 zkoW=oD8zMJtwWO#YGnC7?0fFIH>rq*2O>_k8I}{WFL*4y z9Tmn&lzNF&A@PcbL09>@@qiz5$LC?6sv{ZpsmhE`aTp%Y(q4n?e)hx%-7Yq;!La%^ z4HFrNj*KOpu@#0Y;iF}Sva6!LGe}7*XTscUt2FY&p49Rz{(Z15&Dny5d6KlXzwa_U zoIxYv_@L2jIL#)FaiBdK8oN$yJ0g;Y!-{uCI}4k*Z(z%Ug9gKs8T#rI(wV2izwQo% zN2$eW>Qp?s|LXZW`k#z`aC3c;v?o`+RIQyaBOX)fTX8HR;$iWTv->gSzJ7rJCNO5d zeFl4ysdcap{j=yV1H#2T%?lJcWEt7~#tGP$(Q=9A!YFB?OujYVfQzsxB5|lVJ1Q2) zlLxHX8TSXW@9K8W&Yz(0(l+XwUs3#qxhbTL9Bo~of)c@&afJXid}RzVfzM(EOIW5h dW#W4Ymx=ER?aEPRm1@S+*2pqkr8$FZe*nfb3UdGe literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/model/StockQuoteTest.class b/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/model/StockQuoteTest.class new file mode 100644 index 0000000000000000000000000000000000000000..b453f12094b03c3886029f12cd4fbd77c7a5c245 GIT binary patch literal 1699 zcmbVMYg5xe6g^uWEg?v$JVZt711v>}3Wx}zyalTwMP~T8q)S;$6HT@_{w!yBjn4Q3 z{85f~)6^E}j5B;lcJJQ1=bn4_?Ed=w{U?BNY#QjnXdIS-7#_Bv8;=Y;#+d$%YjYxj zCwiQWAvUurvAY*u?RV3@i{?oAOW%HI+Q_2Cmk|3=wWvLv=- zASuC|>w1bS>A8eYx&5NGUnZi~yx8@8-5XO8z=}}omF_0%Vj}4FC_*=rp(C>LQA>@y zSN3hOEOm94Ydz7MNA*dWxPhAt-HlF7`<6`fqA!kR6DxRSVijv9uArZqIJdr@GjSEy z7{)GeEE@f_iR&03)#Uf+Ak(3S(lSWfp6?4=naJTy9B)m$!#YDxB}xnFOwfC*QTr+- zr_XpckY|{@06E=6+_K6TxomtfiN`;QcaoR zI;~fu=uG1jwn-u&lrtgGb(qdHzCv|iVdVMCqKPF4JQB;5D*E}$n5;={E(nBAg_%5@ zEPXC>N2@(zQGXfhGFI9#eSSrA&;?fH*haIe6uYZ*>LGE9UYH(woto)MBB9YNrsWlm zB&~2HiO|>rrnO4{G+7pnOs{57z`oHWMo>U&xY&u?G&d^&xP!Z7F$~h?Sh(4X;wG{` z5Zg``PSA9O=Ikk2j?sFAcs7+dLK``a?d%~r4r%ESZ6|0yf>}$}OPoM#JBV)|U4#MR zJ5GYGC7+0r4@K1Og+wxciM&8lNU|%{5hXH@ap@GDwIuqj2C+_3eKp{&e}IQW;A{in pWW=6;yBYuw67bM}fkzqur*uo`BjC#ofU^WV@?YTl#5;xue*iC0gRTGo literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.class b/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/services/DatabaseStockServiceTest.class new file mode 100644 index 0000000000000000000000000000000000000000..dea85990605cb25e8865a3ea296d6d294fbb34c2 GIT binary patch literal 1379 zcmbtUT~8B16g|_HZYc}21w}w~iyyRntqQ0FV?+UCQYu=~#K-A&Xa~BxvO5d%;(zi5 zh$j93f0Xg=wo;;)5NVUSGxyG%d*+@y`{U==?*JCDoQ96PhRHNy$fs~8w0Bdum&Sce zrBFzti0N=KqhVIV97FP%bfkLD5HA#~42f56T`&xmq$A3KT@&6mueHdNE4dbLRk?dqAGn!HC%NZSMey!kSV!d!`ux> z3$s&saVQLnJ4Qn& zgBwv{jQvm`W5;uCLp6m_uW5Lw;}I4Z#y9z%F#Nz1QK(&J->|u|ni>{$Ea9<^CwR)R zc2&M%rKomY0pHekg+;ERuIo$$h7?_)qv@N%-?A6~Q|C-qx>cXrobvbcXi|1nIcQOn zOupNw`vGs!n_a#XqjNxK9Fa#K zeP+U640Kft&^SmdlPn|KGkpT~B?@O~Oh!%}S(@wZ4ai}LR`kN@a6CHvnQVf5liv{g zaDsR#m)M+{Jw{JCmz+C=mP^gf9i#UY=`QjZVFMYY2)mCkvxGWAn0Z`_vQ4)UJK0hg oBmZ^E+DE%aaD(V)=|4*TIK~MnL9v^dpjpWI7FmYdG{#{30v_jpYXATM literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.class b/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/services/StockServiceFactoryTest.class new file mode 100644 index 0000000000000000000000000000000000000000..13d94763a07f7433137e65f89e4006beefd54b03 GIT binary patch literal 854 zcmb_aOK;Oa5dPLlW9qtTD6~*0l-?4M*b66$Kvf?I$qEvwa-VFLbc3@idDlVwEKXD$ z_yPPV#Mp_{2#Es^ALc#Z%zWPOKfZng@C=6u)^Iz)4t5jV!QB{pG42VpUKne_OMynW zHxy`|xUm-4%8b?hayHV%1&wl!Y-dhUKBU4_{xaAMm&Oa6Wy;N@E6jvu#=H07BNbW( zP3lt8curR7vGlr_8>PJ*1gAa>7T!6j;EGQd+J_^a8d$&9;f?j7Y7$8OO0mH6zaGTs zd+$mc%uElBH+;gewJuOF&hiDF%oP(kEtv|rTqYT~vQYZmRM+qSX6dI>np27v;u!Z+ z?BhX~ynV&pGN1afl{A&gzT6FA_1!8|+Eeg7w*TU^?yfp!HfQ-N PuB-;$tl_s=M!5A8G&tty literal 0 HcmV?d00001 diff --git a/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.class b/stockquote-week5/target/test-classes/com/origamisoftware/teach/advanced/util/DatabaseUtilsTest.class new file mode 100644 index 0000000000000000000000000000000000000000..75ed0e2cfda83a26490a61f183599f9ed9f74795 GIT binary patch literal 1694 zcmbVM+g95~6y0M4a%@Au;Sxe=M4Ah?M7@x-sZ&xe2~Czm)+&^)#oHhTBO*(UG$Lsq z`$v5$=|exDAJx@8lCYdr@)AF2W{%F;XP-S={^#Gn{sypu=QRxDP7U)|sA92(B`nu* z7x$`g>-ZdBRPm(=epSUv4fpZD#@9B!5g2;phrV7F7?@w!6Rr6nET{l(V`;-^u^={W*$XahyvD%T!l|T422F zy>lLAYg@flUaF~!*cX^FNY4oE%fSCloex>SP0Z&QfebtDj*k7X(=t*wjqvYR7@4zK z`*S(yPL#%;dg_~tm^_E?X?V|+G%$k8Hok43g+~InPgU$6{p#prshu~<@nq<9ly;<3 zD(ghAY<$;ezbphv!!4!4^Bv3;7S?lSw!IeM>P=`rf#M0 z1g7Q}N>h|C=!((OV{1vGVp18F*`}CS;LZhR=)3ZKg3KQI5bv9wAEp;8nzQFc`k|jr zFHSbiOa%kbiwaz5Mq0R*^W2S7W3dZJ?in?vtlSFqZw&Ys~?*?JO#Oufp2Y19chPPl6XGZYqcm>z|xf n8Ml=jtKdddzPm{oEOIwORah~Ru^ix9&sbU?WO<9cD!Bb0LkNyX literal 0 HcmV?d00001 diff --git a/stockquote-week5/week-5-stock-ticker.iml b/stockquote-week5/week-5-stock-ticker.iml new file mode 100644 index 0000000..bad55fd --- /dev/null +++ b/stockquote-week5/week-5-stock-ticker.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file