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) { - - } -}