RowFilter.NumberFilter: não pode lidar com tipos de números concretos “mistos”
Happens se pelo menos um dos valores (valores == valor no RowFilter, valor na entrada) for decimal. Aqui está um teste com falha:
@Test
public void testRowFilterNumberMixCore() {
TestEntry entry = new TestEntry(1.2f);
RowFilter filter = RowFilter.numberFilter(ComparisonType.AFTER, 1, 0);
assertTrue(entry + "must be included " + filter, filter.include(entry));
}
A saída é:
junit.framework.AssertionFailedError: [entry: 1.2] must be included [RowFilter: ComparisonType = AFTER, comparableValue: 1, comparableClass: class java.lang.Integer]
O motivo é que NumberFilter volta a comparar os números pelo número.longValue () se eles não são da mesma classe (e comparáveis entre si)
Conhecendo esses detalhes, a falha no teste não é surpreendente (em retrospectiva, nunca teria pensado nisso ;-) Um nível de defesa é garantir - no código do cliente - que os números para compararestamo da mesma classe. Isso nem sempre é possível (pense f.i .: uma tableColumn com columnClass Number) Então, eu estou pensando se / como melhorar o fallback. Algo como
if (one instanceof Comparable && one.getClass() == other.getClass()) {
// same class, use comparator
return ((Comparable) one).compareTo(other);
}
if (areIntegers(one, other)) {
// all integers, use longValue
return longCompare(one, other);
}
if (areDecimals(one, other)) {
// anything to do here?
}
// at last resort convert to BigDecimal and compare those:
BigDecimal bigOne = new BigDecimal(one.toString());
BigDecimal bigOther = new BigDecimal(other.toString());
return bigOne.compareTo(bigOther);
Fazendo isso, faz o teste passar - eu sou um pouco cauteloso em relação às armadilhas ocultas (leia-se: desconhecido para mim :). Quaisquer avisos / alternativas muito bem-vindos!
FYI: postado cruzadamente em Fórum do Swing da OTN
Acompanhament
mplementado conforme descrito acima, agora aguardando a reclamação dos clientes - nesse caso, apontará os dedos para todos que não me avisaram aqui: -)