1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.polo.wire.xml; 18 19 import com.google.polo.exception.PoloException; 20 import com.google.polo.exception.ProtocolErrorException; 21 import com.google.polo.json.JSONArray; 22 import com.google.polo.json.JSONException; 23 import com.google.polo.json.JSONObject; 24 import com.google.polo.json.XML; 25 import com.google.polo.pairing.PoloUtil; 26 import com.google.polo.pairing.message.ConfigurationAckMessage; 27 import com.google.polo.pairing.message.ConfigurationMessage; 28 import com.google.polo.pairing.message.EncodingOption; 29 import com.google.polo.pairing.message.EncodingOption.EncodingType; 30 import com.google.polo.pairing.message.OptionsMessage; 31 import com.google.polo.pairing.message.OptionsMessage.ProtocolRole; 32 import com.google.polo.pairing.message.PairingRequestAckMessage; 33 import com.google.polo.pairing.message.PairingRequestMessage; 34 import com.google.polo.pairing.message.PoloMessage; 35 import com.google.polo.pairing.message.PoloMessage.PoloMessageType; 36 import com.google.polo.pairing.message.SecretAckMessage; 37 import com.google.polo.pairing.message.SecretMessage; 38 39 /** 40 * A collection of methods to convert {@link PoloMessage}s to and from XML 41 * format. 42 * <p> 43 * This wire format was specified by a third party; it uses a proprietary 44 * 64-byte message header/delimiter, and message internals are inconsistent with 45 * the protocol buffer in several places. 46 */ 47 public class XmlMessageBuilder { 48 49 /* 50 * Status types. 51 * NOTE(mikey): These do not match the values defined by 52 * OuterMessage.MessageType in polo.proto. 53 */ 54 55 public static final int STATUS_OK = 1; 56 public static final int STATUS_ERROR = 2; 57 58 /* 59 * Key names for XML versions of messages. 60 */ 61 62 // OuterMessage XML key names 63 private static final String OUTER_FIELD_TYPE = "msg_type"; 64 private static final String OUTER_FIELD_STATUS = "status"; 65 private static final String OUTER_FIELD_MSG_ID = "msg_id"; 66 private static final String OUTER_FIELD_PAYLOAD = "pairing_msg"; 67 68 // PairingRequestMessage XML key names 69 private static final String PAIRING_REQUEST_FIELD_PROTOCOL_VERSION = 70 "proto_version"; 71 72 // OptionsMessage XML key names 73 private static final String OPTIONS_FIELD_PREFERRED_ROLE = "pref_role"; 74 private static final String OPTIONS_FIELD_OUTPUT_ENCODINGS = "out_encodings"; 75 private static final String OPTIONS_FIELD_INPUT_ENCODINGS = "in_encodings"; 76 77 // ConfigurationMessage XML key names 78 private static final String CONFIG_FIELD_CLIENT_ROLE = "role"; 79 80 // EncodingOption XML key names 81 private static final String ENCODING_FIELD_TYPE = "type"; 82 private static final String ENCODING_FIELD_SYMBOL_LENGTH = "min_length"; 83 private static final String ENCODING_FIELD_MAX_LENGTH = "max_length"; 84 private static final String ENCODING_SUBFIELD_ENCODING = "encoding"; 85 86 // SecretMessage XML key names 87 private static final String SECRET_FIELD_SECRET = "bytes"; 88 89 // Payload container names 90 private static final String MESSAGE_CONTAINER_NAME_PAIRING_REQUEST = 91 "pairing_req"; 92 private static final String MESSAGE_CONTAINER_NAME_PAIRING_REQUEST_ACK = 93 "pairing_req_ack"; 94 private static final String MESSAGE_CONTAINER_NAME_OPTIONS = "config_options"; 95 private static final String MESSAGE_CONTAINER_NAME_CONFIG = "config"; 96 private static final String MESSAGE_CONTAINER_NAME_SECRET = "secret"; 97 private static final String PAIRING_REQUEST_FIELD_SERVICE_NAME = "svc_name"; 98 private static final String PAIRING_REQUEST_FIELD_CLIENT_NAME = "client_name"; 99 private static final String PAIRING_REQUEST_ACK_FIELD_SERVER_NAME = 100 "server_name"; 101 102 // 103 // Encoding types -- these do not match polo.proto's enum. 104 // 105 106 public static final int ENCODING_TYPE_NUMERIC = 1; 107 public static final int ENCODING_TYPE_HEXADECIMAL = 2; 108 public static final int ENCODING_TYPE_ALPHANUMERIC = 3; 109 public static final int ENCODING_TYPE_QRCODE = 4; 110 111 /** 112 * Cache of the last message id header value received. The value should be 113 * copied to any response. 114 */ 115 private String mLastMessageId; 116 XmlMessageBuilder()117 public XmlMessageBuilder() { 118 mLastMessageId = null; 119 } 120 121 /** 122 * Builds a {@link PoloMessage} from the XML version of the outer message. 123 * 124 * @param outerXml the outermost XML string 125 * @return a new {@link PoloMessage} 126 * @throws PoloException on error parsing the message 127 */ outerXMLToPoloMessage(String outerXml)128 PoloMessage outerXMLToPoloMessage(String outerXml) throws PoloException { 129 JSONObject outerMessage; 130 try { 131 outerMessage = XML.toJSONObject(outerXml); 132 } catch (JSONException e) { 133 throw new PoloException(e); 134 } 135 136 JSONObject payload; 137 PoloMessageType messageType; 138 try { 139 payload = outerMessage.getJSONObject(OUTER_FIELD_PAYLOAD); 140 141 int status = payload.getInt(OUTER_FIELD_STATUS); 142 if (status != STATUS_OK) { 143 throw new ProtocolErrorException("Peer reported an error."); 144 } 145 146 int msgIntVal = payload.getInt(OUTER_FIELD_TYPE); 147 messageType = PoloMessageType.fromIntVal(msgIntVal); 148 } catch (JSONException e) { 149 throw new PoloException("Bad outer message.", e); 150 } 151 152 if (outerMessage.has("msg_id")) { 153 try { 154 mLastMessageId = outerMessage.getString("msg_id"); 155 } catch (JSONException e) { 156 } 157 } else { 158 mLastMessageId = null; 159 } 160 161 switch (messageType) { 162 case PAIRING_REQUEST: 163 return getPairingRequest(payload); 164 case PAIRING_REQUEST_ACK: 165 return getPairingRequestAck(payload); 166 case OPTIONS: 167 return getOptionsMessage(payload); 168 case CONFIGURATION: 169 return getConfigMessage(payload); 170 case CONFIGURATION_ACK: 171 return getConfigAckMessage(payload); 172 case SECRET: 173 return getSecretMessage(payload); 174 case SECRET_ACK: 175 return getSecretAckMessage(payload); 176 default: 177 return null; 178 } 179 180 } 181 182 /* 183 * Methods to convert XML inner messages to PoloMessage instances. 184 * 185 * NOTE(mikey): These methods are implemented in terms of JSONObject 186 * as a convenient way to represent hierarchical key->(dict|list|value) 187 * structures. 188 * 189 * Note that these methods are very similar to those found in 190 * JsonWireAdapter. However, the XML wire format was specified with slight 191 * differences compared to the protocol buffer definition. For example, 192 * in the OptionsMessage, encodings are wrapped in an "<options>" container. 193 * 194 * Also, many fields names have slight differences compared to the names in 195 * the protocol buffer (for example, in PairingRequestMessage, "service_name" 196 * is called "svc_name".) 197 */ 198 199 /** 200 * Generates a new {@link PairingRequestMessage} from a JSON payload. 201 * 202 * @param body the JSON payload 203 * @return the new message 204 * @throws PoloException on error parsing the {@link JSONObject} 205 */ getPairingRequest(JSONObject body)206 PairingRequestMessage getPairingRequest(JSONObject body) 207 throws PoloException { 208 try { 209 JSONObject jsonObj = body.getJSONObject( 210 MESSAGE_CONTAINER_NAME_PAIRING_REQUEST); 211 String serviceName = jsonObj.getString( 212 PAIRING_REQUEST_FIELD_SERVICE_NAME); 213 String clientName = null; 214 if (jsonObj.has(PAIRING_REQUEST_FIELD_CLIENT_NAME)) { 215 clientName = jsonObj.getString(PAIRING_REQUEST_FIELD_CLIENT_NAME); 216 } 217 return new PairingRequestMessage(serviceName, clientName); 218 } catch (JSONException e) { 219 throw new PoloException("Malformed message.", e); 220 } 221 } 222 223 /** 224 * Generates a new {@link PairingRequestAckMessage} from a JSON payload. 225 * 226 * @param body the JSON payload 227 * @return the new message 228 * @throws PoloException on error parsing the {@link JSONObject} 229 */ getPairingRequestAck(JSONObject body)230 PairingRequestAckMessage getPairingRequestAck(JSONObject body) 231 throws PoloException { 232 try { 233 JSONObject jsonObj = body.getJSONObject( 234 MESSAGE_CONTAINER_NAME_PAIRING_REQUEST_ACK); 235 String serverName = null; 236 if (jsonObj.has(PAIRING_REQUEST_ACK_FIELD_SERVER_NAME)) { 237 serverName = jsonObj.getString(PAIRING_REQUEST_ACK_FIELD_SERVER_NAME); 238 } 239 return new PairingRequestAckMessage(serverName); 240 } catch (JSONException e) { 241 throw new PoloException("Malformed message.", e); 242 } 243 } 244 245 /** 246 * Generates a new {@link OptionsMessage} from a JSON payload. 247 * 248 * @param body the JSON payload 249 * @return the new message 250 * @throws PoloException on error parsing the {@link JSONObject} 251 */ getOptionsMessage(JSONObject body)252 OptionsMessage getOptionsMessage(JSONObject body) throws PoloException { 253 OptionsMessage options = new OptionsMessage(); 254 JSONObject jsonOptions; 255 try { 256 jsonOptions = body.getJSONObject(MESSAGE_CONTAINER_NAME_OPTIONS); 257 258 JSONObject inEnc = jsonOptions.getJSONObject( 259 OPTIONS_FIELD_INPUT_ENCODINGS); 260 JSONObject outEnc = jsonOptions.getJSONObject( 261 OPTIONS_FIELD_OUTPUT_ENCODINGS); 262 263 // Input encodings 264 JSONArray inEncodings = new JSONArray(); 265 try { 266 inEncodings = inEnc.getJSONArray(ENCODING_SUBFIELD_ENCODING); 267 } catch (JSONException e) { 268 if (inEnc.has(ENCODING_SUBFIELD_ENCODING)) { 269 JSONObject enc = inEnc.getJSONObject(ENCODING_SUBFIELD_ENCODING); 270 inEncodings.put(enc); 271 } 272 } 273 274 for (int i = 0; i < inEncodings.length(); i++) { 275 JSONObject enc = inEncodings.getJSONObject(i); 276 options.addInputEncoding(getEncodingOption(enc)); 277 } 278 279 // Output encodings 280 JSONArray outEncodings = new JSONArray(); 281 try { 282 outEncodings = outEnc.getJSONArray(ENCODING_SUBFIELD_ENCODING); 283 } catch (JSONException e) { 284 if (outEnc.has(ENCODING_SUBFIELD_ENCODING)) { 285 JSONObject enc = outEnc.getJSONObject(ENCODING_SUBFIELD_ENCODING); 286 outEncodings.put(enc); 287 } 288 } 289 290 for (int i = 0; i < outEncodings.length(); i++) { 291 JSONObject enc = outEncodings.getJSONObject(i); 292 options.addOutputEncoding(getEncodingOption(enc)); 293 } 294 295 // Role 296 ProtocolRole role = ProtocolRole.fromIntVal( 297 jsonOptions.getInt(OPTIONS_FIELD_PREFERRED_ROLE)); 298 options.setProtocolRolePreference(role); 299 } catch (JSONException e) { 300 throw new PoloException("Malformed message.", e); 301 } 302 303 return options; 304 } 305 306 /** 307 * Generates a new {@link ConfigurationMessage} from a JSON payload. 308 * 309 * @param body the JSON payload 310 * @return the new message 311 * @throws PoloException on error parsing the {@link JSONObject} 312 */ getConfigMessage(JSONObject body)313 ConfigurationMessage getConfigMessage(JSONObject body) 314 throws PoloException { 315 try { 316 EncodingOption encoding = getEncodingOption( 317 body.getJSONObject(MESSAGE_CONTAINER_NAME_CONFIG) 318 .getJSONObject(ENCODING_SUBFIELD_ENCODING)); 319 ProtocolRole role = ProtocolRole.fromIntVal( 320 body.getJSONObject(MESSAGE_CONTAINER_NAME_CONFIG) 321 .getInt(CONFIG_FIELD_CLIENT_ROLE)); 322 return new ConfigurationMessage(encoding, role); 323 } catch (JSONException e) { 324 throw new PoloException("Malformed message.", e); 325 } 326 } 327 328 /** 329 * Generates a new {@link ConfigurationAckMessage} from a JSON payload. 330 * 331 * @param body the JSON payload 332 * @return the new message 333 */ getConfigAckMessage(JSONObject body)334 ConfigurationAckMessage getConfigAckMessage(JSONObject body) { 335 return new ConfigurationAckMessage(); 336 } 337 338 /** 339 * Generates a new {@link SecretMessage} from a JSON payload. 340 * 341 * @param body the JSON payload 342 * @return the new message 343 * @throws PoloException on error parsing the {@link JSONObject} 344 */ getSecretMessage(JSONObject body)345 SecretMessage getSecretMessage(JSONObject body) throws PoloException { 346 String secret; 347 try { 348 secret = body.getJSONObject(MESSAGE_CONTAINER_NAME_SECRET) 349 .getString(SECRET_FIELD_SECRET); 350 } catch (JSONException e) { 351 throw new PoloException("Malformed message.", e); 352 } 353 byte[] secretBytes = PoloUtil.hexStringToBytes(secret); 354 return new SecretMessage(secretBytes); 355 } 356 357 /** 358 * Generates a new {@link SecretAckMessage} from a JSON payload. 359 * 360 * @param body the JSON payload 361 * @return the new message 362 */ getSecretAckMessage(JSONObject body)363 SecretAckMessage getSecretAckMessage(JSONObject body) { 364 return new SecretAckMessage(null); 365 } 366 367 /** 368 * Generates a new {@link EncodingOption} from a JSON sub-dictionary. 369 * 370 * @param option the JSON sub-dictionary describing the option 371 * @return the new {@link EncodingOption} 372 * @throws JSONException on error parsing the {@link JSONObject} 373 */ getEncodingOption(JSONObject option)374 EncodingOption getEncodingOption(JSONObject option) throws JSONException { 375 int length = option.getInt(ENCODING_FIELD_SYMBOL_LENGTH); 376 int intType = option.getInt(ENCODING_FIELD_TYPE); 377 EncodingType type = encodingTypeFromIntValue(intType); 378 return new EncodingOption(type, length); 379 } 380 381 /** 382 * Converts a {@link PoloMessage} to an XML string. 383 * 384 * @param message the message to convert 385 * @return the same message, as translated to XML 386 */ poloMessageToXML(PoloMessage message)387 public String poloMessageToXML(PoloMessage message) { 388 try { 389 if (message instanceof PairingRequestMessage) { 390 return toXML((PairingRequestMessage) message); 391 } else if (message instanceof PairingRequestAckMessage) { 392 return toXML((PairingRequestAckMessage) message); 393 } else if (message instanceof OptionsMessage) { 394 return toXML((OptionsMessage) message); 395 } else if (message instanceof ConfigurationMessage) { 396 return toXML((ConfigurationMessage) message); 397 } else if (message instanceof ConfigurationAckMessage) { 398 return toXML((ConfigurationAckMessage) message); 399 } else if (message instanceof SecretMessage) { 400 return toXML((SecretMessage) message); 401 } else if (message instanceof SecretAckMessage) { 402 return toXML((SecretAckMessage) message); 403 } 404 return null; 405 } catch (JSONException e) { 406 e.printStackTrace(); 407 return ""; 408 } 409 410 } 411 412 /** 413 * Generates a String corresponding to a full wire message (wrapped in 414 * an outer message) for the given payload. 415 */ getOuterXML(PoloMessage message, int status)416 public String getOuterXML(PoloMessage message, int status) { 417 StringBuffer out = new StringBuffer(); 418 419 420 out.append("<" + OUTER_FIELD_PAYLOAD + ">\n"); 421 422 // status 423 out.append("<" + OUTER_FIELD_STATUS + ">"); 424 out.append(status); 425 out.append("</" + OUTER_FIELD_STATUS + ">\n"); 426 427 // msg_id (optional) 428 if (mLastMessageId != null) { 429 out.append("<" + OUTER_FIELD_MSG_ID + ">"); 430 out.append(mLastMessageId); 431 out.append("</" + OUTER_FIELD_MSG_ID + ">\n"); 432 } 433 434 // payload 435 if (message != null) { 436 int msgType = message.getType().getAsInt(); 437 out.append("<" + OUTER_FIELD_TYPE + ">"); 438 out.append(msgType); 439 out.append("</" + OUTER_FIELD_TYPE + ">\n"); 440 441 out.append(poloMessageToXML(message)); 442 out.append("\n"); 443 } 444 445 out.append("</" + OUTER_FIELD_PAYLOAD + ">\n"); 446 return out.toString(); 447 } 448 449 450 451 /** 452 * Generates an error payload corresponding to an outer message with an 453 * error code in the status field. The error code is determined by the type 454 * of the exception. 455 * 456 * @param exception the {@link Exception} to use to determine the error 457 * code 458 * @return a string outer message 459 * @throws PoloException on error building the message 460 */ getErrorXML(Exception exception)461 public String getErrorXML(Exception exception) 462 throws PoloException { 463 return getOuterXML(null, STATUS_ERROR); 464 } 465 466 /** 467 * Translates a {@link PairingRequestMessage} to an XML string. 468 * 469 * @throws JSONException on error generating the {@link String}. 470 */ toXML(PairingRequestMessage message)471 String toXML(PairingRequestMessage message) throws JSONException { 472 JSONObject jsonObj = new JSONObject(); 473 JSONObject pairingReq = new JSONObject(); 474 jsonObj.put(MESSAGE_CONTAINER_NAME_PAIRING_REQUEST, pairingReq); 475 pairingReq.put(PAIRING_REQUEST_FIELD_SERVICE_NAME, 476 message.getServiceName()); 477 if (message.hasClientName()) { 478 pairingReq.put(PAIRING_REQUEST_FIELD_CLIENT_NAME, 479 message.getServiceName()); 480 } 481 pairingReq.put(PAIRING_REQUEST_FIELD_PROTOCOL_VERSION, 1); 482 return XML.toString(jsonObj); 483 } 484 485 /** 486 * Translates a {@link PairingRequestAckMessage} to an XML string. 487 * 488 * @throws JSONException on error generating the {@link String}. 489 */ toXML(PairingRequestAckMessage message)490 String toXML(PairingRequestAckMessage message) throws JSONException { 491 JSONObject jsonObj = new JSONObject(); 492 JSONObject pairingReq = new JSONObject(); 493 jsonObj.put(MESSAGE_CONTAINER_NAME_PAIRING_REQUEST_ACK, pairingReq); 494 if (message.hasServerName()) { 495 jsonObj.put(PAIRING_REQUEST_ACK_FIELD_SERVER_NAME, 496 message.getServerName()); 497 } 498 pairingReq.put(PAIRING_REQUEST_FIELD_PROTOCOL_VERSION, 1); 499 return XML.toString(jsonObj); 500 } 501 502 /** 503 * Translates a {@link OptionsMessage} to an XML string. 504 * 505 * @throws JSONException on error generating the {@link String}. 506 */ toXML(OptionsMessage message)507 String toXML(OptionsMessage message) throws JSONException { 508 JSONObject jsonObj = new JSONObject(); 509 JSONObject options = new JSONObject(); 510 511 JSONObject inEncs = new JSONObject(); 512 JSONArray inEncsArray = new JSONArray(); 513 for (EncodingOption encoding : message.getInputEncodingSet()) { 514 inEncsArray.put(encodingToJson(encoding)); 515 } 516 inEncs.put(ENCODING_SUBFIELD_ENCODING, inEncsArray); 517 options.put(OPTIONS_FIELD_INPUT_ENCODINGS, inEncs); 518 519 JSONObject outEncs = new JSONObject(); 520 JSONArray outEncsArray = new JSONArray(); 521 for (EncodingOption encoding : message.getOutputEncodingSet()) { 522 outEncsArray.put(encodingToJson(encoding)); 523 } 524 outEncs.put(ENCODING_SUBFIELD_ENCODING, outEncsArray); 525 options.put(OPTIONS_FIELD_OUTPUT_ENCODINGS, outEncs); 526 527 options.put(OPTIONS_FIELD_PREFERRED_ROLE, 528 message.getProtocolRolePreference().ordinal()); 529 jsonObj.put(MESSAGE_CONTAINER_NAME_OPTIONS, options); 530 return XML.toString(jsonObj); 531 } 532 533 /** 534 * Translates a {@link ConfigurationMessage} to an XML string. 535 * 536 * @throws JSONException on error generating the {@link String}. 537 */ toXML(ConfigurationMessage message)538 String toXML(ConfigurationMessage message) throws JSONException { 539 JSONObject jsonObj = new JSONObject(); 540 JSONObject config = new JSONObject(); 541 JSONObject encoding = encodingToJson(message.getEncoding()); 542 config.put(ENCODING_SUBFIELD_ENCODING, encoding); 543 config.put(CONFIG_FIELD_CLIENT_ROLE, message.getClientRole().ordinal()); 544 jsonObj.put(MESSAGE_CONTAINER_NAME_CONFIG, config); 545 return XML.toString(jsonObj); 546 } 547 548 /** 549 * Translates a {@link ConfigurationAckMessage} to an XML string. 550 */ toXML(ConfigurationAckMessage message)551 String toXML(ConfigurationAckMessage message) { 552 return ""; 553 } 554 555 /** 556 * Translates a {@link SecretMessage} to an XML string. 557 * 558 * @throws JSONException on error generating the {@link String}. 559 */ toXML(SecretMessage message)560 String toXML(SecretMessage message) throws JSONException { 561 JSONObject jsonObj = new JSONObject(); 562 JSONObject secret = new JSONObject(); 563 String bytesStr = PoloUtil.bytesToHexString(message.getSecret()); 564 secret.put(SECRET_FIELD_SECRET, bytesStr); 565 jsonObj.put(MESSAGE_CONTAINER_NAME_SECRET, secret); 566 return XML.toString(jsonObj); 567 } 568 569 /** 570 * Translates a {@link SecretAckMessage} to an XML string. 571 */ toXML(SecretAckMessage message)572 String toXML(SecretAckMessage message) { 573 return ""; 574 } 575 576 /** 577 * Translates a {@link EncodingOption} to a {@link JSONObject}. 578 * 579 * @throws JSONException on error generating the {@link JSONObject} 580 */ encodingToJson(EncodingOption encoding)581 JSONObject encodingToJson(EncodingOption encoding) throws JSONException { 582 JSONObject result = new JSONObject(); 583 int intType = encodingTypeToIntVal(encoding.getType()); 584 result.put(ENCODING_FIELD_TYPE, intType); 585 result.put(ENCODING_FIELD_SYMBOL_LENGTH, encoding.getSymbolLength()); 586 result.put(ENCODING_FIELD_MAX_LENGTH, encoding.getSymbolLength()); 587 return result; 588 } 589 590 /** 591 * Converts an {@link EncodingType} to the numeric value used on the wire. 592 * <p> 593 * Note that in this implementation, the values used on the wire do not match 594 * those returned by {@link EncodingType#getAsInt()}, hence the extra method. 595 * 596 * @param type the {@link EncodingType} 597 * @return an integer representation 598 */ encodingTypeToIntVal(EncodingType type)599 private static int encodingTypeToIntVal(EncodingType type) { 600 switch (type) { 601 case ENCODING_ALPHANUMERIC: 602 return ENCODING_TYPE_ALPHANUMERIC; 603 case ENCODING_NUMERIC: 604 return ENCODING_TYPE_NUMERIC; 605 case ENCODING_HEXADECIMAL: 606 return ENCODING_TYPE_HEXADECIMAL; 607 case ENCODING_QRCODE: 608 return ENCODING_TYPE_QRCODE; 609 case ENCODING_UNKNOWN: 610 default: 611 return 0; 612 } 613 } 614 615 /** 616 * Converts a numeric value used on the wire to the corresponding 617 * {@link EncodingType}. 618 * <p> 619 * Note that in this implementation, the values used on the wire do not match 620 * those returned by {@link EncodingType#getAsInt()}, hence the extra method. 621 * 622 * @param intType the value used on the wire 623 * @return the corresponding {@link EncodingType} 624 */ encodingTypeFromIntValue(int intType)625 private static EncodingType encodingTypeFromIntValue(int intType) { 626 EncodingType type = EncodingType.ENCODING_UNKNOWN; 627 switch (intType) { 628 case ENCODING_TYPE_ALPHANUMERIC: 629 type = EncodingType.ENCODING_ALPHANUMERIC; 630 break; 631 case ENCODING_TYPE_NUMERIC: 632 type = EncodingType.ENCODING_NUMERIC; 633 break; 634 case ENCODING_TYPE_HEXADECIMAL: 635 type = EncodingType.ENCODING_HEXADECIMAL; 636 break; 637 case ENCODING_TYPE_QRCODE: 638 type = EncodingType.ENCODING_QRCODE; 639 break; 640 default: 641 type = EncodingType.ENCODING_UNKNOWN; 642 break; 643 } 644 return type; 645 } 646 647 } 648