package nl.tudelft.bw4t.map; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.LinkedList; import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlRootElement; import org.apache.log4j.Logger; /** * New map structure, using Zones and stronger typechecking. * * <b>NewMap is not thread safe. </b> */ @XmlRootElement public class NewMap implements Serializable { private static final Logger LOGGER = Logger.getLogger(NewMap.class); /** Serialization id. */ private static final long serialVersionUID = -1346330091943903326L; /** * Boolean, true when there is one Bot per Corridor Zone default false */ private Boolean oneBotPerCorridorZone = false; /** * The number of random colored blocks to be added to the map (not to the * sequence) */ private Integer randomBlocks = 0; /** * Number of random colored blocks to be added to the sequence AND to the * map. */ private Integer randomSequence = 0; /** * Seed for random stuff */ private Integer seed = null; /** * Initial point for an area. */ private Point area = new Point(); /** * List containing all zones at the map. */ private List<Zone> zones = new LinkedList<>(); /** * Sequence, a list of BlockColor. This sequence defines what kind of blocks * the bot needs to pick up. */ private List<BlockColor> sequence = new LinkedList<>(); /** * Initial entities. */ private List<Entity> entities = new LinkedList<>(); /** * Empty Constructor, initialize newMap. */ public NewMap() { } /** * Constructor that creates a map from an inputstream that contains XML. * * @param instream * InputStream, contains XML * @return NewMap * @throws JAXBException */ public static NewMap create(InputStream instream) throws JAXBException { JAXBContext context = JAXBContext.newInstance(NewMap.class); Unmarshaller jaxbUnmarshaller = context.createUnmarshaller(); return (NewMap) jaxbUnmarshaller.unmarshal(instream); } /** * Convert the given {@link NewMap} object to a XML string * * @param map * the map to convert * @return the created XML string * @throws JAXBException * if an error occured during conversion */ public static String toXML(NewMap map) throws JAXBException { OutputStream baos = new ByteArrayOutputStream(); toXML(map, baos); return baos.toString(); } /** * Convert the given {@link NewMap} object to XML and write it to the given * outputstream. * * @param map * the map to convert * @param os * the outputstream to write to * @throws JAXBException * if we fail to convert the map object */ public static void toXML(NewMap map, OutputStream os) throws JAXBException { JAXBContext context = JAXBContext.newInstance(NewMap.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.marshal(map, os); } public List<BlockColor> getSequence() { return sequence; } public void setSequence(List<BlockColor> sequence) { this.sequence = sequence; } public List<Zone> getZones() { return zones; } public void setZones(List<Zone> zones) { this.zones = zones; } public Boolean getOneBotPerCorridorZone() { return oneBotPerCorridorZone; } public void setOneBotPerCorridorZone(Boolean oneBotPerCorridorZone) { this.oneBotPerCorridorZone = oneBotPerCorridorZone; } /** * Add new zone * * @param zone * new zone to add * @throws IllegalArgumentException * if zone already in the map */ public void addZone(Zone zone) { if (zones.contains(zone)) { throw new IllegalArgumentException("zone already in the map " + zone); } zones.add(zone); } /** * @param type * {@link EntityType}. * @return List of {@Link Zone} of given type */ public List<Zone> getZones(Zone.Type type) { List<Zone> list = new LinkedList<>(); for (Zone z : zones) { if (z.getType() == type) { list.add(z); } } return list; } public Zone getZone(String name) throws IllegalArgumentException { for (Zone z : zones) { if (name.equals(z.getName())) { return z; } } throw new IllegalArgumentException("zone " + name + " not found"); } @Override public String toString() { return "Map[onebotperzone=" + oneBotPerCorridorZone + ", randomblocks=" + randomBlocks + ",seed=" + seed + ",sequence=" + sequence + ",zones=" + zones + "]"; } public void setRandomBlocks(Integer randomBlocks) { this.randomBlocks = randomBlocks; } public Integer getRandomBlocks() { return randomBlocks; } public void setArea(Point area) { this.area = area; } public Point getArea() { return area; } public void setSeed(Integer seed) { this.seed = seed; } public Integer getSeed() { return this.seed; } /** * Sets the available entities for this map to the given list. * * @param entities * list of entities for this map. Should not be null. */ public void setEntities(List<Entity> entities) { if (entities == null) { throw new NullPointerException("entities=null"); } this.entities = entities; } /** * Gets the entities available for this map * * @param entities * list of entities. Should never be null. */ public List<Entity> getEntities() { return entities; } /** * Add @param e Entity to map */ public void addEntity(Entity e) { entities.add(e); } /** * @param randomSequence * Number of blocks to be added to the sequence AND to the map. */ public void setRandomSequence(Integer randomSequence) { this.randomSequence = randomSequence; } public Integer getRandomSequence() { return randomSequence; } @Override public int hashCode() { try { return NewMap.toXML(this).hashCode(); } catch (JAXBException e) { LOGGER.info( "Failed to create a stable hash code, reverting back to java jvm unstable.", e); final int prime = 31; int result = 1; result = prime * result + ((area == null) ? 0 : area.hashCode()); result = prime * result + ((entities == null) ? 0 : entities.hashCode()); result = prime * result + ((randomBlocks == null) ? 0 : randomBlocks.hashCode()); result = prime * result + ((randomSequence == null) ? 0 : randomSequence.hashCode()); result = prime * result + ((sequence == null) ? 0 : sequence.hashCode()); result = prime * result + ((zones == null) ? 0 : zones.hashCode()); return result; } } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; NewMap other = (NewMap) obj; if (area == null) { if (other.area != null) return false; } else if (!area.equals(other.area)) return false; if (entities == null) { if (other.entities != null) return false; } else if (!entities.equals(other.entities)) return false; if (randomBlocks == null) { if (other.randomBlocks != null) return false; } else if (!randomBlocks.equals(other.randomBlocks)) return false; if (randomSequence == null) { if (other.randomSequence != null) return false; } else if (!randomSequence.equals(other.randomSequence)) return false; if (seed == null) { if (other.seed != null) return false; } else if (!seed.equals(other.seed)) return false; if (sequence == null) { if (other.sequence != null) return false; } else if (!sequence.equals(other.sequence)) return false; if (zones == null) { if (other.zones != null) return false; } else if (!zones.equals(other.zones)) return false; return true; } }