/* Copyright (C) 2011 ApPeAL Group, Politecnico di Torino This file is part of TraCI4J. TraCI4J is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. TraCI4J is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TraCI4J. If not, see <http://www.gnu.org/licenses/>. */ package it.polito.appeal.traci.protocol; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import de.uniluebeck.itm.tcpip.Storage; /** * Represents a message sent from the server. A response message is made of an * ordered collection of status responses, response commands and/or sub-responses. * @author Enrico Gueli <enrico.gueli@polito.it> * */ public class ResponseMessage { /** * The list of IDs of responses that have no response commands. */ public static final int[] STATUS_ONLY_RESPONSES = new int[] { Constants.CMD_CLOSE, Constants.CMD_SET_LANE_VARIABLE, Constants.CMD_SET_TL_VARIABLE, Constants.CMD_SET_VEHICLE_VARIABLE, Constants.CMD_SET_POI_VARIABLE, Constants.CMD_SET_POLYGON_VARIABLE, Constants.CMD_SET_EDGE_VARIABLE, Constants.CMD_SET_GUI_VARIABLE }; private List<ResponseContainer> pairs = new ArrayList<ResponseContainer>(); /** * Constructor that unpacks all the data from a {@link DataInputStream}, * populating the list of {@link ResponseContainer}s. * <p> * A response message is made of individual packets. It is assumed that the * first packet is always a status response. According to the status * response, different data are expected next: * <ul> * <li>if the status response is not {@link Constants#RTYPE_OK}, another * status response or the end of the stream are expected.</li> * <li>if the status ID is equal to {@link Constants#CMD_SIMSTEP2}, it is * expected an integer representing N and N following sub-responses;</li> * <li>if the status ID matches one of the commands in * {@link #STATUS_ONLY_RESPONSES} , it is expected another status response; * <li>if the status ID doesn't match any of the above, it is expected a * response command. * </ul> * A new {@link ResponseMessage}, collecting all the data that belong to the * same request, is built and appended to an internal list. * * @param dis * @throws IOException */ public ResponseMessage(DataInputStream dis) throws IOException { int totalLen = dis.readInt() - Integer.SIZE/8; byte[] buffer = new byte[totalLen]; dis.readFully(buffer); Storage s = new Storage(buffer); while (s.validPos()) { StatusResponse sr = new StatusResponse(s); ResponseContainer responseContainer; if (sr.result() != Constants.RTYPE_OK) { responseContainer = new ResponseContainer(sr, null); } else if (sr.id() == Constants.CMD_SIMSTEP2) { int nSubResponses = s.readInt(); List<Command> subResponses = new ArrayList<Command>( nSubResponses); for (int i = 0; i < nSubResponses; i++) { subResponses.add(new Command(s)); } responseContainer = new ResponseContainer(sr, null, subResponses); } else if (isStatusOnlyResponse(sr.id())) { responseContainer = new ResponseContainer(sr, null); } else responseContainer = new ResponseContainer(sr, new Command(s)); pairs.add(responseContainer); } } private boolean isStatusOnlyResponse(int statusResponseID) { for (int id : STATUS_ONLY_RESPONSES) if (id == statusResponseID) return true; return false; } public List<ResponseContainer> responses() { return Collections.unmodifiableList(pairs); } }