Refactored to avoid use of exceptions in parsing, at the suggestion of Jeff Griffin (thanks). These "exceptional cases" are frequent and are expensive; a static parse() / private constructor approach proves no more complex, and a smidge more efficient.

git-svn-id: https://zxing.googlecode.com/svn/trunk@239 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-03-03 21:37:40 +00:00
parent 905b1f7676
commit 36a5e32021
10 changed files with 128 additions and 83 deletions

View file

@ -19,9 +19,12 @@ package com.google.zxing.client.result;
import java.util.Vector;
/**
* See
* <p>See
* <a href="http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/about/s2.html">
* DoCoMo's documentation</a> about the result types represented by subclasses of this class.
* DoCoMo's documentation</a> about the result types represented by subclasses of this class.</p>
*
* <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
* on exception-based mechanisms during parsing.</p>
*
* @author srowen@google.com (Sean Owen)
*/
@ -66,7 +69,7 @@ abstract class AbstractDoCoMoResult extends ParsedReaderResult {
}
}
}
if (matches == null) {
if (matches == null || matches.isEmpty()) {
return null;
}
int size = matches.size();
@ -82,14 +85,6 @@ abstract class AbstractDoCoMoResult extends ParsedReaderResult {
return matches == null ? null : matches[0];
}
static String[] matchRequiredPrefixedField(String prefix, String rawText) {
String[] result = matchPrefixedField(prefix, rawText);
if (result == null) {
throw new IllegalArgumentException("Did not match prefix " + prefix);
}
return result;
}
private static String unescape(String escaped) {
if (escaped != null) {
int backslash = escaped.indexOf((int) '\\');

View file

@ -34,16 +34,29 @@ public final class AddressBookDoCoMoResult extends AbstractDoCoMoResult {
private final String note;
private final String address;
public AddressBookDoCoMoResult(String rawText) {
private AddressBookDoCoMoResult(String name, String[] phoneNumbers, String email, String note, String address) {
super(ParsedReaderResultType.ADDRESSBOOK);
this.name = name;
this.phoneNumbers = phoneNumbers;
this.email = email;
this.note = note;
this.address = address;
}
public static AddressBookDoCoMoResult parse(String rawText) {
if (!rawText.startsWith("MECARD:")) {
throw new IllegalArgumentException("Does not begin with MECARD");
return null;
}
name = parseName(matchRequiredPrefixedField("N:", rawText)[0]);
phoneNumbers = matchPrefixedField("TEL:", rawText);
email = matchSinglePrefixedField("EMAIL:", rawText);
note = matchSinglePrefixedField("NOTE:", rawText);
address = matchSinglePrefixedField("ADR:", rawText);
String[] rawName = matchPrefixedField("N:", rawText);
if (rawName == null) {
return null;
}
String name = parseName(rawName[0]);
String[] phoneNumbers = matchPrefixedField("TEL:", rawText);
String email = matchSinglePrefixedField("EMAIL:", rawText);
String note = matchSinglePrefixedField("NOTE:", rawText);
String address = matchSinglePrefixedField("ADR:", rawText);
return new AddressBookDoCoMoResult(name, phoneNumbers, email, note, address);
}
public String getName() {

View file

@ -24,17 +24,26 @@ public final class BookmarkDoCoMoResult extends AbstractDoCoMoResult {
private final String title;
private final String uri;
public BookmarkDoCoMoResult(String rawText) {
private BookmarkDoCoMoResult(String title, String uri) {
super(ParsedReaderResultType.BOOKMARK);
this.title = title;
this.uri = uri;
}
public static BookmarkDoCoMoResult parse(String rawText) {
if (!rawText.startsWith("MEBKM:")) {
throw new IllegalArgumentException("Does not begin with MEBKM");
return null;
}
title = matchSinglePrefixedField("TITLE:", rawText);
String uriString = matchRequiredPrefixedField("URL:", rawText)[0];
if (!URIParsedResult.isBasicallyValidURI(uriString)) {
throw new IllegalArgumentException("Invalid URI: " + uriString);
String title = matchSinglePrefixedField("TITLE:", rawText);
String[] rawUri = matchPrefixedField("URL:", rawText);
if (rawUri == null) {
return null;
}
uri = uriString;
String uri = rawUri[0];
if (!URIParsedResult.isBasicallyValidURI(uri)) {
return null;
}
return new BookmarkDoCoMoResult(title, uri);
}
public String getTitle() {

View file

@ -26,17 +26,23 @@ public final class EmailAddressResult extends AbstractDoCoMoResult {
private final String emailAddress;
public EmailAddressResult(String rawText) {
private EmailAddressResult(String emailAddress) {
super(ParsedReaderResultType.EMAIL_ADDRESS);
this.emailAddress = emailAddress;
}
public static EmailAddressResult parse(String rawText) {
String emailAddress;
if (rawText.startsWith("mailto:")) {
// If it starts with mailto:, assume it is definitely trying to be an email address
emailAddress = rawText.substring(7);
} else {
if (!EmailDoCoMoResult.isBasicallyValidEmailAddress(rawText)) {
throw new IllegalArgumentException("Invalid email address: " + rawText);
return null;
}
emailAddress = rawText;
}
return new EmailAddressResult(emailAddress);
}
public String getEmailAddress() {

View file

@ -29,17 +29,28 @@ public final class EmailDoCoMoResult extends AbstractDoCoMoResult {
private final String subject;
private final String body;
public EmailDoCoMoResult(String rawText) {
private EmailDoCoMoResult(String to, String subject, String body) {
super(ParsedReaderResultType.EMAIL);
this.to = to;
this.subject = subject;
this.body = body;
}
public static EmailDoCoMoResult parse(String rawText) {
if (!rawText.startsWith("MATMSG:")) {
throw new IllegalArgumentException("Does not begin with MATMSG");
return null;
}
to = matchRequiredPrefixedField("TO:", rawText)[0];
String[] rawTo = matchPrefixedField("TO:", rawText);
if (rawTo == null) {
return null;
}
String to = rawTo[0];
if (!isBasicallyValidEmailAddress(to)) {
throw new IllegalArgumentException("Invalid email address: " + to);
return null;
}
subject = matchSinglePrefixedField("SUB:", rawText);
body = matchSinglePrefixedField("BODY:", rawText);
String subject = matchSinglePrefixedField("SUB:", rawText);
String body = matchSinglePrefixedField("BODY:", rawText);
return new EmailDoCoMoResult(to, subject, body);
}
public String getTo() {

View file

@ -17,6 +17,14 @@
package com.google.zxing.client.result;
/**
* <p>Abstract class representing the result of decoding a barcode, as more than
* a String -- as some type of structured data. This might be a subclass which represents
* a URL, or an e-mail address. {@link #parseReaderResult(String)} will turn a raw
* decoded string into the most appropriate type of structured representation.</p>
*
* <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
* on exception-based mechanisms during parsing.</p>
*
* @author srowen@google.com (Sean Owen)
*/
public abstract class ParsedReaderResult {
@ -37,42 +45,23 @@ public abstract class ParsedReaderResult {
// This is a bit messy, but given limited options in MIDP / CLDC, this may well be the simplest
// way to go about this. For example, we have no reflection available, really.
// Order is important here.
try {
return new BookmarkDoCoMoResult(rawText);
} catch (IllegalArgumentException iae) {
// continue
ParsedReaderResult result;
if ((result = BookmarkDoCoMoResult.parse(rawText)) != null) {
return result;
} else if ((result = AddressBookDoCoMoResult.parse(rawText)) != null) {
return result;
} else if ((result = EmailDoCoMoResult.parse(rawText)) != null) {
return result;
} else if ((result = EmailAddressResult.parse(rawText)) != null) {
return result;
} else if ((result = URLTOResult.parse(rawText)) != null) {
return result;
} else if ((result = URIParsedResult.parse(rawText)) != null) {
return result;
} else if ((result = UPCParsedResult.parse(rawText)) != null) {
return result;
}
try {
return new AddressBookDoCoMoResult(rawText);
} catch (IllegalArgumentException iae) {
// continue
}
try {
return new EmailDoCoMoResult(rawText);
} catch (IllegalArgumentException iae) {
// continue
}
try {
return new EmailAddressResult(rawText);
} catch (IllegalArgumentException iae) {
// continue
}
try {
return new URLTOResult(rawText);
} catch (IllegalArgumentException iae) {
// continue
}
try {
return new URIParsedResult(rawText);
} catch (IllegalArgumentException iae) {
// continue
}
try {
return new UPCParsedResult(rawText);
} catch (IllegalArgumentException iae) {
// continue
}
return new TextParsedResult(rawText);
return TextParsedResult.parse(rawText);
}
public String toString() {

View file

@ -23,9 +23,13 @@ public final class TextParsedResult extends ParsedReaderResult {
private final String text;
public TextParsedResult(String rawText) {
private TextParsedResult(String text) {
super(ParsedReaderResultType.TEXT);
text = rawText;
this.text = text;
}
public static TextParsedResult parse(String rawText) {
return new TextParsedResult(rawText);
}
public String getText() {

View file

@ -23,19 +23,24 @@ public final class UPCParsedResult extends ParsedReaderResult {
private final String upc;
public UPCParsedResult(String rawText) {
private UPCParsedResult(String upc) {
super(ParsedReaderResultType.UPC);
this.upc = upc;
}
public static UPCParsedResult parse(String rawText) {
int length = rawText.length();
if (length != 12 && length != 13) {
throw new IllegalArgumentException("Wrong number of digits for UPC");
return null;
}
for (int x = 0; x < length; x++) {
char c = rawText.charAt(x);
if (c < '0' || c > '9') {
throw new IllegalArgumentException("Invalid character found in UPC");
return null;
}
}
upc = rawText;
// Not actually checking the checkusm again here
return new UPCParsedResult(rawText);
}
public String getUPC() {

View file

@ -23,13 +23,17 @@ public final class URIParsedResult extends ParsedReaderResult {
private final String uri;
public URIParsedResult(String rawText) {
private URIParsedResult(String uri) {
super(ParsedReaderResultType.URI);
if (!isBasicallyValidURI(rawText)) {
throw new IllegalArgumentException("Invalid URI: " + rawText);
}
uri = massagePossibleURI(rawText);
this.uri = uri;
}
public static URIParsedResult parse(String rawText) {
if (!isBasicallyValidURI(rawText)) {
return null;
}
String uri = massagePossibleURI(rawText);
return new URIParsedResult(uri);
}
public String getURI() {

View file

@ -28,14 +28,23 @@ public final class URLTOResult extends ParsedReaderResult {
private final String title;
private final String uri;
public URLTOResult(String rawText) {
private URLTOResult(String title, String uri) {
super(ParsedReaderResultType.URLTO);
this.title = title;
this.uri = uri;
}
public static URLTOResult parse(String rawText) {
if (!rawText.startsWith("URLTO:")) {
throw new IllegalArgumentException("Does not begin with URLTO");
return null;
}
int titleEnd = rawText.indexOf(':', 6);
title = rawText.substring(6, titleEnd);
uri = rawText.substring(titleEnd + 1);
if (titleEnd < 0) {
return null;
}
String title = rawText.substring(6, titleEnd);
String uri = rawText.substring(titleEnd + 1);
return new URLTOResult(title, uri);
}
public String getTitle() {