/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package logic;
import framework.*;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import framework.*;
import framework.IAirport.ITower;
import framework.IAirport.IRunway;
//import framework.IILSPath;
import framework.IILSCoord;
//import framework.IILSPath.IILSCoord;
//import logic.ILSCoord;
import java.io.*;
import java.util.*;
import org.jdom.input.*;
import org.jdom.output.*;
import org.jdom.*;
/**
*
* @author Dimitri Nüscheler
*
* Reads and writes NavaidCoord to a map XML file
* After construction the given map XML file should not be accessed by any other object until the latest writing operation (before garbage collection) of the Navaids instance has finished.
*
* A map XML file may contain random other elements and character data, but should not be accessed
* by any other object after construction of this
*/
public class AirportXML extends XMLMapAccess implements IAirportXML {
public AirportXML(File xmlFile) {
super(xmlFile);
}
public AirportXML(File xmlFile, Document domDocument) {
super(xmlFile, domDocument);
}
public void addAirport(IAirport airportData) throws IOException {
add(airportData);
write();
}
public void setAirports(Collection<IAirport> airportData) throws IOException {
Map<String, IAirport> existingAirports = getAirports();
for (IAirport t : airportData) {
existingAirports.remove(t.getID());
add(t);
}
for (String t : existingAirports.keySet()) {
remove(t);
}
write();
}
private void add(IAirport airport) throws IOException {
if (domDocument == null) {
read();
}
Element root = domDocument.getRootElement();
List<Element> existingElements = root.getChildren("airport");
for (Element t : existingElements) {
if (airport.getID().equals(t.getAttributeValue("id"))) {
updateAirport(t, airport);
//write();
return;
}
}
root.addContent(generateElement(airport));
//domDocument.getRootElement()
//domDocument.put(name, navaidCoord);
}
private void remove(String id) throws IOException {
if (domDocument == null) {
read();
}
Element root = domDocument.getRootElement();
List<Element> airports = root.getChildren("airport");
List<Element> removeCandidates = new LinkedList<Element>(); //This is necessary to delay removal to avoid ConcurrentModification (Element.getChildren returns it's internal list instead of a copy)
for (Element t : airports) {
if (id.equals(t.getAttributeValue("id"))) {
removeCandidates.add(t);
}
}
for (Element t : removeCandidates) {
root.removeContent(t);
}
}
public void addAirports(Collection<IAirport> airportData) throws IOException {
for (IAirport t : airportData) {
add(t);
}
write();
}
public void removeAirport(String id) throws IOException {
remove(id);
write();
}
public void removeAirports(Collection<String> idSet) throws IOException {
for (String t : idSet) {
remove(t);
}
write();
}
public Map<String, IAirport> getAirports() throws IOException {
if (domDocument == null) {
read();
}
Map<String, IAirport> airportMap = new HashMap();
List<Element> airportElementList = domDocument.getRootElement().getChildren("airport");
//List<Element> removeCandidates = new LinkedList<Element>();
for (Element t : airportElementList)//TODO: Decide what to do with Elements that do not validate: Ignore element, throw IOException, delete Element //For now: delete Element
{
if (!parseAirport(t, airportMap)) {
//removeCandidates.add(t);
}
}
/*for (Element t : removeCandidates)
{
domDocument.getRootElement().removeContent(t);
}*/
return airportMap;
}
private boolean parseAirport(Element t, Map<String, IAirport> airportMap) {
String name = t.getAttributeValue("name");
String id = t.getAttributeValue("id");
if (name == null || id == null) {
return false;
}
Airport airport = new Airport(name, id);
List<Element> runwayList = t.getChildren("runway");
for (Element u : runwayList) {
try {
boolean startils = false, endils = false;
float width = Float.parseFloat(u.getAttributeValue("width"));
Element start = u.getChild("start");
float startlat = Float.parseFloat(start.getAttributeValue("lat"));
float startlon = Float.parseFloat(start.getAttributeValue("lon"));
String startnum = start.getAttributeValue("num");
Element startILS = start.getChild("ils");
startils = parseILS(startILS);
Element end = u.getChild("end");
float endlat = Float.parseFloat(end.getAttributeValue("lat"));
float endlon = Float.parseFloat(end.getAttributeValue("lon"));
String endnum = end.getAttributeValue("num");
Element endILS = end.getChild("ils");
endils = parseILS(endILS);
airport.addRunway(startlat, startlon, startnum, endlat, endlon, endnum, width, true, startils, endils);
/*Element ilspathElement = u.getChild("ilspath");
ILSPath ilspath = null;
if (ilspathElement != null) {
ilspath = parseILSPath(ilspathElement);
}
if (ilspath == null){
airport.addRunway(startlat, startlon, startnum, endlat, endlon, endnum, width, true, null);
} else {
airport.addRunway(startlat, startlon, startnum, endlat, endlon, endnum, width,true, ilspath);
}*/
} catch (NumberFormatException ex) {/*ignore, continue*/
} catch (NullPointerException ex) {/* ignore, continue */
} //Caused by "runway" element if missing children "start" or "end"
}
Element towerElement = t.getChild("tower");
if (towerElement != null) {
try {
airport.addTower(Float.parseFloat(towerElement.getAttributeValue("lat")), Float.parseFloat(towerElement.getAttributeValue("lon")), towerElement.getAttributeValue("name"));
} catch (NumberFormatException ex) {
} catch (NullPointerException ex) {
}
}
airportMap.put(airport.getID(), airport);
return true;
}
/*private ILSPath parseILSPath(Element ilspathElement)
{
ArrayList<ILSCoord> coords = new ArrayList<ILSCoord>();
List<Element> coordElements = ilspathElement.getChildren("ilscoord");
for (Element t : coordElements){
try {
coords.add(new ILSCoord(Float.parseFloat(t.getAttributeValue("lat")),Float.parseFloat(t.getAttributeValue("lon"))));
} catch (NumberFormatException ex) {}
catch (NullPointerException ex) {}
}
ILSPath ilspath = new ILSPath(coords);
return ilspath;
}*/
private boolean parseILS(Element coordElement) {
try {
return Boolean.parseBoolean(coordElement.getAttributeValue("ils"));
} catch (NumberFormatException ex) {
} catch (NullPointerException ex) {
}
return false;
}
private Element generateElement(IAirport airport) {
Element airportElement = new Element("airport");
airportElement.setAttribute("id", airport.getID());
airportElement.setAttribute("name", airport.getName());
Iterator<? extends IRunway> i = airport.getRunways();
while (i.hasNext()) {
airportElement.addContent(generateElement(i.next()));
}
ITower tower = airport.getTower();
if (tower != null) {
airportElement.addContent(generateElement(tower));
}
return airportElement;
//TODO
}
private Element generateElement(ITower tower) {
Element towerElement = new Element("tower");
towerElement.setAttribute("lat", Float.toString(tower.getLat()));
towerElement.setAttribute("lon", Float.toString(tower.getLon()));
towerElement.setAttribute("name", tower.getName());
return towerElement;
}
private Element generateElement(IRunway runway) {
Element runwayElement = new Element("runway");
runwayElement.setAttribute("width", Float.toString(runway.getWidth()));
Element start = new Element("start");
start.setAttribute("lat", Float.toString(runway.getStartLat()));
start.setAttribute("lon", Float.toString(runway.getStartLon()));
start.setAttribute("num", runway.getStartNum());
boolean startILS = runway.hasStartILS();
start.addContent(generateElement(startILS));
runwayElement.addContent(start);
Element end = new Element("end");
end.setAttribute("lat", Float.toString(runway.getEndLat()));
end.setAttribute("lon", Float.toString(runway.getEndLon()));
end.setAttribute("num", runway.getEndNum());
boolean endILS = runway.hasEndILS();
end.addContent(generateElement(endILS));
runwayElement.addContent(end);
/*IILSPath ilspath = runway.getILSPath();
if (ilspath != null)
{
runwayElement.addContent(generateElement(ilspath));
}*/
return runwayElement;
}
/*private Element generateElement(IILSPath ilspath)
{
Element ilspathElement = new Element("ilspath");
for (IILSCoord t : ilspath.getCoords()) {
ilspathElement.addContent(generateElement(t));
}
return ilspathElement;
}*/
private Element generateElement(boolean coord) {
Element coordElement = new Element("ils");
coordElement.setAttribute("ils", coord+"");
return coordElement;
}
private void updateAirport(Element t, IAirport airport) {
Element generatedAirport = generateElement(airport);
List<Attribute> attList = generatedAirport.getAttributes();
List<Attribute> newList = new ArrayList<Attribute>();
for (Attribute a : attList) {
newList.add(a); //This step is required because the list of getAttributes is an internal list modified when method Attribute.detach is used
}
for (Attribute a : newList) {
a.detach();
}
//List<Attribute> newList = new ArrayList<Attribute>();
//System.out.println(attList.size());
//for (Attribute a : attList) {
/*Iterator<Attribute> iterator = attList.iterator();
while (iterator.hasNext()) {
Attribute a = iterator.next();
a.detach();
System.out.println("Njamo" + a);
}*/
//}
t.setAttributes(newList);
List<Content> contentList = generatedAirport.removeContent();
t.setContent(contentList);
//System.out.println("Final element: " + t.getAttribute("name"));
/*
List<Attribute> origList = generatedAirport.getAttributes();
LinkedList<Attribute> copyList = new LinkedList<Attribute>();
for (Attribute u : origList)
{
copyList.add((Attribute)u.clone());
}
t.setAttributes(copyList);*/
}
}