Major overhaul: coh++, test cov++

deliverable_9
asdfasdf 6 years ago
parent 08d7475257
commit 30ea1ec59c

@ -4,6 +4,8 @@ Author: Benny Leung
J-WatchList is a simple stock market watch list tracker. J-WatchList is a simple stock market watch list tracker.
## Dependencies ## Dependencies
External libarary:
Build deps: Build deps:
- gradle - gradle

@ -0,0 +1,31 @@
package data;
import java.util.ArrayList;
//Singleton pattern from https://www.tutorialspoint.com/java/java_using_singleton.htm
public class ListOfWatchList {
private static ListOfWatchList lowl = new ListOfWatchList();
private ArrayList<WatchList> wlists;
private ListOfWatchList() {
wlists = new ArrayList<WatchList>();
}
public static ListOfWatchList getList() {
return lowl;
}
public void addWatchList(WatchList wlist) {
if (!(wlists.contains(wlist))) {
wlists.add(wlist);
}
}
public void delWatchList(WatchList wlist) {
wlists.remove(wlist);
}
public WatchList getWatchList(int index) {
return (WatchList) wlists.get(index);
}
}

@ -1,5 +1,7 @@
package data; package data;
import java.util.Objects;
public class StockEntry { public class StockEntry {
private String identifier; private String identifier;
private StockType stype; private StockType stype;
@ -24,4 +26,25 @@ public class StockEntry {
public String getID() { public String getID() {
return this.identifier; return this.identifier;
} }
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof StockEntry)) {
return false;
}
StockEntry tmp = (StockEntry) obj;
if (tmp.getID().equals(identifier)
&& tmp.getTypeName().equals(stype.getName())) {
return true;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(identifier, stype.getName());
}
} }

@ -45,7 +45,6 @@ public abstract class StockType {
} }
//Effects: return name of type //Effects: return name of type
//Require: working sources
public String getName() { public String getName() {
return this.name; return this.name;
} }

@ -13,23 +13,41 @@ import data.Nasdaq;
//Contains one instance of all supported //Contains one instance of all supported
//StockType //StockType
//Singleton from https://www.tutorialspoint.com/java/java_using_singleton.htm
public class StypeMap { public class StypeMap {
private HashMap<String, StockType> smap; private static HashMap<String, StockType> smap;
private static StypeMap stypemap = new StypeMap();
// Effects: smap is initialized // Effects: smap is initialized
// with supported StockType // with supported StockType
public StypeMap() { private StypeMap() {
smap = new HashMap<String, StockType>(); smap = new HashMap<String, StockType>();
smap.put("Nyse", new Nyse()); addStype(new Nyse());
smap.put("Nasdaq", new Nasdaq()); addStype(new Nasdaq());
//smap.put("Jpx", new Jpx()); //addStype(new Jpx());
//smap.put("Sse", new Sse()); //addStype(new Sse());
//smap.put("Hkse", new Hkse()); //addStype(new Hkse());
} }
// Effects: Returns the StockType // Effects: Returns the StockType
// Require: Valid typeString // Require: Valid typeString
public StockType getStype(String typeString) { public static StockType getStype(String typeString) {
return smap.get(typeString); return stypemap.getInstStype(typeString);
}
private void addStype(StockType stype) {
smap.put(stype.getName(), stype);
}
protected StockType getInstStype(String typeString) {
return this.smap.get(typeString);
}
public static StypeMap getMap() {
return stypemap;
}
protected HashMap getHMap() {
return smap;
} }
} }

