| 1 | package org.europa.together.application; | |
| 2 | ||
| 3 | import com.google.zxing.BarcodeFormat; | |
| 4 | import com.google.zxing.BinaryBitmap; | |
| 5 | import com.google.zxing.EncodeHintType; | |
| 6 | import com.google.zxing.MultiFormatReader; | |
| 7 | import com.google.zxing.MultiFormatWriter; | |
| 8 | import com.google.zxing.client.j2se.BufferedImageLuminanceSource; | |
| 9 | import com.google.zxing.client.j2se.MatrixToImageWriter; | |
| 10 | import com.google.zxing.common.BitMatrix; | |
| 11 | import com.google.zxing.common.HybridBinarizer; | |
| 12 | import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; | |
| 13 | import java.io.File; | |
| 14 | import java.io.FileInputStream; | |
| 15 | import java.nio.file.Paths; | |
| 16 | import java.time.LocalDateTime; | |
| 17 | import java.time.ZonedDateTime; | |
| 18 | import java.time.format.DateTimeFormatter; | |
| 19 | import java.util.HashMap; | |
| 20 | import java.util.Map; | |
| 21 | import javax.imageio.ImageIO; | |
| 22 | import org.europa.together.business.Logger; | |
| 23 | import org.europa.together.business.QrCodeGenerator; | |
| 24 | import org.europa.together.domain.LogLevel; | |
| 25 | import org.springframework.stereotype.Repository; | |
| 26 | ||
| 27 | /** | |
| 28 | * Implementation of the QR Code Generator. | |
| 29 | */ | |
| 30 | @Repository | |
| 31 | public class ZxingGenerator implements QrCodeGenerator { | |
| 32 | ||
| 33 | private static final long serialVersionUID = 7L; | |
| 34 | private static final Logger LOGGER = new LogbackLogger(ZxingGenerator.class); | |
| 35 | ||
| 36 | private final String charset; | |
| 37 | private int dimensionHeight; | |
| 38 | private int dimensionWidth; | |
| 39 | private String fileOutputPath; | |
| 40 | private final Map<EncodeHintType, Object> errorMap = new HashMap<>(); | |
| 41 | ||
| 42 | /** | |
| 43 | * Constructor. | |
| 44 | */ | |
| 45 | public ZxingGenerator() { | |
| 46 | errorMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); | |
| 47 | charset = "UTF-8"; | |
| 48 | LOGGER.log("instance class", LogLevel.INFO); | |
| 49 | } | |
| 50 | ||
| 51 | @Override | |
| 52 | public void setup(final String fileOutputPath, final int dimensions) { | |
| 53 | this.dimensionHeight = dimensions; | |
| 54 | this.dimensionWidth = dimensions; | |
| 55 | this.fileOutputPath = fileOutputPath; | |
| 56 | } | |
| 57 | ||
| 58 | @Override | |
| 59 | public String generateDataForvCard(final Map<String, String> contact) { | |
| 60 | String data = null; | |
| 61 |
2
1. generateDataForvCard : negated conditional → KILLED 2. generateDataForvCard : negated conditional → KILLED |
if (contact == null || contact.isEmpty()) { |
| 62 | LOGGER.log("Contact information are empty.", LogLevel.WARN); | |
| 63 | } else { | |
| 64 | LocalDateTime now = LocalDateTime.now(); | |
| 65 | String dateStr | |
| 66 | = now.format(DateTimeFormatter.ofPattern("yyyy-mm-dd hh:mm:ss")); | |
| 67 | data = "BEGIN:VCARD\n VERSION:3.0\n PROFILE:VCARD\n" | |
| 68 | + "N:" + contact.get("name") + ";" | |
| 69 | + contact.get("surname") + ";;" + contact.get("gender") + ";\n" | |
| 70 | + "FN:" + contact.get("surname") + " " + contact.get("name") + "\n" | |
| 71 | + "ORG:" + contact.get("organization") + "\n" | |
| 72 | + "TITLE:" + contact.get("title") + "\n" | |
| 73 | + "TEL;TYPE=WORK,CELL:" + contact.get("work-mobile") + "\n" | |
| 74 | + "TEL;TYPE=WORK,VOICE:" + contact.get("work-phone") + "\n" | |
| 75 | + "TEL;TYPE=HOME,CELL:" + contact.get("home-mobile") + "\n" | |
| 76 | + "TEL;TYPE=HOME,VOICE:" + contact.get("home-phone") + "\n" | |
| 77 | + "ADR;TYPE=WORK,PREF:;;" + contact.get("home-street") + ";" | |
| 78 | + contact.get("home-city") + ";" + contact.get("home-state") + ";" | |
| 79 | + contact.get("home-zipcode") + ";" + contact.get("home-country") + "\n" | |
| 80 | + "LABEL;TYPE=WORK,PREF:" + contact.get("work-street") + "\\n" | |
| 81 | + contact.get("work-city") + "\\, " + contact.get("work-state") + " " | |
| 82 | + contact.get("work-zipcode") + "\\n " + contact.get("work-country") + "\n" | |
| 83 | + "ADR;TYPE=WORK,PREF:;;" + contact.get("work-street") + ";" | |
| 84 | + contact.get("work-city") + ";" + contact.get("work-state") + ";" | |
| 85 | + contact.get("work-zipcode") + ";" + contact.get("work-country") + "\n" | |
| 86 | + "ADR;TYPE=HOME:;;" + contact.get("home-street") + ";" | |
| 87 | + contact.get("home-city") + ";" + contact.get("home-state") + ";" | |
| 88 | + contact.get("home-zipcode") + ";" + contact.get("home-country") + "\n" | |
| 89 | + "LABEL;TYPE=HOME:" + contact.get("home-street") + "\\n" | |
| 90 | + contact.get("home-city") + "\\, " + contact.get("home-state") + " " | |
| 91 | + contact.get("home-zipcode") + "\\n " + contact.get("home-country") + "\n" | |
| 92 | + "URL:" + contact.get("homepage") + "\n" | |
| 93 | + "EMAIL:" + contact.get("e-mail") + "\n" | |
| 94 | + "REV:" + dateStr + "\nEND:VCARD"; | |
| 95 | } | |
| 96 |
1
1. generateDataForvCard : replaced return value with "" for org/europa/together/application/ZxingGenerator::generateDataForvCard → KILLED |
return data; |
| 97 | } | |
| 98 | ||
| 99 | @Override | |
| 100 | public String generateDataForCalendarEvent(final String event, | |
| 101 | final ZonedDateTime start, final ZonedDateTime end) { | |
| 102 | String data = "BEGIN:VEVENT\n" | |
| 103 | + "SUMMARY:" + event | |
| 104 | + "\n DTSTART:" + start.format(DateTimeFormatter.ofPattern("yyyy-mm-dd hh:mm:ss")) | |
| 105 | + "\n DTEND: " + end.format(DateTimeFormatter.ofPattern("yyyy-mm-dd hh:mm:ss")) | |
| 106 | + "\n END:VEVENT"; | |
| 107 |
1
1. generateDataForCalendarEvent : replaced return value with "" for org/europa/together/application/ZxingGenerator::generateDataForCalendarEvent → KILLED |
return data; |
| 108 | } | |
| 109 | ||
| 110 | @Override | |
| 111 | public String generateDataForUrl(final String url) { | |
| 112 | String data = url.replace("//", ""); | |
| 113 |
1
1. generateDataForUrl : replaced return value with "" for org/europa/together/application/ZxingGenerator::generateDataForUrl → KILLED |
return "URLTO:" + data; |
| 114 | } | |
| 115 | ||
| 116 | @Override | |
| 117 | public String generateDataForGeoLocation(final String latitude, final String longitude) { | |
| 118 |
1
1. generateDataForGeoLocation : replaced return value with "" for org/europa/together/application/ZxingGenerator::generateDataForGeoLocation → KILLED |
return "geo:" + latitude + "," + longitude + ",100"; |
| 119 | } | |
| 120 | ||
| 121 | @Override | |
| 122 | public boolean encode(final String data) { | |
| 123 | boolean success = false; | |
| 124 | try { | |
| 125 | BitMatrix matrix = new MultiFormatWriter().encode( | |
| 126 | new String(data.getBytes(charset), charset), | |
| 127 | BarcodeFormat.QR_CODE, | |
| 128 | dimensionWidth, | |
| 129 | dimensionHeight, | |
| 130 | errorMap); | |
| 131 |
1
1. encode : removed call to com/google/zxing/client/j2se/MatrixToImageWriter::writeToPath → SURVIVED |
MatrixToImageWriter.writeToPath(matrix, "png", Paths.get(fileOutputPath)); |
| 132 | success = true; | |
| 133 | } catch (Exception ex) { | |
| 134 | LOGGER.catchException(ex); | |
| 135 | } | |
| 136 |
2
1. encode : replaced boolean return with false for org/europa/together/application/ZxingGenerator::encode → KILLED 2. encode : replaced boolean return with true for org/europa/together/application/ZxingGenerator::encode → KILLED |
return success; |
| 137 | } | |
| 138 | ||
| 139 | @Override | |
| 140 | public String decode(final File qrCode) { | |
| 141 | String decode = null; | |
| 142 | try { | |
| 143 | BinaryBitmap binaryBitmap | |
| 144 | = new BinaryBitmap( | |
| 145 | new HybridBinarizer( | |
| 146 | new BufferedImageLuminanceSource( | |
| 147 | ImageIO.read(new FileInputStream(qrCode))))); | |
| 148 | decode = new MultiFormatReader().decode(binaryBitmap).getText(); | |
| 149 | } catch (Exception ex) { | |
| 150 | LOGGER.catchException(ex); | |
| 151 | } | |
| 152 |
1
1. decode : replaced return value with "" for org/europa/together/application/ZxingGenerator::decode → KILLED |
return decode; |
| 153 | } | |
| 154 | } | |
Mutations | ||
| 61 |
1.1 2.2 |
|
| 96 |
1.1 |
|
| 107 |
1.1 |
|
| 113 |
1.1 |
|
| 118 |
1.1 |
|
| 131 |
1.1 |
|
| 136 |
1.1 2.2 |
|
| 152 |
1.1 |