Skip to content

Commit

Permalink
Move separator and character set from bill format to bill
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelbl committed May 30, 2024
1 parent cc24805 commit 4bd9cc7
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ private char getCharWidth(char ch) {
else if (ch >= 0xa0 && ch <= 0x017f) {
width = charWidthxA0x17F[ch - 0xa0];
} else if (ch >= 0x0218 && ch <= 0x021b) {
width = charWidthx218x21B[ch - 0xa0];
width = charWidthx218x21B[ch - 0x0218];
} else if (ch == 0x2013) {
width = charNDashWidth;
} else if (ch == 0x20AC) {
Expand Down
68 changes: 65 additions & 3 deletions generator/src/main/java/net/codecrete/qrbill/generator/Bill.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public enum Version {
private AlternativeScheme[] alternativeSchemes = null;
/** Bill format */
private BillFormat format = new BillFormat();
/** Data separator for QR code data */
private QrDataSeparator separator = QrDataSeparator.LF;
/** Character set used for the QR bill data */
private SPSCharacterSet characterSet = SPSCharacterSet.LATIN_1_SUBSET;

/**
* Creates a new instance with default values for the format.
Expand Down Expand Up @@ -240,7 +244,7 @@ public void updateReferenceType() {
if (ref != null) {
if (ref.startsWith("RF"))
referenceType = REFERENCE_TYPE_CRED_REF;
else if (ref.length() > 0)
else if (!ref.isEmpty())
referenceType = REFERENCE_TYPE_QR_REF;
else
referenceType = REFERENCE_TYPE_NO_REF;
Expand Down Expand Up @@ -412,6 +416,60 @@ public void setFormat(BillFormat format) {
this.format = format;
}

/**
* Gets the line separator for the QR code data fields.
* <p>
* The default is {@link QrDataSeparator#LF}. There is no need to change it except
* for improving compatibility with a non-compliant software processing the QR code data.
* </p>
* @return the line separator for the QR code data fields.
*/
public QrDataSeparator getSeparator() {
return separator;
}

/**
* Sets the line separator for the QR code data fields.
* <p>
* The default is {@link QrDataSeparator#LF}. There is no need to change it except
* for improving compatibility with a non-compliant software processing the QR code data.
* </p>
* @param separator the line separator for the QR code data fields.
*/
public void setSeparator(QrDataSeparator separator) {
this.separator = separator;
}

/**
* Gets the character set used for the QR bill data.
* <p>
* Defaults to {@link SPSCharacterSet#LATIN_1_SUBSET}.
* </p>
* <p>
* Until November 21, 2025, {@link SPSCharacterSet#LATIN_1_SUBSET} is the only value that will generate
* QR bills accepted by all banks. This will change by November 21, 2025.
* </p>
* @return the character set used for the QR bill data.
*/
public SPSCharacterSet getCharacterSet() {
return characterSet;
}

/**
* Sets the character set used for the QR bill data.
* <p>
* Defaults to {@link SPSCharacterSet#LATIN_1_SUBSET}.
* </p>
* <p>
* Until November 21, 2025, {@link SPSCharacterSet#LATIN_1_SUBSET} is the only value that will generate
* QR bills accepted by all banks. This will change by November 21, 2025.
* </p>
* @param characterSet the character set used for the QR bill data.
*/
public void setCharacterSet(SPSCharacterSet characterSet) {
this.characterSet = characterSet;
}

/**
* {@inheritDoc}
*/
Expand All @@ -431,7 +489,9 @@ public boolean equals(Object o) {
Objects.equals(unstructuredMessage, bill.unstructuredMessage) &&
Objects.equals(billInformation, bill.billInformation) &&
Arrays.equals(alternativeSchemes, bill.alternativeSchemes) &&
Objects.equals(format, bill.format);
Objects.equals(format, bill.format) &&
Objects.equals(separator, bill.separator) &&
Objects.equals(characterSet, bill.characterSet);
}

/**
Expand All @@ -441,7 +501,7 @@ public boolean equals(Object o) {
public int hashCode() {

int result = Objects.hash(version, amount, currency, account, creditor, referenceType, reference,
debtor, unstructuredMessage, billInformation, format);
debtor, unstructuredMessage, billInformation, format, separator, characterSet);
result = 31 * result + Arrays.hashCode(alternativeSchemes);
return result;
}
Expand All @@ -464,6 +524,8 @@ public String toString() {
", billInformation='" + billInformation + '\'' +
", alternativeSchemes=" + Arrays.toString(alternativeSchemes) +
", format=" + format +
", qrDataSeparator=" + separator +
", characterSet=" + characterSet +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ public class BillFormat implements Serializable {
/** ISO country code of local country */
private String localCountryCode = "CH";

/** Data separator for QR code data */
private QrDataSeparator qrDataSeparator = QrDataSeparator.LF;

/** Character set used for the QR bill data */
private SPSCharacterSet characterSet = SPSCharacterSet.LATIN_1_SUBSET;

/**
* Creates a new instance with default values
*/
Expand All @@ -69,8 +63,6 @@ public BillFormat(BillFormat format) {
marginLeft = format.marginLeft;
marginRight = format.marginRight;
localCountryCode = format.localCountryCode;
qrDataSeparator = format.qrDataSeparator;
characterSet = format.characterSet;
}

/**
Expand Down Expand Up @@ -324,62 +316,6 @@ public void setLocalCountryCode(String localCountryCode) {
this.localCountryCode = localCountryCode;
}

/**
* Gets the line separator for the QR code data fields.
* <p>
* The default is {@link QrDataSeparator#LF}. There is no need to change it except
* for improving compatibility with a non-compliant software processing the QR code data.
* </p>
* @return the line separator for the QR code data fields.
*/
public QrDataSeparator getQrDataSeparator() {
return qrDataSeparator;
}

/**
* Sets the line separator for the QR code data fields.
* <p>
* The default is {@link QrDataSeparator#LF}. There is no need to change it except
* for improving compatibility with a non-compliant software processing the QR code data.
* </p>
* @param qrDataSeparator the line separator for the QR code data fields.
*/
public void setQrDataSeparator(QrDataSeparator qrDataSeparator) {
this.qrDataSeparator = qrDataSeparator;
}

/**
* Gets the character set used for the QR bill data.
* <p>
* Defaults to {@link SPSCharacterSet#LATIN_1_SUBSET}.
* </p>
* <p>
* Until November 21, 2025, {@link SPSCharacterSet#LATIN_1_SUBSET} is the only value that will generate
* QR bills accepted by all banks. This will change by November 21, 2025. A release after that date
* wil change the default to {@link SPSCharacterSet#EXTENDED_LATIN}.
* </p>
* @return the character set used for the QR bill data.
*/
public SPSCharacterSet getCharacterSet() {
return characterSet;
}

/**
* Sets the character set used for the QR bill data.
* <p>
* Defaults to {@link SPSCharacterSet#LATIN_1_SUBSET}.
* </p>
* <p>
* Until November 21, 2025, {@link SPSCharacterSet#LATIN_1_SUBSET} is the only value that will generate
* QR bills accepted by all banks. This will change by November 21, 2025. A release after that date
* wil change the default to {@link SPSCharacterSet#EXTENDED_LATIN}.
* </p>
* @param characterSet the character set used for the QR bill data.
*/
public void setCharacterSet(SPSCharacterSet characterSet) {
this.characterSet = characterSet;
}

/**
* {@inheritDoc}
*/
Expand All @@ -396,9 +332,7 @@ public boolean equals(Object o) {
resolution == that.resolution &&
marginLeft == that.marginLeft &&
marginRight == that.marginRight &&
Objects.equals(localCountryCode, that.localCountryCode) &&
qrDataSeparator == that.qrDataSeparator &&
characterSet == that.characterSet;
Objects.equals(localCountryCode, that.localCountryCode);
}

/**
Expand All @@ -407,7 +341,7 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
return Objects.hash(outputSize, language, separatorType, fontFamily, graphicsFormat, resolution, marginLeft,
marginLeft, localCountryCode, qrDataSeparator, characterSet);
marginLeft, localCountryCode);
}

/**
Expand All @@ -425,8 +359,6 @@ public String toString() {
", marginLeft=" + marginLeft +
", marginRight=" + marginRight +
", localCountryCode='" + localCountryCode + '\'' +
", qrDataSeparator=" + qrDataSeparator +
", characterSet=" + characterSet +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public static ValidationResult validate(Bill bill) {
* @see #draw
*/
public static byte[] generate(Bill bill) {
try (Canvas canvas = createCanvas(bill.getFormat())) {
try (Canvas canvas = createCanvas(bill)) {
validateAndGenerate(bill, canvas);
return ((ByteArrayResult) canvas).toByteArray();
} catch (IOException e) {
Expand Down Expand Up @@ -277,9 +277,10 @@ public static Bill decodeQrCodeText(String text) {
return QRCodeText.decode(text);
}

private static Canvas createCanvas(BillFormat format) throws IOException {
private static Canvas createCanvas(Bill bill) throws IOException {
double drawingWidth;
double drawingHeight;
BillFormat format = bill.getFormat();

// define page size
switch (format.getOutputSize()) {
Expand Down Expand Up @@ -313,7 +314,7 @@ private static Canvas createCanvas(BillFormat format) throws IOException {
break;
case PDF:
canvas = new PDFCanvas(drawingWidth, drawingHeight,
format.getCharacterSet() != SPSCharacterSet.LATIN_1_SUBSET
bill.getCharacterSet() != SPSCharacterSet.LATIN_1_SUBSET
? PDFFontSettings.embeddedLiberationSans()
: PDFFontSettings.standardHelvetica());
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class QRCodeText {
private QRCodeText(Bill bill) {
this.bill = bill;
textBuilder = new StringBuilder();
dataSeparator = bill.getFormat().getQrDataSeparator() == QrDataSeparator.CR_LF ? "\r\n" : "\n";
dataSeparator = bill.getSeparator() == QrDataSeparator.CR_LF ? "\r\n" : "\n";
}

/**
Expand Down Expand Up @@ -141,7 +141,7 @@ public static Bill decode(String text) {

Bill bill = new Bill();
bill.setVersion(Bill.Version.V2_0);
bill.getFormat().setQrDataSeparator(text.contains("\r\n") ? QrDataSeparator.CR_LF : QrDataSeparator.LF);
bill.setSeparator(text.contains("\r\n") ? QrDataSeparator.CR_LF : QrDataSeparator.LF);

bill.setAccount(lines[3]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,9 @@ private static boolean replaceCodePoint(int codePoint, SPSCharacterSet character
String codePointString = new String(new int[] { codePoint }, 0, 1);

// check if canonical decomposition yields a valid string
String canoncial = decomposedString(codePointString, characterSet, Normalizer.Form.NFD);
if (canoncial != null) {
sb.append(canoncial);
String canonical = decomposedString(codePointString, characterSet, Normalizer.Form.NFD);
if (canonical != null) {
sb.append(canonical);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ private ValidationResult validateBill() {

billOut.setFormat(billIn.getFormat() != null ? new BillFormat(billIn.getFormat()) : null);
billOut.setVersion(billIn.getVersion());
billOut.setSeparator(billIn.getSeparator());
billOut.setCharacterSet(billIn.getCharacterSet());

validateAccountNumber();
validateCreditor();
Expand Down Expand Up @@ -403,15 +405,15 @@ private String clippedValue(String value, int maxLength, String fieldRoot, Strin

private String cleanedValue(String value, String fieldRoot, String subfield) {
CleaningResult result = new CleaningResult();
StringCleanup.cleanText(value, billOut.getFormat().getCharacterSet(), true, result);
StringCleanup.cleanText(value, billOut.getCharacterSet(), true, result);
if (result.replacedUnsupportedChars)
validationResult.addMessage(Type.WARNING, fieldRoot + subfield, ValidationConstants.KEY_REPLACED_UNSUPPORTED_CHARACTERS);
return result.cleanedString;
}

private String cleanedValue(String value, String fieldName) {
CleaningResult result = new CleaningResult();
StringCleanup.cleanText(value, billOut.getFormat().getCharacterSet(), true, result);
StringCleanup.cleanText(value, billOut.getCharacterSet(), true, result);
if (result.replacedUnsupportedChars)
validationResult.addMessage(Type.WARNING, fieldName, ValidationConstants.KEY_REPLACED_UNSUPPORTED_CHARACTERS);
return result.cleanedString;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void createA4PDFBill8a() {
@Test
void createA4PDFBill8b() {
Bill bill = SampleData.getExample8();
bill.getFormat().setCharacterSet(SPSCharacterSet.EXTENDED_LATIN);
bill.setCharacterSet(SPSCharacterSet.EXTENDED_LATIN);
generateAndCompareBill(bill, GraphicsFormat.PDF, "a4bill_ex8b.pdf");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,13 @@ void defaultValueTest() {
assertEquals(144, format.getResolution());
assertEquals(5.0, format.getMarginLeft());
assertEquals(5.0, format.getMarginRight());
assertEquals(QrDataSeparator.LF, format.getQrDataSeparator());
assertEquals(SPSCharacterSet.LATIN_1_SUBSET, format.getCharacterSet());
}

@Test
void hashCodeTest() {
BillFormat format1 = new BillFormat();
BillFormat format2 = new BillFormat();
assertEquals(format1.hashCode(), format2.hashCode());
format1.setCharacterSet(SPSCharacterSet.FULL_UNICODE);
assertNotEquals(format1.hashCode(), format2.hashCode());
}

@Test
void toStringTest() {
BillFormat format = new BillFormat();
String text = format.toString();
assertEquals("BillFormat{outputSize=QR_BILL_ONLY, language=EN, separatorType=DASHED_LINE_WITH_SCISSORS, fontFamily='Helvetica,Arial,\"Liberation Sans\"', graphicsFormat=SVG, resolution=144, marginLeft=5.0, marginRight=5.0, localCountryCode='CH', qrDataSeparator=LF, characterSet=LATIN_1_SUBSET}", text);
assertEquals("BillFormat{outputSize=QR_BILL_ONLY, language=EN, separatorType=DASHED_LINE_WITH_SCISSORS, fontFamily='Helvetica,Arial,\"Liberation Sans\"', graphicsFormat=SVG, resolution=144, marginLeft=5.0, marginRight=5.0, localCountryCode='CH'}", text);
}

@Test
Expand Down
Loading

0 comments on commit 4bd9cc7

Please sign in to comment.