LOG121_TP01/src/configuration/XmlConfigurationParser.java
2022-06-15 15:27:06 -04:00

209 lines
8.3 KiB
Java

package configuration;
import metadata.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import simulation.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class XmlConfigurationParser implements ConfigurationParser {
public static final String TAG_METADATA = "metadonnees";
public static final String TAG_SIMULATION_DATA = "simulation";
public static final String TAG_BUILDING = "usine";
public static final String TAG_ROUTES = "chemins";
public static final String TAG_ICONS = "icones";
public static final String TAG_INPUT = "entree";
public static final String TAG_OUTPUT = "sortie";
public static final String TAG_PRODUCTION_INTERVAL = "interval-production";
public static final String ATTRIBUTE_TYPE = "type";
public static final String ATTRIBUTE_PATH = "path";
public static final String ATTRIBUTE_QUANTITY = "quantite";
public static final String ATTRIBUTE_CAPACITY = "capacite";
public static final String ATTRIBUTE_ID = "id";
public static final String ATTRIBUTE_X = "x";
public static final String ATTRIBUTE_Y = "y";
public static final String ATTRIBUTE_FROM = "de";
public static final String ATTRIBUTE_TO = "vers";
@Override
public SimulationConfiguration parseConfiguration(File file) throws ConfigurationParsingException {
Document document = parseDocument(file);
Map<String, BuildingMetadata> buildingsMetadata = parseBuildingsMetadata(document);
SimulationData simulationData = parseSimulationData(document, buildingsMetadata);
return new SimulationConfiguration(buildingsMetadata, simulationData);
}
private Document parseDocument(File file) throws ConfigurationParsingException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(file);
document.getDocumentElement().normalize();
return document;
} catch (ParserConfigurationException | IOException | SAXException e) {
throw new ConfigurationParsingException("La lecture du fichier a échoué", e);
}
}
private Map<String, BuildingMetadata> parseBuildingsMetadata(Document document) {
Node metadataNode = document.getElementsByTagName(TAG_METADATA).item(0);
Map<String, BuildingMetadata> metadata = new HashMap<>();
for (Element elem : new IterableElementList(metadataNode.getChildNodes())) {
String buildingType = elem.getAttribute(ATTRIBUTE_TYPE);
metadata.put(buildingType, parseBuildingMetadata(elem));
}
return metadata;
}
private BuildingMetadata parseBuildingMetadata(Element buildingElement) {
String type = buildingElement.getAttribute(ATTRIBUTE_TYPE);
return type.equals(BuildingMetadata.TYPE_WAREHOUSE) ?
parseWarehouseMetadata(buildingElement, type) :
parseFactoryMetadata(buildingElement, type);
}
private BuildingMetadata parseFactoryMetadata(Element factoryElement, String type) {
Map<BuildingState, String> iconsPaths = null;
Collection<FactoryInput> inputs = new ArrayList<>();
FactoryOutput output = null;
int productionInterval = -1;
for (Element elem : new IterableElementList(factoryElement.getChildNodes())) {
switch (elem.getNodeName()) {
case TAG_ICONS -> iconsPaths = parseBuildingIcons(elem);
case TAG_INPUT -> {
FactoryInput input = parseFactoryInput(elem);
inputs.add(input);
}
case TAG_OUTPUT -> output = parseFactoryOutput(elem);
case TAG_PRODUCTION_INTERVAL -> productionInterval = Integer.parseInt(elem.getTextContent());
}
}
return new FactoryMetadata(type, iconsPaths, productionInterval, inputs, output);
}
private BuildingMetadata parseWarehouseMetadata(Element warehouseElement, String type) {
Map<BuildingState, String> iconsPaths = null;
WarehouseInput input = null;
for (Element elem : new IterableElementList(warehouseElement.getChildNodes())) {
switch (elem.getNodeName()) {
case TAG_ICONS -> iconsPaths = parseBuildingIcons(elem);
case TAG_INPUT -> input = parseWarehouseInput(elem);
}
}
return new WarehouseMetadata(type, iconsPaths, input);
}
private Map<BuildingState, String> parseBuildingIcons(Element iconsElement) {
Map<BuildingState, String> iconsPaths = new HashMap<>();
for (Element elem : new IterableElementList(iconsElement.getChildNodes())) {
BuildingState state = BuildingState.getFromTypeName(elem.getAttribute(ATTRIBUTE_TYPE));
String path = elem.getAttribute(ATTRIBUTE_PATH);
iconsPaths.put(state, path);
}
return iconsPaths;
}
private FactoryInput parseFactoryInput(Element inputElement) {
ComponentType type = ComponentType.getForTypeName(inputElement.getAttribute(ATTRIBUTE_TYPE));
int quantity = Integer.parseInt(inputElement.getAttribute(ATTRIBUTE_QUANTITY));
return new FactoryInput(type, quantity);
}
private WarehouseInput parseWarehouseInput(Element inputElement) {
ComponentType type = ComponentType.getForTypeName(inputElement.getAttribute(ATTRIBUTE_TYPE));
int capacity = Integer.parseInt(inputElement.getAttribute(ATTRIBUTE_CAPACITY));
return new WarehouseInput(type, capacity);
}
private FactoryOutput parseFactoryOutput(Element outputElement) {
ComponentType type = ComponentType.getForTypeName(outputElement.getAttribute(ATTRIBUTE_TYPE));
return new FactoryOutput(type);
}
private SimulationData parseSimulationData(Document document, Map<String, BuildingMetadata> buildingMetadata) {
Node dataNode = document.getElementsByTagName(TAG_SIMULATION_DATA).item(0);
Collection<Building> buildings = new ArrayList<>();
Collection<Route> routes = null;
for (Element elem : new IterableElementList(dataNode.getChildNodes())) {
switch (elem.getNodeName()) {
case TAG_BUILDING -> buildings.add(parseBuilding(elem, buildingMetadata));
case TAG_ROUTES -> routes = parseRoutes(elem);
}
}
subscribeFactories(buildings);
return new SimulationData(buildings, routes);
}
private void subscribeFactories(Collection<Building> buildings) {
Warehouse warehouse = (Warehouse) buildings.stream()
.filter(b -> b.getType().equals(BuildingMetadata.TYPE_WAREHOUSE))
.findFirst().get();
for (Building building : buildings) {
if (!(building instanceof Factory)) {
continue;
}
warehouse.attach(((Factory) building));
}
}
private Building parseBuilding(Element buildingElement, Map<String, BuildingMetadata> buildingMetadata) {
String type = buildingElement.getAttribute(ATTRIBUTE_TYPE);
int id = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_ID));
int x = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_X));
int y = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_Y));
BuildingMetadata metadata = buildingMetadata.get(type);
return type.equals(BuildingMetadata.TYPE_WAREHOUSE) ?
new Warehouse(id, type, x, y, (WarehouseMetadata) metadata) :
new Factory(id, type, x, y, (FactoryMetadata) metadata);
}
private Collection<Route> parseRoutes(Element routesElement) {
Collection<Route> routes = new ArrayList<>();
for (Element elem : new IterableElementList(routesElement.getChildNodes())) {
int from = Integer.parseInt(elem.getAttribute(ATTRIBUTE_FROM));
int to = Integer.parseInt(elem.getAttribute(ATTRIBUTE_TO));
routes.add(new Route(from, to));
}
return routes;
}
}