@ -8,31 +8,30 @@ import data.exceptions.*;
public class WatchList implements Load,Save { public class WatchList implements Load,Save {
private LinkedHashMap<String, StockEntry> listdata; private LinkedHashMap<String, StockEntry> listdata;
private Main mainObj;
public static final String DEFAULT_SAVEFILE = ".jwatch.list"; public static final String DEFAULT_SAVEFILE = ".jwatch.list";
// Effects: List is empty // Effects: List is empty
// or loaded with save values // or loaded with save values
public WatchList(Main mainObj) { public WatchList() {
listdata = new LinkedHashMap<String, StockEntry>(); listdata = new LinkedHashMap<String, StockEntry>();
this.mainObj = mainObj;
if (fileExists(DEFAULT_SAVEFILE)) { if (fileExists(DEFAULT_SAVEFILE)) {
load(""); load("");
} }
ListOfWatchList.getList().addWatchList(this);
} }
// Debug constructor // Debug constructor
public WatchList(Main mainObj, boolean debug) { public WatchList(boolean debug) {
listdata = new LinkedHashMap<String, StockEntry>(); listdata = new LinkedHashMap<String, StockEntry>();
this.mainObj = mainObj;
} }
// Effects: Add an entry with key==target // Effects: Add an entry with key==target
// (XXX For now, only Nyse) // (XXX For now, only Nyse)
// Modifies: this.listdata // Modifies: this.listdata
// Requires: target doesn't already exists // Requires: target doesn't already exists
public void addStock(String target, StockType stype) { public void addStock(String target) {
//The only implementation yet //The only implementation yet
StockType stype = StypeMap.getStype("NYSE");
this.listdata.put(target, new StockEntry(stype, target)); this.listdata.put(target, new StockEntry(stype, target));
} }
@ -96,7 +95,7 @@ public class WatchList implements Load,Save {
FileReader freader = new FileReader(filename); FileReader freader = new FileReader(filename);
BufferedReader breader = new BufferedReader(freader); BufferedReader breader = new BufferedReader(freader);
while ((sss = breader.readLine()) != null) { while ((sss = breader.readLine()) != null) {
mainObj.addWatchStock(sss); addStock(sss);
System.out.println("Imported: " + sss); System.out.println("Imported: " + sss);
} }
breader.close(); breader.close();

@ -5,9 +5,9 @@ import ui.Tui;
public class IfaceFactory { public class IfaceFactory {
// Produce Iface given the config // Produce Iface given the config
public static Iface getIface(Main mainobj) { public static Iface getIface() {
//uses Tui for now //uses Tui for now
return new Tui(mainobj); return new Tui();
} }
//public static Iface getIface(Options iOpts) { //public static Iface getIface(Options iOpts) {
// //XXX iOpts not ready // //XXX iOpts not ready

@ -11,8 +11,6 @@ import data.exceptions.*;
public class Main { public class Main {
private Iface iface; private Iface iface;
private Options allOptions; private Options allOptions;
private WatchList mainList;
private StypeMap stypeMap;
//Constructor, not the java main //Constructor, not the java main
public Main(String[] args) { public Main(String[] args) {
@ -21,11 +19,10 @@ public class Main {
allOptions = new Options(); allOptions = new Options();
//parse args, uses //parse args, uses
allOptions.parseArgs(args); allOptions.parseArgs(args);
stypeMap = new StypeMap(); WatchList mainList = new WatchList();
mainList = new WatchList(this);
//initalize UI thread, options not ready //initalize UI thread, options not ready
//this.Iface = IfaceFactory.getIface(allOptions.getSection("ui")); //this.Iface = IfaceFactory.getIface(allOptions.getSection("ui"));
iface = IfaceFactory.getIface(this); iface = IfaceFactory.getIface();
} }
//Constructor for testing //Constructor for testing
@ -33,48 +30,11 @@ public class Main {
//init options, it will load defaults //init options, it will load defaults
//from resource xml //from resource xml
allOptions = new Options(); allOptions = new Options();
stypeMap = new StypeMap(); WatchList mainList = new WatchList();
mainList = new WatchList(this, true);
} }
// java main // java main
public static void main(String[] args) { public static void main(String[] args) {
new Main(args); new Main(args);
} }
public WatchList getWatchList() {
//XXX volatile, threaded consideration
//instant/cached?
return this.mainList;
}
// Consider moving all to watchlist
public void addWatchStock(String target) {
//XXX Concurrency not ready
// Should add runnable to executor
// nyse only for now
StockType stype = this.stypeMap.getStype("Nyse");
mainList.addStock(target, stype);
}
// Consider moving all to watchlist
public void delWatchStock(String target) {
//XXX Concurrency not ready
// Should add runnable to executor
boolean success = true;
try {
mainList.delStock(target);
success = true;
} catch (StockNotExistsException e) {
System.out.println("Stock: " + target + " doesn't exists");
success = false;
} finally {
System.out.println(success ? "Deleted: " + target : "Failed to delete: " + target);
}
}
// Consider moving all to watchlist
public void saveWatch(String file) {
mainList.save(file);
}
} }

@ -7,7 +7,8 @@ import ui.Main;
import data.Const; import data.Const;
import data.WatchList; import data.WatchList;
import data.StockEntry; import data.StockEntry;
import data.ListOfWatchList;
import data.exceptions.*;
public class Tui implements Iface { public class Tui implements Iface {
private static final String SAVE_CURSOR = "\u001b[s"; private static final String SAVE_CURSOR = "\u001b[s";
@ -16,12 +17,10 @@ public class Tui implements Iface {
private int maxrow; private int maxrow;
private int maxcol; private int maxcol;
private BufferedReader stdin; private BufferedReader stdin;
private Main main;
public Tui(Main main) { public Tui() {
stdin = new BufferedReader(new InputStreamReader(System.in)); stdin = new BufferedReader(new InputStreamReader(System.in));
getMax(); getMax();
this.main = main;
//XXX Start ui thread //XXX Start ui thread
demo(); demo();
} }
@ -133,13 +132,14 @@ public class Tui implements Iface {
demomenu(); demomenu();
cont = demoinput(); cont = demoinput();
} }
saveWatch(); WatchList watch = ListOfWatchList.getList().getWatchList(0);
watch.save("");
System.out.println("Thank you for using " + Const.PROGRAM_NAME + "!"); System.out.println("Thank you for using " + Const.PROGRAM_NAME + "!");
} }
public void printWatchList() { private void printWatchList() {
WatchList watch = main.getWatchList(); WatchList watch = ListOfWatchList.getList().getWatchList(0);
Iterator watchit = watch.iterator(); Iterator watchit = watch.iterator();
while (watchit.hasNext()) { while (watchit.hasNext()) {
Map.Entry entry = (Map.Entry)watchit.next(); Map.Entry entry = (Map.Entry)watchit.next();
@ -149,19 +149,25 @@ public class Tui implements Iface {
} }
} }
public void addWatch() { private void addWatch() {
System.out.print("Enter your stock number and press enter: "); System.out.print("Enter your stock number and press enter: ");
String userin = getInputLine(); String userin = getInputLine();
main.addWatchStock(userin); WatchList watch = ListOfWatchList.getList().getWatchList(0);
watch.addStock(userin);
} }
public void delWatch() { private void delWatch() {
boolean success = false;
System.out.print("Enter your stock number and press enter: "); System.out.print("Enter your stock number and press enter: ");
String userin = getInputLine(); String userin = getInputLine();
main.delWatchStock(userin); WatchList watch = ListOfWatchList.getList().getWatchList(0);
} try {
watch.delStock(userin);
public void saveWatch() { success = true;
main.saveWatch(""); } catch (StockNotExistsException e) {
System.out.println("Stock: " + userin + " doesn't exists");
} finally {
System.out.println(success ? "Deleted: " + userin : "Failed to delete: " + userin);
}
} }
} }

@ -10,13 +10,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
public class NasdaqTest { public class NasdaqTest {
private StypeMap smap;
private StockType naasdaq; private StockType naasdaq;
@BeforeEach @BeforeEach
public void runBefore() { public void runBefore() {
smap = new StypeMap(); naasdaq = StypeMap.getStype("NASDAQ");
naasdaq = smap.getStype("Nasdaq");
} }
@Test @Test

@ -10,13 +10,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
public class NyseTest { public class NyseTest {
private StypeMap smap;
private StockType nyyyse; private StockType nyyyse;
@BeforeEach @BeforeEach
public void runBefore() { public void runBefore() {
smap = new StypeMap(); nyyyse = StypeMap.getStype("NYSE");
nyyyse = smap.getStype("Nyse");
} }
@Test @Test
@ -30,4 +28,17 @@ public class NyseTest {
assertEquals(farray[0],0.0); assertEquals(farray[0],0.0);
assertEquals(farray[1],0.0); assertEquals(farray[1],0.0);
} }
@Test
public void testEqualsHash() {
StockType testst1 = new Nyse();
StockType testst2 = new Nasdaq();
String asdf = "asdf";
assertEquals(nyyyse, nyyyse);
assertEquals(nyyyse, testst1);
assertFalse(nyyyse.equals(testst2));
assertFalse(nyyyse.equals(asdf));
assertEquals(nyyyse.hashCode(), testst1.hashCode());
assertFalse(nyyyse.hashCode() == testst2.hashCode());
}
} }

@ -14,13 +14,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class StockEntryTest { public class StockEntryTest {
private StockEntry entry; private StockEntry entry;
private StypeMap smap;
private StockType nyyyse; private StockType nyyyse;
@BeforeEach @BeforeEach
public void runBefore() { public void runBefore() {
smap = new StypeMap(); nyyyse = StypeMap.getStype("NYSE");
nyyyse = smap.getStype("Nyse");
} }
@Test @Test

@ -10,16 +10,14 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
public class StypeMapTest { public class StypeMapTest {
private StypeMap stypemap;
@BeforeEach @BeforeEach
public void runBefore() { public void runBefore() {
stypemap = new StypeMap();
} }
@Test @Test
public void testGetStype() { public void testGetStype() {
StockType stype = stypemap.getStype("Nyse"); StockType stype = StypeMap.getStype("NYSE");
assertEquals(stype.getName(), "NYSE"); assertEquals(stype.getName(), "NYSE");
} }
} }

@ -16,39 +16,32 @@ import static org.junit.jupiter.api.Assertions.fail;
public class WatchListTest { public class WatchListTest {
private WatchList watchlist; private WatchList watchlist;
private Main mainObj;
private StypeMap smap;
@BeforeEach @BeforeEach
public void runBefore() { public void runBefore() {
mainObj = new Main(true); watchlist = new WatchList();
watchlist = mainObj.getWatchList();
smap = new StypeMap();
} }
@Test @Test
public void testAddStock() { public void testAddStock() {
StockType nyyyse = smap.getStype("Nyse");
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
watchlist.addStock(Integer.toString(i), nyyyse); watchlist.addStock(Integer.toString(i));
} }
} }
@Test @Test
public void testSize() { public void testSize() {
assertEquals(watchlist.size(), 0); assertEquals(watchlist.size(), 0);
StockType nyyyse = smap.getStype("Nyse");
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
watchlist.addStock(Integer.toString(i), nyyyse); watchlist.addStock(Integer.toString(i));
} }
assertEquals(watchlist.size(), 100); assertEquals(watchlist.size(), 100);
} }
@Test @Test
public void testDelStockNoThrow() { public void testDelStockNoThrow() {
StockType nyyyse = smap.getStype("Nyse");
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
watchlist.addStock(Integer.toString(i), nyyyse); watchlist.addStock(Integer.toString(i));
} }
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
try { try {
@ -62,9 +55,8 @@ public class WatchListTest {
@Test @Test
public void testDelNotExistsStock() { public void testDelNotExistsStock() {
StockType nyyyse = smap.getStype("Nyse");
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
watchlist.addStock(Integer.toString(i), nyyyse); watchlist.addStock(Integer.toString(i));
} }
try { try {
watchlist.delStock(Integer.toString(-1)); watchlist.delStock(Integer.toString(-1));
@ -76,17 +68,30 @@ public class WatchListTest {
@Test @Test
public void testSaveLoad() { public void testSaveLoad() {
StockType nyyyse = smap.getStype("Nyse");
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
watchlist.addStock(Integer.toString(i), nyyyse); watchlist.addStock(Integer.toString(i));
} }
watchlist.save(""); watchlist.save("");
assertTrue(watchlist.fileExists(watchlist.DEFAULT_SAVEFILE)); assertTrue(watchlist.fileExists(watchlist.DEFAULT_SAVEFILE));
Main testMain = new Main(true); WatchList testlist = new WatchList();
WatchList testlist = testMain.getWatchList();
testlist.load(""); testlist.load("");
assertEquals(watchlist.size(), testlist.size()); assertEquals(watchlist.size(), testlist.size());
File testFile = new File(watchlist.DEFAULT_SAVEFILE); File testFile = new File(watchlist.DEFAULT_SAVEFILE);
testFile.delete(); testFile.delete();
} }
@Test
public void testFileNotFound() {
//redirect stdout: https://stackoverflow.com/questions/1119385/junit-test-for-system-out-println
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
ByteArrayOutputStream errContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
PrintStream originalErr = System.err;
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
watchlist.load("thisfiledoesnotexist-andwillneverexists");
assertEquals("File not found: thisfiledoesnotexist-andwillneverexists\n", outContent.toString());
System.setOut(originalOut);
System.setErr(originalErr);
}
} }

Loading…
Cancel
Save