View Javadoc
1   package org.oxerr.okcoin.rest.dto.valuereader;
2   
3   import java.math.BigDecimal;
4   import java.text.ParseException;
5   import java.text.SimpleDateFormat;
6   import java.time.Instant;
7   import java.util.TimeZone;
8   
9   import org.oxerr.okcoin.rest.dto.IcebergOrder;
10  import org.oxerr.okcoin.rest.dto.IcebergOrderHistory;
11  import org.oxerr.okcoin.rest.dto.Status;
12  import org.oxerr.okcoin.rest.dto.Type;
13  import org.oxerr.okcoin.rest.service.web.LoginRequiredException;
14  import org.w3c.dom.Node;
15  import org.w3c.dom.NodeList;
16  import org.w3c.dom.Text;
17  import org.w3c.dom.html.HTMLAnchorElement;
18  import org.w3c.dom.html.HTMLCollection;
19  import org.w3c.dom.html.HTMLDivElement;
20  import org.w3c.dom.html.HTMLDocument;
21  import org.w3c.dom.html.HTMLTableCellElement;
22  import org.w3c.dom.html.HTMLTableElement;
23  import org.w3c.dom.html.HTMLTableRowElement;
24  
25  public class IcebergOrdersReader extends HtmlPageReader<IcebergOrderHistory> {
26  
27  	private static final IcebergOrdersReader INSTANCE = new IcebergOrdersReader();
28  
29  	public static IcebergOrdersReader getInstance() {
30  		return INSTANCE;
31  	}
32  
33  	private final SimpleDateFormat dateFormat;
34  
35  	public IcebergOrdersReader() {
36  		dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
37  		dateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
38  	}
39  
40  	/**
41  	 * {@inheritDoc}
42  	 */
43  	@Override
44  	public IcebergOrderHistory read(HTMLDocument doc) {
45  		NodeList tableNodeList = doc.getElementsByTagName("table");
46  		if (tableNodeList.getLength() == 0) {
47  			throw new LoginRequiredException("No HTML table found.");
48  		}
49  
50  		Node tableNode = tableNodeList.item(0);
51  		HTMLTableElement table = (HTMLTableElement) tableNode;
52  		HTMLCollection rows = table.getRows();
53  		IcebergOrder[] orders = new IcebergOrder[rows.getLength() - 1];
54  		for (int i = 1; i < rows.getLength(); i++) {
55  			HTMLTableRowElement row = (HTMLTableRowElement) rows.item(i);
56  			HTMLCollection cells = row.getCells();
57  
58  			if (cells.getLength() == 1) {
59  				// no open orders
60  				orders = new IcebergOrder[0];
61  				break;
62  			}
63  
64  			HTMLTableCellElement dateCell = (HTMLTableCellElement) cells.item(0);
65  			HTMLTableCellElement sideCell = (HTMLTableCellElement) cells.item(1);
66  			HTMLTableCellElement tradeValueCell = (HTMLTableCellElement) cells.item(2);
67  			HTMLTableCellElement singleAvgCell = (HTMLTableCellElement) cells.item(3);
68  			HTMLTableCellElement depthRangeCell = (HTMLTableCellElement) cells.item(4);
69  			HTMLTableCellElement protectedPriceCell = (HTMLTableCellElement) cells.item(5);
70  			HTMLTableCellElement filledCell = (HTMLTableCellElement) cells.item(6);
71  			HTMLTableCellElement statusCell = (HTMLTableCellElement) cells.item(7);
72  
73  			String dateContent = dateCell.getTextContent();
74  			String sideContent = sideCell.getTextContent();
75  			String tradeValueContent = tradeValueCell.getTextContent();
76  			String singleAvgContent = singleAvgCell.getTextContent();
77  			String depthRangeContent = depthRangeCell.getTextContent();
78  			String protetedPriceContent = protectedPriceCell.getTextContent();
79  			String filledContent = filledCell.getTextContent();
80  			String idContent = statusCell.getId();
81  
82  			Instant date;
83  			synchronized (dateFormat) {
84  				try {
85  					date = dateFormat.parse(dateContent).toInstant();
86  				} catch (ParseException e) {
87  					throw new IllegalArgumentException(e);
88  				}
89  			}
90  
91  			Type side = sideContent.equals("Bid") ? Type.BUY : Type.SELL;
92  			BigDecimal tradeValue = new BigDecimal(tradeValueContent.substring(1));
93  			BigDecimal singleAvg = new BigDecimal(singleAvgContent.substring(1));
94  			BigDecimal depthRange = new BigDecimal(depthRangeContent.substring(0, depthRangeContent.length() - 1));
95  			BigDecimal protectedPrice = new BigDecimal(protetedPriceContent.substring(1).replace(",", ""));
96  			BigDecimal filled = new BigDecimal(filledContent.substring(1));
97  			long id = Long.valueOf(idContent.substring("continuous_".length()));
98  
99  			NodeList statusChildNodes = statusCell.getChildNodes();
100 			Node statusFirstChild = statusChildNodes.item(0);
101 			Status status = Status.UNFILLED;
102 			if (statusFirstChild instanceof HTMLAnchorElement) {
103 				// order is open
104 				status = filled.compareTo(BigDecimal.ZERO) == 0 ? Status.UNFILLED : Status.PARTIALLY_FILLED;
105 			} else if (statusFirstChild instanceof Text){
106 				String statusText = statusFirstChild.getTextContent();
107 				switch (statusText) {
108 				case "Cancelled":
109 					status = Status.CANCELLED;
110 					break;
111 				default:
112 					status = Status.UNFILLED;
113 					break;
114 				}
115 			}
116 
117 			orders[i - 1] = new IcebergOrder(id, date, side, tradeValue, singleAvg, depthRange, protectedPrice, filled, status);
118 		}
119 
120 		// page
121 		int currentPage = 1;
122 		boolean hasNextPage = false;
123 		NodeList divNodeList = doc.getElementsByTagName("div");
124 		if (divNodeList.getLength() > 0) {
125 			HTMLDivElement div = (HTMLDivElement) divNodeList.item(0);
126 			NodeList anchorNodeList = div.getElementsByTagName("a");
127 			for (int i = 0; i < anchorNodeList.getLength(); i++) {
128 				HTMLAnchorElement anchor = (HTMLAnchorElement) anchorNodeList.item(i);
129 				if ("current_ss".equals(anchor.getClassName())) {
130 					currentPage = Integer.parseInt(anchor.getTextContent());
131 				}
132 				if (">".equals(anchor.getTextContent())) {
133 					hasNextPage = true;
134 				}
135 			}
136 		}
137 
138 		return new IcebergOrderHistory(currentPage, hasNextPage, orders);
139 	}
140 
141 }