-
Notifications
You must be signed in to change notification settings - Fork 773
/
AddressLookup.java
451 lines (402 loc) · 16.9 KB
/
AddressLookup.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
/**********************************************************************
* This file is part of Adempiere ERP Bazaar *
* http://www.adempiere.org *
* *
* Copyright (C) Akuna Group Ltd. *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Michael Judd (michael.judd@akunagroup.com *
**********************************************************************/
package com.akunagroup.uk.postcode;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.adempiere.util.GenerateModel;
import org.compiere.util.CLogger;
import org.spin.util.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Manages connections with the postcode server, retrieves the response and
* parses it. The best way to use it is to first issue a postcode lookup.
* Please see Capscan Doucmentation located at:
* http://www.capscanondemand.com/docs/OnDemand.pdf
*
* @author Michael Judd
* @version $Id$
*/
public class AddressLookup implements AddressLookupInterface {
/** The logger. */
private static CLogger log = CLogger.getCLogger(GenerateModel.class);
/**
* The access code which is used along with clientID to authenticate the
* client.
*/
private String accessCode = null;
/**
* The clientID. which is used along with accessCode to authenticate the
* client.
*/
private String clientID = null;
/** The URL of the server to lookup the postcode on. */
private String serverUrl = null;
/**
* Postcode lookup results.<br>
* Keys are
* <li>the Postcode</li>
* <li>a Postcode object</li>
*
*/
private HashMap<String, Object> postcodeData = new HashMap<String, Object>();
//
/**
* Creates a new instance of AddressLookup.
*/
public AddressLookup() {
// Default constructor logic here -if any!
}
/**
* Creates a new instance of AddressLookup.
*
* @param serverUrl
* URL of the postcode server.
* @param serialNo
* Serial no. (used in authentication along with password)
* @param password
* Password (used in authentication along with Serial no.)
*
*/
public AddressLookup(String serverUrl, String serialNo, String password) {
this.serverUrl = serverUrl.trim();
this.clientID = serialNo.trim();
this.accessCode = password.trim();
}
/**
* Builds the URL of the appropriate application on the server.
*
* @param postcode
* Postcode
* @return The URL
*/
private URL buildUrl(String postcode) {
try {
StringBuffer urlStr = new StringBuffer();
urlStr.append(serverUrl);
urlStr.append(serverUrl.endsWith("/") ? "" : "/");
urlStr.append("/query?op=query&");
urlStr.append("cc=" + clientID + "&");
urlStr.append("ac=" + accessCode + "&");
urlStr.append("DSGID=1&AmbiguityId=1&MaxReturns=250&FieldList=&ParamList=&sAppID=Adempiere&MaxReturns=200");
urlStr.append("&Lookfor=" + postcode);
URL url = new URL(urlStr.toString());
return url;
} catch (MalformedURLException e) {
log.log(Level.SEVERE, "Lookup URL: " + e.getMessage());
e.printStackTrace();
}
return null;
} // buildUrl
/**
* Extracts the information out of server postcode lookup response.
*
* @param resultDoc
* The result document from server.
* @return The number of addresses extracted.
*/
private int extractPCodeInfo(Document xmlDoc) {
Postcode postcode = new Postcode();
int resultCode = 0;
xmlDoc.getDocumentElement().normalize();
// Get the root element.
Element doc = xmlDoc.getDocumentElement();
//System.out.println("Root Node: " + doc.getNodeName());
// Get the children.
NodeList DataElements = doc.getElementsByTagName("DataElement");
System.out.println("Number of DataElements: " + DataElements.getLength());
for (int i = 0; i < DataElements.getLength(); i++ ) {
// need to loop through elements to find the
Node firstDataNode = DataElements.item(i);
if (firstDataNode.getNodeType() == Node.ELEMENT_NODE) {
Element firstElement = (Element) firstDataNode;
NodeList firstNameList = firstElement.getElementsByTagName("Name");
Element NameElement = (Element) firstNameList.item(0);
log.log(Level.FINE, "Name: " + NameElement.getChildNodes().item(0).getNodeValue().trim() + " Node: " + i);
// Found and ADDR Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("ADDR")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setAddr(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and STREET Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("STREET")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setStreet1(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and LOCALITY Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("LOCALITY")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setStreet2(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and POSTTOWN Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("POSTTOWN")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setCity(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and COUNTY Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("COUNTY")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setRegion(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and POSTCODE Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("POSTCODE")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setPostcode(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and COUNTRY Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("COUNTRY")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setCountry(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and COUNTRYCODE Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("COUNTRYCODE")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setCountryCode(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and TRADCOUNTY Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("TRADCOUNTY")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setTradCounty(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and LONLOCOUT Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("LONLOCOUT")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setLonLocation(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and ADMINCOUNTY Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("ADMINCOUNTY")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
postcode.setAdminCounty(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
// Found and ADMINCOUNTY Node
if (NameElement.getChildNodes().item(0).getNodeValue().trim().equals("RESCODE")) {
NodeList firstValueList = firstElement.getElementsByTagName("Value");
Element ValueElement = (Element) firstValueList.item(0);
log.log(Level.FINE, "Value: " + ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim() + " Node: " + i);
resultCode = (int) new Integer(ValueElement.getChildNodes().item(0).getNodeValue().replaceAll("\n","").trim());
}
}
}
int returnValue = 0;
switch (resultCode)
{
case 0: // internal error
{
String errorMsg = "An internal error occurred when connecting to Capscan Service";
String errorTitle = "Error";
JOptionPane.showMessageDialog(null, errorMsg, errorTitle, JOptionPane.ERROR_MESSAGE);
break;
}
case 1: // address matched to postcode
{
returnValue = 1;
break;
}
case 2: // No hits found
{
String errorMsg = "No matching addresses found for this post code";
String errorTitle = "Error";
JOptionPane.showMessageDialog(null, errorMsg, errorTitle, JOptionPane.ERROR_MESSAGE);
break;
}
case 3: // Insufficient information to determine postcode
{
String errorMsg = "Insufficient information provided to determin post code";
String errorTitle = "Error";
JOptionPane.showMessageDialog(null, errorMsg, errorTitle, JOptionPane.ERROR_MESSAGE);
break;
}
case 4: // Results cover more than one postcode
{
String errorMsg = "The results cover more than one postcode";
String errorTitle = "Error";
JOptionPane.showMessageDialog(null, errorMsg, errorTitle, JOptionPane.ERROR_MESSAGE);
break;
}
case 5: // Not a UK address
{
String errorMsg = "Not a UK address";
String errorTitle = "Error";
JOptionPane.showMessageDialog(null, errorMsg, errorTitle, JOptionPane.ERROR_MESSAGE);
break;
}
}
if (returnValue == 1) // address found
{
// put the London Location in to the City where the County is London and the Country is the UK
if (postcode.getRegion().equals("London") && (postcode.getCountryCode().equals("UK") || postcode.getCountryCode().equals("GB")))
postcode.setCity(postcode.getLonLocation());
else
postcode.setRegion(postcode.getAdminCounty());
postcodeData.put(postcode.getPostcode(), postcode);
} else
log.log(Level.WARNING, "Postcode lookup error: " + postcode.getPostcode());
//if (postcode.getPostcode().length()==0)
// System.out.println("Postcode NOT found! ");
//else
return returnValue;
}
/**
* Fetch the lookup result from server.
*
* @param cgiUrl
* The URL of the CGI or application to call on server.
* @return The result in form of a document.
*/
private Document fetchResult(URL cgiUrl) {
try {
// Get document builder.
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
// Add default features
XMLUtils.setDefaultFeatures(docBuilderFactory);
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
// Get the connection.
URLConnection URLconnection = cgiUrl.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) URLconnection;
// TODO try block here to catch connection (java.net) exceptions
int responseCode = httpConnection.getResponseCode();
// Fetch the result.
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inStream = httpConnection.getInputStream();
try {
Document doc = docBuilder.parse(inStream);
return doc;
} catch (org.xml.sax.SAXException e) {
log.log(Level.SEVERE, "Fetch Result: " + e.getMessage());
e.printStackTrace();
}
}
} catch (Exception e) {
log.log(Level.SEVERE, "Fetch Result: " + e.getMessage());
e.printStackTrace();
}
return null;
} // fetchResult
/**
* @return the accessCode
*/
public String getPassword() {
return accessCode;
}
public HashMap<String, Object> getAddressData() {
return (HashMap<String, Object>) postcodeData;
}
/**
* @return the clientID
*/
public String getClientID() {
return clientID;
}
/**
* @return the serverUrl
*/
public String getServerUrl() {
return serverUrl;
}
/**
* Performs a postcode lookup fetching a set of addresses from server.
*
* @param postcode
* The postcode to lookup for.
* @return The number of addresses fetched or -1 in case of error.
*/
public int lookupPostcode(String postcode) {
// Build server application URL.
URL url = buildUrl(postcode);
if (url == null) {
log.log(Level.SEVERE, "URL: Can't build URL.");
return -1;
}
// Fetch the lookup result from server.
Document resultDoc = fetchResult(url);
if (resultDoc == null) {
log.log(Level.SEVERE, "Result document is null.");
return -1;
}
// Extract addresses and postkeys out of lookup results.
return extractPCodeInfo(resultDoc);
}
/**
* @param accessCode
* the accessCode to set
*/
public void setPassword(String password) {
this.accessCode = password.trim();
}
/**
* @param clientID
* the clientID to set
*/
public void setClientID(String clientID) {
this.clientID = clientID.trim();
}
/**
* @param serverUrl
* the serverUrl to set
*/
public void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl.trim();
}
/**
* Creates a new instance of PostcodeLookup.
*/
public AddressLookupInterface newInstance() {
return new AddressLookup();
}
} // PostcodeLookup