/*******************************************************************************
* Copyright (c) 2012 Hallvard Tr�tteberg.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Hallvard Tr�tteberg - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.geomap.jface;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import javax.xml.parsers.SAXParserFactory;
import org.eclipse.nebula.widgets.geomap.PointD;
import org.eclipse.nebula.widgets.geomap.internal.URLService;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* An abstract super class for search servers
* @since 3.3
*
*/
public abstract class SearchServer extends URLService {
/**
* Initializes the SearchServer with a specific URL and url format
* @param url
* @param urlFormat
*/
public SearchServer(String url, String urlFormat) {
super(url, urlFormat);
}
/**
* Initializes the SearchServer with a specific URL and default url format
* @param url
*/
public SearchServer(String url) {
parseUrl(url, "format=xml&q={0}"); //$NON-NLS-1$
}
@Override
protected Object[] getURLFormatArguments(Object ref) {
return new Object[]{ref};
}
/**
* Gets the URL used for a specific search
* @param search
* @return the URL
*/
public String getSearchURL(String search) {
return getServiceURL(search);
}
/**
* Tries to parse s as a Double, defaulting to Double.NaN
* @param s the String to parse
* @return the double or NaN, if the String couldn't be parsed
*/
protected static double tryDouble(String s) {
try {
return Double.valueOf(s);
} catch (Exception e) {
return Double.NaN;
}
}
protected boolean checkPath(String[] qNames, AbstractList<String> path) {
for (int i = 0; i < qNames.length; i++) {
int pathPos = path.size() - i - 1;
if (pathPos < 0 || (! qNames[qNames.length - i - 1].equals(path.get(pathPos)))) {
return false;
}
}
return true;
}
protected Object startElement(String qName, Stack<String> path, Attributes attributes, Stack<Object> objects) {
return null;
}
protected Object characters(String qName, Stack<String> path, char[] ch, int start, int length, Stack<Object> objects) {
return null;
}
protected Object endElement(String qName, Stack<String> path, Stack<Object> objects) {
return null;
}
public Object[] doSearch(String search) {
return doSearchInternal(search);
}
private Object[] doSearchInternal(String search) {
final List<Object> results = new ArrayList<Object>();
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(false);
final Stack<String> path = new Stack<String>();
final Stack<Object> objects = new Stack<Object>();
factory.newSAXParser().parse(getSearchURL(search), new DefaultHandler() {
private void addResult(Object result) {
if (result != null) {
results.add(result);
}
}
public void startElement(String uri, String localName, String qName, Attributes attributes) {
addResult(SearchServer.this.startElement(qName, path, attributes, objects));
path.push(qName);
}
public void endElement(String uri, String localName, String qName) throws SAXException {
addResult(SearchServer.this.endElement(qName, path, objects));
path.pop();
}
public void characters(char[] ch, int start, int length) throws SAXException {
String qName = path.pop();
addResult(SearchServer.this.characters(qName, path, ch, start, length, objects));
path.push(qName);
}
});
return (results.size() > 0 ? results.toArray() : null);
} catch (Exception e) {
}
return null;
}
public static class Result extends Located.Static {
private double lon = Double.NaN, lat = Double.NaN;
private String name, text;
public PointD getLonLat() {
return (Double.isNaN(lon) || Double.isNaN(lat) ? null : new PointD(lon, lat));
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name.trim();
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text.trim();
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public void setLon(String lon) {
this.lon = tryDouble(lon.trim());
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public void setLat(String lat) {
this.lat = tryDouble(lat.trim());
}
public String toString() {
return "SearchResult [text=" + text + ", location=" + getLonLat() + "]";
}
}
}