diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 13566b8..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
deleted file mode 100644
index fdc392f..0000000
--- a/.idea/jarRepositories.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 62299b6..a23de2e 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -4,7 +4,5 @@
-
-
-
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..35eb1dd 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 58956bc..83eb2d5 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
-# VCardGenerator
+# Signature Card Generator
Worky thingy
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 823975f..d152bfa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,8 +3,8 @@ plugins {
id 'com.github.johnrengelman.shadow' version '5.2.0'
}
-group 'tech.nevets.vcardgen'
-version '1.1'
+group 'tech.nevets'
+version '2.0.0'
repositories {
mavenCentral()
@@ -20,7 +20,7 @@ dependencies {
jar {
manifest {
attributes(
- 'Main-Class': 'tech.nevets.vcardgen.Main'
+ 'Main-Class': 'tech.nevets.signaturecardgen.Main'
)
}
}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index b578887..b32f466 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,2 @@
-rootProject.name = 'VCardGenerator'
+rootProject.name = 'SignatureCardGenerator'
diff --git a/src/main/java/tech/nevets/vcardgen/Card.java b/src/main/java/tech/nevets/signaturecardgen/Card.java
similarity index 62%
rename from src/main/java/tech/nevets/vcardgen/Card.java
rename to src/main/java/tech/nevets/signaturecardgen/Card.java
index 94643b9..4b2a7f3 100644
--- a/src/main/java/tech/nevets/vcardgen/Card.java
+++ b/src/main/java/tech/nevets/signaturecardgen/Card.java
@@ -1,18 +1,13 @@
-package tech.nevets.vcardgen;
+package tech.nevets.signaturecardgen;
-import com.google.gson.Gson;
import com.google.gson.JsonObject;
import javax.imageio.*;
-import javax.imageio.metadata.IIOMetadata;
-import javax.imageio.metadata.IIOMetadataNode;
-import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
-//TODO Clear layer when new data is written...
public class Card {
public static final Map CARD_SESSIONS = new HashMap<>();
@@ -30,18 +25,17 @@ public class Card {
private static final Font ARIAL38I = new Font("Arial", Font.ITALIC, 38);
// ---------------- LAYERS ---------------- //
- private BufferedImage background;
- private BufferedImage nameLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
- private BufferedImage titleLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
- private BufferedImage emailLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
- private BufferedImage locationLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
- private BufferedImage phoneNumbersLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
+ private final BufferedImage background;
+ private final BufferedImage nameLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
+ private final BufferedImage titleLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
+ private final BufferedImage emailLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
+ private final BufferedImage locationLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
+ private final BufferedImage phoneNumbersLayer = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
// ---------------- Working Images ---------------- //
private Graphics2D graphics;
- private BufferedImage rawImage = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
+ private final BufferedImage rawImage = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
private BufferedImage workingImage = new BufferedImage(1080, 602, BufferedImage.TYPE_INT_ARGB);
- private IIOImage finalImage;
// ---------------- DATA ---------------- //
public final String id;
@@ -53,14 +47,13 @@ public class Card {
private String directNumber;
private String cellNumber;
private int size;
- private boolean hasLongAddress;
private boolean hasDirectNumber;
private boolean hasCellNumber;
/**
* Constructs an empty card.
- * Calls:
{@link tech.nevets.vcardgen.Card#Card(String, String, String, String, String, String, String, int)} with empty strings and full size image
+ * Calls:
{@link tech.nevets.signaturecardgen.Card#Card(String, String, String, String, String, String, String, int)} with empty strings and full size image
*/
public Card() {
this("", "", "", "", "", "", "", 1);
@@ -68,19 +61,19 @@ public class Card {
/**
* Constructor that fills out entire Card details.
- * Calls:
{@link tech.nevets.vcardgen.Card#Card(String, String, String, String, String, String, String, int)}
+ * Calls:
{@link tech.nevets.signaturecardgen.Card#Card(String, String, String, String, String, String, String, int)}
* @param json Json object from frontend
*/
public Card(JsonObject json) {
this(
- json.get("name").getAsString(), //name
- json.get("title").getAsString(), //title
- json.get("email").getAsString(), //email
- json.get("locationId").getAsString(), //locationId
- json.get("extension").getAsString(), //extension
- json.get("directNumber").getAsString(), //directNumber
- json.get("cellNumber").getAsString(), //cellNumber
- json.get("size").getAsInt() //size
+ json.get("name").getAsString(),
+ json.get("title").getAsString(),
+ json.get("email").getAsString(),
+ json.get("locationId").getAsString(),
+ json.get("extension").getAsString(),
+ json.get("directNumber").getAsString(),
+ json.get("cellNumber").getAsString(),
+ json.get("size").getAsInt()
);
}
@@ -90,8 +83,8 @@ public class Card {
* @param title User's Title
* @param email User's Email
* @param locationId User's Location ID
- * @param extension User's Extension (can be empty if {@link tech.nevets.vcardgen.Card#directNumber} is populated)
- * @param directNumber User's Direct Number (can be empty if {@link tech.nevets.vcardgen.Card#extension} is populated)
+ * @param extension User's Extension (can be empty if {@link tech.nevets.signaturecardgen.Card#directNumber} is populated)
+ * @param directNumber User's Direct Number (can be empty if {@link tech.nevets.signaturecardgen.Card#extension} is populated)
* @param cellNumber User's Cell Phone Number (can be empty)
* @param size Size to set the Card to (0 for Outlook 2016 size, 1 for full size)
*/
@@ -144,21 +137,31 @@ public class Card {
hasCellNumber = cellNumber.length() > 0;
}
+ public void setSize(int size) {
+ this.size = size;
+ }
+
public BufferedImage getBackground() {
return background;
}
- private BufferedImage renderLayer(BufferedImage layer, String content, Color textColor, Font font, int x, int y) {
+ private void clearLayer(BufferedImage layer) {
+ Graphics2D g = layer.createGraphics();
+ g.setComposite(AlphaComposite.Clear);
+ g.fillRect(0, 0, 1080, 602);
+ g.dispose();
+ }
+
+ private void renderLayer(BufferedImage layer, String content, Color textColor, Font font, int x, int y) {
graphics = layer.createGraphics();
setAntiAlias(graphics);
graphics.setColor(textColor);
graphics.setFont(font);
graphics.drawString(content, x, y);
graphics.dispose();
- return layer;
}
- private BufferedImage renderResizableLayer(BufferedImage layer, String content, Color textColor, int maxLength, Font defaultFont, Font smallFont, int x, int y) {
+ private void renderResizableLayer(BufferedImage layer, String content, Color textColor, int maxLength, Font defaultFont, Font smallFont, int x, int y) {
graphics = layer.createGraphics();
setAntiAlias(graphics);
graphics.setColor(textColor);
@@ -166,19 +169,24 @@ public class Card {
else graphics.setFont(smallFont);
graphics.drawString(content, x, y);
graphics.dispose();
- return layer;
}
public BufferedImage renderNameLayer() {
- return renderResizableLayer(nameLayer, name, WHITE, 970, ARIAL65, ARIAL55, 85, 112);
+ clearLayer(nameLayer);
+ renderResizableLayer(nameLayer, name, WHITE, 970, ARIAL65, ARIAL55, 85, 112);
+ return nameLayer;
}
public BufferedImage renderTitleLayer() {
- return renderResizableLayer(titleLayer, title, WHITE, 970, ARIAL45I, ARIAL40I, 89, 176);
+ clearLayer(titleLayer);
+ renderResizableLayer(titleLayer, title, WHITE, 970, ARIAL45I, ARIAL40I, 89, 176);
+ return titleLayer;
}
public BufferedImage renderEmailLayer() {
- return renderLayer(emailLayer, email, WHITE, ARIAL45, 62, (380 - getOffsets(0)));
+ clearLayer(emailLayer);
+ renderLayer(emailLayer, email, WHITE, ARIAL45, 62, (380 + getOffsets(0)));
+ return emailLayer;
}
public BufferedImage renderLocationLayer() {
@@ -203,15 +211,18 @@ public class Card {
sb.insert(newLineIndex - 2, "\n");
sb.deleteCharAt(sb.length() - 1);
}
- renderLayer(locationLayer, location.getName(), GREEN, ARIAL44I, 59, (447 - getOffsets(0)));
- return renderLayer(locationLayer, sb.toString(), GREEN, ARIAL38I, 59, (491 - getOffsets(0)));
+ clearLayer(locationLayer);
+ renderLayer(locationLayer, location.getName(), GREEN, ARIAL44I, 59, (447 + getOffsets(0)));
+ renderLayer(locationLayer, sb.toString(), GREEN, ARIAL38I, 59, (491 + getOffsets(0)));
+ return locationLayer;
}
public BufferedImage renderPhoneNumbersLayer() {
+ clearLayer(phoneNumbersLayer);
if (hasDirectNumber) {
- renderLayer(phoneNumbersLayer, ("W: " + directNumber), GREEN, ARIAL38I, 59, (540 - getOffsets(1)));
+ renderLayer(phoneNumbersLayer, ("W: " + directNumber), GREEN, ARIAL38I, 59, (540 + getOffsets(1)));
} else {
- renderLayer(phoneNumbersLayer, ("W: " + location.getNumber() + " x" + extension), GREEN, ARIAL38I, 59, (540 - getOffsets(1)));
+ renderLayer(phoneNumbersLayer, ("W: " + location.getNumber() + " x" + extension), GREEN, ARIAL38I, 59, (540 + getOffsets(1)));
}
if (hasCellNumber) {
renderLayer(phoneNumbersLayer, ("C: " + cellNumber), GREEN, ARIAL38I, 59, 540);
@@ -220,15 +231,15 @@ public class Card {
}
public void renderImage() {
+ clearLayer(rawImage);
graphics = rawImage.createGraphics();
- setAntiAlias(graphics);
graphics.drawImage(background, 0, 0, null);
- graphics.drawImage(renderNameLayer(), 0, 0, null);
- graphics.drawImage(renderTitleLayer(), 0, 0, null);
- graphics.drawImage(renderEmailLayer(), 0, 0, null);
- graphics.drawImage(renderLocationLayer(), 0, 0, null);
- graphics.drawImage(renderPhoneNumbersLayer(), 0, 0, null);
+ graphics.drawImage(nameLayer, 0, 0, null);
+ graphics.drawImage(titleLayer, 0, 0, null);
+ graphics.drawImage(emailLayer, 0, 0, null);
+ graphics.drawImage(locationLayer, 0, 0, null);
+ graphics.drawImage(phoneNumbersLayer, 0, 0, null);
graphics.dispose();
resizeImage();
@@ -241,7 +252,7 @@ public class Card {
*/
private int getOffsets(int type) {
int totalOffset = 0;
- int doubleNumberOffset = hasDirectNumber ? 40 : 0;
+ int doubleNumberOffset = hasCellNumber ? 40 : 0;
int longAddrOffset = fitsDimensions(location.getAddress(), ARIAL38I, 700) ? 0 : 40;
switch (type) {
case 0 -> {
@@ -277,31 +288,9 @@ public class Card {
return resizedImage;
}
- public void addMetadata() throws IOException {
+ public byte[] toByteArray() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(workingImage, "png", baos);
-
- ImageReader reader = ImageIO.getImageReadersByMIMEType("image/png").next();
- reader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(baos.toByteArray())));
- finalImage = reader.readAll(0, null);
-
- IIOMetadataNode text = new IIOMetadataNode("tEXt");
- IIOMetadataNode textEntry = new IIOMetadataNode("tEXtEntry");
- textEntry.setAttribute("contents", toMetaString(this));
- text.appendChild(textEntry);
- IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");
- root.appendChild(text);
-
- finalImage.getMetadata().mergeTree("javax_imageio_png_1.0", root);
- }
-
- public byte[] toByteArray() throws IOException {
- addMetadata();
- ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/png").next();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
- writer.setOutput(ios);
- writer.write(finalImage);
return baos.toByteArray();
}
@@ -317,38 +306,6 @@ public class Card {
return C.getFontMetrics(font).stringWidth(text);
}
- public static String toMetaString(Card card) {
- return "name=" + card.name + ";" +
- "title=" + card.title + ";" +
- "email=" + card.email + ";" +
- "locationId=" + card.location.getId() + ";" +
- "extension=" + card.extension + ";" +
- "directNumber=" + card.directNumber + ";" +
- "cellNumber=" + card.cellNumber + ";";
- }
-
- public static String getDataFromVCard(InputStream rawImage) throws IOException {
- ImageReader reader = ImageIO.getImageReadersByMIMEType("image/png").next();
- reader.setInput(ImageIO.createImageInputStream(rawImage));
-
- IIOMetadata metadata = reader.getImageMetadata(0);
- IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree("javax_imageio_png_1.0");
- IIOMetadataNode text = (IIOMetadataNode) root.getElementsByTagName("tEXt").item(0);
- if (text == null) {
- return "$null";
- }
-
- Map keyValueMap = new HashMap<>();
- String contents = ((IIOMetadataNode) text.item(0)).getAttribute("contents");
- String[] contentSplit = contents.split(";");
- for (String entry : contentSplit) {
- String[] kvPair = entry.split("=");
- keyValueMap.put(kvPair[0], kvPair[1]);
- }
-
- return new Gson().toJson(keyValueMap);
- }
-
private static String getUniqueId() {
String uuid = UUID.randomUUID().toString().split("-")[4];
while (true) {
diff --git a/src/main/java/tech/nevets/signaturecardgen/GenerateRoute.java b/src/main/java/tech/nevets/signaturecardgen/GenerateRoute.java
new file mode 100644
index 0000000..55ec8eb
--- /dev/null
+++ b/src/main/java/tech/nevets/signaturecardgen/GenerateRoute.java
@@ -0,0 +1,46 @@
+package tech.nevets.signaturecardgen;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import spark.Request;
+import spark.Response;
+import spark.Route;
+
+import java.io.IOException;
+
+public class GenerateRoute implements Route {
+ @Override
+ public Object handle(Request req, Response res) {
+ Card card;
+ String id = req.queryParams("id");
+ if (!id.isEmpty()) {
+ card = Card.CARD_SESSIONS.get(id);
+ if (card == null) {
+ res.type("text/plain");
+ res.status(404);
+ return "Card with that id not found.";
+ }
+ } else {
+ JsonObject data;
+ try {
+ data = new Gson().fromJson(req.body(), JsonObject.class);
+ } catch (JsonSyntaxException e) {
+ res.status(422);
+ return "Not valid json: " + e.getMessage();
+ }
+ System.out.println("JSON Data: " + data.toString());
+ card = new Card(data);
+ }
+ card.renderImage();
+
+ res.type("image/png");
+ try {
+ res.status(200);
+ return card.toByteArray();
+ } catch (IOException e) {
+ res.status(500);
+ return "Error getting image stream: " + e.getMessage();
+ }
+ }
+}
diff --git a/src/main/java/tech/nevets/vcardgen/LiveGenWebSocket.java b/src/main/java/tech/nevets/signaturecardgen/LiveGenWebSocket.java
similarity index 91%
rename from src/main/java/tech/nevets/vcardgen/LiveGenWebSocket.java
rename to src/main/java/tech/nevets/signaturecardgen/LiveGenWebSocket.java
index 43785e9..a1c843a 100644
--- a/src/main/java/tech/nevets/vcardgen/LiveGenWebSocket.java
+++ b/src/main/java/tech/nevets/signaturecardgen/LiveGenWebSocket.java
@@ -1,4 +1,4 @@
-package tech.nevets.vcardgen;
+package tech.nevets.signaturecardgen;
import org.eclipse.jetty.websocket.api.*;
import org.eclipse.jetty.websocket.api.annotations.*;
@@ -25,21 +25,25 @@ public class LiveGenWebSocket {
@OnWebSocketError
public void error(Session session, Throwable throwable) {
- throwable.printStackTrace();
+ if (throwable instanceof CloseException) {
+ System.out.println("Connection with session address " + session.getRemoteAddress() + " closed");
+ } else {
+ throwable.printStackTrace();
+ }
}
@OnWebSocketMessage
public void message(Session session, String message) throws IOException {
RemoteEndpoint client = session.getRemote();
- System.out.println(message);
+ System.out.println("WS Msg: " + message);
String[] splitMsg = message.split(";");
String messageType = splitMsg[0];
if (splitMsg.length == 1) {
if (messageType.equals("start")) {
card = new Card();
- client.sendString("success;Card successfully created.");
+ client.sendString("success;" + card.id);
}
return;
}
diff --git a/src/main/java/tech/nevets/vcardgen/Location.java b/src/main/java/tech/nevets/signaturecardgen/Location.java
similarity index 90%
rename from src/main/java/tech/nevets/vcardgen/Location.java
rename to src/main/java/tech/nevets/signaturecardgen/Location.java
index cb7ab8b..eb2288e 100644
--- a/src/main/java/tech/nevets/vcardgen/Location.java
+++ b/src/main/java/tech/nevets/signaturecardgen/Location.java
@@ -1,4 +1,4 @@
-package tech.nevets.vcardgen;
+package tech.nevets.signaturecardgen;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
@@ -53,6 +53,7 @@ public class Location {
URL backgroundURL = this.getClass().getResource("/backgrounds/" + id + ".png");
if (backgroundURL == null) backgroundURL = this.getClass().getResource("/backgrounds/default.png");
try {
+ assert backgroundURL != null;
background = ImageIO.read(backgroundURL);
} catch (IOException e) {
e.printStackTrace();
@@ -86,13 +87,4 @@ public class Location {
}
return new Location("", "", "", "");
}
-
- public static String getLocationId(String name) {
- for (Location loc : LOCATIONS) {
- if (loc.getName().equals(name)) {
- return loc.getId();
- }
- }
- return null;
- }
}
\ No newline at end of file
diff --git a/src/main/java/tech/nevets/vcardgen/Main.java b/src/main/java/tech/nevets/signaturecardgen/Main.java
similarity index 94%
rename from src/main/java/tech/nevets/vcardgen/Main.java
rename to src/main/java/tech/nevets/signaturecardgen/Main.java
index a565964..7621a41 100644
--- a/src/main/java/tech/nevets/vcardgen/Main.java
+++ b/src/main/java/tech/nevets/signaturecardgen/Main.java
@@ -1,4 +1,4 @@
-package tech.nevets.vcardgen;
+package tech.nevets.signaturecardgen;
import java.io.*;
@@ -39,8 +39,6 @@ public class Main {
post("/generate", new GenerateRoute());
-
- post("/edit", new EditRoute());
});
}
}
diff --git a/src/main/java/tech/nevets/vcardgen/EditRoute.java b/src/main/java/tech/nevets/vcardgen/EditRoute.java
deleted file mode 100644
index 0a9e5f7..0000000
--- a/src/main/java/tech/nevets/vcardgen/EditRoute.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package tech.nevets.vcardgen;
-
-import spark.Request;
-import spark.Response;
-import spark.Route;
-
-import javax.servlet.MultipartConfigElement;
-import javax.servlet.http.Part;
-import java.io.IOException;
-
-public class EditRoute implements Route {
- @Override
- public Object handle(Request req, Response res) {
- req.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp"));
- Part cardFile;
- try {
- cardFile = req.raw().getPart("card");
- } catch (Exception e) {
- res.status(500);
- return "Error processing file: " + e.getMessage();
- }
- if (cardFile.getSize() > 1000000) {
- res.status(413);
- return "File too large";
- }
- if (!cardFile.getContentType().equalsIgnoreCase("image/png")) {
- res.status(415);
- return "Content is not of type image/png";
- }
- String cardData;
- try {
- cardData = Card.getDataFromVCard(cardFile.getInputStream());
- } catch (IOException e) {
- res.status(500);
- return "Error retrieving data from card" + e.getMessage();
- }
- if (cardData.equals("$null")) {
- res.status(422);
- return "Card does not contain required metadata";
- }
- res.type("application/json");
- res.status(200);
- return cardData;
- }
-}
diff --git a/src/main/java/tech/nevets/vcardgen/GenerateRoute.java b/src/main/java/tech/nevets/vcardgen/GenerateRoute.java
deleted file mode 100644
index b1a5fdf..0000000
--- a/src/main/java/tech/nevets/vcardgen/GenerateRoute.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package tech.nevets.vcardgen;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSyntaxException;
-import spark.Request;
-import spark.Response;
-import spark.Route;
-
-import java.io.IOException;
-
-public class GenerateRoute implements Route {
- private Card card;
- @Override
- public Object handle(Request req, Response res) {
- JsonObject data;
- try {
- data = new Gson().fromJson(req.body(), JsonObject.class);
- } catch (JsonSyntaxException e) {
- res.status(422);
- return "Not valid json: " + e.getMessage();
- }
- card = new Card(data);
- card.renderImage();
-
- res.type("image/png");
- res.header("Access-Control-Expose-Headers", "Id");
- res.header("Id", card.id);
- try {
- res.status(200);
- return card.toByteArray();
- } catch (IOException e) {
- res.status(500);
- return "Error getting image stream: " + e.getMessage();
- }
- }
-}
diff --git a/src/main/java/tech/nevets/vcardgen/TestMain.java b/src/main/java/tech/nevets/vcardgen/TestMain.java
deleted file mode 100644
index 3544aa8..0000000
--- a/src/main/java/tech/nevets/vcardgen/TestMain.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package tech.nevets.vcardgen;
-
-public class TestMain {
- public static void main(String[] args) {
-
- }
-}