001package jmri.jmrix.ecos; 002 003import java.util.Arrays; 004import java.util.List; 005import org.slf4j.Logger; 006import org.slf4j.LoggerFactory; 007 008/** 009 * Carries the reply to an EcosMessage. 010 * <p> 011 * Some rudimentary support is provided for the "binary" option. 012 * 013 * @author Bob Jacobsen Copyright (C) 2001, 2008 014 * @author Daniel Boudreau Copyright (C) 2007 015 */ 016public class EcosReply extends jmri.jmrix.AbstractMRReply { 017 018 // create a new one 019 public EcosReply() { 020 super(); 021 } 022 023 public EcosReply(String s) { 024 super(s); 025 } 026 027 public EcosReply(EcosReply l) { 028 super(l); 029 } 030 031 // these can be very large 032 @Override 033 public int maxSize() { 034 return 10000; 035 } 036 037 // no need to do anything 038 @Override 039 protected int skipPrefix(int index) { 040 return index; 041 } 042 043 @Override 044 public int value() { 045 if (isBinary()) { 046 return getElement(0) & 0xFF; // avoid stupid sign extension 047 } else { 048 return super.value(); 049 } 050 } 051 052 //knowing where the end is we can then determine the error code 053 int endAtElement = -1; 054 055 /** 056 * Check for last line starts with {@code "<END "}. 057 * @return true if contains END, else false. 058 */ 059 public boolean containsEnd() { 060 for (int i = 0; i < getNumDataElements() - 6; i++) { 061 if ((getElement(i) == 0x0A) 062 && (getElement(i + 1) == '<') 063 && (getElement(i + 2) == 'E') 064 && (getElement(i + 3) == 'N') 065 && (getElement(i + 4) == 'D') 066 && (getElement(i + 5) == ' ')) { 067 endAtElement = i; 068 return true; 069 } 070 } 071 return false; 072 } 073 074 /** 075 * Get the Result Code. 076 * @return result code, else -1 if the end code has not been found. 077 */ 078 public int getResultCode() { 079 if (!containsEnd()) { 080 log.error("Trying to get message end code before message is complete"); 081 return -1; 082 } 083 if (endAtElement == -1) { 084 //just a double check incase endAtElement never got set. 085 return -1; 086 } 087 String resultCode = Character.toString((char) (getElement(endAtElement + 6))); 088 resultCode = resultCode + (char) (getElement(endAtElement + 7)); 089 resultCode = resultCode.trim(); 090 091 try { 092 return Integer.parseInt(resultCode); 093 } catch (java.lang.NumberFormatException ex) { 094 log.error("Unable to convert result code to a number {}", resultCode); 095 return -1; 096 } 097 } 098 099 /** 100 * Is this EcosReply actually an independent {@code <EVENT} message? 101 * @return true if it is an independent message 102 */ 103 boolean isEvent() { 104 if (getNumDataElements() < 8) { 105 return false; 106 } 107 if (getElement(0) != '<') { 108 return false; 109 } 110 if (getElement(1) != 'E') { 111 return false; 112 } 113 if (getElement(2) != 'V') { 114 return false; 115 } 116 if (getElement(3) != 'E') { 117 return false; 118 } 119 if (getElement(4) != 'N') { 120 return false; 121 } 122 if (getElement(5) != 'T') { 123 return false; 124 } 125 if (getElement(6) != ' ') { 126 return false; 127 } 128 return true; 129 } 130 131 //An event message is Unsolicited 132 @Override 133 public boolean isUnsolicited() { 134 if (isEvent()) { 135 setUnsolicited(); 136 return true; 137 } else { 138 return false; 139 } 140 } 141 142 public boolean isReply() { 143 if (getNumDataElements() < 8) { 144 return false; 145 } 146 if (getElement(0) != '<') { 147 return false; 148 } 149 if (getElement(1) != 'R') { 150 return false; 151 } 152 if (getElement(2) != 'E') { 153 return false; 154 } 155 if (getElement(3) != 'P') { 156 return false; 157 } 158 if (getElement(4) != 'L') { 159 return false; 160 } 161 if (getElement(5) != 'Y') { 162 return false; 163 } 164 if (getElement(6) != ' ') { 165 return false; 166 } 167 return true; 168 } 169 170 String replyType = null; 171 172 public String getReplyType() { 173 if (!isReply()) { 174 return ""; 175 } 176 if (replyType != null) { 177 return replyType; 178 } 179 StringBuilder sb = new StringBuilder(); 180 for (int i = 7; i < getNumDataElements(); i++) { 181 if (getElement(i) == '(') { 182 break; 183 } 184 sb.append((char) getElement(i)); 185 } 186 replyType = sb.toString(); 187 return sb.toString(); 188 } 189 190 List<String> headerDetails = null; 191 192 public List<String> getReplyHeaderDetails() { 193 if (!isReply()) { 194 return Arrays.asList(new String[0]); 195 } 196 if (headerDetails != null) { 197 return headerDetails; 198 } 199 StringBuilder sb = new StringBuilder(); 200 int iOffSet = 8 + getReplyType().length() + ("" + getEcosObjectId()).length(); 201 if (getElement(iOffSet) == ',') { 202 iOffSet++; 203 } 204 if (getElement(iOffSet) == ' ') { 205 iOffSet++; 206 } 207 for (int i = iOffSet; i < getNumDataElements(); i++) { 208 if (getElement(i) == ')') { 209 break; 210 } 211 sb.append((char) getElement(i)); 212 } 213 headerDetails = Arrays.asList(sb.toString().split(",")); 214 return headerDetails; 215 } 216 217 int objectId = -1; 218 219 public int getEcosObjectId() { 220 if (objectId != -1) { 221 return objectId; 222 } 223 224 StringBuilder sb = new StringBuilder(); 225 int iOffSet = 7 + getReplyType().length(); 226 if (!isEvent()) { 227 iOffSet = iOffSet + 1; 228 } 229 for (int i = iOffSet; i < getNumDataElements(); i++) { 230 if (getElement(i) == '>') { 231 break; 232 } else if (getElement(i) == ',') { 233 break; 234 } else if (getElement(i) == ')') { 235 break; 236 } 237 sb.append((char) getElement(i)); 238 } 239 objectId = Integer.parseInt(sb.toString()); 240 return objectId; 241 } 242 243 /** 244 * get the contents of the reply, excluding the header and footer 245 * @return array with reply values. 246 */ 247 public String[] getContents() { 248 String[] lines = toString().split("\n"); 249 int length = lines.length - 2; 250 251 String[] returnval = new String[length]; 252 for (int i = 1; i <= length; i++) { 253 returnval[i - 1] = lines[i]; 254 } 255 return returnval; 256 } 257 258 static public String getContentDetail(String str) { 259 int start = str.indexOf("[") + 1; 260 int end = str.indexOf("]"); 261 return str.substring(start, end); 262 } 263 264 static public String getContentDetails(String line, String item) { 265 int startval = line.indexOf(item) + item.length() + 1; 266 int endval = (line.substring(startval)).indexOf("]") + startval; 267 return line.substring(startval, endval); 268 } 269 270 private final static Logger log = LoggerFactory.getLogger(EcosReply.class); 271 272}