Compare commits
24 Commits
deliverabl
...
deliverabl
| Author | SHA1 | Date |
|---|---|---|
|
|
ca8d7e876a | 6 years ago |
|
|
8f6cd85a2e | 6 years ago |
|
|
7adccd3cc5 | 6 years ago |
|
|
4e2180dd6f | 6 years ago |
|
|
88e46f3b41 | 6 years ago |
|
|
6b4cd4ebc9 | 6 years ago |
|
|
69bf511fd2 | 6 years ago |
|
|
85c1de8f3a | 6 years ago |
|
|
7ab1b38684 | 6 years ago |
|
|
f476d1e3cb | 6 years ago |
|
|
5e92eae32f | 6 years ago |
|
|
bc7542de7a | 6 years ago |
|
|
3629449c0f | 6 years ago |
|
|
58c5cbe870 | 6 years ago |
|
|
ba13fcad28 | 6 years ago |
|
|
b6d67611ca | 6 years ago |
|
|
e33a1e9ab6 | 6 years ago |
|
|
71fe283b9f | 6 years ago |
|
|
e997c9d00d | 6 years ago |
|
|
7c48f55481 | 6 years ago |
|
|
401b60fe5b | 6 years ago |
|
|
ccbdd480dc | 6 years ago |
|
|
202ee6e220 | 6 years ago |
|
|
30ea1ec59c | 6 years ago |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,36 @@
|
||||
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;
|
||||
}
|
||||
|
||||
//Effect: add a watchlist to this list, if it isn't already in the list
|
||||
//Modifies: this
|
||||
public void addWatchList(WatchList wlist) {
|
||||
if (!(wlists.contains(wlist))) {
|
||||
wlists.add(wlist);
|
||||
}
|
||||
}
|
||||
|
||||
//Effect: remove a watchlist
|
||||
//Modifies: this
|
||||
public void delWatchList(WatchList wlist) {
|
||||
wlists.remove(wlist);
|
||||
}
|
||||
|
||||
//Effect: return a watchlist by index
|
||||
public WatchList getWatchList(int index) {
|
||||
return (WatchList) wlists.get(index);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package network;
|
||||
|
||||
import data.StypeMap;
|
||||
import java.io.IOException;
|
||||
import javax.json.JsonObject;
|
||||
import data.DataSource;
|
||||
import network.exceptions.*;
|
||||
|
||||
public class AlphaVantage extends DataSource {
|
||||
|
||||
public AlphaVantage() {
|
||||
super("AlphaVantage", "https://www.alphavantage.co/query", "4MC2LL0HOQ2TFQL1");
|
||||
}
|
||||
|
||||
//Effect: get intraday price and %change through JSON given the stock ticker
|
||||
@Override
|
||||
public double[] update(String stype, String idstring) throws IOException {
|
||||
double[] result = {0.0, 0.0};
|
||||
try {
|
||||
String urlString = Net.urlStringBuilder(url, "function", "TIME_SERIES_INTRADAY", "symbol", idstring,
|
||||
"interval", "5min",
|
||||
"apikey", apiKey);
|
||||
JsonObject response = StockJson.urlToJson(urlString);
|
||||
JsonObject preJson = StockJson.jsonInJson(response, "Time Series (5min)");
|
||||
if (preJson == null) {
|
||||
throw new IOException("Error getting data from " + name);
|
||||
}
|
||||
JsonObject mainJson = StockJson.timeSeriesElement(preJson, 0);
|
||||
//System.out.print(mainJson);
|
||||
result[0] = Double.parseDouble(StockJson.stringGetter(mainJson, "4. close"));
|
||||
Double open = Double.parseDouble(StockJson.stringGetter(mainJson, "1. open"));
|
||||
result[1] = (result[0] - open) / open;
|
||||
} catch (ParaMismatchException e) {
|
||||
e.printStackTrace();
|
||||
} //catch (IOException e) {
|
||||
// System.out.println("Error getting data from: " + name);
|
||||
//e.printStackTrace();
|
||||
//}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package network;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import network.exceptions.*;
|
||||
|
||||
//Ref: https://stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests
|
||||
public class Net {
|
||||
//Effect: returns a String of url built with given url and paras
|
||||
public static String urlStringBuilder(String url, String... paras) throws ParaMismatchException {
|
||||
String urlString = url;
|
||||
String charset = "UTF-8";
|
||||
if ((paras.length % 2) != 0) {
|
||||
throw new ParaMismatchException("Except even paras, but have " + paras.length);
|
||||
}
|
||||
if (paras.length != 0) {
|
||||
urlString += "?";
|
||||
try {
|
||||
for (int i = 0; i < paras.length - 3; i = i + 2) {
|
||||
urlString += paras[i] + "=" + URLEncoder.encode(paras[i + 1], charset) + "&";
|
||||
}
|
||||
urlString += paras[paras.length - 2] + "=" + URLEncoder.encode(paras[paras.length - 1], charset);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
System.out.println("Error during encoding url: Unsupported encoding");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return urlString;
|
||||
}
|
||||
|
||||
//Effect: Open connection, fires a http GET and returns the InputStream of result
|
||||
public static InputStream urlToInputStream(String url) throws IOException {
|
||||
try {
|
||||
return (new URL(url).openStream());
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package network;
|
||||
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonReader;
|
||||
import javax.json.JsonNumber;
|
||||
import javax.json.JsonArray;
|
||||
import javax.json.JsonValue;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
//Json library from https://docs.oracle.com/javaee/7/api/javax/json/Json.html
|
||||
public class StockJson {
|
||||
public static JsonObject inputStreamToJson(InputStream istream) {
|
||||
JsonReader jreader = Json.createReader(istream);
|
||||
JsonObject jobj = jreader.readObject();
|
||||
jreader.close();
|
||||
return jobj;
|
||||
}
|
||||
|
||||
public static JsonObject urlToJson(String url) throws IOException {
|
||||
try {
|
||||
return inputStreamToJson(Net.urlToInputStream(url));
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// Effect: return double from jsonnumber
|
||||
public static double doubleGetter(JsonObject jobj, String name) {
|
||||
return jobj.getJsonNumber(name).doubleValue();
|
||||
}
|
||||
|
||||
// Effect: return jsonobject from jsonobject
|
||||
public static JsonObject jsonInJson(JsonObject jobj, String name) {
|
||||
return jobj.getJsonObject(name);
|
||||
}
|
||||
|
||||
// Effect: return string from jsonstring
|
||||
public static String stringGetter(JsonObject jobj, String name) {
|
||||
return jobj.getString(name);
|
||||
}
|
||||
|
||||
// Effect: return double from percentage string
|
||||
public static double doublePercent(JsonObject jobj, String name) {
|
||||
String temp = stringGetter(jobj, name);
|
||||
return Double.parseDouble(temp.split("%")[0]);
|
||||
}
|
||||
|
||||
// From https://stackoverflow.com/questions/33531041/jsonobject-get-value-of-first-node-regardless-of-name
|
||||
// Effect: extract the jsonobject from jsonobject by index
|
||||
public static JsonObject timeSeriesElement(JsonObject jobj, int index) {
|
||||
String name = (String) jobj.keySet().toArray()[index];
|
||||
return jsonInJson(jobj, name);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package network.exceptions;
|
||||
|
||||
public class ParaMismatchException extends Exception {
|
||||
public ParaMismatchException(String sss) {
|
||||
super(sss);
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,83 @@
|
||||
package ui;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.GroupLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.LayoutManager;
|
||||
import ui.guicomp.*;
|
||||
import data.WatchList;
|
||||
import data.ListOfWatchList;
|
||||
import static data.Const.PROGRAM_NAME;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
|
||||
public class Gui {
|
||||
//public Gui() {
|
||||
// JLabel label = new JLabel("Hello World");
|
||||
// based on http://zetcode.com/tutorials/javaswingtutorial/firstprograms/
|
||||
public class Gui extends JFrame implements Iface {
|
||||
private JButton addButton;
|
||||
private JButton delButton;
|
||||
private JButton upButton;
|
||||
private WatchTablePane wtable;
|
||||
private WatchList wlist;
|
||||
private Runnable init = new Runnable() {
|
||||
//Effect: Init gui all components
|
||||
//Modifies: this
|
||||
public void run() {
|
||||
addComponents();
|
||||
createLayout();
|
||||
setTitle(PROGRAM_NAME);
|
||||
setSize(300, 200);
|
||||
setLocationRelativeTo(null);
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
// JFrame.setDefaultLookAndFeelDecorated(true);
|
||||
// JFrame f = new JFrame("Hello World");
|
||||
// f.setSize(300,150);
|
||||
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
private void addComponents() {
|
||||
addButton = new AddButt(wlist);
|
||||
delButton = new DelButt(wlist);
|
||||
upButton = new UpButt(wlist);
|
||||
wtable = new WatchTablePane(wlist);
|
||||
}
|
||||
|
||||
// f.add(label);
|
||||
private void createLayout() {
|
||||
Container pane = getContentPane();
|
||||
GroupLayout lman = new GroupLayout(pane);
|
||||
pane.setLayout(lman);
|
||||
lman.setAutoCreateContainerGaps(true);
|
||||
lman.setHorizontalGroup(lman.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(wtable.getPane())
|
||||
.addGroup(lman.createSequentialGroup()
|
||||
.addComponent(addButton)
|
||||
.addComponent(delButton)
|
||||
.addComponent(upButton)
|
||||
));
|
||||
lman.setVerticalGroup(lman.createSequentialGroup()
|
||||
.addComponent(wtable.getPane())
|
||||
.addGroup(lman.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(addButton)
|
||||
.addComponent(delButton)
|
||||
.addComponent(upButton)
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// f.setVisible(true);
|
||||
//}
|
||||
public Gui() {
|
||||
wlist = ListOfWatchList.getList().getWatchList(0);
|
||||
SwingUtilities.invokeLater(init);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
//Effect: nothing
|
||||
//not enough time to do something useful for this
|
||||
@Override
|
||||
public void redraw() {
|
||||
//Nothing for now
|
||||
}
|
||||
|
||||
//Effect: nothing
|
||||
//not enough time to do something useful for this
|
||||
@Override
|
||||
public void destory() {
|
||||
//Nothing for now
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,13 @@
|
||||
package ui;
|
||||
|
||||
import ui.Options;
|
||||
import ui.Tui;
|
||||
|
||||
public class IfaceFactory {
|
||||
// Produce Iface given the config
|
||||
public static Iface getIface(Main mainobj) {
|
||||
public static Iface getIface() {
|
||||
//uses Tui for now
|
||||
return new Tui(mainobj);
|
||||
//return new Tui();
|
||||
//Test Gui
|
||||
return new Gui();
|
||||
}
|
||||
//public static Iface getIface(Options iOpts) {
|
||||
// //XXX iOpts not ready
|
||||
// //uses Tui for now
|
||||
// return new Tui(iOpts);
|
||||
//}
|
||||
}
|
||||
|
||||
@ -1,150 +0,0 @@
|
||||
package ui;
|
||||
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.InvalidPreferencesFormatException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import data.Const;
|
||||
|
||||
public class Options {
|
||||
private Preferences store;
|
||||
private boolean wasEmpty;
|
||||
private boolean noSave;
|
||||
private static final String DEF_OPTS_PATH = "";
|
||||
private static final String DEF_BACKUP = ".jwatch-backup.xml";
|
||||
private static final String RES_DEF = "defPref.xml";
|
||||
|
||||
public Options() {
|
||||
store = Preferences.userRoot();
|
||||
try {
|
||||
wasEmpty = store.nodeExists(Const.PROGRAM_NAME);
|
||||
store = store.node(Const.PROGRAM_NAME);
|
||||
if (wasEmpty) {
|
||||
//load default opts from resource
|
||||
//XXX
|
||||
//importDefPreferences();
|
||||
}
|
||||
} catch (BackingStoreException e) {
|
||||
System.out.println("Critical Error: preference backing cannot be initialized");
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public Options(String pathname) {
|
||||
store = Preferences.userRoot().node(pathname);
|
||||
}
|
||||
|
||||
public Options getSection(String section) {
|
||||
//String path = Const.PROGRAM_NAME + "/" + section;
|
||||
//Options result = new Options(path);
|
||||
//return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void importPreferences(String xmlpath) {
|
||||
try {
|
||||
File tarFile = new File(xmlpath);
|
||||
FileInputStream tarStream = new FileInputStream(tarFile);
|
||||
store.importPreferences(tarStream);
|
||||
tarStream.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("File not found: " + xmlpath);
|
||||
} catch (IOException e) {
|
||||
System.out.println("IO Error when reading: " + xmlpath);
|
||||
e.printStackTrace();
|
||||
} catch (InvalidPreferencesFormatException e) {
|
||||
System.out.println("Import format error, possible file corruption");
|
||||
}
|
||||
}
|
||||
|
||||
public void importDefPreferences() {
|
||||
try {
|
||||
InputStream istream = getClass().getResourceAsStream(RES_DEF);
|
||||
store.importPreferences(istream);
|
||||
istream.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("IO Error while reading def pref: "
|
||||
+ RES_DEF);
|
||||
} catch (InvalidPreferencesFormatException e) {
|
||||
System.out.println("Def resPref format error, possible program corruption");
|
||||
}
|
||||
}
|
||||
|
||||
public void exportPreferences(String xmlpath) {
|
||||
try {
|
||||
File tarFile = new File(xmlpath);
|
||||
if (tarFile.isFile()) {
|
||||
tarFile.delete();
|
||||
} else {
|
||||
tarFile.createNewFile();
|
||||
}
|
||||
FileOutputStream tarStream = new FileOutputStream(tarFile);
|
||||
store.exportSubtree(tarStream);
|
||||
tarStream.flush();
|
||||
tarStream.close();
|
||||
System.out.println("Exported preference to: " + xmlpath);
|
||||
} catch (IOException e) {
|
||||
System.out.println("IO Error when writing: " + xmlpath);
|
||||
} catch (BackingStoreException e) {
|
||||
System.out.println("Error retriving pref from store");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
// Clear config if requested or config was empty
|
||||
// and is not saving
|
||||
if (wasEmpty && noSave) {
|
||||
try {
|
||||
this.store.clear();
|
||||
} catch (BackingStoreException e) {
|
||||
System.out.println("Error clearing pref store");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (noSave) {
|
||||
restorePrevious();
|
||||
}
|
||||
delBackup();
|
||||
}
|
||||
|
||||
public void backupPref() {
|
||||
exportPreferences(DEF_BACKUP);
|
||||
System.out.println("User Pref Backup created");
|
||||
}
|
||||
|
||||
public void delBackup() {
|
||||
try {
|
||||
File tarFile = new File(DEF_BACKUP);
|
||||
tarFile.delete();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error deleting backup user pref");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void restorePrevious() {
|
||||
importPreferences(DEF_BACKUP);
|
||||
}
|
||||
|
||||
// Default all false bool pref to be safe
|
||||
// Default should be imported by constructor regardless
|
||||
public boolean getBool(String key) {
|
||||
return this.store.getBoolean(key, false);
|
||||
}
|
||||
|
||||
// Default all empty string pref to be safe
|
||||
// Default should be imported by constructor regardless
|
||||
public String getString(String key) {
|
||||
return this.store.get(key, "");
|
||||
}
|
||||
|
||||
public void parseArgs(String[] args) {
|
||||
//XXX
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package ui.guicomp;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JOptionPane;
|
||||
import data.WatchList;
|
||||
|
||||
public class AddButt extends JButton {
|
||||
private WatchList wlist;
|
||||
|
||||
public AddButt(WatchList wlist) {
|
||||
super("Add Stock...");
|
||||
//https://coderanch.com/t/580497/java/JButton-clicked-action
|
||||
if (getActionListeners().length < 1) {
|
||||
addActionListener(new AddButtList());
|
||||
}
|
||||
this.wlist = wlist;
|
||||
}
|
||||
|
||||
private class AddButtList implements ActionListener {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//https://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html#input
|
||||
//https://docs.oracle.com/javase/7/docs/api/javax/swing/JOptionPane.html
|
||||
String userin = (String)JOptionPane.showInputDialog("Enter the identifier:");
|
||||
if ((userin != null) && (userin.length() > 0)) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
wlist.addStock(userin);
|
||||
wlist.updateList();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package ui.guicomp;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JOptionPane;
|
||||
import data.WatchList;
|
||||
import data.exceptions.StockNotExistsException;
|
||||
|
||||
public class DelButt extends JButton {
|
||||
private WatchList wlist;
|
||||
|
||||
public DelButt(WatchList wlist) {
|
||||
super("Remove Stock...");
|
||||
if (getActionListeners().length < 1) {
|
||||
addActionListener(new DelButtList());
|
||||
}
|
||||
this.wlist = wlist;
|
||||
}
|
||||
|
||||
private class DelButtList implements ActionListener {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//https://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html#input
|
||||
//https://docs.oracle.com/javase/7/docs/api/javax/swing/JOptionPane.html
|
||||
String[] names = wlist.getNames();
|
||||
String userin = (String)JOptionPane.showInputDialog(
|
||||
null, "Choose a stock to delete:", "Delete Stock",
|
||||
JOptionPane.PLAIN_MESSAGE, null, names, null);
|
||||
if ((userin != null) && (userin.length() > 0)) {
|
||||
//https://stackoverflow.com/questions/12771500/best-way-of-creating-and-using-an-anonymous-runnable-class
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wlist.delStock(userin);
|
||||
} catch (StockNotExistsException e) {
|
||||
//impossible
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package ui.guicomp;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import data.WatchList;
|
||||
|
||||
public class UpButt extends JButton {
|
||||
private WatchList wlist;
|
||||
|
||||
public UpButt(WatchList wlist) {
|
||||
super("Update");
|
||||
if (getActionListeners().length < 1) {
|
||||
addActionListener(new UpButtList());
|
||||
}
|
||||
this.wlist = wlist;
|
||||
}
|
||||
|
||||
private class UpButtList implements ActionListener {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
wlist.updateList();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package ui.guicomp;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.TableModel;
|
||||
import javax.swing.event.*;
|
||||
import data.WatchList;
|
||||
import data.WatchList.Wevent;
|
||||
import data.StockEntry;
|
||||
import java.util.Observer;
|
||||
import java.util.Observable;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
// Ref: https://docs.oracle.com/javase/tutorial/uiswing/components/table.html
|
||||
// Ref2: https://docs.oracle.com/javase/8/docs/api/javax/swing/table/AbstractTableModel.html
|
||||
public class WatchTableModel extends AbstractTableModel implements Observer {
|
||||
private final String[] colnames = {"Identifier", "Price", "% change", "Status"};
|
||||
private final Object[] example = {"asdf", 0.0, "asdf", "asdf"};
|
||||
private WatchList watch;
|
||||
|
||||
public WatchTableModel(WatchList wlist) {
|
||||
watch = wlist;
|
||||
watch.addObserver(this);
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return colnames.length;
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return watch.size();
|
||||
}
|
||||
|
||||
public String getColumnName(int num) {
|
||||
return colnames[num];
|
||||
}
|
||||
|
||||
//Effect: return generated table data for whatever asked
|
||||
public Object getValueAt(int stock, int field) {
|
||||
StockEntry entry = watch.getStock(stock);
|
||||
switch (field) {
|
||||
case 0: //Name
|
||||
return entry.getID();
|
||||
case 1: //Price
|
||||
return entry.getPrice();
|
||||
case 2: //% change
|
||||
return entry.getChange() + " %";
|
||||
case 3:
|
||||
return entry.isUpdating() ? "Updating" : "Ok";
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Class getColumnClass(int col) {
|
||||
return example[col].getClass();
|
||||
}
|
||||
|
||||
//Effect: updates table for different events, ran by event dispatch thread as recommanded
|
||||
//Modifies: Table displayed
|
||||
@Override
|
||||
public void update(Observable obsed, Object event) {
|
||||
Wevent weve = (Wevent) event;
|
||||
switch (weve.getType()) {
|
||||
case UPDATE:
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
fireTableDataChanged(); });
|
||||
break;
|
||||
case ADD:
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
fireTableRowsInserted(weve.getData(), weve.getData()); });
|
||||
break;
|
||||
case DEL:
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
fireTableRowsDeleted(weve.getData(), weve.getData()); });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package ui.guicomp;
|
||||
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.table.TableModel;
|
||||
import data.WatchList;
|
||||
|
||||
//https://docs.oracle.com/javase/7/docs/api/javax/swing/JTable.html
|
||||
public class WatchTablePane {
|
||||
private JTable table;
|
||||
private TableModel tmodel;
|
||||
private JScrollPane spane;
|
||||
|
||||
public WatchTablePane(WatchList wlist) {
|
||||
tmodel = new WatchTableModel(wlist);
|
||||
table = new JTable(tmodel);
|
||||
spane = new JScrollPane(table);
|
||||
}
|
||||
|
||||
public JScrollPane getPane() {
|
||||
return spane;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package data;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import network.AlphaVantage;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DataSourceTest {
|
||||
private StockType testStype;
|
||||
private DataSource testSource;
|
||||
|
||||
@BeforeEach
|
||||
public void runBefore() {
|
||||
testStype = StypeMap.getStype("NYSE");
|
||||
testSource = new AlphaVantage();
|
||||
}
|
||||
|
||||
//Effect: test add and double deleting for many to many relationship
|
||||
@Test
|
||||
public void testAddDel() {
|
||||
testStype.addSource(testSource);
|
||||
testSource.delStype(testStype);
|
||||
testSource.delStype(testStype);
|
||||
}
|
||||
|
||||
//Effect: test overridden equals and hashcode
|
||||
@Test
|
||||
public void testEqualsHash() {
|
||||
DataSource testSource2 = new AlphaVantage();
|
||||
DataSource testSource3 = new DataSource("test source", "asdf", "asdf") {
|
||||
@Override
|
||||
public double[] update(String asdf, String asdf2) throws IOException {
|
||||
double[] asdfjkl = {0.0, 0.0};
|
||||
return asdfjkl;
|
||||
}
|
||||
};
|
||||
String asdf = "asdf";
|
||||
assertEquals(testSource, testSource);
|
||||
assertEquals(testSource, testSource2);
|
||||
assertFalse(testSource.equals(asdf));
|
||||
assertFalse(testSource.equals(testSource3));
|
||||
assertEquals(testSource.hashCode(), testSource2.hashCode());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package data;
|
||||
|
||||
import data.ListOfWatchList;
|
||||
import data.WatchList;
|
||||
import data.exceptions.*;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class ListOfWatchListTest {
|
||||
private WatchList watchlist;
|
||||
|
||||
@BeforeEach
|
||||
public void runBefore() {
|
||||
watchlist = new WatchList();
|
||||
}
|
||||
|
||||
//Effect: check if only one instance is returned
|
||||
@Test
|
||||
public void singletonCheck() {
|
||||
assertTrue(ListOfWatchList.getList() == ListOfWatchList.getList());
|
||||
}
|
||||
|
||||
//Effect: check double adding and deleting watchlists
|
||||
@Test
|
||||
public void addDelWatchList() {
|
||||
ListOfWatchList lowl = ListOfWatchList.getList();
|
||||
lowl.addWatchList(watchlist);
|
||||
assertEquals(watchlist, lowl.getWatchList(0));
|
||||
lowl.addWatchList(watchlist);
|
||||
assertEquals(watchlist, lowl.getWatchList(0));
|
||||
try {
|
||||
lowl.getWatchList(1);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// expected fail
|
||||
}
|
||||
lowl.delWatchList(watchlist);
|
||||
try {
|
||||
lowl.getWatchList(0);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// expected fail
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue