package games.strategy.triplea.attachments; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import games.strategy.engine.data.Attachable; import games.strategy.engine.data.DefaultAttachment; import games.strategy.engine.data.GameData; import games.strategy.engine.data.GameParseException; import games.strategy.engine.data.IAttachment; import games.strategy.engine.data.Territory; import games.strategy.engine.data.UnitType; import games.strategy.engine.data.annotations.GameProperty; import games.strategy.triplea.Constants; import games.strategy.triplea.MapSupport; import games.strategy.triplea.delegate.Matches; import games.strategy.util.Match; @MapSupport public class CanalAttachment extends DefaultAttachment { private static final long serialVersionUID = -1991066817386812634L; private String m_canalName = null; private HashSet<Territory> m_landTerritories = null; private HashSet<UnitType> m_excludedUnits = null; public CanalAttachment(final String name, final Attachable attachable, final GameData gameData) { super(name, attachable, gameData); } public static Set<Territory> getAllCanalSeaZones(final String canalName, final GameData data) { final Set<Territory> rVal = new HashSet<>(); for (final Territory t : data.getMap()) { final Set<CanalAttachment> canalAttachments = get(t); if (canalAttachments.isEmpty()) { continue; } for (final CanalAttachment canalAttachment : canalAttachments) { if (canalAttachment.getCanalName().equals(canalName)) { rVal.add(t); } } } if (rVal.size() != 2) { throw new IllegalStateException( "Wrong number of sea zones for canal (exactly 2 sea zones may have the same canalName):" + rVal); } return rVal; } public static Set<CanalAttachment> get(final Territory t) { final Set<CanalAttachment> rVal = new HashSet<>(); final Map<String, IAttachment> map = t.getAttachments(); final Iterator<String> iter = map.keySet().iterator(); while (iter.hasNext()) { final IAttachment attachment = map.get(iter.next()); final String name = attachment.getName(); if (name.startsWith(Constants.CANAL_ATTACHMENT_PREFIX)) { rVal.add((CanalAttachment) attachment); } } return rVal; } public static CanalAttachment get(final Territory t, final String nameOfAttachment) { final CanalAttachment rVal = (CanalAttachment) t.getAttachment(nameOfAttachment); if (rVal == null) { throw new IllegalStateException( "CanalAttachment: No canal attachment for:" + t.getName() + " with name: " + nameOfAttachment); } return rVal; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setCanalName(final String name) { if (name == null) { m_canalName = null; return; } m_canalName = name; } public String getCanalName() { return m_canalName; } public void resetCanalName() { m_canalName = null; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setLandTerritories(final String landTerritories) { if (landTerritories == null) { m_landTerritories = null; return; } final HashSet<Territory> terrs = new HashSet<>(); for (final String name : landTerritories.split(":")) { final Territory territory = getData().getMap().getTerritory(name); if (territory == null) { throw new IllegalStateException("Canals: No territory called: " + name + thisErrorMsg()); } terrs.add(territory); } m_landTerritories = terrs; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setLandTerritories(final HashSet<Territory> value) { m_landTerritories = value; } public HashSet<Territory> getLandTerritories() { return m_landTerritories; } public void resetLandTerritories() { m_landTerritories = null; } /** * Adds to, not sets. Anything that adds to instead of setting needs a clear function as well. */ @GameProperty(xmlProperty = true, gameProperty = true, adds = true) public void setExcludedUnits(final String value) { if (value == null) { m_excludedUnits = null; return; } if (m_excludedUnits == null) { m_excludedUnits = new HashSet<>(); } if (value.equalsIgnoreCase("NONE")) { return; } if (value.equalsIgnoreCase("ALL")) { m_excludedUnits.addAll(getData().getUnitTypeList().getAllUnitTypes()); return; } for (final String name : value.split(":")) { final UnitType ut = getData().getUnitTypeList().getUnitType(name); if (ut == null) { throw new IllegalStateException("Canals: No UnitType called: " + name + thisErrorMsg()); } m_excludedUnits.add(ut); } } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setExcludedUnits(final HashSet<UnitType> value) { m_excludedUnits = value; } public HashSet<UnitType> getExcludedUnits(final GameData data) { if (m_excludedUnits == null) { return new HashSet<>( Match.getMatches(getData().getUnitTypeList().getAllUnitTypes(), Matches.UnitTypeIsAir)); } return m_excludedUnits; } public void clearExcludedUnits() { m_excludedUnits.clear(); } public void resetExcludedUnits() { m_excludedUnits = null; } @Override public void validate(final GameData data) throws GameParseException { if (m_canalName == null) { throw new GameParseException("Canals must have a canalName set!" + thisErrorMsg()); } if (m_landTerritories == null || m_landTerritories.size() == 0) { throw new GameParseException("Canal named " + m_canalName + " must have landTerritories set!" + thisErrorMsg()); } } }