package tools.map.xml.creator; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; 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 com.google.common.base.Joiner; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import games.strategy.triplea.Constants; import games.strategy.triplea.attachments.CanalAttachment; import games.strategy.triplea.attachments.TechAttachment; import games.strategy.triplea.attachments.TerritoryAttachment; import games.strategy.triplea.attachments.UnitAttachment; import games.strategy.triplea.delegate.BattleDelegate; import games.strategy.util.Triple; import tools.map.xml.creator.MapXmlCreator.GameStep; import tools.map.xml.creator.TerritoryDefinitionDialog.DEFINITION; /** * This class reads, writes and keeps the Map XML properties. */ public class MapXmlHelper { private static final String XML_ATTR_VALUE_SEPARATOR_OPTION_VALUE = ":"; public static final String XML_ATTR_STEP_NAME_DISPLAY = "display"; public static final String XML_ATTR_CONNECTION_NAME_T2 = "t2"; public static final String XML_ATTR_CONNECTION_NAME_T1 = "t1"; // XML Node Constants public static final String XML_NODE_NAME_ALLIANCE = "alliance"; public static final String XML_NODE_NAME_ATTACHMENT = "attachment"; public static final String XML_NODE_NAME_ATTACHMENT_LIST = "attachmentList"; public static final String XML_NODE_NAME_BOOLEAN = "boolean"; public static final String XML_NODE_NAME_CONNECTION = "connection"; public static final String XML_NODE_NAME_COST = "cost"; public static final String XML_NODE_NAME_DELEGATE = "delegate"; public static final String XML_NODE_NAME_FRONTIER_RULES = "frontierRules"; public static final String XML_NODE_NAME_GAME = "game"; public static final String XML_NODE_NAME_GAME_PLAY = "gamePlay"; public static final String XML_NODE_NAME_INFO = "info"; public static final String XML_NODE_NAME_INITIALIZE = "initialize"; public static final String XML_NODE_NAME_MAP = "map"; public static final String XML_NODE_NAME_NUMBER = "number"; public static final String XML_NODE_NAME_OPTION = "option"; public static final String XML_NODE_NAME_OWNER_INITIALIZE = "ownerInitialize"; public static final String XML_NODE_NAME_PLAYER = "player"; public static final String XML_NODE_NAME_PLAYER_LIST = "playerList"; public static final String XML_NODE_NAME_PRODUCTION = "production"; public static final String XML_NODE_NAME_PRODUCTION_FRONTIER = "productionFrontier"; public static final String XML_NODE_NAME_PRODUCTION_RULE = "productionRule"; public static final String XML_NODE_NAME_PROPERTY = "property"; public static final String XML_NODE_NAME_PROPERTY_LIST = "propertyList"; public static final String XML_NODE_NAME_RESOURCE = "resource"; public static final String XML_NODE_NAME_RESOURCE_LIST = "resourceList"; public static final String XML_NODE_NAME_RESULT = "result"; public static final String XML_NODE_NAME_SEQUENCE = "sequence"; public static final String XML_NODE_NAME_STEP = "step"; public static final String XML_NODE_NAME_TERRITORY = "territory"; public static final String XML_NODE_NAME_TERRITORY_OWNER = "territoryOwner"; public static final String XML_NODE_NAME_UNIT_INITIALIZE = "unitInitialize"; public static final String XML_NODE_NAME_UNIT_LIST = "unitList"; public static final String XML_NODE_NAME_UNIT_PLACEMENT = "unitPlacement"; public static final String XML_NODE_NAME_VALUE = "value"; public static final String XML_NODE_NAME_UNIT = "unit"; // XML Attribute Constants public static final String XML_ATTR_ALLIANCE_NAME_PLAYER = "player"; public static final String XML_ATTR_ALLIANCE_NAME_ALLIANCE = "alliance"; public static final String XML_ATTR_ATTACHMENT_NAME_NAME = "name"; public static final String XML_ATTR_ATTACHMENT_NAME_ATTACH_TO = "attachTo"; public static final String XML_ATTR_ATTACHMENT_NAME_TYPE = "type"; public static final String XML_ATTR_ATTACHMENT_NAME_JAVA_CLASS = "javaClass"; public static final String XML_ATTR_ATTACHMENT_NAME_TERRITORY = "territory"; public static final String XML_ATTR_ATTACHMENT_NAME_UNIT_TYPE = "unitType"; public static final String XML_ATTR_ATTACHMENT_NAME_PLAYER = "player"; public static final String XML_ATTR_COST_NAME_RESOURCE = "resource"; public static final String XML_ATTR_NUMBER_NAME_MAX = "max"; public static final String XML_ATTR_NUMBER_NAME_MIN = "min"; public static final String XML_ATTR_OPTION_NAME_NAME = "name"; public static final String XML_ATTR_OPTION_NAME_VALUE = "value"; public static final String XML_ATTR_PLAYER_NAME_NAME = "name"; public static final String XML_ATTR_PLAYER_NAME_OPTIONAL = "optional"; public static final String XML_ATTR_PROPERTY_NAME_NAME = "name"; public static final String XML_ATTR_PROPERTY_NAME_VALUE = "value"; public static final String XML_ATTR_PROPERTY_NAME_EDITABLE = "editable"; public static final String XML_ATTR_RESOURCE_NAME_NAME = "name"; public static final String XML_ATTR_RESULT_NAME_QUANTITY = "quantity"; public static final String XML_ATTR_RESULT_NAME_RESOURCE_OR_UNIT = "resourceOrUnit"; public static final String XML_ATTR_STEP_NAME_DELEGATE = "delegate"; public static final String XML_ATTR_STEP_NAME_PLAYER = "player"; public static final String XML_ATTR_STEP_NAME_NAME = "name"; public static final String XML_ATTR_STEP_NAME_MAX_RUN_COUNT = "maxRunCount"; public static final String XML_ATTR_TERRITORY_OWNER_NAME_TERRITORY = "territoryOwner"; public static final String XML_ATTR_UNIT_PLACEMENT_NAME_OWNER = "owner"; public static final String XML_ATTR_UNIT_PLACEMENT_NAME_TERRITORY = "territory"; public static final String XML_ATTR_UNIT_PLACEMENT_NAME_UNIT_TYPE = "unitType"; // XML Attribute Value Constants public static final String XML_ATTR_VALUE_PLAYER_OPTIONAL_NAME_FALSE = "false"; public static final String XML_ATTR_VALUE_OPTION_NAME_CANAL_NAME = "canalName"; public static final String XML_ATTR_VALUE_OPTION_NAME_LAND_TERRITORIES = "landTerritories"; public static final String XML_ATTR_VALUE_PROPERTY_NAME_MAP_NAME = "mapName"; public static final String XML_ATTR_VALUE_PROPERTY_NAME_NOTES = "notes"; public static final String TRIPLEA_JAVA_CLASS_DELEGATE_PATH = BattleDelegate.class.getPackage().toString().concat("."); /////////////////////////////////////////// // Getter and Setter methods for mapXmlData attributes /////////////////////////////////////////// public static Map<String, String> getXmlStringsMap() { return mapXmlData.getXmlStringsMap(); } public static void setXmlStrings(final Map<String, String> xmlStrings) { mapXmlData.setXmlStringsMap(xmlStrings); } public static List<String> getResourceList() { return mapXmlData.getResourceList(); } public static void setResourceList(final List<String> resourceList) { mapXmlData.setResourceList(resourceList); } public static Map<String, Map<DEFINITION, Boolean>> getTerritoryDefintionsMap() { return mapXmlData.getTerritoryDefintionsMap(); } public static void setTerritoryDefintions(final Map<String, Map<DEFINITION, Boolean>> territoryDefintions) { mapXmlData.setTerritoryDefintionsMap(territoryDefintions); } public static Map<String, Set<String>> getTerritoryConnectionsMap() { return mapXmlData.getTerritoryConnectionsMap(); } public static void setTerritoryConnections(final Map<String, Set<String>> territoryConnections) { mapXmlData.setTerritoryConnectionsMap(territoryConnections); } public static List<String> getPlayerNames() { return mapXmlData.getPlayerNames(); } public static void setPlayerNames(final List<String> playerName) { mapXmlData.setPlayerNames(playerName); } public static Map<String, String> getPlayerAllianceMap() { return mapXmlData.getPlayerAllianceMap(); } public static void setPlayerAlliance(final Map<String, String> playerAlliance) { mapXmlData.setPlayerAllianceMap(playerAlliance); } public static Map<String, Integer> getPlayerInitResourcesMap() { return mapXmlData.getPlayerInitResourcesMap(); } public static void setPlayerInitResources(final Map<String, Integer> playerInitResources) { mapXmlData.setPlayerInitResourcesMap(playerInitResources); } public static Map<String, List<Integer>> getUnitDefinitionsMap() { return mapXmlData.getUnitDefinitionsMap(); } public static void setUnitDefinitions(final Map<String, List<Integer>> unitDefinitions) { mapXmlData.setUnitDefinitionsMap(unitDefinitions); } public static Map<String, List<String>> getGamePlaySequenceMap() { return mapXmlData.getGamePlaySequenceMap(); } public static void setGamePlaySequence(final Map<String, List<String>> gamePlaySequence) { mapXmlData.setGamePlaySequenceMap(gamePlaySequence); } public static Map<String, Triple<String, String, Integer>> getPlayerSequenceMap() { return mapXmlData.getPlayerSequenceMap(); } public static void setPlayerSequence(final Map<String, Triple<String, String, Integer>> playerSequence) { mapXmlData.setPlayerSequenceMap(playerSequence); } public static Map<String, List<String>> getTechnologyDefinitionsMap() { return mapXmlData.getTechnologyDefinitionsMap(); } public static void setTechnologyDefinitions(final Map<String, List<String>> technologyDefinitions) { mapXmlData.setTechnologyDefinitionsMap(technologyDefinitions); } public static Map<String, List<String>> getProductionFrontiersMap() { return mapXmlData.getProductionFrontiersMap(); } public static void setProductionFrontiers(final Map<String, List<String>> productionFrontiers) { mapXmlData.setProductionFrontiersMap(productionFrontiers); } public static Map<String, List<String>> getUnitAttachmentsMap() { return mapXmlData.getUnitAttachmentsMap(); } public static void setUnitAttachments(final Map<String, List<String>> unitAttachments) { mapXmlData.setUnitAttachmentsMap(unitAttachments); } public static Map<String, Integer> getTerritoyProductionsMap() { return mapXmlData.getTerritoyProductionsMap(); } public static void setTerritoyProductions(final Map<String, Integer> territoyProductions) { mapXmlData.setTerritoyProductionsMap(territoyProductions); } public static Map<String, CanalTerritoriesTuple> getCanalDefinitionsMap() { return mapXmlData.getCanalDefinitionsMap(); } public static void setCanalDefinitions(final Map<String, CanalTerritoriesTuple> canalDefinitions) { mapXmlData.setCanalDefinitionsMap(canalDefinitions); } public static Map<String, String> getTerritoryOwnershipsMap() { return mapXmlData.getTerritoryOwnershipsMap(); } public static void setTerritoryOwnerships(final Map<String, String> territoryOwnerships) { mapXmlData.setTerritoryOwnershipsMap(territoryOwnerships); } public static Map<String, Map<String, Map<String, Integer>>> getUnitPlacementsMap() { return mapXmlData.getUnitPlacementsMap(); } public static void setUnitPlacements(final Map<String, Map<String, Map<String, Integer>>> unitPlacements) { mapXmlData.setUnitPlacementsMap(unitPlacements); } public static Map<String, List<String>> getGameSettingsMap() { return mapXmlData.getGameSettingsMap(); } public static void setGameSettings(final Map<String, List<String>> gameSettings) { mapXmlData.setGameSettingsMap(gameSettings); } public static String getNotes() { return mapXmlData.getNotes(); } public static void setNotes(final String notes) { mapXmlData.setNotes(notes); } public static File getMapXMLFile() { return mapXmlData.getMapXMLFile(); } public static void setMapXMLFile(final File mapXMLFile) { MapXmlHelper.mapXmlData.setMapXMLFile(mapXMLFile); } static void setMapXmlData(final MapXmlData mapXmlData) { MapXmlHelper.mapXmlData = mapXmlData; } private static MapXmlData mapXmlData = new MapXmlData(); static void putXmlStrings(final String key, final String value) { getXmlStringsMap().put(key, value); } static void addResourceList(final String value) { getResourceList().add(value); } static void addResourceList(final int index, final String value) { getResourceList().add(index, value); } static void putTerritoryDefintions(final String key, final HashMap<DEFINITION, Boolean> value) { getTerritoryDefintionsMap().put(key, value); } static void putTerritoryConnections(final String key, final Set<String> value) { getTerritoryConnectionsMap().put(key, value); } static void addPlayerName(final String value) { getPlayerNames().add(value); } static void putPlayerAlliance(final String key, final String value) { getPlayerAllianceMap().put(key, value); } static void putPlayerInitResources(final String key, final int value) { getPlayerInitResourcesMap().put(key, value); } static void putUnitDefinitions(final String key, final ArrayList<Integer> value) { getUnitDefinitionsMap().put(key, value); } static void putGamePlaySequence(final String key, final ArrayList<String> value) { getGamePlaySequenceMap().put(key, value); } static void putPlayerSequence(final String key, final Triple<String, String, Integer> value) { getPlayerSequenceMap().put(key, value); } static void putTechnologyDefinitions(final String key, final ArrayList<String> value) { getTechnologyDefinitionsMap().put(key, value); } static void putProductionFrontiers(final String key, final ArrayList<String> value) { getProductionFrontiersMap().put(key, value); } static void putUnitAttachments(final String key, final ArrayList<String> value) { getUnitAttachmentsMap().put(key, value); } static void putTerritoyProductions(final String key, final int value) { getTerritoyProductionsMap().put(key, value); } static void putCanalDefinitions(final String key, final CanalTerritoriesTuple value) { getCanalDefinitionsMap().put(key, value); } static void putTerritoyOwnerships(final String key, final String value) { getTerritoryOwnershipsMap().put(key, value); } static void putUnitPlacements(final String key, final Map<String, Map<String, Integer>> value) { getUnitPlacementsMap().put(key, value); } static void putGameSettings(final String key, final ArrayList<String> value) { getGameSettingsMap().put(key, value); } static void clearXmlStrings() { getXmlStringsMap().clear(); } static void clearResourceList() { getResourceList().clear(); } static void clearTerritoyDefintions() { getTerritoryDefintionsMap().clear(); } static void clearTerritoryConnections() { getTerritoryConnectionsMap().clear(); } static void clearPlayerName() { getPlayerNames().clear(); } static void clearPlayerAlliance() { getPlayerAllianceMap().clear(); } static void clearPlayerInitResources() { getPlayerInitResourcesMap().clear(); } static void clearUnitDefinitions() { getUnitDefinitionsMap().clear(); } static void clearGamePlaySequence() { getGamePlaySequenceMap().clear(); } static void clearPlayerSequence() { getPlayerSequenceMap().clear(); } static void clearTechnologyDefinitions() { getTechnologyDefinitionsMap().clear(); } static void clearProductionFrontiers() { getProductionFrontiersMap().clear(); } static void clearUnitAttachments() { getUnitAttachmentsMap().clear(); } static void clearTerritoyProductions() { getTerritoyProductionsMap().clear(); } static void clearCanalDefinitions() { getCanalDefinitionsMap().clear(); } static void clearTerritoyOwnerships() { getTerritoryOwnershipsMap().clear(); } static void clearUnitPlacements() { getUnitPlacementsMap().clear(); } static void clearGameSettings() { getGameSettingsMap().clear(); } /////////////////////////////////////////// // Start of XML parsing methods /////////////////////////////////////////// public static GameStep parseValuesFromXML(final Document dom) { initializeAll(); final Node mainlastChild = dom.getLastChild(); if (!mainlastChild.getNodeName().equals(XML_NODE_NAME_GAME)) { throw new IllegalArgumentException( "Last node of XML document is not the expeced 'game' node, but '" + mainlastChild.getNodeName() + "'"); } return parseGameNode(mainlastChild); } /** * @return step to go to. */ public static GameStep parseGameNode(final Node gameNode) { GameStep stepToGo = MapXmlCreator.GAME_STEP_FIRST; final NodeList children = gameNode.getChildNodes(); for (int i = 0; i < children.getLength(); ++i) { final Node childNode = children.item(i); final String childNodeName = childNode.getNodeName(); if (childNodeName.equals(XML_NODE_NAME_INFO)) { final HashMap<String, String> infoAttr = getAttributesMap(childNode.getAttributes()); for (final Entry<String, String> infoAttrEntry : infoAttr.entrySet()) { getXmlStringsMap().put("info_@" + infoAttrEntry.getKey(), infoAttrEntry.getValue()); } } else if (childNodeName.equals(XML_NODE_NAME_RESOURCE_LIST)) { final NodeList resourceNodes = childNode.getChildNodes(); for (int j = 0; j < resourceNodes.getLength(); ++j) { final Node resourceNode = resourceNodes.item(j); if (resourceNode.getNodeName().equals(XML_NODE_NAME_RESOURCE)) { getResourceList().add(resourceNode.getAttributes().item(0).getNodeValue()); } } } else if (childNodeName.equals(XML_NODE_NAME_MAP)) { parseMapNode(childNode.getChildNodes()); stepToGo = MapXmlCreator.getMaxGameStep(stepToGo, (getTerritoryConnectionsMap().isEmpty() ? GameStep.TERRITORY_DEFINITIONS : GameStep.TERRITORY_CONNECTIONS)); } else if (childNodeName.equals(XML_NODE_NAME_PLAYER_LIST)) { parsePlayerListNode(childNode.getChildNodes()); stepToGo = MapXmlCreator.getMaxGameStep(stepToGo, GameStep.PLAYERS_AND_ALLIANCES); } else if (childNodeName.equals(XML_NODE_NAME_PRODUCTION)) { putNodesToProductionFrontiers(childNode.getChildNodes()); stepToGo = MapXmlCreator.getMaxGameStep(stepToGo, (getProductionFrontiersMap().isEmpty() ? GameStep.UNIT_DEFINITIONS : GameStep.PRODUCTION_FRONTIERS)); } else if (childNodeName.equals(XML_NODE_NAME_GAME_PLAY)) { putNodesToPlayerSequence(childNode.getChildNodes()); stepToGo = MapXmlCreator.getMaxGameStep(stepToGo, (getPlayerSequenceMap().isEmpty() ? GameStep.UNIT_ATTACHMENTS : GameStep.TERRITORY_PRODUCTION)); } else if (childNodeName.equals(XML_NODE_NAME_ATTACHMENT_LIST)) { final NodeList attachmentListChildNodes = childNode.getChildNodes(); for (int j = 0; j < attachmentListChildNodes.getLength(); ++j) { final Node attachment = attachmentListChildNodes.item(j); if (attachment.getNodeName().equals(XML_NODE_NAME_ATTACHMENT)) { parseAttachmentNode(attachment); } } stepToGo = MapXmlCreator.getMaxGameStep(MapXmlCreator.getMaxGameStep(stepToGo, getUnitAttachmentsMap().isEmpty() ? GameStep.PRODUCTION_FRONTIERS : GameStep.UNIT_ATTACHMENTS), getTerritoyProductionsMap().isEmpty() ? GameStep.UNIT_ATTACHMENTS : GameStep.TERRITORY_PRODUCTION); } else if (childNodeName.equals(XML_NODE_NAME_INITIALIZE)) { final NodeList initializeChildNodes = childNode.getChildNodes(); for (int j = 0; j < initializeChildNodes.getLength(); ++j) { final Node ownerInitialize = initializeChildNodes.item(j); if (ownerInitialize.getNodeName().equals(XML_NODE_NAME_OWNER_INITIALIZE)) { putNodesToTerritoryOwnerships(ownerInitialize.getChildNodes()); } else if (ownerInitialize.getNodeName().equals(XML_NODE_NAME_UNIT_INITIALIZE)) { putNodesToUnitPlacements(ownerInitialize.getChildNodes()); } } stepToGo = MapXmlCreator.getMaxGameStep(stepToGo, (getUnitPlacementsMap().isEmpty() ? GameStep.TERRITORY_OWNERSHIP : GameStep.UNIT_PLACEMENTS)); } else if (childNodeName.equals(XML_NODE_NAME_PROPERTY_LIST)) { final NodeList propertyListChildNodes = childNode.getChildNodes(); for (int j = 0; j < propertyListChildNodes.getLength(); ++j) { final Node property = propertyListChildNodes.item(j); if (property.getNodeName().equals(XML_NODE_NAME_PROPERTY)) { parsePropertyNode(property); } } if (!getGameSettingsMap().isEmpty()) { stepToGo = (getNotes().length() > 0 ? GameStep.MAP_FINISHED : GameStep.GAME_SETTINGS); } } } return stepToGo; } public static void initializeAll() { MapXmlCreator.mapFolderLocation = null; MapXmlCreator.mapImageFile = null; MapXmlCreator.mapCentersFile = null; mapXmlData.initialize(); } public static void putNodesToProductionFrontiers(final NodeList productionChildNodes) { for (int i = 0; i < productionChildNodes.getLength(); ++i) { final Node productionRule = productionChildNodes.item(i); if (productionRule.getNodeName().equals(XML_NODE_NAME_PRODUCTION_RULE)) { parseProductionRuleNode(productionRule.getChildNodes()); } else if (productionRule.getNodeName().equals(XML_NODE_NAME_PRODUCTION_FRONTIER)) { final String playerName = productionRule.getAttributes().getNamedItem(XML_ATTR_ATTACHMENT_NAME_NAME).getNodeValue().substring(10); final ArrayList<String> frontierRules = new ArrayList<>(); final NodeList productionFrontierChildNodes = productionRule.getChildNodes(); for (int j = 0; j < productionFrontierChildNodes.getLength(); ++j) { final Node productionFrontierChildNode = productionFrontierChildNodes.item(j); if (productionFrontierChildNode.getNodeName().equals(XML_NODE_NAME_FRONTIER_RULES)) { frontierRules .add(productionFrontierChildNode.getAttributes().getNamedItem(XML_ATTR_ATTACHMENT_NAME_NAME) .getNodeValue().substring(3)); } } getProductionFrontiersMap().put(playerName, frontierRules); } } } public static void putNodesToPlayerSequence(final NodeList gamePlayChildNodes) { for (int i = 0; i < gamePlayChildNodes.getLength(); ++i) { final Node gamePlayChildNode = gamePlayChildNodes.item(i); if (gamePlayChildNode.getNodeName().equals(XML_NODE_NAME_DELEGATE)) { final HashMap<String, String> attrDelegate = getAttributesMap(gamePlayChildNode.getAttributes()); final ArrayList<String> newValues = new ArrayList<>(); newValues .add(attrDelegate.get(XML_ATTR_ATTACHMENT_NAME_JAVA_CLASS).replace(TRIPLEA_JAVA_CLASS_DELEGATE_PATH, "")); newValues.add(attrDelegate.get(XML_ATTR_STEP_NAME_DISPLAY)); getGamePlaySequenceMap().put(attrDelegate.get(XML_ATTR_ATTACHMENT_NAME_NAME), newValues); } else if (gamePlayChildNode.getNodeName().equals(XML_NODE_NAME_SEQUENCE)) { final NodeList sequenceChildNodes = gamePlayChildNode.getChildNodes(); for (int j = 0; j < sequenceChildNodes.getLength(); ++j) { final Node sequenceChildNode = sequenceChildNodes.item(j); if (sequenceChildNode.getNodeName().equals(XML_NODE_NAME_STEP)) { final HashMap<String, String> attrSequence = getAttributesMap(sequenceChildNode.getAttributes()); final String maxRunCount = attrSequence.get(XML_ATTR_STEP_NAME_MAX_RUN_COUNT); final String player = attrSequence.get(XML_ATTR_STEP_NAME_PLAYER); final Triple<String, String, Integer> newValues = Triple.of(attrSequence.get(XML_ATTR_STEP_NAME_DELEGATE), (player == null ? "" : player), (maxRunCount == null ? 0 : Integer.parseInt(maxRunCount))); getPlayerSequenceMap().put(attrSequence.get(XML_ATTR_STEP_NAME_NAME), newValues); } } } } } public static void putNodesToUnitPlacements(final NodeList initializeUnitChildNodes) { for (int i = 0; i < initializeUnitChildNodes.getLength(); ++i) { final Node unitPlacement = initializeUnitChildNodes.item(i); if (unitPlacement.getNodeName().equals(XML_NODE_NAME_UNIT_PLACEMENT)) { final HashMap<String, String> attrUnitPlacements = getAttributesMap(unitPlacement.getAttributes()); final String territory = attrUnitPlacements.get(XML_NODE_NAME_TERRITORY); final String owner = attrUnitPlacements.get(XML_ATTR_UNIT_PLACEMENT_NAME_OWNER); Map<String, Map<String, Integer>> terrPlacements = getUnitPlacementsMap().get(territory); if (terrPlacements == null) { terrPlacements = Maps.newHashMap(); getUnitPlacementsMap().put(territory, terrPlacements); } Map<String, Integer> terrOwnerPlacements = terrPlacements.get(owner); if (terrOwnerPlacements == null) { terrOwnerPlacements = Maps.newLinkedHashMap(); terrPlacements.put(owner, terrOwnerPlacements); } terrOwnerPlacements.put(attrUnitPlacements.get(XML_ATTR_UNIT_PLACEMENT_NAME_UNIT_TYPE), Integer.parseInt(attrUnitPlacements.get(XML_ATTR_RESULT_NAME_QUANTITY))); } } } public static void putNodesToTerritoryOwnerships(final NodeList initializeOwnerChildNodes) { for (int i = 0; i < initializeOwnerChildNodes.getLength(); ++i) { final Node territoryOwner = initializeOwnerChildNodes.item(i); if (territoryOwner.getNodeName().equals(XML_NODE_NAME_TERRITORY_OWNER)) { final HashMap<String, String> attrTerrOwner = getAttributesMap(territoryOwner.getAttributes()); getTerritoryOwnershipsMap().put(attrTerrOwner.get(XML_NODE_NAME_TERRITORY), attrTerrOwner.get(XML_ATTR_UNIT_PLACEMENT_NAME_OWNER)); } } } private static void parsePropertyNode(final Node property) { final HashMap<String, String> propertyAttr = getAttributesMap(property.getAttributes()); final ArrayList<String> settingValues = new ArrayList<>(); final String propertyName = propertyAttr.get(XML_ATTR_PROPERTY_NAME_NAME); if (propertyName.equals(XML_ATTR_VALUE_PROPERTY_NAME_NOTES) || propertyName.equals(XML_ATTR_VALUE_PROPERTY_NAME_MAP_NAME)) { final NodeList propertyListChildNodes = property.getChildNodes(); for (int i = 0; i < propertyListChildNodes.getLength(); ++i) { final Node subProperty = propertyListChildNodes.item(i); if (subProperty.getNodeName().equals(XML_NODE_NAME_VALUE)) { setNotes(subProperty.getTextContent()); } } return; } settingValues.add(propertyAttr.get(XML_NODE_NAME_VALUE)); settingValues.add(Boolean.toString(Boolean.parseBoolean(propertyAttr.get(XML_ATTR_PROPERTY_NAME_EDITABLE)))); final NodeList propertyNodes = property.getChildNodes(); for (int i = 0; i < propertyNodes.getLength(); ++i) { final Node propertyRange = propertyNodes.item(i); if (propertyRange.getNodeName().equals(XML_NODE_NAME_NUMBER)) { final HashMap<String, String> propertyRangeAttr = getAttributesMap(propertyRange.getAttributes()); settingValues.add(propertyRangeAttr.get(XML_ATTR_NUMBER_NAME_MIN)); settingValues.add(propertyRangeAttr.get(XML_ATTR_NUMBER_NAME_MAX)); getGameSettingsMap().put(propertyName, settingValues); break; } else if (propertyRange.getNodeName().equals(XML_NODE_NAME_BOOLEAN)) { settingValues.add("0"); // min settingValues.add("0"); // max getGameSettingsMap().put(propertyName, settingValues); break; } } } private static void parseAttachmentNode(final Node attachment) { final HashMap<String, String> attachmentAttr = getAttributesMap(attachment.getAttributes()); final String attachmentName = attachmentAttr.get(XML_ATTR_ATTACHMENT_NAME_NAME); final String attachmentType = attachmentAttr.get(XML_ATTR_ATTACHMENT_NAME_TYPE); final String attachmentAttachTo = attachmentAttr.get(XML_ATTR_ATTACHMENT_NAME_ATTACH_TO); if (attachmentName.equals(Constants.TECH_ATTACHMENT_NAME) && attachmentType.equals(XML_ATTR_ATTACHMENT_NAME_PLAYER)) { parseNodeTechAttachment(attachment, attachmentAttachTo); } else if (attachmentName.equals(Constants.UNIT_ATTACHMENT_NAME) && attachmentType.equals(XML_ATTR_ATTACHMENT_NAME_UNIT_TYPE)) { parseNodeUnitAttachment(attachment, attachmentAttachTo); } else if (attachmentName.equals(Constants.INF_ATTACHMENT_NAME) && attachmentType.equals(XML_ATTR_ATTACHMENT_NAME_TERRITORY)) { parseNodeCanalAttachment(attachment, attachmentAttachTo); } else if (attachmentName.equals(Constants.TERRITORY_ATTACHMENT_NAME) && attachmentType.equals(XML_ATTR_ATTACHMENT_NAME_NAME)) { parseNodeTerritoryAttachment(attachment, attachmentAttachTo); } } private static void parseNodeTerritoryAttachment(final Node attachment, final String attachmentAttachTo) { final NodeList attachmentOptionNodes = attachment.getChildNodes(); for (int i = 0; i < attachmentOptionNodes.getLength(); ++i) { final Node attachmentOption = attachmentOptionNodes.item(i); if (attachmentOption.getNodeName().equals(XML_NODE_NAME_OPTION)) { final HashMap<String, String> attachmentOptionAttr = getAttributesMap(attachmentOption.getAttributes()); final String optionNameAttr = attachmentOptionAttr.get(XML_ATTR_OPTION_NAME_NAME); if (optionNameAttr.equals(XML_NODE_NAME_PRODUCTION)) { getTerritoyProductionsMap().put(attachmentAttachTo, Integer.parseInt(attachmentOptionAttr.get(XML_NODE_NAME_VALUE))); } else { Map<DEFINITION, Boolean> terrDefinitions = getTerritoryDefintionsMap().get(attachmentAttachTo); if (terrDefinitions == null) { terrDefinitions = Maps.newHashMap(); getTerritoryDefintionsMap().put(attachmentAttachTo, terrDefinitions); } switch (TerritoryDefinitionDialog.valueOf(optionNameAttr)) { case IS_CAPITAL: terrDefinitions.put(DEFINITION.IS_CAPITAL, true); break; case IS_VICTORY_CITY: terrDefinitions.put(DEFINITION.IS_VICTORY_CITY, true); break; case IS_WATER: terrDefinitions.put(DEFINITION.IS_WATER, true); break; case IMPASSABLE: terrDefinitions.put(DEFINITION.IMPASSABLE, true); break; } } } } } private static void parseNodeTechAttachment(final Node attachment, final String attachmentAttachTo) { final NodeList attachmentOptionNodes = attachment.getChildNodes(); for (int i = 0; i < attachmentOptionNodes.getLength(); ++i) { final Node attachmentOption = attachmentOptionNodes.item(i); if (attachmentOption.getNodeName().equals(XML_NODE_NAME_OPTION)) { final HashMap<String, String> attachmentOptionAttr = getAttributesMap(attachmentOption.getAttributes()); final ArrayList<String> values = new ArrayList<>(); values.add(attachmentAttachTo); // playerName values.add(attachmentOptionAttr.get(XML_NODE_NAME_VALUE)); getTechnologyDefinitionsMap().put( attachmentOptionAttr.get(XML_ATTR_ATTACHMENT_NAME_NAME) + "_" + attachmentAttachTo, values); } } } private static void parseNodeUnitAttachment(final Node attachment, final String attachmentAttachTo) { final NodeList attachmentOptionNodes = attachment.getChildNodes(); for (int i = 0; i < attachmentOptionNodes.getLength(); ++i) { final Node attachmentOption = attachmentOptionNodes.item(i); if (attachmentOption.getNodeName().equals(XML_NODE_NAME_OPTION)) { final HashMap<String, String> attachmentOptionAttr = getAttributesMap(attachmentOption.getAttributes()); final ArrayList<String> values = new ArrayList<>(); values.add(attachmentAttachTo); // unitName values.add(attachmentOptionAttr.get(XML_NODE_NAME_VALUE)); getUnitAttachmentsMap().put( attachmentOptionAttr.get(XML_ATTR_ATTACHMENT_NAME_NAME) + "_" + attachmentAttachTo, values); } } } private static void parseNodeCanalAttachment(final Node attachment, final String attachmentAttachTo) { final NodeList attachmentOptionNodes = attachment.getChildNodes(); CanalTerritoriesTuple canalDef = null; String newCanalName = null; final SortedSet<String> newLandTerritories = new TreeSet<>(); for (int i = 0; i < attachmentOptionNodes.getLength(); ++i) { final Node attachmentOption = attachmentOptionNodes.item(i); if (attachmentOption.getNodeName().equals(XML_NODE_NAME_OPTION)) { final HashMap<String, String> attachmentOptionAttr = getAttributesMap(attachmentOption.getAttributes()); final String attachOptAttrName = attachmentOptionAttr.get(XML_ATTR_OPTION_NAME_NAME); if (attachOptAttrName.equals(XML_ATTR_VALUE_OPTION_NAME_CANAL_NAME)) { newCanalName = attachmentOptionAttr.get(XML_NODE_NAME_VALUE); canalDef = getCanalDefinitionsMap().get(newCanalName); if (canalDef != null) { break; } } else if (attachOptAttrName.equals(XML_ATTR_VALUE_OPTION_NAME_LAND_TERRITORIES)) { newLandTerritories.addAll(Arrays .asList( attachmentOptionAttr.get(XML_ATTR_OPTION_NAME_VALUE).split(XML_ATTR_VALUE_SEPARATOR_OPTION_VALUE))); } } } if (canalDef == null) { final SortedSet<String> newWaterTerritories = new TreeSet<>(); newWaterTerritories.add(attachmentAttachTo); getCanalDefinitionsMap().put(newCanalName, new CanalTerritoriesTuple(newWaterTerritories, newLandTerritories)); } else { canalDef.getWaterTerritories().add(attachmentAttachTo); } } private static void parseProductionRuleNode(final NodeList productionRuleChildNodes) { HashMap<String, String> attrMapCost = null; HashMap<String, String> attrMapResult = null; for (int i = 0; i < productionRuleChildNodes.getLength(); ++i) { final Node productionRuleChildNode = productionRuleChildNodes.item(i); final String productionRuleChildNodeName = productionRuleChildNode.getNodeName(); if (productionRuleChildNodeName.equals(XML_NODE_NAME_COST)) { attrMapCost = getAttributesMap(productionRuleChildNode.getAttributes()); if (attrMapResult != null) { break; } } else if (productionRuleChildNodeName.equals(XML_NODE_NAME_RESULT)) { attrMapResult = getAttributesMap(productionRuleChildNode.getAttributes()); if (attrMapCost != null) { break; } } } final ArrayList<Integer> newValues = new ArrayList<>(); newValues.add(Integer.parseInt(attrMapCost.get(XML_ATTR_RESULT_NAME_QUANTITY))); newValues.add(Integer.parseInt(attrMapResult.get(XML_ATTR_RESULT_NAME_QUANTITY))); putUnitDefinitions(attrMapResult.get(XML_ATTR_RESULT_NAME_RESOURCE_OR_UNIT), newValues); } private static HashMap<String, String> getAttributesMap(final NamedNodeMap attrNodeMap) { final HashMap<String, String> rVal = Maps.newHashMap(); for (int i = 0; i < attrNodeMap.getLength(); ++i) { final Node attrNodeItem = attrNodeMap.item(i); rVal.put(attrNodeItem.getNodeName(), attrNodeItem.getNodeValue()); } return rVal; } private static void parsePlayerListNode(final NodeList playerListChildNodes) { for (int i = 0; i < playerListChildNodes.getLength(); ++i) { final Node playerListChildNode = playerListChildNodes.item(i); final String playerListChildNodeName = playerListChildNode.getNodeName(); if (playerListChildNodeName.equals(XML_NODE_NAME_PLAYER)) { final HashMap<String, String> attrMapPlayer = getAttributesMap(playerListChildNode.getAttributes()); final String playerNameAttr = attrMapPlayer.get(XML_ATTR_PLAYER_NAME_NAME); getPlayerNames().add(playerNameAttr); getPlayerInitResourcesMap().put(playerNameAttr, 0); // TODO: add logic for optional value // attrMapPlayer.get("optional") } else if (playerListChildNodeName.equals(XML_NODE_NAME_ALLIANCE)) { final HashMap<String, String> attrMapPlayer = getAttributesMap(playerListChildNode.getAttributes()); getPlayerAllianceMap().put(attrMapPlayer.get(XML_ATTR_ALLIANCE_NAME_PLAYER), attrMapPlayer.get(XML_ATTR_ALLIANCE_NAME_ALLIANCE)); } } } private static void parseMapNode(final NodeList mapChildNodes) { for (int i = 0; i < mapChildNodes.getLength(); ++i) { final Node mapChildNode = mapChildNodes.item(i); final String mapChildNodeName = mapChildNode.getNodeName(); if (mapChildNodeName.equals(XML_NODE_NAME_TERRITORY)) { parseNodeTerritory(mapChildNode); } else if (mapChildNodeName.equals(XML_NODE_NAME_CONNECTION)) { parseNodeConnection(mapChildNode); } } } private static void parseNodeConnection(final Node mapChildNode) { final NamedNodeMap connectionAttrNodes = mapChildNode.getAttributes(); String t1Name = connectionAttrNodes.item(0).getNodeValue(); String t2Name = connectionAttrNodes.item(1).getNodeValue(); if (t1Name.compareTo(t2Name) > 0) { final String swapHelper = t1Name; t1Name = t2Name; t2Name = swapHelper; } Set<String> t1Connections = getTerritoryConnectionsMap().get(t1Name); if (t1Connections != null) { t1Connections.add(t2Name); } else { t1Connections = Sets.newLinkedHashSet(); t1Connections.add(t2Name); getTerritoryConnectionsMap().put(t1Name, t1Connections); } } private static void parseNodeTerritory(final Node mapChildNode) { final NamedNodeMap terrAttrNodes = mapChildNode.getAttributes(); String terrName = null; final HashMap<DEFINITION, Boolean> terrDef = Maps.newHashMap(); for (int i = 0; i < terrAttrNodes.getLength(); ++i) { final Node terrAttrNode = terrAttrNodes.item(i); if (terrAttrNode.getNodeName().equals(XML_ATTR_ATTACHMENT_NAME_NAME)) { terrName = terrAttrNode.getNodeValue(); } else { terrDef.put(TerritoryDefinitionDialog.valueOf(terrAttrNode.getNodeName()), Boolean.valueOf(terrAttrNode.getNodeValue())); } } getTerritoryDefintionsMap().put(terrName, terrDef); } /////////////////////////////////////////// // Start of XML creation methods /////////////////////////////////////////// static Document getXMLDocument() throws ParserConfigurationException { // TODO: break into smaller chunks, consider builder pattern final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); final DocumentBuilder db = dbf.newDocumentBuilder(); final Document doc = db.newDocument(); final Element game = doc.createElement(XML_NODE_NAME_GAME); doc.appendChild(game); appendFromXMLStrings(doc, game); final Element map = doc.createElement(XML_NODE_NAME_MAP); game.appendChild(map); map.appendChild(doc.createComment(" Territory Definitions ")); boolean territoryAttachmentNeeded = appendFromTerritoryDefinitions(doc, map); appendFromResourceList(doc, game); appendFromPlayerName(doc, game); appendFromUnitDefinitions(doc, game, map); appendFromGamePlaySequence(doc, game); if (!getTerritoyProductionsMap().isEmpty()) { territoryAttachmentNeeded = true; } if (!getTechnologyDefinitionsMap().isEmpty() || !getUnitAttachmentsMap().isEmpty() || territoryAttachmentNeeded || !getCanalDefinitionsMap().isEmpty()) { final Element attachmentList = doc.createElement(XML_NODE_NAME_ATTACHMENT_LIST); game.appendChild(attachmentList); appendToAttachmentList(doc, territoryAttachmentNeeded, attachmentList); } appendInitialize(doc, game); return doc; } private static void appendInitialize(final Document doc, final Element game) { final Element initialize = doc.createElement(XML_NODE_NAME_INITIALIZE); game.appendChild(initialize); appendFromTerritoryOwnerships(doc, initialize); appendFromUnitPlacements(doc, initialize); appendPropertyList(doc, game); } private static void appendPropertyList(final Document doc, final Element game) { final Element propertyList = doc.createElement(XML_NODE_NAME_PROPERTY_LIST); game.appendChild(propertyList); appendFromGameSettings(doc, propertyList); if (getNotes().length() > 0) { final Element property = doc.createElement(XML_NODE_NAME_PROPERTY); property.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, XML_ATTR_VALUE_PROPERTY_NAME_NOTES); final Element propertyValue = doc.createElement(XML_NODE_NAME_VALUE); propertyValue.appendChild(doc.createCDATASection(getNotes())); property.appendChild(propertyValue); propertyList.appendChild(property); } if (getMapXMLFile() != null) { propertyList.appendChild(doc.createComment(" Map Name: also used for map utils when asked ")); final Element property = doc.createElement(XML_NODE_NAME_PROPERTY); property.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, XML_ATTR_VALUE_PROPERTY_NAME_MAP_NAME); final String fileName = getMapXMLFile().getName(); property.setAttribute(XML_ATTR_PROPERTY_NAME_VALUE, fileName.substring(0, fileName.lastIndexOf(".") - 1)); property.setAttribute(XML_ATTR_PROPERTY_NAME_EDITABLE, Constants.PROPERTY_FALSE); propertyList.appendChild(property); } } public static void appendFromGameSettings(final Document doc, final Element propertyList) { if (!getGameSettingsMap().isEmpty()) { for (final Entry<String, List<String>> gameSettingsEntry : getGameSettingsMap().entrySet()) { final Element property = doc.createElement(XML_NODE_NAME_PROPERTY); final List<String> settingsValue = gameSettingsEntry.getValue(); property.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, gameSettingsEntry.getKey()); final String valueString = settingsValue.get(0); property.setAttribute(XML_ATTR_PROPERTY_NAME_VALUE, valueString); property.setAttribute(XML_ATTR_PROPERTY_NAME_EDITABLE, settingsValue.get(1)); if (valueString.equals(Constants.PROPERTY_TRUE) || valueString.equals(Constants.PROPERTY_FALSE)) { property.appendChild(doc.createElement(XML_NODE_NAME_BOOLEAN)); } else { final String minString = settingsValue.get(2); final String maxString = settingsValue.get(3); try { Integer.valueOf(minString); Integer.valueOf(maxString); final Element number = doc.createElement(XML_NODE_NAME_NUMBER); number.setAttribute(XML_ATTR_NUMBER_NAME_MIN, minString); number.setAttribute(XML_ATTR_NUMBER_NAME_MAX, maxString); property.appendChild(number); } catch (final NumberFormatException nfe) { // nothing to do } } propertyList.appendChild(property); } } } public static void appendFromUnitPlacements(final Document doc, final Element initialize) { if (!getUnitPlacementsMap().isEmpty()) { final Element unitInitialize = doc.createElement(XML_NODE_NAME_UNIT_INITIALIZE); initialize.appendChild(unitInitialize); for (final Entry<String, Map<String, Map<String, Integer>>> placementEntry : getUnitPlacementsMap() .entrySet()) { final Element unitPlacementTemplate = doc.createElement(XML_NODE_NAME_UNIT_PLACEMENT); unitPlacementTemplate.setAttribute(XML_ATTR_UNIT_PLACEMENT_NAME_TERRITORY, placementEntry.getKey()); for (final Entry<String, Map<String, Integer>> playerPlacements : placementEntry.getValue() .entrySet()) { final Element playerUnitPlacementTemplate = (Element) unitPlacementTemplate.cloneNode(false); if (playerPlacements.getKey() != null) { playerUnitPlacementTemplate.setAttribute(XML_ATTR_UNIT_PLACEMENT_NAME_OWNER, playerPlacements.getKey()); } for (final Entry<String, Integer> unitDetails : playerPlacements.getValue().entrySet()) { if (unitDetails.getValue() > 0) { final Element unitPlacement = (Element) playerUnitPlacementTemplate.cloneNode(false); unitPlacement.setAttribute(XML_ATTR_ATTACHMENT_NAME_UNIT_TYPE, unitDetails.getKey()); unitPlacement.setAttribute(XML_ATTR_RESULT_NAME_QUANTITY, unitDetails.getValue().toString()); unitInitialize.appendChild(unitPlacement); } } } } } } public static void appendFromTerritoryOwnerships(final Document doc, final Element initialize) { if (!getTerritoryOwnershipsMap().isEmpty()) { final Element ownerInitialize = doc.createElement(XML_NODE_NAME_OWNER_INITIALIZE); initialize.appendChild(ownerInitialize); final HashMap<String, ArrayList<String>> playerTerritories = Maps.newHashMap(); for (final String player : getPlayerNames()) { playerTerritories.put(player, new ArrayList<>()); } for (final Entry<String, String> ownershipEntry : getTerritoryOwnershipsMap().entrySet()) { playerTerritories.get(ownershipEntry.getValue()).add(ownershipEntry.getKey()); } for (final Entry<String, ArrayList<String>> playerTerritoriesEntry : playerTerritories.entrySet()) { doc.createComment(" " + playerTerritoriesEntry.getKey() + " Owned Territories "); final Element territoryOwnerTemplate = doc.createElement(XML_NODE_NAME_TERRITORY_OWNER); territoryOwnerTemplate.setAttribute(XML_ATTR_UNIT_PLACEMENT_NAME_OWNER, playerTerritoriesEntry.getKey()); for (final String territory : playerTerritoriesEntry.getValue()) { final Element territoryOwner = (Element) territoryOwnerTemplate.cloneNode(false); territoryOwner.setAttribute(XML_ATTR_TERRITORY_OWNER_NAME_TERRITORY, territory); ownerInitialize.appendChild(territoryOwner); } } } } public static void appendFromResourceList(final Document doc, final Element game) { if (!getResourceList().isEmpty()) { final Element resourceListElement = doc.createElement(XML_NODE_NAME_RESOURCE_LIST); game.appendChild(resourceListElement); for (final String resourceName : getResourceList()) { final Element resourceElement = doc.createElement(XML_NODE_NAME_RESOURCE); resourceElement.setAttribute(XML_ATTR_RESOURCE_NAME_NAME, resourceName); resourceListElement.appendChild(resourceElement); } } } public static void appendToAttachmentList(final Document doc, final boolean territoryAttachmentNeeded, final Element attachmentList) { final Element attachmentTemplate = doc.createElement(XML_NODE_NAME_ATTACHMENT); if (!getTechnologyDefinitionsMap().isEmpty()) { setAttachmentTemplateAttributes(attachmentTemplate, Constants.TECH_ATTACHMENT_NAME, TechAttachment.class.getName(), XML_ATTR_ATTACHMENT_NAME_PLAYER); writeAttachmentNodes(doc, attachmentList, getTechnologyDefinitionsMap(), attachmentTemplate); } if (!getUnitAttachmentsMap().isEmpty()) { setAttachmentTemplateAttributes(attachmentTemplate, Constants.UNIT_ATTACHMENT_NAME, UnitAttachment.class.getName(), XML_ATTR_ATTACHMENT_NAME_UNIT_TYPE); writeAttachmentNodes(doc, attachmentList, getUnitAttachmentsMap(), attachmentTemplate); } if (territoryAttachmentNeeded) { setAttachmentTemplateAttributes(attachmentTemplate, Constants.TERRITORY_ATTACHMENT_NAME, TerritoryAttachment.class.getName(), XML_NODE_NAME_TERRITORY); writeAttachmentNodes(doc, attachmentList, getTerritoryAttachments(), attachmentTemplate); } if (!getCanalDefinitionsMap().isEmpty()) { setAttachmentTemplateAttributes(attachmentTemplate, Constants.INF_ATTACHMENT_NAME, CanalAttachment.class.getName(), XML_NODE_NAME_TERRITORY); addCanalDefinitionsAttachmentNodes(doc, attachmentList, attachmentTemplate); writeAttachmentNodes(doc, attachmentList, getUnitAttachmentsMap(), attachmentTemplate); } } private static void setAttachmentTemplateAttributes(final Element attachmentTemplate, final String name, final String javaClass, final String player) { attachmentTemplate.setAttribute(XML_ATTR_ATTACHMENT_NAME_NAME, name); attachmentTemplate.setAttribute(XML_ATTR_ATTACHMENT_NAME_JAVA_CLASS, javaClass); attachmentTemplate.setAttribute(XML_ATTR_ATTACHMENT_NAME_TYPE, player); } private static void addCanalDefinitionsAttachmentNodes(final Document doc, final Element attachmentList, final Element attachmentTemplate) { for (final Entry<String, CanalTerritoriesTuple> canalDefEntry : getCanalDefinitionsMap() .entrySet()) { final CanalTerritoriesTuple canalDef = canalDefEntry.getValue(); final Iterator<String> iter_landTerrs = canalDef.getLandTerritories().iterator(); final StringBuilder sb = new StringBuilder(iter_landTerrs.next()); while (iter_landTerrs.hasNext()) { sb.append(XML_ATTR_VALUE_SEPARATOR_OPTION_VALUE).append(iter_landTerrs.next()); } final String landTerritories = sb.toString(); final Element attachmentTemplateCanal = (Element) attachmentTemplate.cloneNode(false); final Element canalOptionName = doc.createElement(XML_NODE_NAME_OPTION); canalOptionName.setAttribute(XML_ATTR_OPTION_NAME_NAME, XML_ATTR_VALUE_OPTION_NAME_CANAL_NAME); canalOptionName.setAttribute(XML_ATTR_PROPERTY_NAME_VALUE, canalDefEntry.getKey()); attachmentTemplateCanal.appendChild(canalOptionName); final Element canalOptionLandTerrs = doc.createElement(XML_NODE_NAME_OPTION); canalOptionLandTerrs.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, XML_ATTR_VALUE_OPTION_NAME_LAND_TERRITORIES); canalOptionLandTerrs.setAttribute(XML_ATTR_PROPERTY_NAME_VALUE, landTerritories); attachmentTemplateCanal.appendChild(canalOptionLandTerrs); for (final String waterTerr : canalDef.getWaterTerritories()) { final Element canalAttachment = (Element) attachmentTemplateCanal.cloneNode(true); canalAttachment.setAttribute(XML_ATTR_ATTACHMENT_NAME_ATTACH_TO, waterTerr); attachmentList.appendChild(canalAttachment); } } } private static Map<String, List<String>> getTerritoryAttachments() { final Map<String, List<String>> territoryAttachments = Maps.newLinkedHashMap(); addAttachmentsFromTerritoryDefinitions(territoryAttachments); addAttachmentsFromTerritoryProductions(territoryAttachments); return territoryAttachments; } private static void addAttachmentsFromTerritoryProductions(final Map<String, List<String>> territoryAttachments) { for (final Entry<String, Integer> productionEntry : getTerritoyProductionsMap().entrySet()) { final int production = productionEntry.getValue(); if (production > 0) { final String territoryName = productionEntry.getKey(); final ArrayList<String> attachmentOptions = new ArrayList<>(); attachmentOptions.add(territoryName); attachmentOptions.add(Integer.toString(production)); territoryAttachments.put("production_" + territoryName, attachmentOptions); } } } private static void addAttachmentsFromTerritoryDefinitions(final Map<String, List<String>> territoryAttachments) { for (final Entry<String, Map<DEFINITION, Boolean>> territoryDefinition : getTerritoryDefintionsMap().entrySet()) { final String territoryName = territoryDefinition.getKey(); for (final Entry<DEFINITION, Boolean> definition : territoryDefinition.getValue().entrySet()) { if (definition.getValue() == Boolean.TRUE) { final ArrayList<String> attachmentOptions = new ArrayList<>(); attachmentOptions.add(territoryName); attachmentOptions.add("true"); // TODO: handle capital different based on owner // owner defined (step 13) only after territory definitions (step 2) // <option name="capital" value="Italians"/> territoryAttachments.put( TerritoryDefinitionDialog.getDefinitionString(definition.getKey()) + "_" + territoryName, attachmentOptions); } } } } public static boolean appendFromTerritoryDefinitions(final Document doc, final Element map) { boolean territoryAttachmentNeeded = false; for (final Entry<String, Map<DEFINITION, Boolean>> entryTerritoryDefinition : getTerritoryDefintionsMap() .entrySet()) { final Element territory = doc.createElement(XML_NODE_NAME_TERRITORY); territory.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, entryTerritoryDefinition.getKey()); final Map<DEFINITION, Boolean> territoryDefinition = entryTerritoryDefinition.getValue(); final int territoryDefinitionSize = territoryDefinition.size(); final Boolean isWater = territoryDefinition.get(DEFINITION.IS_WATER); if (isWater != null && isWater) { territory.setAttribute(TerritoryDefinitionDialog.getDefinitionString(DEFINITION.IS_WATER), "true"); if (territoryDefinitionSize > 1) { territoryAttachmentNeeded = true; } } else if (territoryDefinitionSize > 1 || isWater == null && territoryDefinitionSize > 0) { territoryAttachmentNeeded = true; } map.appendChild(territory); } map.appendChild(doc.createComment(" Territory Connections ")); for (final Entry<String, Set<String>> entryTerritoryConnection : getTerritoryConnectionsMap().entrySet()) { final Element connectionTemp = doc.createElement(XML_NODE_NAME_CONNECTION); connectionTemp.setAttribute(XML_ATTR_CONNECTION_NAME_T1, entryTerritoryConnection.getKey()); for (final String t2 : entryTerritoryConnection.getValue()) { connectionTemp.setAttribute(XML_ATTR_CONNECTION_NAME_T2, t2); map.appendChild(connectionTemp.cloneNode(false)); } } return territoryAttachmentNeeded; } public static void appendFromXMLStrings(final Document doc, final Element game) { Element currentElem = null; String prevKeyNode = null; for (final Entry<String, String> entryXMLString : getXmlStringsMap().entrySet()) { final String key = entryXMLString.getKey(); final String[] split = key.split("_@"); if (!split[0].equals(prevKeyNode)) { Element parentElem = game; for (final String newNode : split[0].split("_")) { currentElem = doc.createElement(newNode); parentElem.appendChild(currentElem); parentElem = currentElem; } } currentElem.setAttribute(split[1], entryXMLString.getValue()); prevKeyNode = split[0]; } } public static void appendFromGamePlaySequence(final Document doc, final Element game) { if (!getGamePlaySequenceMap().isEmpty()) { final Element gamePlay = doc.createElement(XML_NODE_NAME_GAME_PLAY); game.appendChild(gamePlay); for (final Entry<String, List<String>> delegateStep : getGamePlaySequenceMap().entrySet()) { final List<String> delegateProperties = delegateStep.getValue(); final Element delegate = doc.createElement(XML_NODE_NAME_DELEGATE); delegate.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, delegateStep.getKey()); delegate.setAttribute(XML_ATTR_ATTACHMENT_NAME_JAVA_CLASS, TRIPLEA_JAVA_CLASS_DELEGATE_PATH + delegateProperties.get(0)); delegate.setAttribute(XML_ATTR_STEP_NAME_DISPLAY, delegateProperties.get(1)); gamePlay.appendChild(delegate); } if (!getPlayerSequenceMap().isEmpty()) { final Element sequence = doc.createElement(XML_NODE_NAME_SEQUENCE); gamePlay.appendChild(sequence); for (final Entry<String, Triple<String, String, Integer>> sequenceStep : getPlayerSequenceMap().entrySet()) { final Triple<String, String, Integer> sequenceProperties = sequenceStep.getValue(); final Element step = doc.createElement(XML_NODE_NAME_STEP); final String sequenceStepKey = sequenceStep.getKey(); step.setAttribute(XML_ATTR_STEP_NAME_NAME, sequenceStepKey); step.setAttribute(XML_ATTR_STEP_NAME_DELEGATE, sequenceProperties.getFirst()); if (sequenceProperties.getSecond().length() > 0) { step.setAttribute(XML_ATTR_ATTACHMENT_NAME_PLAYER, sequenceProperties.getSecond()); } final int maxRunCount = sequenceProperties.getThird(); if (maxRunCount > 0) { step.setAttribute(XML_ATTR_STEP_NAME_MAX_RUN_COUNT, Integer.toString(maxRunCount)); } if (stepNameIndicatesNonCombatMove(sequenceStepKey)) { step.setAttribute(XML_ATTR_STEP_NAME_DISPLAY, "Non Combat Move"); } sequence.appendChild(step); } } } } // TODO REPLACE 'endsWith("NonCombatMove")'-checks IN REMAINING PROJEKT /** * @param stepName - string of the step name. * @return true if string ends with "NonCombatMove", false otherwise */ private static boolean stepNameIndicatesNonCombatMove(final String stepName) { return stepName.endsWith("NonCombatMove"); } public static void appendFromPlayerName(final Document doc, final Element game) { if (!getPlayerNames().isEmpty()) { final Element playerList = doc.createElement(XML_NODE_NAME_PLAYER_LIST); game.appendChild(playerList); playerList.appendChild(doc.createComment(" In Turn Order ")); appendChildrenWithTwoAttributesFromList(doc, playerList, getPlayerNames(), XML_NODE_NAME_PLAYER, XML_ATTR_PLAYER_NAME_NAME, XML_ATTR_PLAYER_NAME_OPTIONAL, XML_ATTR_VALUE_PLAYER_OPTIONAL_NAME_FALSE); final HashMap<String, ArrayList<String>> alliances = Maps.newHashMap(); for (final Entry<String, String> allianceEntry : getPlayerAllianceMap().entrySet()) { final String allianceName = allianceEntry.getValue(); ArrayList<String> players = alliances.get(allianceName); if (players == null) { players = new ArrayList<>(); alliances.put(allianceName, players); } players.add(allianceEntry.getKey()); } for (final Entry<String, ArrayList<String>> allianceEntry : alliances.entrySet()) { final String allianceName = allianceEntry.getKey(); playerList.appendChild(doc.createComment(" " + allianceName + " Alliance ")); appendChildrenWithTwoAttributesFromList(doc, playerList, allianceEntry.getValue(), XML_NODE_NAME_ALLIANCE, XML_ATTR_ATTACHMENT_NAME_PLAYER, XML_NODE_NAME_ALLIANCE, allianceName); } } } public static void appendFromUnitDefinitions(final Document doc, final Element game, final Element map) { if (!getUnitDefinitionsMap().isEmpty()) { map.appendChild(doc.createComment(" Unit Definitions ")); final Element unitList = doc.createElement(XML_NODE_NAME_UNIT_LIST); game.appendChild(unitList); final Element production = doc.createElement(XML_NODE_NAME_PRODUCTION); game.appendChild(production); final String firstResourceName = getResourceList().get(0); for (final Entry<String, List<Integer>> unitDefinition : getUnitDefinitionsMap().entrySet()) { final String unitName = unitDefinition.getKey(); final Element unit = doc.createElement(XML_NODE_NAME_UNIT); unit.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, unitName); unitList.appendChild(unit); final List<Integer> definition = unitDefinition.getValue(); final Element productionRule = doc.createElement(XML_NODE_NAME_PRODUCTION_RULE); productionRule.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, getProductionRuleAttrNameValue(unitName)); production.appendChild(productionRule); final Element prCost = doc.createElement(XML_NODE_NAME_COST); prCost.setAttribute(XML_ATTR_COST_NAME_RESOURCE, firstResourceName); prCost.setAttribute(XML_ATTR_RESULT_NAME_QUANTITY, definition.get(0).toString()); productionRule.appendChild(prCost); final Element prResult = doc.createElement(XML_NODE_NAME_RESULT); prResult.setAttribute(XML_ATTR_RESULT_NAME_RESOURCE_OR_UNIT, unitName); prResult.setAttribute(XML_ATTR_RESULT_NAME_QUANTITY, definition.get(1).toString()); productionRule.appendChild(prResult); } for (final Entry<String, List<String>> productionFrontierEntry : getProductionFrontiersMap().entrySet()) { final String productionFrontierName = productionFrontierEntry.getKey(); final Element productionFrontier = doc.createElement(XML_NODE_NAME_PRODUCTION_FRONTIER); productionFrontier.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, productionFrontierName); production.appendChild(productionFrontier); for (final String frontierRuleName : productionFrontierEntry.getValue()) { final Element frontierRule = doc.createElement(XML_NODE_NAME_FRONTIER_RULES); frontierRule.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, getFrontierRuleValue(frontierRuleName)); productionFrontier.appendChild(frontierRule); } } } } private static String getFrontierRuleValue(final String frontierRuleName) { return "buy" + frontierRuleName; } private static String getProductionRuleAttrNameValue(final String unitName) { return "buy" + unitName.substring(0, 1).toUpperCase() + unitName.substring(1); } /** * Appends new Elements to parentElement from list having two attributes. * Attribute 1 is coming from the provided list * Attribute 2 has a fix value for all new elements */ public static void appendChildrenWithTwoAttributesFromList(final Document doc, final Element parentElement, final List<String> list, final String childName, final String attrOneKey, final String attrTwoKey, final String attrTwoFixValue) { for (final String attrOneValue : list) { final Element newChild = doc.createElement(childName); newChild.setAttribute(attrOneKey, attrOneValue); newChild.setAttribute(attrTwoKey, attrTwoFixValue); parentElement.appendChild(newChild); } } protected static void writeAttachmentNodes(final Document doc, final Element attachmentList, final Map<String, List<String>> hashMap, final Element attachmentTemplate) { final HashMap<String, List<Element>> playerAttachOptions = Maps.newHashMap(); for (final Entry<String, List<String>> technologyDefinition : hashMap.entrySet()) { final List<String> definitionValues = technologyDefinition.getValue(); final Element option = doc.createElement(XML_NODE_NAME_OPTION); final String techKey = technologyDefinition.getKey(); option.setAttribute(XML_ATTR_PROPERTY_NAME_NAME, techKey.substring(0, techKey.lastIndexOf(definitionValues.get(0)) - 1)); option.setAttribute(XML_ATTR_PROPERTY_NAME_VALUE, definitionValues.get(1)); final String playerName = definitionValues.get(0); List<Element> elementList = playerAttachOptions.get(playerName); if (elementList == null) { elementList = new ArrayList<>(); playerAttachOptions.put(playerName, elementList); } elementList.add(option); } for (final Entry<String, List<Element>> optionElementList : playerAttachOptions.entrySet()) { final String playerName = optionElementList.getKey(); final Element attachment = (Element) attachmentTemplate.cloneNode(false); attachment.setAttribute(XML_ATTR_ATTACHMENT_NAME_ATTACH_TO, playerName); attachmentList.appendChild(attachment); for (final Element option : optionElementList.getValue()) { attachment.appendChild(option); } } } public static final String playerNeutral = "<Neutral>"; public static String[] getPlayersListInclNeutral() { getPlayerNames().add(playerNeutral); final String[] rVal = getPlayerNames().toArray(new String[getPlayerNames().size()]); getPlayerNames().remove(playerNeutral); return rVal; } public static void filterForWaterTerrsWithAtLeastOneWaterNeighbor(final Set<String> waterTerrs2) { final Set<String> waterTerrs2Copy = new TreeSet<>(waterTerrs2); for (final Iterator<String> iter_waterTerr2 = waterTerrs2.iterator(); iter_waterTerr2.hasNext();) { final String waterTerr2 = iter_waterTerr2.next(); waterTerrs2Copy.remove(waterTerr2); final Set<String> waterTerrs2ReqNeighbors = new TreeSet<>(waterTerrs2Copy); final Set<String> waterTerr2Neightbors = getTerritoryConnectionsMap().get(waterTerr2); if (waterTerr2Neightbors != null) { for (final String waterTerr2Neighbor : waterTerr2Neightbors) { waterTerrs2ReqNeighbors.remove(waterTerr2Neighbor); } } if (!waterTerrs2ReqNeighbors.isEmpty()) { iter_waterTerr2.remove(); } } } public static void validateAndAddCanalDefinition(final String landTerr, final Set<String> waterTerrs, final Set<String> landTerrNeighbors, final Entry<String, Set<String>> landWaterTerrConn2) { final String landTerr2 = landWaterTerrConn2.getKey(); Set<String> landTerrNeighbors2 = getTerritoryConnectionsMap().get(landTerr2); if (landTerrNeighbors2 == null) { landTerrNeighbors2 = Sets.newLinkedHashSet(); } if (!landTerrNeighbors.contains(landTerr2) && !landTerrNeighbors2.contains(landTerr)) { return; } final Set<String> waterTerrs2 = new TreeSet<>(landWaterTerrConn2.getValue()); waterTerrs2.retainAll(waterTerrs); if (waterTerrs2.size() > 1) { filterForWaterTerrsWithAtLeastOneWaterNeighbor(waterTerrs2); // create canal only if at least 2 water territories remain if (waterTerrs2.size() > 1) { final Set<String> newLandSet = new TreeSet<>(); newLandSet.add(landTerr); newLandSet.add(landTerr2); final CanalTerritoriesTuple terrTuple = new CanalTerritoriesTuple(new TreeSet<>(waterTerrs2), newLandSet); putCanalDefinitions("Canal" + getCanalDefinitionsMap().size(), terrTuple); } } } public static void validateAndAddCanalDefinitions(final Map<String, Set<String>> landWaterTerritoyConnections) { final Map<String, Set<String>> landWaterTerrConnChecks = Maps.newHashMap(landWaterTerritoyConnections); for (final Entry<String, Set<String>> landWaterTerrConn : landWaterTerritoyConnections.entrySet()) { final String landTerr = landWaterTerrConn.getKey(); final Set<String> waterTerrs = landWaterTerrConn.getValue(); Set<String> landTerrNeighbors = getTerritoryConnectionsMap().get(landTerr); if (landTerrNeighbors == null) { landTerrNeighbors = Sets.newLinkedHashSet(); } landWaterTerrConnChecks.remove(landTerr); for (final Entry<String, Set<String>> landWaterTerrConn2 : landWaterTerrConnChecks.entrySet()) { validateAndAddCanalDefinition(landTerr, waterTerrs, landTerrNeighbors, landWaterTerrConn2); } } } /** * @return HTML string listing the canal definitions in the following format: * ' - <canal name>: <water territory 1>-<water territory 2>- ...' */ public static String getHtmlStringFromCanalDefinitions() { final StringBuilder sb = new StringBuilder(); sb.append("<html>The following ").append(getCanalDefinitionsMap().size()).append(" canals have been build:"); for (final Entry<String, CanalTerritoriesTuple> canalDef : getCanalDefinitionsMap() .entrySet()) { sb.append(CanalDefinitionsPanel.HTML_CANAL_KEY_PREFIX).append(canalDef.getKey()) .append(CanalDefinitionsPanel.HTML_CANAL_KEY_POSTFIX); sb.append(Joiner.on("-").join(canalDef.getValue().getWaterTerritories().iterator())); } sb.append("</html>"); return sb.toString(); } }