/*
* Copyright 2011 mapsforge.org
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.muxe.advancedtouristmap.sourcefiles;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import android.util.Log;
/**
* Class for managing the source files needed by the different mapsforge components used in this
* app. Handles reading of XML files and checking the correctness.
*
* @author Max Dörfler
*
*/
public class FileManager {
private String baseDirectory;
private ArrayList<MapBundle> installedBundles;
private DocumentBuilder dBuilder;
// some pre compiled xpath expressions to find data in the XML
// private XPathExpression xpathGetName;
// private XPathExpression xpathGetMap;
// private XPathExpression xpathGetRoutingFiles;
// private XPathExpression xpathGetAddress;
// private XPathExpression xpathGetPoi;
// private XPathExpression xpathGetFilename;
// private XPathExpression xpathGetPath;
// private XPathExpression xpathGetMD5;
// private XPathExpression xpathGetFileSize;
// private XPathExpression xpathGetDate;
// private XPathExpression xpathGetDesc;
// private XPathExpression xpathGetBoundingBox;
public FileManager(String baseDirectory) {
this.baseDirectory = baseDirectory;
// XPathFactory factory = XPathFactory.newInstance();
// XPath xpath = factory.newXPath();
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
try {
this.dBuilder = dbFactory.newDocumentBuilder();
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
}
// try {
// this.xpathGetName = xpath.compile("/mapbundle/name/text()");
// this.xpathGetMap = xpath.compile("/mapbundle/map[1]");
// this.xpathGetRoutingFiles = xpath.compile("/mapbundle/routingfiles/routingfile");
// this.xpathGetAddress = xpath.compile("/mapbundle/addressfile[1]");
// this.xpathGetPoi = xpath.compile("/mapbundle/poifile[1]");
// this.xpathGetFilename = xpath.compile("child::filename/text()");
// this.xpathGetPath = xpath.compile("child::path/text()");
// this.xpathGetDate = xpath.compile("child::date_of_creation/text()");
// this.xpathGetMD5 = xpath.compile("child::md5/text()");
// this.xpathGetFileSize = xpath.compile("child::file_size/text()");
// this.xpathGetDesc = xpath.compile("child::desc/text()");
// this.xpathGetBoundingBox = xpath.compile("child::bounding_box/@*");
//
// } catch (XPathExpressionException e) {
// e.printStackTrace();
// }
}
public void rescan(String directory) {
if (directory != null) {
this.baseDirectory = directory;
}
if (this.installedBundles != null) {
this.installedBundles.clear();
} else {
this.installedBundles = new ArrayList<MapBundle>();
}
this.findBundleXML(this.baseDirectory);
}
private void findBundleXML(String directory) {
File[] xmlFiles = new File(directory).listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
return filename.endsWith(".xml");
}
});
if (xmlFiles != null) {
for (File f : xmlFiles) {
// MapBundle bundle = buildMapBundle(loadXml("file:" + f.getAbsolutePath()),
// f.getAbsolutePath());
MapBundle bundle = buildMapBundleDOM(loadXml("file:" + f.getAbsolutePath()),
f.getAbsolutePath());
if (bundle != null) {
this.installedBundles.add(bundle);
}
}
}
}
/**
* Opens a remote/local File and returns a InputStream
*
* @param path
* Path of the File as URL (for local files use: file:/path/to/go)
* @return InputStream for the File
*/
private InputStream loadXml(String path) {
try {
URL url = new URL(path);
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
return is;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Parses a XML-File (as InputStream) and builds a MapBundle
*
* @param xmlStream
* the XML file as InputStream
* @param filePath
* the full path of the XML-File
* @return MapBundle representation of the XML
*/
private MapBundle buildMapBundleDOM(InputStream xmlStream, String filePath) {
String basePath = new File(filePath).getParent();
if (xmlStream == null) {
return null;
}
try {
Document doc = this.dBuilder.parse(xmlStream);
doc.getDocumentElement().normalize();
NodeList mapBundleNodes = doc.getElementsByTagName("mapbundle");
if (mapBundleNodes.getLength() == 1) {
MapBundle mapBundle = new MapBundle();
mapBundle.setFilepathXml(filePath);
Node mapBundleNode = mapBundleNodes.item(0);
NodeList subFiles = mapBundleNode.getChildNodes();
for (int j = 0; j < subFiles.getLength(); j++) {
Node subFile = subFiles.item(j);
String subFileType = subFile.getNodeName();
if (subFileType.equalsIgnoreCase("name")) {
String mapBundleName = subFile.getFirstChild().getNodeValue();
mapBundle.setName(mapBundleName);
}
// get map
if (subFileType.equalsIgnoreCase("map")) {
MapFile mapFile = new MapFile();
parseBasicFileInfoDOM(mapFile, subFile);
// get bounding box
NodeList boundingBoxes = ((Element) subFile)
.getElementsByTagName("bounding_box");
if (boundingBoxes.getLength() == 1) {
NamedNodeMap bboxMap = boundingBoxes.item(0).getAttributes();
mapFile.setMin_lat(Double.parseDouble(bboxMap.getNamedItem(
"min_lat").getNodeValue()));
mapFile.setMax_lat(Double.parseDouble(bboxMap.getNamedItem(
"max_lat").getNodeValue()));
mapFile.setMin_lon(Double.parseDouble(bboxMap.getNamedItem(
"min_lon").getNodeValue()));
mapFile.setMax_lon(Double.parseDouble(bboxMap.getNamedItem(
"max_lon").getNodeValue()));
}
if (mapFile.isValid(basePath, false)) {
mapBundle.setMapFile(mapFile);
}
} else if (subFileType.equalsIgnoreCase("routingfiles")) {
NodeList routingFileNodes = subFile.getChildNodes();
for (int l = 0; l < routingFileNodes.getLength(); l++) {
Node routingFileNode = routingFileNodes.item(l);
String routingFileNodeName = routingFileNode.getNodeName();
if (routingFileNodeName.equalsIgnoreCase("routingfile")) {
RoutingFile routingFile = new RoutingFile();
parseBasicFileInfoDOM(routingFile, routingFileNode);
if (routingFile.isValid(basePath, false)) {
mapBundle.addRoutingFile(routingFile);
}
}
}
} else if (subFileType.equalsIgnoreCase("poifile")) {
Log.d("FileManager", "found Poifile");
PoiFile poiFile = new PoiFile();
parseBasicFileInfoDOM(poiFile, subFile);
if (poiFile.isValid(basePath, false)) {
Log.d("FileManager", "valid Poifile");
mapBundle.setPoiFile(poiFile);
}
} else if (subFileType.equalsIgnoreCase("addressfile")) {
AddressFile addressFile = new AddressFile();
parseBasicFileInfoDOM(addressFile, subFile);
Log.d("FileManager",
addressFile.getFilename() + " " + addressFile.getDescription());
if (addressFile.isValid(basePath, false)) {
mapBundle.setAddressFile(addressFile);
}
}
}
if (mapBundle.isValid()) {
return mapBundle;
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
return null;
}
/**
* Reads all the default SourceFile attributes from a given node and stores them in a given
* SourceFile Object
*
* @param sf
* The SourceFile to store the attributes in
* @param node
* The DOM-Node in which the attributes are stored
* @throws NumberFormatException
* if there are non-numeric values stored in numeric fields
*/
private void parseBasicFileInfoDOM(SourceFile sf, Node node) throws NumberFormatException {
NodeList subFileProperties = node.getChildNodes();
for (int k = 0; k < subFileProperties.getLength(); k++) {
Node subFileProperty = subFileProperties.item(k);
String subFilePropertyName = subFileProperty.getNodeName();
if (subFilePropertyName.equalsIgnoreCase("filename")) {
sf.setFilename(subFileProperty.getFirstChild().getNodeValue());
} else if (subFilePropertyName.equalsIgnoreCase("desc")) {
sf.setDescription(subFileProperty.getFirstChild().getNodeValue());
} else if (subFilePropertyName.equalsIgnoreCase("path")) {
sf.setPath(subFileProperty.getFirstChild().getNodeValue());
} else if (subFilePropertyName.equalsIgnoreCase("md5")) {
sf.setMd5(subFileProperty.getFirstChild().getNodeValue());
} else if (subFilePropertyName.equalsIgnoreCase("file_size")) {
sf.setFilesize(Long.parseLong(subFileProperty.getFirstChild().getNodeValue()));
} else if (subFilePropertyName.equalsIgnoreCase("date_of_creation")) {
sf.setCreated(new Date(Long.parseLong(subFileProperty.getFirstChild()
.getNodeValue())));
}
}
}
// /**
// * Parses a XML-File (as InputStream) and builds a MapBundle
// *
// * @param xmlStream
// * the XML file as InputStream
// * @param filePath
// * the full path of the XML-File
// * @return MapBundle representation of the XML
// */
// private MapBundle buildMapBundle(InputStream xmlStream, String filePath) {
// String basePath = new File(filePath).getParent();
// MapBundle mapBundle = new MapBundle();
// mapBundle.setFilepathXml(filePath);
// if (xmlStream == null) {
// return null;
// }
// try {
// Document doc = this.dBuilder.parse(xmlStream);
//
// doc.getDocumentElement().normalize();
// // getName
// String name = (String) this.xpathGetName.evaluate(doc, XPathConstants.STRING);
// mapBundle.setName(name);
//
// // get Mapfile
// Node mapNode = (Node) this.xpathGetMap.evaluate(doc, XPathConstants.NODE);
// MapFile mapFile = new MapFile();
// this.parseBasicFileInfo(mapFile, mapNode);
//
// // get bounding box (as attributes)
// NodeList bounding_box = (NodeList) this.xpathGetBoundingBox.evaluate(mapNode,
// XPathConstants.NODESET);
// for (int i = 0; i < bounding_box.getLength(); i++) {
// String nodeName = bounding_box.item(i).getNodeName();
// double nodeValue = Double.parseDouble(bounding_box.item(i).getNodeValue());
// if (nodeName.equals("min_lat")) {
// mapFile.setMin_lat(nodeValue);
// } else if (nodeName.equals("max_lat")) {
// mapFile.setMax_lat(nodeValue);
// } else if (nodeName.equals("min_lon")) {
// mapFile.setMin_lon(nodeValue);
// } else if (nodeName.equals("max_lon")) {
// mapFile.setMax_lon(nodeValue);
// }
// }
// if (mapFile.isValid(basePath, false)) {
// mapBundle.setMapFile(mapFile);
// }
//
// // get RoutingFiles
// NodeList routingNodes = (NodeList) this.xpathGetRoutingFiles.evaluate(doc,
// XPathConstants.NODESET);
// // loop routing files
// for (int i = 0; i < routingNodes.getLength(); i++) {
// RoutingFile rf = new RoutingFile();
// this.parseBasicFileInfo(rf, routingNodes.item(i));
// if (rf.isValid(basePath, false)) {
// mapBundle.addRoutingFile(rf);
// }
// }
//
// // get Address File
// Node addressNode = (Node) this.xpathGetAddress.evaluate(doc, XPathConstants.NODE);
// if (addressNode != null) {
// AddressFile addressFile = new AddressFile();
// this.parseBasicFileInfo(addressFile, addressNode);
// if (addressFile.isValid(basePath, false)) {
// mapBundle.setAddressFile(addressFile);
// }
// }
//
// // get POI File
// Node poiNode = (Node) this.xpathGetPoi.evaluate(doc, XPathConstants.NODE);
// if (poiNode != null) {
// PoiFile poiFile = new PoiFile();
// this.parseBasicFileInfo(poiFile, poiNode);
// if (poiFile.isValid(basePath, false)) {
// mapBundle.setPoiFile(poiFile);
// }
// }
// if (mapBundle.isValid()) {
// return mapBundle;
// }
// } catch (SAXException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// } catch (XPathExpressionException e) {
// e.printStackTrace();
// } catch (NumberFormatException e) {
// e.printStackTrace();
// } catch (NullPointerException e) {
// e.printStackTrace();
// }
// return null;
// }
// /**
// * Reads all the default SourceFile attributes from a given node and stores them in a
// given
// * SourceFile Object
// *
// * @param sf
// * The SourceFile to store the attributes in
// * @param node
// * The DOM-Node in which the attributes are stored
// * @throws XPathExpressionException
// * if the xpath expression is malformed
// * @throws NumberFormatException
// * if there are non-numeric values stored in numeric fields
// */
// private void parseBasicFileInfo(SourceFile sf, Node node) throws
// XPathExpressionException,
// NumberFormatException {
// sf.setFilename((String) this.xpathGetFilename.evaluate(node, XPathConstants.STRING));
// sf.setFilesize(Long.parseLong((String) this.xpathGetFileSize.evaluate(node,
// XPathConstants.STRING)));
// sf.setCreated(new Date(Long.parseLong((String) this.xpathGetDate.evaluate(node,
// XPathConstants.STRING))));
// sf.setDescription((String) this.xpathGetDesc.evaluate(node, XPathConstants.STRING));
// sf.setMd5((String) this.xpathGetMD5.evaluate(node, XPathConstants.STRING));
// sf.setPath((String) this.xpathGetPath.evaluate(node, XPathConstants.STRING));
// }
public ArrayList<MapBundle> getInstalledBundles() {
if (this.installedBundles == null) {
Log.d("FileManager", "get new bundle");
this.installedBundles = new ArrayList<MapBundle>();
findBundleXML(this.baseDirectory);
}
Log.d("FileManager", "return bundle");
return this.installedBundles;
}
public String getBaseDirectory() {
return this.baseDirectory;
}
public MapBundle getSingleBundle(String path) {
// MapBundle bundle = buildMapBundle(loadXml("file:" + path), path);
MapBundle bundle = buildMapBundleDOM(loadXml("file:" + path), path);
return bundle;
}
}