Commit cf7427d7 by Tuomas Riihimäki

Create numeric comparator.

1 parent a1745bab
......@@ -54,37 +54,32 @@ public class GenericEntity extends EntityEquals implements ModelInterface, Entit
return "";
}
}
@Transient
public void setMetaStringValue(String key, String value) {
JsonObjectBuilder metaBuilder = Json.createObjectBuilder();
if(getMeta() != null) {
for(String valKey : getMeta().keySet()) {
if(!valKey.equals(key)) {
if (getMeta() != null) {
for (String valKey : getMeta().keySet()) {
if (!valKey.equals(key)) {
metaBuilder.add(valKey, getMeta().get(valKey));
}
}
}
metaBuilder.add(key, value);
setMeta(metaBuilder.build());
}
}
@Transient
protected Integer getNonNullId()
{
if (getId() != null) {
return getId();
}
return getRndid();
}
}
......@@ -14,6 +14,8 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import fi.codecrew.moya.utilities.NumericStringComparator;
/**
*
*/
......@@ -276,71 +278,35 @@ public class Place extends GenericEntity implements Comparable<Place> {
}
/**
* Note: this class has a natural ordering that is inconsistent with equals.
*/
/**
* Note: this class has a natural ordering that is inconsistent with equals.
*/
@Override
@Transient
public int compareTo(Place o) {
if(this.getName().equals(o.getName())) {
return 0;
}
// check empty string etc.
if(o.getName().length() == 0) {
if(this.getName().length() > 0)
return 1;
if (this.equals(o)) {
return 0;
}
if(this.getName().length() == 0 && o.getName().length() > 0) {
return -1;
}
// check prefixes
String splitted[] = o.getName().split("[0-9]");
if(splitted.length > 0 && splitted[0].length() > 0) {
if(splitted[0].length() > this.getName().length()) {
return this.getName().compareTo(splitted[0]);
}
} else {
return 1;
}
String myPrefix = this.getName().substring(0, splitted[0].length());
if(myPrefix.compareTo(splitted[0]) != 0)
return myPrefix.compareTo(splitted[0]);
// prefixes are same, find numbers and check them
String otherNumber = o.getName().substring(splitted[0].length());
String myNumber = this.getName().substring(splitted[0].length());
try {
int other = Integer.parseInt(otherNumber);
int me = Integer.parseInt(myNumber);
if(other < me) {
// Check null values;
// Null is smaller than non null value.
if (this.getName() == null || o.getName() == null) {
if (this.getName() == null) {
return 1;
}
if(other > me)
if (o.getName() == null) {
return -1;
}
// both names are null. Compare IDs
return this.getNonNullId().compareTo(o.getNonNullId());
}
if (this.getName().equals(o.getName())) {
return 0;
} catch(NumberFormatException x) {
return myNumber.compareTo(otherNumber);
}
return NumericStringComparator.numericCompare(this.getName(), o.getName());
}
}
package fi.codecrew.moya.utilities;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NumericStringComparator implements Comparator<String> {
// \D non numeric
// \d numeric
private static final Pattern NUMERIC_COMPARE_PATTERN = Pattern.compile("(\\D*)(\\d*)");
public static int numericCompare(String o1, String o2) {
Matcher m1 = NUMERIC_COMPARE_PATTERN.matcher(o1);
Matcher m2 = NUMERIC_COMPARE_PATTERN.matcher(o2);
Integer.compare(1, 2);
// Match fails only in end of either string
while (m1.find() && m2.find()) {
// Compare non digit part of the match (can be empty, but not null)
int nonDigitCompare = m1.group(1).compareTo(m2.group(1));
if (0 != nonDigitCompare) {
return nonDigitCompare;
}
// compare digit part of the match.
if (m1.group(2).isEmpty()) {
return m2.group(2).isEmpty() ? 0 : -1;
} else if (m2.group(2).isEmpty()) {
return +1;
}
// Integer might overflow.. Unlikely, but possible. Use bigint
BigInteger n1 = new BigInteger(m1.group(2));
BigInteger n2 = new BigInteger(m2.group(2));
int numberCompare = n1.compareTo(n2);
if (0 != numberCompare) {
return numberCompare;
}
}
// when we hit the end of either string
return m1.hitEnd() && m2.hitEnd() ? 0 : m1.hitEnd() ? -1 : +1;
}
@Override
public int compare(String o1, String o2) {
return numericCompare(o1, o2);
}
}
......@@ -35,10 +35,17 @@ public abstract class EntityEquals {
return ret;
}
private Integer getRndid() {
@Transient
// Always negative!
protected Integer getRndid() {
if (rndid == null) {
Random rng = new Random(new Date().getTime());
rndid = Integer.valueOf(rng.nextInt());
int i = 0;
while (i == 0)
i = rng.nextInt();
if (i > 0)
i *= -1;
rndid = Integer.valueOf(i);
}
return rndid;
}
......
package fi.codecrew.moya.utilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
public class StringUtilsTest {
private static final Logger logger = LoggerFactory.getLogger(StringUtilsTest.class);
@Test
public void numericTest1()
{
Assert.assertTrue(NumericStringComparator.numericCompare("ABC123", "ABC123") == 0);
Assert.assertTrue(NumericStringComparator.numericCompare("123ABC", "123ABC") == 0);
Assert.assertTrue(NumericStringComparator.numericCompare("A10", "A9") > 0);
Assert.assertTrue(NumericStringComparator.numericCompare("10A", "9A") > 0);
Assert.assertTrue(NumericStringComparator.numericCompare("10A11", "10A9") > 0);
Assert.assertTrue(NumericStringComparator.numericCompare("10A11", "9A9") > 0);
Assert.assertTrue(NumericStringComparator.numericCompare("10A", "10A") == 0);
Assert.assertTrue(NumericStringComparator.numericCompare("10A1234", "10A1234") == 0);
// Lexicographically... ie 'a'< 'b'
Assert.assertTrue(NumericStringComparator.numericCompare("A", "a") < 0);
Assert.assertTrue(NumericStringComparator.numericCompare("A", "B") < 0);
Assert.assertTrue(NumericStringComparator.numericCompare("a", "9") > 0);
Assert.assertTrue(NumericStringComparator.numericCompare("A", "9") > 0);
Assert.assertTrue(NumericStringComparator.numericCompare("10", "9") > 0);
}
@Test(expectedExceptions = NullPointerException.class)
public void nulltest1() {
Assert.assertTrue(NumericStringComparator.numericCompare(null, "asd") == 0);
}
@Test(expectedExceptions = NullPointerException.class)
public void nulltest2() {
Assert.assertTrue(NumericStringComparator.numericCompare("asd", null) == 0);
}
@Test(expectedExceptions = NullPointerException.class)
public void nulltest3() {
Assert.assertTrue(NumericStringComparator.numericCompare(null, null) == 0);
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!