Fonema.java
package io.github.lvrodrigues.fonema;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Implementação do algorítimo BuscarBR para pesquisa fonética no idioma português.
*
* @author $Criado por: $
* @author $Alterado por: $
* @version $Ramo: main$
* @see <a href="https://github.com/LVRodrigues/jfonemabr/blob/main/docs/NOVOB.pdf">NOVOB.pdf</a>
*/
public final class Fonema {
/**
* Lista de caracteres acentuados que devem ser substituidos.
*
* <p>Como o primeiro passo para obter o fonema é passar o texto para maiúsculo,
* não há necessidade de tratar os caracteres minúsculos acentuados.
*
* <p>A primeira dimensão possui a lista de caracteres acentuados. A segunda
* dimensão poussui os caracteres de substituição.
*/
private static final char[][] INVALID_CHARS = {
{
'Á', 'É', 'Í', 'Ó', 'Ú',
'À', 'È', 'Ì', 'Ò', 'Ù',
'Â', 'Ê', 'Î', 'Ô', 'Û',
'Ã', 'Ẽ', 'Ĩ', 'Õ', 'Ũ',
'Ä', 'Ë', 'Ï', 'Ö', 'Ü',
'Ç', 'Ÿ', 'Ý', 'Ñ'
},
{
'A', 'E', 'I', 'O', 'U',
'A', 'E', 'I', 'O', 'U',
'A', 'E', 'I', 'O', 'U',
'A', 'E', 'I', 'O', 'U',
'A', 'E', 'I', 'O', 'U',
'C', 'Y', 'Y', 'N'
}
};
/**
* Índice da coluna de pesquisa da matriz de caracteres inválidos.
*/
private static final int INVALID_SEARCH_INDEX = 0;
/**
* Índice da coluna de troca de valores da matriz de caracteres inválidos.
*/
private static final int INVALID_REPLACE_INDEX = 1;
/**
* Expressão regular para ignorar os caracteres de A até Z e de 0 (zero) até 9 (nove)
* e remover os demais caracteres.
*/
private static final Pattern INVALID_PATTERN = Pattern.compile("[^A-Z0-9\s]");
/**
* Conjunto de expressões regulares (primeira dimensão) e seus caracteres de
* substituição (segunda dimensão).
*/
@SuppressWarnings("MultipleStringLiterals")
private static final Object[][] REPLACES = {
{Pattern.compile("(BL|BR)"), "B"},
{Pattern.compile("(PH)"), "F"},
{Pattern.compile("(GL|GR|MG|NG|RG)"), "G"},
{Pattern.compile("Y"), "I"},
{Pattern.compile("(GE|GI|RJ|MJ)"), "J"},
{Pattern.compile("(CA|CO|CU|CK)|Q"), "K"},
{Pattern.compile("N"), "M"},
{Pattern.compile("(AO|AUM|GM|MD|OM)"), "M"},
{Pattern.compile("(PR)"), "P"},
{Pattern.compile("L"), "R"},
{Pattern.compile("(CE|CI|CH|CS|RS|TS|X|Z)"), "S"},
{Pattern.compile("(TR|TL)"), "T"},
{Pattern.compile("(CT|RT|ST|PT)"), "T"},
{Pattern.compile("W|\\bU"), "V"},
{Pattern.compile("RM"), "SM"},
{Pattern.compile("[MRS]\\b"), ""},
{Pattern.compile("[AEIOUH]"), ""}
};
/**
* Índice da coluna de expressões regulares para pesquisa de fonemas.
*/
private static final int REPLACE_PATTERN_INDEX = 0;
/**
* Índice da coluna de troca de valores para a pesquisa de fonemas.
*/
private static final int REPLACE_VALUE_INDEX = 1;
/**
* Construtor oculto, tornando uma classe utilitária.
*/
private Fonema() {
}
/**
* Processa um texto aplicando as regras do algorítimo BuscarBR.
*
* @param text Texto para extrair os fonemas.
* @return Fonemas.
*/
public static String process(final String text) {
// 1. Converter para maiúsculas.
String result = text.toUpperCase();
// 2. Remover caracteres especiais e acentos:
result = clean(result);
// 3. Trocar dados por letras de fonéticas:
result = replaces(result);
// 4. Remover caracteres duplicados consecutivamente.
result = duplicates(result);
// 5. Remover vogais? Realizado no final do passo 3 utilizando expressões regulares.
return result;
}
/**
* Remove caracteres duplicados consecutivamente.
*
* @param text Texto para processar.
* @return Fonema.
*/
private static String duplicates(final String text) {
char current = 0;
final StringBuilder result = new StringBuilder();
for (char c : text.toCharArray()) {
if (current != c) {
result.append(c);
}
current = c;
}
return result.toString();
}
/**
* Troca letras baseadas em expressões regulares.
*
* @param text Texto para manipular.
* @return Texto manipulado.
*/
private static String replaces(final String text) {
String result = text;
for (int i = 0; i < REPLACES.length; i++) {
final Matcher matcher = ((Pattern) REPLACES[i][REPLACE_PATTERN_INDEX]).matcher(result);
result = matcher.replaceAll((String) REPLACES[i][REPLACE_VALUE_INDEX]);
}
return result;
}
/**
* Limpa os caracteres acentuados e especiais do texto.
*
* @param text Texto para ser limpo.
* @return Texto manipulado.
*/
private static String clean(final String text) {
String result = text;
for (int i = 0; i < INVALID_CHARS[INVALID_SEARCH_INDEX].length; i++) {
result = result.replace(INVALID_CHARS[INVALID_SEARCH_INDEX][i],
INVALID_CHARS[INVALID_REPLACE_INDEX][i]);
}
// Removendo os demais caracteres especiais:
final Matcher matcher = INVALID_PATTERN.matcher(result);
return matcher.replaceAll("");
}
}