diff --git a/README.md b/README.md
index 3665a33..987a24f 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ Maven Site: [http://bekkopen.github.com/NoCommons/](http://bekkopen.github.com/N
* validering
* Bank
* Kontonummer validering og generering
+ * KID generering
* KID validering
* Norsk språk o.l.
* Konvertering av norske bokstaver i en tekst til de engelske erstatningene aa, ae og oe
@@ -28,11 +29,8 @@ Maven Site: [http://bekkopen.github.com/NoCommons/](http://bekkopen.github.com/N
* Sjekk om dato er arbeidsdag (dvs. ikke helligdag eller helg)
* Legg til x antall arbeidsdager til en gitt dato
* Liste ut alle helligdager
-
## Features som ikke er implementert, men som kan passe inn
-* Bank
- * KID generator
* Fylkesnummer
* Finn fylkesnummer for fylke
* Finn fylke for fylkesnummer
diff --git a/pom.xml b/pom.xml
index aab60c3..2f2ba0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -372,6 +372,6 @@
2.4
UTF-8
- 1.5
+ 1.6
diff --git a/src/main/java/no/bekk/bekkopen/banking/Kidnummer.java b/src/main/java/no/bekk/bekkopen/banking/Kidnummer.java
index 90c3625..69aff4d 100644
--- a/src/main/java/no/bekk/bekkopen/banking/Kidnummer.java
+++ b/src/main/java/no/bekk/bekkopen/banking/Kidnummer.java
@@ -2,15 +2,66 @@
import no.bekk.bekkopen.common.StringNumber;
+import java.math.BigInteger;
+
+import static no.bekk.bekkopen.common.Checksums.*;
+
/**
* This class represent a Norwegian KID-nummer - a number used to identify
* a customer on invoices. A Kidnummer consists of digits only, and the last
* digit is a checksum digit (either mod10 or mod11).
*/
public class Kidnummer extends StringNumber {
-
- Kidnummer(String kontonummer) {
- super(kontonummer);
+
+ Kidnummer(String kidnummer) {
+ super(kidnummer);
+ }
+
+ /**
+ * Return a valid mod10 Kidnummer by adding checksum digit
+ * @param baseNumber input number, digits only
+ * @return Kidnummer
+ */
+ public static Kidnummer mod10Kid(String baseNumber) {
+ return Kidnummer.mod10Kid(baseNumber, baseNumber.length()+1);
+ }
+
+ /**
+ * Create a valid KID numer of the wanted length, using MOD10.
+ * Input is padded with leading zeros to reach wanted target length
+ * @param baseNumber base number to calculate checksum digit for
+ * @param targetLength wanted length, 0-padded. Between 2-25
+ * @return Kidnummer
+ */
+ public static Kidnummer mod10Kid(String baseNumber, int targetLength) {
+ if (baseNumber.length() >= targetLength)
+ throw new IllegalArgumentException("baseNumber too long");
+ String padded = String.format("%0" + (targetLength-1) + "d", new BigInteger(baseNumber));
+ Kidnummer k = new Kidnummer(padded + "0");
+ return KidnummerValidator.getKidnummer(padded + calculateMod10CheckSum(getMod10Weights(k), k));
+ }
+
+ /**
+ * Return a valid mod10 Kidnummer by adding checksum digit
+ * @param baseNumber input number, digits only
+ * @return Kidnummer
+ */
+ public static Kidnummer mod11Kid(String baseNumber) {
+ return Kidnummer.mod11Kid(baseNumber, baseNumber.length()+1);
}
+ /**
+ * Create a valid KID numer of the wanted length, using MOD11.
+ * Input is padded with leading zeros to reach wanted target length
+ * @param baseNumber base number to calculate checksum digit for
+ * @param targetLength wanted length, 0-padded. Between 2-25
+ * @return Kidnummer
+ */
+ public static Kidnummer mod11Kid(String baseNumber, int targetLength) {
+ if (baseNumber.length() >= targetLength)
+ throw new IllegalArgumentException("baseNumber too long");
+ String padded = String.format("%0" + (targetLength-1) + "d", new BigInteger(baseNumber));
+ Kidnummer k = new Kidnummer(padded + "0");
+ return KidnummerValidator.getKidnummer(padded + calculateMod11CheckSum(getMod11Weights(k), k));
+ }
}
diff --git a/src/main/java/no/bekk/bekkopen/banking/KidnummerValidator.java b/src/main/java/no/bekk/bekkopen/banking/KidnummerValidator.java
index 97acafc..b80f937 100644
--- a/src/main/java/no/bekk/bekkopen/banking/KidnummerValidator.java
+++ b/src/main/java/no/bekk/bekkopen/banking/KidnummerValidator.java
@@ -6,6 +6,8 @@
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
+import static no.bekk.bekkopen.common.Checksums.*;
+
public class KidnummerValidator extends StringNumberValidator implements ConstraintValidator {
public static final String ERROR_LENGTH = "A Kidnummer is between 2 and 25 digits";
diff --git a/src/main/java/no/bekk/bekkopen/banking/KontonummerValidator.java b/src/main/java/no/bekk/bekkopen/banking/KontonummerValidator.java
index 066a0ed..41f91e8 100644
--- a/src/main/java/no/bekk/bekkopen/banking/KontonummerValidator.java
+++ b/src/main/java/no/bekk/bekkopen/banking/KontonummerValidator.java
@@ -5,6 +5,10 @@
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
+import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM;
+import static no.bekk.bekkopen.common.Checksums.calculateMod11CheckSum;
+import static no.bekk.bekkopen.common.Checksums.getMod11Weights;
+
/**
* Provides methods that validates if a Kontonummer is valid with respect to
* syntax (length and digits only) and that the checksum digit is correct.
diff --git a/src/main/java/no/bekk/bekkopen/common/Checksums.java b/src/main/java/no/bekk/bekkopen/common/Checksums.java
new file mode 100644
index 0000000..f4b1429
--- /dev/null
+++ b/src/main/java/no/bekk/bekkopen/common/Checksums.java
@@ -0,0 +1,68 @@
+package no.bekk.bekkopen.common;
+
+public class Checksums {
+ public static final String ERROR_INVALID_CHECKSUM = "Invalid checksum : ";
+ private static int[] BASE_MOD11_WEIGHTS = new int[]{2, 3, 4, 5, 6, 7};
+
+ /**
+ * Calculate the check sum for the given weights and number.
+ *
+ * @param weights The weights
+ * @param number The number
+ * @return The checksum
+ */
+ public static int calculateMod11CheckSum(int[] weights, StringNumber number) {
+ int c = calculateChecksum(weights, number, false) % 11;
+ if (c == 1) {
+ throw new IllegalArgumentException(ERROR_INVALID_CHECKSUM + number);
+ }
+ return c == 0 ? 0 : 11 - c;
+ }
+
+ /**
+ * Calculate the check sum for the given weights and number.
+ *
+ * @param weights The weights
+ * @param number The number
+ * @return The checksum
+ */
+ public static int calculateMod10CheckSum(int[] weights, StringNumber number) {
+ int c = calculateChecksum(weights, number, true) % 10;
+ return c == 0 ? 0 : 10 - c;
+ }
+
+ public static int calculateChecksum(int[] weights, StringNumber number, boolean tverrsum) {
+ int checkSum = 0;
+ for (int i = 0; i < weights.length; i++) {
+ int product = weights[i] * number.getAt(weights.length - 1 - i);
+ if (tverrsum) {
+ checkSum += (product > 9 ? product - 9 : product);
+ } else {
+ checkSum += product;
+ }
+ }
+ return checkSum;
+ }
+
+ public static int[] getMod10Weights(StringNumber k) {
+ int[] weights = new int[k.getLength() - 1];
+ for (int i = 0; i < weights.length; i++) {
+ if ((i % 2) == 0) {
+ weights[i] = 2;
+ } else {
+ weights[i] = 1;
+ }
+ }
+ return weights;
+ }
+
+ public static int[] getMod11Weights(StringNumber k) {
+ int[] weights = new int[k.getLength() - 1];
+ for (int i = 0; i < weights.length; i++) {
+ int j = i % BASE_MOD11_WEIGHTS.length;
+ weights[i] = BASE_MOD11_WEIGHTS[j];
+ }
+ return weights;
+ }
+
+}
diff --git a/src/main/java/no/bekk/bekkopen/common/StringNumberValidator.java b/src/main/java/no/bekk/bekkopen/common/StringNumberValidator.java
index 4bf58e7..865517f 100644
--- a/src/main/java/no/bekk/bekkopen/common/StringNumberValidator.java
+++ b/src/main/java/no/bekk/bekkopen/common/StringNumberValidator.java
@@ -6,56 +6,12 @@
*/
public abstract class StringNumberValidator {
- public static final String ERROR_INVALID_CHECKSUM = "Invalid checksum : ";
-
public static final String ERROR_SYNTAX = "Only digits are allowed : ";
-
- private static int[] BASE_MOD11_WEIGHTS = new int[]{2, 3, 4, 5, 6, 7};
-
+
protected StringNumberValidator() {
super();
}
- /**
- * Calculate the check sum for the given weights and number.
- *
- * @param weights The weights
- * @param number The number
- * @return The checksum
- */
- protected static int calculateMod11CheckSum(int[] weights, StringNumber number) {
- int c = calculateChecksum(weights, number, false) % 11;
- if (c == 1) {
- throw new IllegalArgumentException(ERROR_INVALID_CHECKSUM + number);
- }
- return c == 0 ? 0 : 11 - c;
- }
-
- /**
- * Calculate the check sum for the given weights and number.
- *
- * @param weights The weights
- * @param number The number
- * @return The checksum
- */
- protected static int calculateMod10CheckSum(int[] weights, StringNumber number) {
- int c = calculateChecksum(weights, number, true) % 10;
- return c == 0 ? 0 : 10 - c;
- }
-
- private static int calculateChecksum(int[] weights, StringNumber number, boolean tverrsum) {
- int checkSum = 0;
- for (int i = 0; i < weights.length; i++) {
- int product = weights[i] * number.getAt(weights.length - 1 - i);
- if (tverrsum) {
- checkSum += (product > 9 ? product - 9 : product);
- } else {
- checkSum += product;
- }
- }
- return checkSum;
- }
-
protected static void validateLengthAndAllDigits(String numberString,
int length) {
if (numberString == null || numberString.length() != length) {
@@ -74,26 +30,4 @@ protected static void validateAllDigits(String numberString) {
}
}
}
-
- protected static int[] getMod10Weights(StringNumber k) {
- int[] weights = new int[k.getLength() - 1];
- for (int i = 0; i < weights.length; i++) {
- if ((i % 2) == 0) {
- weights[i] = 2;
- } else {
- weights[i] = 1;
- }
- }
- return weights;
- }
-
- protected static int[] getMod11Weights(StringNumber k) {
- int[] weights = new int[k.getLength() - 1];
- for (int i = 0; i < weights.length; i++) {
- int j = i % BASE_MOD11_WEIGHTS.length;
- weights[i] = BASE_MOD11_WEIGHTS[j];
- }
- return weights;
- }
-
}
diff --git a/src/main/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidator.java b/src/main/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidator.java
index 9ece14a..0a9f863 100644
--- a/src/main/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidator.java
+++ b/src/main/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidator.java
@@ -5,6 +5,10 @@
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
+import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM;
+import static no.bekk.bekkopen.common.Checksums.calculateMod11CheckSum;
+import static no.bekk.bekkopen.common.Checksums.getMod11Weights;
+
/**
* Provides methods that validates if an Organisasjonsnummer is valid with
* respect to syntax (length and digits only) and that the checksum digit is
diff --git a/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java b/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java
index baee994..4b60e5a 100644
--- a/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java
+++ b/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java
@@ -8,6 +8,9 @@
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM;
+import static no.bekk.bekkopen.common.Checksums.calculateMod11CheckSum;
+
/**
* Provides methods that validates if a Fodselsnummer is valid with respect to
* syntax, Individnummer, Date and checksum digits.
diff --git a/src/test/java/no/bekk/bekkopen/banking/KidnummerTest.java b/src/test/java/no/bekk/bekkopen/banking/KidnummerTest.java
new file mode 100644
index 0000000..2b1979a
--- /dev/null
+++ b/src/test/java/no/bekk/bekkopen/banking/KidnummerTest.java
@@ -0,0 +1,54 @@
+package no.bekk.bekkopen.banking;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class KidnummerTest {
+ @Test
+ public void mod10Kid() throws Exception {
+ assertValidKid("0000001230", Kidnummer.mod10Kid("123", 10));
+ assertValidKid("0000012344", Kidnummer.mod10Kid("1234", 10));
+ }
+
+ @Test
+ public void mod11Kid() throws Exception {
+ assertValidKid("0000001236", Kidnummer.mod11Kid("123", 10));
+ assertValidKid("0000012343", Kidnummer.mod11Kid("1234", 10));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void tooLongBaseMod10() {
+ Kidnummer.mod10Kid("1234567890", 3);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void tooLongBaseMod101() {
+ Kidnummer.mod11Kid("1234567890", 3);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void belowRangeMod10() {
+ Kidnummer.mod10Kid("12", 1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void belowRangeMod11() {
+ Kidnummer.mod11Kid("12", 1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void aboveRangeMod10() {
+ Kidnummer.mod10Kid("12", 26);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void aboveRangeMod11() {
+ Kidnummer.mod11Kid("12", 26);
+ }
+
+ private void assertValidKid(String expected, Kidnummer kidnummer) {
+ KidnummerValidator.isValid(kidnummer.toString());
+ assertEquals(expected, kidnummer.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/no/bekk/bekkopen/banking/KidnummerValidatorTest.java b/src/test/java/no/bekk/bekkopen/banking/KidnummerValidatorTest.java
index 1caad93..8c95d4b 100644
--- a/src/test/java/no/bekk/bekkopen/banking/KidnummerValidatorTest.java
+++ b/src/test/java/no/bekk/bekkopen/banking/KidnummerValidatorTest.java
@@ -5,6 +5,7 @@
import org.junit.Test;
+import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM;
import static org.junit.Assert.*;
public class KidnummerValidatorTest extends NoCommonsTestCase {
@@ -61,7 +62,7 @@ public void testInvalidKidnummerWrongChecksum() {
KidnummerValidator.validateChecksum(KIDNUMMER_INVALID_CHECKSUM);
fail();
} catch (IllegalArgumentException e) {
- assertMessageContains(e, StringNumberValidator.ERROR_INVALID_CHECKSUM);
+ assertMessageContains(e, ERROR_INVALID_CHECKSUM);
}
}
diff --git a/src/test/java/no/bekk/bekkopen/banking/KontonummerValidatorTest.java b/src/test/java/no/bekk/bekkopen/banking/KontonummerValidatorTest.java
index 5aef7e0..f42b42a 100644
--- a/src/test/java/no/bekk/bekkopen/banking/KontonummerValidatorTest.java
+++ b/src/test/java/no/bekk/bekkopen/banking/KontonummerValidatorTest.java
@@ -1,5 +1,6 @@
package no.bekk.bekkopen.banking;
+import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -38,7 +39,7 @@ public void testInvalidKontonummerWrongChecksum() {
KontonummerValidator.validateChecksum(KONTONUMMER_INVALID_CHECKSUM);
fail();
} catch (IllegalArgumentException e) {
- assertMessageContains(e, KontonummerValidator.ERROR_INVALID_CHECKSUM);
+ assertMessageContains(e, ERROR_INVALID_CHECKSUM);
}
}
diff --git a/src/test/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidatorTest.java b/src/test/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidatorTest.java
index 9bf53f3..5335035 100644
--- a/src/test/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidatorTest.java
+++ b/src/test/java/no/bekk/bekkopen/org/OrganisasjonsnummerValidatorTest.java
@@ -1,5 +1,6 @@
package no.bekk.bekkopen.org;
+import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -38,7 +39,7 @@ public void testInvalidOrgnummerWrongChecksum() {
OrganisasjonsnummerValidator.validateChecksum(ORGNUMMER_INVALID_CHECKSUM);
fail();
} catch (IllegalArgumentException e) {
- assertMessageContains(e, OrganisasjonsnummerValidator.ERROR_INVALID_CHECKSUM);
+ assertMessageContains(e, ERROR_INVALID_CHECKSUM);
}
}
diff --git a/src/test/java/no/bekk/bekkopen/person/FodselsnummerValidatorTest.java b/src/test/java/no/bekk/bekkopen/person/FodselsnummerValidatorTest.java
index 52f3556..7e5f40c 100644
--- a/src/test/java/no/bekk/bekkopen/person/FodselsnummerValidatorTest.java
+++ b/src/test/java/no/bekk/bekkopen/person/FodselsnummerValidatorTest.java
@@ -1,5 +1,6 @@
package no.bekk.bekkopen.person;
+import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -95,7 +96,7 @@ public void testInvalidFodselsnummerChecksum() {
FodselsnummerValidator.validateChecksums("01010101010");
fail();
} catch (IllegalArgumentException e) {
- assertMessageContains(e, FodselsnummerValidator.ERROR_INVALID_CHECKSUM);
+ assertMessageContains(e, ERROR_INVALID_CHECKSUM);
}
}