2017-01-01 1 views
0

У меня есть метод ниже, который расшифровывает URL-адреса для значения, переданного вместе с использованием кодировки.рекурсивно вызывать метод, но регистрировать только второй раз?

public String decodeValue(String value, Charset charset) { 
    if (!Strings.isNullOrEmpty(value)) { 
     try { 
     value = URLDecoder.decode(value, charset.name()); 
     } catch (UnsupportedEncodingException ex) { 
     // log error 
     return null; 
     } 
    } 
    return value; 
    } 

Теперь, если URLDecoder.decode линия бросает UnsupportedEncodingException в первый раз, то я хочу, чтобы запустить же value против ниже три линий:

value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25"); 
value = value.replaceAll("\\+", "%2B"); 
value = URLDecoder.decode(value, charset.name()); 

И если затем снова URLDecoder.decode линия бросает исключение во второй раз, то я буду регистрировать но только второй раз и возвращает значение null в противном случае возвращает значение, которое декодируется.

Каков наилучший и элегантный способ сделать это?

+0

Вы ищете любой способ сделать это или самое элегантное решение? – shmosel

+0

Добавление другого блока try/catch, о котором я уже знал. Я искал какой-то лучший или элегантный способ сделать это, если он есть. –

+1

Я предложил изменение, которое кажется отклоненным. Где здесь рекурсия? –

ответ

1

Самый простой способ - сделать частную версию вашей сигнатуры функции, которая включает дополнительный флаг.

private String decodeValue(String value, Charset charset, boolean isFirstTime) { 
    if (!Strings.isNullOrEmpty(value)) { 
     try { 
     value = URLDecoder.decode(value, charset.name()); 
     } catch (UnsupportedEncodingException ex) { 
     if (isFirstTime) { 
      value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25"); 
      value = value.replaceAll("\\+", "%2B"); 
      return decodeValue(value, charset.name(), false); 
     } else { 
      // log error 
      return null; 
     } 
     } 
    } 
    return value; 
    } 

Тогда просто передать true в первый раз и false в рекурсивном вызове. Внутри функции выполняются только следующие три строки, если передано true.

Публичная версия может пройти true.

public String decodeValue(String value, Charset charset) { 
     decodeValue(value, charset, true); 
    } 
+0

Я бы сделал эту подпись приватной. – shmosel

+0

@ merlin2011 Как я буду использовать эту логическую переменную для выполнения трех строк и ведения журнала. Немного смущенный, можете ли вы привести пример, как это будет работать. –

+0

, чтобы сообщить вам мой метод декодирования и метод 'URLDecoder.decode', это два разных метода. Я обновил свой вопрос, чтобы изменить имя метода. В вашем случае вы передаете false методу URLDecoder, который не принимает этот параметр. –

0

Здесь вы идете:

public String decode(String value, Charset charset) { 
    if (!Strings.isNullOrEmpty(value)) { 
     try { 
     value = URLDecoder.decode(value, charset.name()); 
     } catch (UnsupportedEncodingException ex) { 
     try { 
     value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25"); 
     value = value.replaceAll("\\+", "%2B"); 
     value = URLDecoder.decode(value, charset.name()); 
     } catch (UnsupportedEncodingException ex) { 
     // log error 
     return null; 
     } 
     } 
    } 
    return value; 
    } 

Надеется, что это решит вашу проблему.

+1

И он дублирует код. Это чаще всего не очень хорошая идея. – GhostCat

+0

Исправить форматирование. – shmosel

0

Добавление флага - опция. Да, это легче; но многие утверждают, что наличие флагов просто говорят: плохая практика.

Вы просто пытаетесь свести к минимуму эти вещи.

Другими словами: если у вас есть метод, который должен вести себя иначе для первого и последующих вызовов; рассмотрите возможность создания двух методов. Конечно, вы избегаете дублирования кода, насколько это возможно, но если это не станет дорогостоящим, вы должны хотя бы подумать об исключении таких аргументов флага.

+0

Можете ли вы привести пример того, как я могу использовать два разных метода здесь и что вызывать в зависимости от того, когда генерируется исключение и вызывается ли оно нормально? –

1

Хотя он не является рекурсивным, вы можете использовать цикл while и флаг.

public String decode(String value, Charset charset) { 
    boolean first = true; 
    while(!Strings.isNullOrEmpty(value)) { 
     try { 
      return value = URLDecoder.decode(value, charset); 
     } catch (UnsupportedEncodingException e) { 
      if(first == false) { 
       // Log error. 
       return null; 
      } 
      value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25").replaceAll("\\+", "%2B"); 
     } 
     first = false; 
    } 
    return value; 
} 
0

Вот версия без дополнительных флагов, дублируется код, рекурсии и петли:

public String decodeValue(final String value, Charset charset) throws UnsupportedEncodingException { 
    String result; 
    if (!Strings.isNullOrEmpty(value)) { 
     UnsupportedEncodingException[] lastException = new UnsupportedEncodingException[1]; 
     result = Stream.<Function<String, String>>of(
       Function.identity(), 
       s -> { 
        s = s.replaceAll("%(?![0-9a-fA-F]{2})", "%25"); 
        s = s.replaceAll("\\+", "%2B"); 
        return s; 
       }) 
       .map(f -> f.apply(value)) 
       .map(appliedValue -> { 
        try { 
         return URLDecoder.decode(appliedValue, charset.name()); 
        } catch (UnsupportedEncodingException e) { 
         lastException[0] = e; 
         return null; 
        } 
       }) 
       .filter(Objects::nonNull) 
       .findFirst() 
       .orElseThrow(() -> lastException[0]); 
    } 
    return result; 
} 

Здесь я просто взять поток с 2-мя функциями: тождественное и функция делает коррекцию строки. Затем я применяю эти функции к исходной строке и пытаюсь декодировать. Если первая попытка успешна, тогда код не будет применять функцию коррекции и просто вернет правильный результат. Если декодер выдает исключение после коррекции значения, тогда «findFirst» не найдет значения. Затем мы бросаем последнее пойманное исключение.

+0

Можете ли вы привести пример Java7. Я не могу использовать Java 8 на данный момент. Если я могу избежать дополнительных флагов, дублированный код в Java 7, тогда это будет хорошо. Пока у меня нет такого ответа. –

+0

В этом случае решение Mattew предпочтительнее. –

Смежные вопросы