package org.scotlandyard.impl.engine.boardmap;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.scotlandyard.engine.GameException;
import org.scotlandyard.engine.boardmap.BoardMap;
import org.scotlandyard.engine.boardmap.Coordinate;
import org.scotlandyard.engine.boardmap.Link;
import org.scotlandyard.engine.constants.TransportationMethod;
import org.scotlandyard.impl.engine.GameEngine;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Implementation of board map object
*
* @author Hussain Al-Mutawa
* @version 1.0
* @since Sun Sep 18 13:28:08 NZST 2011
*/
public final class BoardMapImpl implements BoardMap {
public static BoardMap getNewInstance(final String mapName) throws GameException{
final BoardMap boardMap = new BoardMapImpl(mapName);
//add this map to the list
GameEngine.instance().getBoardMaps().put(mapName, boardMap);
return boardMap;
}
public static void main(final String[] args) throws GameException
{
BoardMapImpl.getNewInstance("pnth.xml");
}
private transient final String name;
private transient final Set<Link> links;
private transient final Map<String,Coordinate> coordinates;
/**
* Initialises a new board map
*
* @param mapName
* @throws GameException if the name is not specified
*/
private BoardMapImpl(final String mapName) throws GameException{
super();
if(mapName==null){
throw new GameException("map name must be specified");
}
name = mapName;
links = new HashSet<Link>();
coordinates = new HashMap<String, Coordinate>();
}
@Override
public boolean addLink(final Link link) {
final boolean added = links.add(link);
if(added){
coordinates.put(link.getCoordinateA().getLabel(),link.getCoordinateA());
coordinates.put(link.getCoordinateB().getLabel(),link.getCoordinateB());
}
return added;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final BoardMapImpl other = (BoardMapImpl) obj;
if (this.toString() == null ? other.toString() != null : !toString().equals(other.toString())) {
return false;
}
return true;
}
@Override
public Set<Coordinate> getCoordinates() {
return new HashSet<Coordinate>(coordinates.values());
}
@Override
public Link getLink(final String coordinateA, final String coordinateB) {
Link link = null;
for(Link l:this.links){
if(l.getOtherEnd(getCoordinate(coordinateA))==getCoordinate(coordinateB)){
link=l;
break;
}
}
return link;
}
@Override
public Coordinate getCoordinate(final String coordinateLabel) {
return coordinates.get(coordinateLabel);
}
@Override
public Set<Link> getLinks() {
return new HashSet<Link>(links);
}
@Override
public Set<Link> getLinks(final Coordinate coordinate) {
final Set<Link> resultLinks = new HashSet<Link>();
for(final Link link:links){
if(link.getOtherEnd(coordinate)!=null){
resultLinks.add(link);
}
}
return resultLinks;
}
@Override
public String getName() {
return name;
}
@Override
public int hashCode() {
return this.toString().hashCode();
}
@Override
public void prepareMap(final String fileName) throws SAXException, IOException, ParserConfigurationException, GameException
{
// prepareMap(BoardMapImpl.class.getResourceAsStream(fileName));
// }
//
// public void prepareMap(final InputStream in) throws SAXException, IOException, ParserConfigurationException, GameException{
final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
final DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
final org.w3c.dom.Document doc = docBuilder.parse (fileName);
NamedNodeMap nodeMap;
final NodeList coords = doc.getElementsByTagName("coordinate");
for(int i=0; i < coords.getLength();i++)
{
nodeMap = coords.item(i).getAttributes();
final double lng = Double.parseDouble(nodeMap.getNamedItem("lng").getNodeValue());
final double lat = Double.parseDouble(nodeMap.getNamedItem("lat").getNodeValue());
final Coordinate coord = new CoordinateImpl(this, lng, lat);
coord.setLabel(nodeMap.getNamedItem("id").getNodeValue());
/// specification add colour
coordinates.put(coord.getLabel(),coord);
}
final NodeList linkList = doc.getElementsByTagName("link");
for(int i=0; i < linkList.getLength();i++)
{
nodeMap = linkList.item(i).getAttributes();
final String toNode = nodeMap.getNamedItem("to").getNodeValue();
final String fromNode = nodeMap.getNamedItem("from").getNodeValue();
final TransportationMethod type = TransportationMethod.valueOf(nodeMap.getNamedItem("type").getNodeValue());
final Link link = new LinkImpl(this, type, coordinates.get(toNode), coordinates.get(fromNode));
links.add(link);
}
}
@Override
public String toString() {
return "Board Map : [" + getName() + "]";
}
@Override
public void addCoordinate(final Coordinate coordinate) {
this.coordinates.put(coordinate.getLabel(), coordinate);
}
@Override
public void removeCoordinate(final Coordinate coordinate) {
this.coordinates.remove(coordinate.getLabel());
}
@Override
public void removeAllCoordinates() {
this.links.clear();
this.coordinates.clear();
}
@Override
public void removeAllLinks() {
this.links.clear();
}
}