/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// package com::google::zxing::client::result;
/**
*
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 #parseResult(Result)} will turn a raw
* decoded string into the most appropriate type of structured representation.
*
* Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
* on exception-based mechanisms during parsing.
*
* @author Sean Owen
*/
const PARSERS: vec![Vec; 20] = vec![BookmarkDoCoMoResultParser::new(), AddressBookDoCoMoResultParser::new(), EmailDoCoMoResultParser::new(), AddressBookAUResultParser::new(), VCardResultParser::new(), BizcardResultParser::new(), VEventResultParser::new(), EmailAddressResultParser::new(), SMTPResultParser::new(), TelResultParser::new(), SMSMMSResultParser::new(), SMSTOMMSTOResultParser::new(), GeoResultParser::new(), WifiResultParser::new(), URLTOResultParser::new(), URIResultParser::new(), ISBNResultParser::new(), ProductResultParser::new(), ExpandedProductResultParser::new(), VINResultParser::new(), ]
;
const DIGITS: Pattern = Pattern::compile("\\d+");
const AMPERSAND: Pattern = Pattern::compile("&");
const EQUALS: Pattern = Pattern::compile("=");
const BYTE_ORDER_MARK: &'static str = "";
const EMPTY_STR_ARRAY: [Option; 0] = [None; 0];
pub struct ResultParser {
}
impl ResultParser {
/**
* Attempts to parse the raw {@link Result}'s contents as a particular type
* of information (email, URL, etc.) and return a {@link ParsedResult} encapsulating
* the result of parsing.
*
* @param theResult the raw {@link Result} to parse
* @return {@link ParsedResult} encapsulating the parsing result
*/
pub fn parse(&self, the_result: &Result) -> ParsedResult ;
pub fn get_massaged_text( result: &Result) -> String {
let mut text: String = result.get_text();
if text.starts_with(&BYTE_ORDER_MARK) {
text = text.substring(1);
}
return text;
}
pub fn parse_result( the_result: &Result) -> ParsedResult {
for let parser: ResultParser in PARSERS {
let result: ParsedResult = parser.parse(the_result);
if result != null {
return result;
}
}
return TextParsedResult::new(&the_result.get_text(), null);
}
pub fn maybe_append( value: &String, result: &StringBuilder) {
if value != null {
result.append('\n');
result.append(&value);
}
}
pub fn maybe_append( value: &Vec, result: &StringBuilder) {
if value != null {
for let s: String in value {
result.append('\n');
result.append(&s);
}
}
}
pub fn maybe_wrap( value: &String) -> Vec {
return if value == null { null } else { : vec![String; 1] = vec![value, ]
};
}
pub fn unescape_backslash( escaped: &String) -> String {
let backslash: i32 = escaped.index_of('\\');
if backslash < 0 {
return escaped;
}
let max: i32 = escaped.length();
let unescaped: StringBuilder = StringBuilder::new(max - 1);
unescaped.append(&escaped.to_char_array(), 0, backslash);
let next_is_escaped: bool = false;
{
let mut i: i32 = backslash;
while i < max {
{
let c: char = escaped.char_at(i);
if next_is_escaped || c != '\\' {
unescaped.append(c);
next_is_escaped = false;
} else {
next_is_escaped = true;
}
}
i += 1;
}
}
return unescaped.to_string();
}
pub fn parse_hex_digit( c: char) -> i32 {
if c >= '0' && c <= '9' {
return c - '0';
}
if c >= 'a' && c <= 'f' {
return 10 + (c - 'a');
}
if c >= 'A' && c <= 'F' {
return 10 + (c - 'A');
}
return -1;
}
pub fn is_string_of_digits( value: &CharSequence, length: i32) -> bool {
return value != null && length > 0 && length == value.length() && DIGITS::matcher(&value)::matches();
}
pub fn is_substring_of_digits( value: &CharSequence, offset: i32, length: i32) -> bool {
if value == null || length <= 0 {
return false;
}
let max: i32 = offset + length;
return value.length() >= max && DIGITS::matcher(&value.sub_sequence(offset, max))::matches();
}
fn parse_name_value_pairs( uri: &String) -> Map {
let param_start: i32 = uri.index_of('?');
if param_start < 0 {
return null;
}
let result: Map = HashMap<>::new(3);
for let key_value: String in AMPERSAND::split(&uri.substring(param_start + 1)) {
::append_key_value(&key_value, &result);
}
return result;
}
fn append_key_value( key_value: &CharSequence, result: &Map) {
let key_value_tokens: Vec = EQUALS::split(&key_value, 2);
if key_value_tokens.len() == 2 {
let key: String = key_value_tokens[0];
let mut value: String = key_value_tokens[1];
let tryResult1 = 0;
'try1: loop {
{
value = ::url_decode(&value);
result.put(&key, &value);
}
break 'try1
}
match tryResult1 {
catch ( iae: &IllegalArgumentException) {
} 0 => break
}
}
}
fn url_decode( encoded: &String) -> String {
let tryResult1 = 0;
'try1: loop {
{
return URLDecoder::decode(&encoded, "UTF-8");
}
break 'try1
}
match tryResult1 {
catch ( uee: &UnsupportedEncodingException) {
throw IllegalStateException::new(&uee);
} 0 => break
}
}
fn match_prefixed_field( prefix: &String, raw_text: &String, end_char: char, trim: bool) -> Vec {
let mut matches: List = null;
let mut i: i32 = 0;
let max: i32 = raw_text.length();
while i < max {
i = raw_text.index_of(&prefix, i);
if i < 0 {
break;
}
// Skip past this prefix we found to start
i += prefix.length();
// Found the start of a match here
let start: i32 = i;
let mut more: bool = true;
while more {
i = raw_text.index_of(end_char, i);
if i < 0 {
// No terminating end character? uh, done. Set i such that loop terminates and break
i = raw_text.length();
more = false;
} else if ::count_preceding_backslashes(&raw_text, i) % 2 != 0 {
// semicolon was escaped (odd count of preceding backslashes) so continue
i += 1;
} else {
// found a match
if matches == null {
// lazy init
matches = ArrayList<>::new(3);
}
let mut element: String = ::unescape_backslash(&raw_text.substring(start, i));
if trim {
element = element.trim();
}
if !element.is_empty() {
matches.add(&element);
}
i += 1;
more = false;
}
}
}
if matches == null || matches.is_empty() {
return null;
}
return matches.to_array(&EMPTY_STR_ARRAY);
}
fn count_preceding_backslashes( s: &CharSequence, pos: i32) -> i32 {
let mut count: i32 = 0;
{
let mut i: i32 = pos - 1;
while i >= 0 {
{
if s.char_at(i) == '\\' {
count += 1;
} else {
break;
}
}
i -= 1;
}
}
return count;
}
fn match_single_prefixed_field( prefix: &String, raw_text: &String, end_char: char, trim: bool) -> String {
let matches: Vec = ::match_prefixed_field(&prefix, &raw_text, end_char, trim);
return if matches == null { null } else { matches[0] };
}
}