package org.microg.networklocation.backends.opencellid;
import android.content.Context;
import android.util.Log;
import org.microg.networklocation.data.CellSpec;
import org.microg.networklocation.data.LocationSpec;
import org.microg.networklocation.helper.Networking;
import org.microg.networklocation.source.LocationSource;
import org.microg.networklocation.source.OnlineDataSource;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
public class OpenCellIdLocationSource extends OnlineDataSource implements LocationSource<CellSpec> {
private static final String TAG = "nlp.OpenCellIdLocationSource";
private static final String NAME = "opencellid.org";
private static final String DESCRIPTION = "Retrieve cell locations from opencellid.org when online";
private static final String COPYRIGHT = "© OpenCellID.org\nLicense: CC BY-SA 3.0";
private static final String SERVICE_URL =
"http://www.opencellid.org/cell/get?fmt=xml&mcc=%d&mnc=%d&lac=%d&cellid=%d&key=%s";
private final Context context;
private final String API_KEY = "36e1c4ff-fb91-46d8-b9ff-c480c35292e5";
public OpenCellIdLocationSource(Context context) {
super(context);
this.context = context;
}
@Override
public String getCopyright() {
return COPYRIGHT;
}
@Override
public String getDescription() {
return DESCRIPTION;
}
@Override
public String getName() {
return NAME;
}
@Override
public Collection<LocationSpec<CellSpec>> retrieveLocation(Collection<CellSpec> cellSpecs) {
Collection<LocationSpec<CellSpec>> locationSpecs = new ArrayList<LocationSpec<CellSpec>>();
for (CellSpec cellSpec : cellSpecs) {
try {
URL url = new URL(String.format(SERVICE_URL, cellSpec.getMcc(), cellSpec.getMnc(), cellSpec.getLac(),
cellSpec.getCid(), API_KEY));
URLConnection connection = url.openConnection();
Networking.setUserAgentOnConnection(connection, context);
connection.setDoInput(true);
InputStream inputStream = connection.getInputStream();
String result = new String(Networking.readStreamToEnd(inputStream));
if ((result == null) || !result.isEmpty()) {
// Add xml tag because it's sometimes not includes in the returned result
if(!result.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")) {
result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + result;
}
LocationSpec<CellSpec> data = parseXMLData(cellSpec, result);
if(data != null) {
locationSpecs.add(data);
}
}
} catch (Throwable t) {
Log.w(TAG, t);
}
}
return locationSpecs;
}
private LocationSpec<CellSpec> parseXMLData(CellSpec cellSpec, String data) throws ParserConfigurationException, SAXException, IOException{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(data)));
NodeList nodeList = doc.getElementsByTagName("cell");
if(nodeList.getLength() >= 1){
Node node = nodeList.item(0);
NamedNodeMap attributes = node.getAttributes();
return new LocationSpec<CellSpec>(cellSpec,
Double.parseDouble(attributes.getNamedItem("lat").getNodeValue()),
Double.parseDouble(attributes.getNamedItem("lon").getNodeValue()),
Double.parseDouble(attributes.getNamedItem("range").getNodeValue()));
}else{
return null;
}
}
}