aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael.foiani@gmail.com>2021-04-09 17:19:58 -0400
committerGitHub <noreply@github.com>2021-04-09 17:19:58 -0400
commita208096eb6d48fc662de33b9564e452c27352635 (patch)
treea6a82b342a737890390ab1bc12a4d69601f4761f
parent3628ded6ad537c01ce51ee9a7ffb008bd1b0e228 (diff)
parentc0b15a96c176f01a7199d3c3d107946341af3e50 (diff)
Merge pull request #3 from cs0320-2021/xml-parse
Xml parse
-rw-r--r--.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml34
-rw-r--r--data/bad.xml7
-rw-r--r--data/xml_derivative_only_test.xml97
-rw-r--r--data/xml_multiple_trades_test.xml174
-rw-r--r--data/xml_single_trade_test.xml111
-rw-r--r--src/main/java/edu/brown/cs/student/term/parsing/LocalXmlParser.java38
-rw-r--r--src/main/java/edu/brown/cs/student/term/parsing/Transaction.java171
-rw-r--r--src/main/java/edu/brown/cs/student/term/parsing/UrlXmlParser.java37
-rw-r--r--src/main/java/edu/brown/cs/student/term/parsing/XmlParser.java37
-rw-r--r--src/main/java/edu/brown/cs/student/term/repl/commands/LoadCommand.java76
-rw-r--r--src/main/java/edu/brown/cs/student/term/trade/Trade.java4
-rw-r--r--src/test/java/edu/brown/cs/student/TransactionTest.java96
-rw-r--r--src/test/java/edu/brown/cs/student/XmlParserTest.java168
13 files changed, 1050 insertions, 0 deletions
diff --git a/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml b/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml
index b3e2a19..4968ca7 100644
--- a/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml
+++ b/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml
@@ -51,5 +51,39 @@
<orderEntry type="library" name="Maven: org.freemarker:freemarker:2.3.26-incubating" level="project" />
<orderEntry type="library" name="Maven: org.xerial:sqlite-jdbc:3.30.1" level="project" />
<orderEntry type="library" name="Maven: org.json:json:20201115" level="project" />
+ <orderEntry type="library" name="Maven: net.sf.jopt-simple:jopt-simple:6.0-alpha-3" level="project" />
+ <orderEntry type="library" name="Maven: junit:junit:4.13" level="project" />
+ <orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
+ <orderEntry type="library" name="Maven: org.hamcrest:hamcrest-all:1.3" level="project" />
+ <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:2.0.0-alpha1" level="project" />
+ <orderEntry type="library" name="Maven: org.slf4j:slf4j-jdk14:2.0.0-alpha1" level="project" />
+ <orderEntry type="library" name="Maven: com.google.guava:guava:28.2-jre" level="project" />
+ <orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
+ <orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
+ <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
+ <orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.10.0" level="project" />
+ <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.4" level="project" />
+ <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
+ <orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.6" level="project" />
+ <orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.9.1" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.18.v20190429" level="project" />
+ <orderEntry type="library" name="Maven: com.sparkjava:spark-template-freemarker:2.7.1" level="project" />
+ <orderEntry type="library" name="Maven: org.freemarker:freemarker:2.3.26-incubating" level="project" />
+ <orderEntry type="library" name="Maven: org.xerial:sqlite-jdbc:3.30.1" level="project" />
+ <orderEntry type="library" name="Maven: org.json:json:20201115" level="project" />
</component>
</module> \ No newline at end of file
diff --git a/data/bad.xml b/data/bad.xml
new file mode 100644
index 0000000..8f17d10
--- /dev/null
+++ b/data/bad.xml
@@ -0,0 +1,7 @@
+<periodOfReport>2021-03-31</periodOfReport>
+
+<notSubjectToSection16>0</notSubjectToSection16>
+
+<issuer>
+<issuerCik>0001517006</issuerCik>
+<issuerName>Gatos Silver, Inc.</issuer \ No newline at end of file
diff --git a/data/xml_derivative_only_test.xml b/data/xml_derivative_only_test.xml
new file mode 100644
index 0000000..cd19564
--- /dev/null
+++ b/data/xml_derivative_only_test.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<ownershipDocument>
+
+ <schemaVersion>X0306</schemaVersion>
+
+ <documentType>4</documentType>
+
+ <periodOfReport>2021-04-07</periodOfReport>
+
+ <issuer>
+ <issuerCik>0001005817</issuerCik>
+ <issuerName>TOMPKINS FINANCIAL CORP</issuerName>
+ <issuerTradingSymbol>TMP</issuerTradingSymbol>
+ </issuer>
+
+ <reportingOwner>
+ <reportingOwnerId>
+ <rptOwnerCik>0001463126</rptOwnerCik>
+ <rptOwnerName>Fessenden Daniel J.</rptOwnerName>
+ </reportingOwnerId>
+ <reportingOwnerAddress>
+ <rptOwnerStreet1>C/O TOMPKINS FINANCIAL CORPORATION</rptOwnerStreet1>
+ <rptOwnerStreet2>P.O. BOX 460</rptOwnerStreet2>
+ <rptOwnerCity>ITHACA</rptOwnerCity>
+ <rptOwnerState>NY</rptOwnerState>
+ <rptOwnerZipCode>14851</rptOwnerZipCode>
+ <rptOwnerStateDescription></rptOwnerStateDescription>
+ </reportingOwnerAddress>
+ <reportingOwnerRelationship>
+ <isDirector>1</isDirector>
+ </reportingOwnerRelationship>
+ </reportingOwner>
+
+ <derivativeTable>
+ <derivativeTransaction>
+ <securityTitle>
+ <value>Phantom Stock</value>
+ </securityTitle>
+ <conversionOrExercisePrice>
+ <footnoteId id="F1"/>
+ </conversionOrExercisePrice>
+ <transactionDate>
+ <value>2021-04-07</value>
+ </transactionDate>
+ <transactionCoding>
+ <transactionFormType>4</transactionFormType>
+ <transactionCode>A</transactionCode>
+ <equitySwapInvolved>0</equitySwapInvolved>
+ </transactionCoding>
+ <transactionTimeliness></transactionTimeliness>
+ <transactionAmounts>
+ <transactionShares>
+ <value>142.275</value>
+ </transactionShares>
+ <transactionPricePerShare>
+ <value>80.8293</value>
+ </transactionPricePerShare>
+ <transactionAcquiredDisposedCode>
+ <value>A</value>
+ </transactionAcquiredDisposedCode>
+ </transactionAmounts>
+ <exerciseDate>
+ <footnoteId id="F1"/>
+ </exerciseDate>
+ <expirationDate>
+ <footnoteId id="F1"/>
+ </expirationDate>
+ <underlyingSecurity>
+ <underlyingSecurityTitle>
+ <value>Common Stock</value>
+ </underlyingSecurityTitle>
+ <underlyingSecurityShares>
+ <value>142.275</value>
+ </underlyingSecurityShares>
+ </underlyingSecurity>
+ <postTransactionAmounts>
+ <sharesOwnedFollowingTransaction>
+ <value>4757.199</value>
+ </sharesOwnedFollowingTransaction>
+ </postTransactionAmounts>
+ <ownershipNature>
+ <directOrIndirectOwnership>
+ <value>D</value>
+ </directOrIndirectOwnership>
+ </ownershipNature>
+ </derivativeTransaction>
+ </derivativeTable>
+
+ <footnotes>
+ <footnote id="F1">Each share of phantom stock is the economic equivalent of one share of common stock. Phantom stock represents deferred stock compensation under the Amended and Restated Retainer Plan for Eligible Directors of Tompkins Financial Corporation and its Wholly-Owned Subsidiaries. These shares are held in a rabbi trust pending distribution upon the occurrence of certain events specified in the Plan. The reporting person has no voting or investment power over the shares prior to such distribution.</footnote>
+ </footnotes>
+
+ <ownerSignature>
+ <signatureName>/s/Daniel J. Fessenden</signatureName>
+ <signatureDate>2021-04-09</signatureDate>
+ </ownerSignature>
+</ownershipDocument>
diff --git a/data/xml_multiple_trades_test.xml b/data/xml_multiple_trades_test.xml
new file mode 100644
index 0000000..89904e6
--- /dev/null
+++ b/data/xml_multiple_trades_test.xml
@@ -0,0 +1,174 @@
+<?xml version="1.0"?>
+<ownershipDocument>
+
+ <schemaVersion>X0306</schemaVersion>
+
+ <documentType>4</documentType>
+
+ <periodOfReport>2021-03-24</periodOfReport>
+
+ <notSubjectToSection16>0</notSubjectToSection16>
+
+ <issuer>
+ <issuerCik>0000066418</issuerCik>
+ <issuerName>MEXCO ENERGY CORP</issuerName>
+ <issuerTradingSymbol>MXC</issuerTradingSymbol>
+ </issuer>
+
+ <reportingOwner>
+ <reportingOwnerId>
+ <rptOwnerCik>0001250054</rptOwnerCik>
+ <rptOwnerName>YANKO DONNA GAIL</rptOwnerName>
+ </reportingOwnerId>
+ <reportingOwnerAddress>
+ <rptOwnerStreet1>4109 DEVON DRIVE</rptOwnerStreet1>
+ <rptOwnerStreet2></rptOwnerStreet2>
+ <rptOwnerCity>EDMOND</rptOwnerCity>
+ <rptOwnerState>TX</rptOwnerState>
+ <rptOwnerZipCode>73034</rptOwnerZipCode>
+ <rptOwnerStateDescription></rptOwnerStateDescription>
+ </reportingOwnerAddress>
+ <reportingOwnerRelationship>
+ <isDirector>0</isDirector>
+ <isOfficer>1</isOfficer>
+ <isTenPercentOwner>0</isTenPercentOwner>
+ <isOther>0</isOther>
+ <officerTitle>VICE PRESIDENT</officerTitle>
+ <otherText></otherText>
+ </reportingOwnerRelationship>
+ </reportingOwner>
+
+ <nonDerivativeTable>
+ <nonDerivativeTransaction>
+ <securityTitle>
+ <value>MXC COMMON STOCK</value>
+ </securityTitle>
+ <transactionDate>
+ <value>2021-03-24</value>
+ </transactionDate>
+ <deemedExecutionDate></deemedExecutionDate>
+ <transactionCoding>
+ <transactionFormType>4</transactionFormType>
+ <transactionCode>S</transactionCode>
+ <equitySwapInvolved>0</equitySwapInvolved>
+ </transactionCoding>
+ <transactionTimeliness></transactionTimeliness>
+ <transactionAmounts>
+ <transactionShares>
+ <value>3000</value>
+ </transactionShares>
+ <transactionPricePerShare>
+ <value>8.20</value>
+ </transactionPricePerShare>
+ <transactionAcquiredDisposedCode>
+ <value>D</value>
+ </transactionAcquiredDisposedCode>
+ </transactionAmounts>
+ <postTransactionAmounts>
+ <sharesOwnedFollowingTransaction>
+ <value>7668</value>
+ </sharesOwnedFollowingTransaction>
+ </postTransactionAmounts>
+ <ownershipNature>
+ <directOrIndirectOwnership>
+ <value>D</value>
+ </directOrIndirectOwnership>
+ </ownershipNature>
+ </nonDerivativeTransaction>
+ <nonDerivativeTransaction>
+ <securityTitle>
+ <value>MXC COMMON STOCK</value>
+ </securityTitle>
+ <transactionDate>
+ <value>2021-03-30</value>
+ </transactionDate>
+ <deemedExecutionDate></deemedExecutionDate>
+ <transactionCoding>
+ <transactionFormType>4</transactionFormType>
+ <transactionCode>S</transactionCode>
+ <equitySwapInvolved>0</equitySwapInvolved>
+ </transactionCoding>
+ <transactionTimeliness></transactionTimeliness>
+ <transactionAmounts>
+ <transactionShares>
+ <value>3000</value>
+ </transactionShares>
+ <transactionPricePerShare>
+ <value>8.40</value>
+ </transactionPricePerShare>
+ <transactionAcquiredDisposedCode>
+ <value>D</value>
+ </transactionAcquiredDisposedCode>
+ </transactionAmounts>
+ <postTransactionAmounts>
+ <sharesOwnedFollowingTransaction>
+ <value>4668</value>
+ </sharesOwnedFollowingTransaction>
+ </postTransactionAmounts>
+ <ownershipNature>
+ <directOrIndirectOwnership>
+ <value>D</value>
+ </directOrIndirectOwnership>
+ </ownershipNature>
+ </nonDerivativeTransaction>
+ <nonDerivativeTransaction>
+ <securityTitle>
+ <value>MXC COMMON STOCK</value>
+ </securityTitle>
+ <transactionDate>
+ <value>2021-04-01</value>
+ </transactionDate>
+ <deemedExecutionDate></deemedExecutionDate>
+ <transactionCoding>
+ <transactionFormType>4</transactionFormType>
+ <transactionCode>S</transactionCode>
+ <equitySwapInvolved>0</equitySwapInvolved>
+ </transactionCoding>
+ <transactionTimeliness></transactionTimeliness>
+ <transactionAmounts>
+ <transactionShares>
+ <value>2000</value>
+ </transactionShares>
+ <transactionPricePerShare>
+ <value>9.00</value>
+ </transactionPricePerShare>
+ <transactionAcquiredDisposedCode>
+ <value>D</value>
+ </transactionAcquiredDisposedCode>
+ </transactionAmounts>
+ <postTransactionAmounts>
+ <sharesOwnedFollowingTransaction>
+ <value>2668</value>
+ </sharesOwnedFollowingTransaction>
+ </postTransactionAmounts>
+ <ownershipNature>
+ <directOrIndirectOwnership>
+ <value>D</value>
+ </directOrIndirectOwnership>
+ </ownershipNature>
+ </nonDerivativeTransaction>
+ <nonDerivativeHolding>
+ <securityTitle>
+ <value>MXC COMMON STOCK</value>
+ </securityTitle>
+ <postTransactionAmounts>
+ <sharesOwnedFollowingTransaction>
+ <value>944</value>
+ </sharesOwnedFollowingTransaction>
+ </postTransactionAmounts>
+ <ownershipNature>
+ <directOrIndirectOwnership>
+ <value>I</value>
+ </directOrIndirectOwnership>
+ <natureOfOwnership>
+ <value>OWNED BY SPOUSE</value>
+ </natureOfOwnership>
+ </ownershipNature>
+ </nonDerivativeHolding>
+ </nonDerivativeTable>
+
+ <ownerSignature>
+ <signatureName>/s/ D. Gail Yanko</signatureName>
+ <signatureDate>2021-04-05</signatureDate>
+ </ownerSignature>
+</ownershipDocument>
diff --git a/data/xml_single_trade_test.xml b/data/xml_single_trade_test.xml
new file mode 100644
index 0000000..9bd5b1b
--- /dev/null
+++ b/data/xml_single_trade_test.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<ownershipDocument>
+
+ <schemaVersion>X0306</schemaVersion>
+
+ <documentType>4</documentType>
+
+ <periodOfReport>2021-03-31</periodOfReport>
+
+ <notSubjectToSection16>0</notSubjectToSection16>
+
+ <issuer>
+ <issuerCik>0001517006</issuerCik>
+ <issuerName>Gatos Silver, Inc.</issuerName>
+ <issuerTradingSymbol>GATO</issuerTradingSymbol>
+ </issuer>
+
+ <reportingOwner>
+ <reportingOwnerId>
+ <rptOwnerCik>0001561844</rptOwnerCik>
+ <rptOwnerName>Levental Igor</rptOwnerName>
+ </reportingOwnerId>
+ <reportingOwnerAddress>
+ <rptOwnerStreet1>C/O GATOS SILVER, INC.,</rptOwnerStreet1>
+ <rptOwnerStreet2>8400 E. CRESCENT PARKWAY, SUITE 600</rptOwnerStreet2>
+ <rptOwnerCity>GREENWOOD VILLAGE</rptOwnerCity>
+ <rptOwnerState>CO</rptOwnerState>
+ <rptOwnerZipCode>80111</rptOwnerZipCode>
+ <rptOwnerStateDescription></rptOwnerStateDescription>
+ </reportingOwnerAddress>
+ <reportingOwnerRelationship>
+ <isDirector>1</isDirector>
+ <isOfficer>0</isOfficer>
+ <isTenPercentOwner>0</isTenPercentOwner>
+ <isOther>0</isOther>
+ <officerTitle></officerTitle>
+ <otherText></otherText>
+ </reportingOwnerRelationship>
+ </reportingOwner>
+
+ <nonDerivativeTable>
+ <nonDerivativeTransaction>
+ <securityTitle>
+ <value>Common Stock</value>
+ </securityTitle>
+ <transactionDate>
+ <value>2021-03-31</value>
+ </transactionDate>
+ <deemedExecutionDate></deemedExecutionDate>
+ <transactionCoding>
+ <transactionFormType>4</transactionFormType>
+ <transactionCode>A</transactionCode>
+ <equitySwapInvolved>0</equitySwapInvolved>
+ </transactionCoding>
+ <transactionTimeliness></transactionTimeliness>
+ <transactionAmounts>
+ <transactionShares>
+ <value>8236</value>
+ <footnoteId id="F1"/>
+ </transactionShares>
+ <transactionPricePerShare>
+ <value>0</value>
+ </transactionPricePerShare>
+ <transactionAcquiredDisposedCode>
+ <value>A</value>
+ </transactionAcquiredDisposedCode>
+ </transactionAmounts>
+ <postTransactionAmounts>
+ <sharesOwnedFollowingTransaction>
+ <value>10799</value>
+ <footnoteId id="F2"/>
+ </sharesOwnedFollowingTransaction>
+ </postTransactionAmounts>
+ <ownershipNature>
+ <directOrIndirectOwnership>
+ <value>D</value>
+ </directOrIndirectOwnership>
+ </ownershipNature>
+ </nonDerivativeTransaction>
+ <nonDerivativeHolding>
+ <securityTitle>
+ <value>Common Stock</value>
+ </securityTitle>
+ <postTransactionAmounts>
+ <sharesOwnedFollowingTransaction>
+ <value>97363</value>
+ </sharesOwnedFollowingTransaction>
+ </postTransactionAmounts>
+ <ownershipNature>
+ <directOrIndirectOwnership>
+ <value>I</value>
+ </directOrIndirectOwnership>
+ <natureOfOwnership>
+ <value>By Levental Family Trust</value>
+ <footnoteId id="F3"/>
+ </natureOfOwnership>
+ </ownershipNature>
+ </nonDerivativeHolding>
+ </nonDerivativeTable>
+
+ <footnotes>
+ <footnote id="F1">Consists entirely of deferred stock units (&quot;DSUs&quot;), which were fully vested on the grant date. Each DSU entitles the holder to receive one share of the Company's common stock upon departure from the Company.</footnote>
+ <footnote id="F2">Includes 10,799 DSUs, which were fully vested on the date of grant.</footnote>
+ <footnote id="F3">The reporting person disclaims beneficial ownership of these shares except to the extent of his pecuniary interest.</footnote>
+ </footnotes>
+
+ <ownerSignature>
+ <signatureName>/s/ Roger Johnson, Attorney-in-Fact for Igor Levental</signatureName>
+ <signatureDate>2021-04-02</signatureDate>
+ </ownerSignature>
+</ownershipDocument>
diff --git a/src/main/java/edu/brown/cs/student/term/parsing/LocalXmlParser.java b/src/main/java/edu/brown/cs/student/term/parsing/LocalXmlParser.java
new file mode 100644
index 0000000..27c3988
--- /dev/null
+++ b/src/main/java/edu/brown/cs/student/term/parsing/LocalXmlParser.java
@@ -0,0 +1,38 @@
+package edu.brown.cs.student.term.parsing;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.IOException;
+
+public class LocalXmlParser extends XmlParser {
+ public LocalXmlParser() {
+ super();
+ }
+
+ /**
+ * Method used to parse the xml file.
+ *
+ * @param pathToXml The path to the xml text file.
+ * @return The tree structure parsed as an xml doc.
+ */
+ @Override
+ public Document parse(String pathToXml) {
+ // TODO: change to online hosted file option
+ // Creating the file reference.
+ System.err.println("LOG: To make file reference for " + pathToXml + " in " + getClass());
+ File file = new File(pathToXml);
+
+ // Parsing the file.
+ try {
+ System.err.println("LOG: Calling builder.parse() in " + getClass());
+ return builder.parse(file);
+ } catch (SAXException e) {
+ System.err.println("INTERNAL: SAX " + getClass() + " : " + e.getClass());
+ } catch (IOException e) {
+ System.err.println("INTERNAL: IO " + getClass() + " : " + e.getClass());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/edu/brown/cs/student/term/parsing/Transaction.java b/src/main/java/edu/brown/cs/student/term/parsing/Transaction.java
new file mode 100644
index 0000000..2111048
--- /dev/null
+++ b/src/main/java/edu/brown/cs/student/term/parsing/Transaction.java
@@ -0,0 +1,171 @@
+package edu.brown.cs.student.term.parsing;
+
+import edu.brown.cs.student.term.hub.Holder;
+import edu.brown.cs.student.term.trade.Trade;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * This class represents the transaction data from the xml file.
+ */
+public class Transaction {
+ private Document doc;
+ private final List<Trade> trades;
+ private final String personName;
+ private final int id;
+ private final String ticker;
+
+ /**
+ * Constructor that represents the transaction from the document.
+ * @param document The document parsed from the xml file.
+ */
+ public Transaction(Document document) {
+ // TODO: add log comments
+ doc = document;
+ trades = new ArrayList<>();
+
+ personName = personName();
+ id = id();
+ ticker = ticker();
+
+ // There are two types of transactions within the xml - derivative and non derivative.
+ NodeList nonDerivative = document.getElementsByTagName("nonDerivativeTransaction");
+ //NodeList derivative = document.getElementsByTagName("derivativeTransaction");
+ // Processing both of their trades into the trades instance var.
+ processTransactions(nonDerivative);
+ //processTransactions(derivative);
+ }
+
+ /**
+ * Takes a transaction as a node list, then processes and stores them into trades.
+ * @param tradesAsNodes The trades within the transaction as a nodelist.
+ */
+ private void processTransactions(NodeList tradesAsNodes) {
+ int numTrades = tradesAsNodes.getLength();
+ for(int i = 0; i < numTrades; i++) {
+ NodeList tradeValues = getValueList(tradesAsNodes.item(i));
+
+ // This stages the params for the trade.
+ // TODO: update with real timestamp
+ double ts = getDate(tradeValues).hashCode();
+ int isBuy = getIsBuy(tradeValues) ? 1 : 0;
+ int numShares = getNumShares(tradeValues);
+ // TODO: update id? unique for each holder?
+ Holder holder = new Holder(id, personName);
+
+ Trade trade = new Trade(id, ticker, ts, isBuy, numShares, holder);
+ trades.add(trade);
+ }
+
+ doc = null;
+ }
+
+ /**
+ * Extracts the id of the transaction from the document.
+ * @return The id.
+ */
+ private int id() {
+ // Id of transaction
+ NodeList idNode = doc.getElementsByTagName("rptOwnerCik");
+ // TODO: add error parsing
+ return Integer.parseInt(idNode.item(0).getTextContent());
+ }
+
+ /**
+ * Extracts the person's name of the transaction from the document.
+ * @return The person's name.
+ */
+ private String personName() {
+ // Name of person
+ NodeList nameNode = doc.getElementsByTagName("rptOwnerName");
+ return nameNode.item(0).getTextContent();
+ }
+
+ /**
+ * Extracts the security ticker of the transaction from the document
+ * @return The ticker.
+ */
+ private String ticker() {
+ // Ticker of security
+ NodeList idNode = doc.getElementsByTagName("issuerTradingSymbol");
+ return idNode.item(0).getTextContent();
+ }
+
+ /**
+ * Extracts the trade data of one trade within a transaction.
+ * @param trade One trade from the transaction as a node.
+ * @return A nodelist with each element holding specific info of the trade.
+ */
+ public NodeList getValueList(Node trade) {
+ // Data of trade in an array of values
+ assert trade.getNodeType() == Node.ELEMENT_NODE;
+ Element tradeElement = (Element) trade;
+ return tradeElement.getElementsByTagName("value");
+ }
+
+ /**
+ * Extracts the trade date from a trade node.
+ * @param values The value array representing the trade.
+ * @return The date in mm-dd-yyyy format as a string.
+ */
+ public String getDate(NodeList values) {
+ return values.item(1).getTextContent();
+ }
+
+ /**
+ * Extracts the number of shares moved from the trade.
+ * @param values The value array representing the trade.
+ * @return The number of shares.
+ */
+ public int getNumShares(NodeList values) {
+ return Integer.parseInt(values.item(2).getTextContent());
+ }
+
+ /**
+ * Extracts the price each share cost from the trade.
+ * @param values The value array representing the trade.
+ * @return The price of each share.
+ */
+ public int getPriceShares(NodeList values) {
+ return Integer.parseInt(values.item(3).getTextContent());
+ }
+
+ /**
+ * Determines whether the shares in the trade were bought or sold.
+ * @param values The value array representing the trade.
+ * @return True if they were bought (acquired). False, if sold.
+ */
+ public boolean getIsBuy(NodeList values) {
+ return values.item(4).getTextContent().equals("A");
+ }
+
+ /**
+ * Returns the list of trades that occurred within the transaction.
+ * @return A list of trade objects.
+ */
+ public List<Trade> getTrades() {
+ return trades;
+ }
+
+ /**
+ * Accessor method that returns the id of the transaction.
+ * @return The id.
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Accessor method that returns the person's name who did the transaction.
+ * @return The name of whom did the transaction.
+ */
+ public String getPersonName() {
+ return personName;
+ }
+}
diff --git a/src/main/java/edu/brown/cs/student/term/parsing/UrlXmlParser.java b/src/main/java/edu/brown/cs/student/term/parsing/UrlXmlParser.java
new file mode 100644
index 0000000..440b898
--- /dev/null
+++ b/src/main/java/edu/brown/cs/student/term/parsing/UrlXmlParser.java
@@ -0,0 +1,37 @@
+package edu.brown.cs.student.term.parsing;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+public class UrlXmlParser extends XmlParser{
+ public UrlXmlParser() {
+ super();
+ }
+
+ /**
+ * Method used to parse the xml file.
+ *
+ * @param pathToXml The path to the xml text file.
+ * @return The tree structure parsed as an xml doc.
+ */
+ @Override
+ public Document parse(String pathToXml) {
+ try {
+ System.err.println("LOG: To make url class in parse() of " + getClass());
+ URL url = new URL(pathToXml);
+ System.err.println("LOG: To establish urlConnection in parse() of " + getClass());
+ URLConnection conn = url.openConnection();
+ System.err.println("LOG: Calling builder.parse() in " + getClass());
+ return builder.parse(conn.getInputStream());
+ } catch (SAXException e) {
+ System.err.println("INTERNAL: SAX " + getClass() + " : " + e.getClass());
+ } catch (IOException e) {
+ System.err.println("INTERNAL: IO " + getClass() + " : " + e.getClass());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/edu/brown/cs/student/term/parsing/XmlParser.java b/src/main/java/edu/brown/cs/student/term/parsing/XmlParser.java
new file mode 100644
index 0000000..d8182d6
--- /dev/null
+++ b/src/main/java/edu/brown/cs/student/term/parsing/XmlParser.java
@@ -0,0 +1,37 @@
+package edu.brown.cs.student.term.parsing;
+
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public abstract class XmlParser {
+ protected DocumentBuilder builder = null;
+
+ /**
+ * This constructor crates and saves the builder that turns the xml text into a tree stricture.
+ */
+ protected XmlParser() {
+ // Builds the immutable factory
+ System.err.println("LOG: Constructor of " + getClass() + ". To make XML parser factory.");
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setValidating(true);
+ factory.setIgnoringElementContentWhitespace(true);
+
+ // Creates the builder from the factory
+ try {
+ System.err.println("LOG: To make documentBuilder in " + getClass());
+ builder = factory.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ System.err.println("INTERNAL: " + getClass() + " : " + e.getClass());
+ }
+ }
+
+ /**
+ * Method used to parse the xml file.
+ * @param pathToXml The path to the xml text file.
+ * @return The tree structure parsed as an xml doc.
+ */
+ public abstract Document parse(String pathToXml);
+}
diff --git a/src/main/java/edu/brown/cs/student/term/repl/commands/LoadCommand.java b/src/main/java/edu/brown/cs/student/term/repl/commands/LoadCommand.java
new file mode 100644
index 0000000..a20c23b
--- /dev/null
+++ b/src/main/java/edu/brown/cs/student/term/repl/commands/LoadCommand.java
@@ -0,0 +1,76 @@
+package edu.brown.cs.student.term.repl.commands;
+
+import edu.brown.cs.student.term.DatabaseQuerier;
+import edu.brown.cs.student.term.parsing.Transaction;
+import edu.brown.cs.student.term.parsing.UrlXmlParser;
+import edu.brown.cs.student.term.repl.Command;
+import edu.brown.cs.student.term.trade.Trade;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class LoadCommand implements Command {
+ private final static Connection CONN = DatabaseQuerier.getConn();
+ private final static UrlXmlParser URL_XML_PARSER = new UrlXmlParser();
+
+ /**
+ * Main run method for every command.
+ *
+ * @param args arguments for the command
+ */
+ @Override
+ public String run(String[] args) {
+ // TODO: add log comments
+ System.err.println("LOG: Entered .run() of " + getClass());
+ // TODO: call to api for urls to call through the urlxmlparser from reagan
+ String[] urls = new String[1];
+ for (String url : urls) {
+ try {
+ System.err.println("LOG: Calling loadTransactionIntoDB() in " + getClass());
+ loadTransactionIntoDB(url);
+ } catch (SQLException throwables) {
+ System.err.println("INTERNAL: SQLException in .run() of " + getClass());
+ //throwables.printStackTrace();
+ }
+ }
+ return "Loaded?";
+ }
+
+ /**
+ * Loads a whole transaction, which can have multiple trades, into the DB.
+ * @param url The url to the public xml file.
+ * @throws SQLException If the prep statement fails or db doesn't exist, throws.
+ */
+ private static void loadTransactionIntoDB(String url) throws SQLException {
+ System.err.println("LOG: Parsing XML into transaction in loadTransactionIntoDB(). URL: " + url);
+ Transaction helper = new Transaction(URL_XML_PARSER.parse(url));
+ for(Trade trade : helper.getTrades()) {
+ System.err.println("LOG: Loading a trade into DB -> " + trade);
+ loadTradeIntoDB(trade);
+ System.err.println("LOG: Loaded that trade.");
+ }
+ }
+
+ /**
+ * Loads one trade into the DB.
+ * @param trade The trade to be loaded.
+ * @throws SQLException If the prep statement fails or db doesn't exist, throws.
+ */
+ private static void loadTradeIntoDB(Trade trade) throws SQLException {
+ PreparedStatement prep = CONN.prepareStatement(
+ "INSERT into trades (stock_name, holder_name, trade_timestamp, is_buy, " +
+ "number_of_shares, holder_id) " +
+ "VALUES (?, ?, ?, ?, ?, ?)");
+
+ prep.setString(1, trade.getStock());
+ prep.setString(2, trade.getHolder().getName());
+ // TODO: update with timestamp @julia
+ prep.setDouble(3, trade.getTimestamp());
+ prep.setInt(4, trade.isBuy() ? 1 : 0);
+ prep.setInt(5, trade.getNumShares());
+ prep.setInt(6, trade.getHolder().getId());
+
+ prep.execute();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/edu/brown/cs/student/term/trade/Trade.java b/src/main/java/edu/brown/cs/student/term/trade/Trade.java
index 13f7ae1..95770e4 100644
--- a/src/main/java/edu/brown/cs/student/term/trade/Trade.java
+++ b/src/main/java/edu/brown/cs/student/term/trade/Trade.java
@@ -44,6 +44,10 @@ public class Trade {
return holder;
}
+ public int getNumShares() {
+ return numShares;
+ }
+
@Override
public String toString() {
return "Trade{" +
diff --git a/src/test/java/edu/brown/cs/student/TransactionTest.java b/src/test/java/edu/brown/cs/student/TransactionTest.java
new file mode 100644
index 0000000..f9a00f7
--- /dev/null
+++ b/src/test/java/edu/brown/cs/student/TransactionTest.java
@@ -0,0 +1,96 @@
+package edu.brown.cs.student;
+
+import edu.brown.cs.student.term.parsing.LocalXmlParser;
+import edu.brown.cs.student.term.parsing.Transaction;
+import edu.brown.cs.student.term.parsing.XmlParser;
+import edu.brown.cs.student.term.trade.Trade;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import static org.junit.Assert.*;
+
+public class TransactionTest {
+ private XmlParser _xmlParser;
+ private Document _doc;
+
+ @Before
+ public void setUp() {
+ _xmlParser = new LocalXmlParser();
+ }
+
+ @After
+ public void tearDown() {
+ _xmlParser = null;
+ }
+
+ @Test
+ public void singleTrade(){
+ setUp();
+ Document doc = _xmlParser.parse("data/xml_single_trade_test.xml");
+ assertNotEquals(doc, null);
+
+ // One trades in transaction
+ Transaction transaction = new Transaction(doc);
+ assertEquals(transaction.getTrades().size(), 1);
+
+ // TODO: add more qualities on trade to test...
+ Trade firstTrade = transaction.getTrades().get(0);
+ assertEquals(firstTrade.getNumShares(), 8236);
+
+ tearDown();
+ }
+
+ @Test
+ public void multipleTrades(){
+ setUp();
+ Document doc = _xmlParser.parse("data/xml_multiple_trades_test.xml");
+ assertNotEquals(doc, null);
+
+ // Three trades in transaction
+ Transaction transaction = new Transaction(doc);
+ assertEquals(transaction.getTrades().size(), 3);
+
+ Trade firstTrade = transaction.getTrades().get(0);
+ assertEquals(firstTrade.getNumShares(), 3000);
+
+ Trade secondTrade = transaction.getTrades().get(1);
+ assertEquals(secondTrade.getNumShares(), 3000);
+
+ Trade lastTrade = transaction.getTrades().get(2);
+ assertEquals(lastTrade.getNumShares(), 2000);
+
+ tearDown();
+ }
+
+ /*
+ @Test
+ public void derivativeTransaction(){
+ setUp();
+ Document doc = _xmlParser.parse("data/xml_derivative_only_test.xml");
+ assertNotEquals(doc, null);
+
+ // One trades in transaction
+ Transaction transaction = new Transaction(doc);
+ assertEquals(transaction.getTrades().size(), 1);
+
+ // TODO: add more qualities on trade to test...
+ Trade firstTrade = transaction.getTrades().get(0);
+ assertEquals(firstTrade.getNumShares(), 8236);
+ assertEquals(firstTrade.getHolder().getId(), 1463126);
+
+ tearDown();
+ }
+ */
+
+ @Test
+ public void noTrades(){
+ setUp();
+ // TODO: add case, but won't realistically come up
+ tearDown();
+ }
+}
diff --git a/src/test/java/edu/brown/cs/student/XmlParserTest.java b/src/test/java/edu/brown/cs/student/XmlParserTest.java
new file mode 100644
index 0000000..684452b
--- /dev/null
+++ b/src/test/java/edu/brown/cs/student/XmlParserTest.java
@@ -0,0 +1,168 @@
+package edu.brown.cs.student;
+
+import edu.brown.cs.student.term.parsing.LocalXmlParser;
+import edu.brown.cs.student.term.parsing.UrlXmlParser;
+import edu.brown.cs.student.term.parsing.XmlParser;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.print.Doc;
+
+import static org.junit.Assert.*;
+
+public class XmlParserTest {
+ private XmlParser _localXmlParser, _urlXmlParser;
+ private Document _doc;
+
+ @Before
+ public void setUp() {
+ _localXmlParser = new LocalXmlParser();
+ _urlXmlParser = new UrlXmlParser();
+ }
+
+ @After
+ public void tearDown() {
+ _localXmlParser = null;
+ _urlXmlParser = null;
+ }
+
+ @Test
+ public void parsesLocal(){
+ setUp();
+ Document doc = _localXmlParser.parse("data/xml_single_trade_test.xml");
+ assertNotNull(doc);
+
+ // Id of person
+ assertEquals(getIdFromDoc(doc), "0001561844");
+ tearDown();
+ }
+
+ @Test
+ public void parsesUrl(){
+ setUp();
+ Document doc =
+ _urlXmlParser.parse("https://www.sec.gov/Archives/edgar/data/1517006/000110465921046242/tm2112036-4_4seq1.xml");
+ assertNotNull(doc);
+
+ // Id of person
+ assertEquals(getIdFromDoc(doc), "0001561844");
+ tearDown();
+ }
+
+ public String getIdFromDoc(Document doc) {
+ // Id of person
+ NodeList idNode = doc.getElementsByTagName("rptOwnerCik");
+ assertEquals(idNode.getLength(), 1);
+ return idNode.item(0).getTextContent();
+ }
+
+ @Test
+ public void urlSameAsLocal(){
+ setUp();
+ Document local = _localXmlParser.parse("data/xml_single_trade_test.xml");
+ Document url =
+ _urlXmlParser.parse("https://www.sec.gov/Archives/edgar/data/1517006/000110465921046242/tm2112036-4_4seq1.xml");
+
+ assertEquals(getIdFromDoc(local), getIdFromDoc(url));
+ tearDown();
+ }
+
+ @Test
+ public void noFileExists(){
+ setUp();
+ tearDown();
+ }
+
+ @Test
+ public void badXmlFormat(){
+ setUp();
+ Document doc = _localXmlParser.parse("data/bad.xml");
+ assertNull(doc);
+ tearDown();
+ }
+
+ @Test
+ public void personDataParse(){
+ setUp();
+ Document doc = _localXmlParser.parse("data/xml_single_trade_test.xml");
+ assertNotNull(doc);
+
+ // Id of person
+ NodeList idNode = doc.getElementsByTagName("rptOwnerCik");
+ assertEquals(idNode.getLength(), 1);
+ String id = idNode.item(0).getTextContent();
+ assertEquals(id, "0001561844");
+
+ // Name of person
+ NodeList nameNode = doc.getElementsByTagName("rptOwnerName");
+ assertEquals(nameNode.getLength(), 1);
+ String name = nameNode.item(0).getTextContent();
+ assertEquals(name, "Levental Igor");
+
+ tearDown();
+ }
+
+ @Test
+ public void securityDataParse(){
+ setUp();
+ Document doc = _localXmlParser.parse("data/xml_single_trade_test.xml");
+ assertNotNull(doc);
+
+ // Ticker of security
+ NodeList idNode = doc.getElementsByTagName("issuerTradingSymbol");
+ assertEquals(idNode.getLength(), 1);
+ String id = idNode.item(0).getTextContent();
+ assertEquals(id, "GATO");
+
+ tearDown();
+ }
+
+ @Test
+ public void tradeDataParse(){
+ setUp();
+ Document doc = _localXmlParser.parse("data/xml_single_trade_test.xml");
+ assertNotEquals(doc, null);
+
+ // Data of trade in an array of values
+ NodeList trade = doc.getElementsByTagName("nonDerivativeTransaction");
+ assertEquals(trade.item(0).getNodeType(), Node.ELEMENT_NODE);
+ Element tradeElement = (Element) trade.item(0);
+ NodeList values = tradeElement.getElementsByTagName("value");
+ assertEquals(values.getLength(), 7);
+
+ // type of stock
+ String stockType = values.item(0).getTextContent();
+ assertEquals(stockType, "Common Stock");
+
+ // date
+ String date = values.item(1).getTextContent();
+ assertEquals(date, "2021-03-31");
+
+ // # of shares
+ String numShares = values.item(2).getTextContent();
+ assertEquals(numShares, "8236");
+
+ // price of shares
+ String priceShares = values.item(3).getTextContent();
+ assertEquals(priceShares, "0");
+
+ // transaction type (A for acquire)
+ String transactionType = values.item(4).getTextContent();
+ assertEquals(transactionType, "A");
+
+ // shared after transaction
+ String sharesAfter = values.item(5).getTextContent();
+ assertEquals(sharesAfter, "10799");
+
+ // ownership type
+ String ownershipType = values.item(6).getTextContent();
+ assertEquals(ownershipType, "D");
+
+ tearDown();
+ }
+}