Added automatic checking for Nicu's docker server

This commit is contained in:
Daniel
2024-10-05 02:17:06 +03:00
parent dcafe73f86
commit 4e53276e88
20 changed files with 792 additions and 21 deletions

5
.idea/misc.xml generated
View File

@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<writeAnnotations>
<writeAnnotation name="org.lumijiez.serializer.LumiSerializeField" />
</writeAnnotations>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">

124
.idea/uiDesigner.xml generated Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

1
filtered.json Normal file

File diff suppressed because one or more lines are too long

1
filtered.xml Normal file

File diff suppressed because one or more lines are too long

1
new.json Normal file

File diff suppressed because one or more lines are too long

1
new.xml Normal file

File diff suppressed because one or more lines are too long

View File

@@ -13,5 +13,5 @@
<maven.compiler.target>23</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@@ -1,17 +1,35 @@
package org.lumijiez;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static void main(String[] args) {
//TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
// to see how IntelliJ IDEA suggests fixing it.
System.out.printf("Hello and welcome!");
import org.lumijiez.models.FilteredProducts;
import org.lumijiez.models.Product;
import org.lumijiez.network.TCPClient;
import org.lumijiez.parsers.DarwinParser;
import org.lumijiez.parsers.DarwinProductParser;
import org.lumijiez.parsers.DarwinProductProcessor;
import org.lumijiez.serializer.Lumi;
for (int i = 1; i <= 5; i++) {
//TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
System.out.println("i = " + i);
}
import java.util.List;
public class Main {
public static void main(String[] args) throws Exception {
String host = "https://darwin.md/search?search=apple&page=1";
String response = TCPClient.getHttps(host);
String productList = DarwinParser.extractProductList(response);
List<Product> products = DarwinProductParser.parseProducts(productList);
FilteredProducts filtered = DarwinProductProcessor.processProducts(products, 0, 1000000);
Lumi.jsonToFile(filtered, "filtered.json");
Lumi.xmlToFile(filtered, "filtered.xml");
System.out.println(TCPClient.checkJson(Lumi.toJson(filtered)));
System.out.println(TCPClient.checkXml(Lumi.toXml(filtered)));
// Serialization/Deserialization Test
System.out.println(
Lumi.toXml(
Lumi.fromJson(
Lumi.toJson(products.getFirst()), Product.class)));
}
}

View File

@@ -1,4 +1,19 @@
package org.lumijiez.models;
import org.lumijiez.serializer.LumiSerializable;
import org.lumijiez.serializer.LumiSerializeField;
import java.util.Date;
import java.util.List;
@LumiSerializable
public class FilteredProducts {
@LumiSerializeField
public List<Product> products;
@LumiSerializeField
public Date date;
@LumiSerializeField
public float price;
}

View File

@@ -1,4 +1,45 @@
package org.lumijiez.models;
import org.lumijiez.serializer.LumiSerializable;
import org.lumijiez.serializer.LumiSerializeField;
@LumiSerializable
public class Product {
@LumiSerializeField
public String id;
@LumiSerializeField
public String name;
@LumiSerializeField
public String imageUrl;
@LumiSerializeField
public String specifications;
@LumiSerializeField
public String oldPrice;
@LumiSerializeField
public String newPrice;
@LumiSerializeField
public String discount;
@LumiSerializeField
public String productLink;
public Product() {}
public Product(String id, String name, String imageUrl, String specifications, String oldPrice, String newPrice, String discount, String productLink) {
this.id = id;
this.name = name;
this.imageUrl = imageUrl;
this.specifications = specifications;
this.oldPrice = oldPrice;
this.newPrice = newPrice;
this.discount = discount;
this.productLink = productLink;
}
}

View File

@@ -1,4 +1,93 @@
package org.lumijiez.network;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class TCPClient {
}
public static String getHttps(String url) {
try {
URI uri = new URI(url);
String host = uri.getHost();
String path = uri.getRawPath();
String query = uri.getRawQuery();
int port = uri.getPort() == -1 ? 443 : uri.getPort();
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setEnabledProtocols(socket.getSupportedProtocols());
socket.startHandshake();
String requestPath = path + (query != null ? "?" + query : "");
String request =
"GET " + requestPath + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n";
return socketIo(socket, request);
} catch (IOException | URISyntaxException e) {
throw new RuntimeException(e);
}
}
public static String checkJson(String jsonData) {
return sendData("application/json", jsonData);
}
public static String checkXml(String xmlData) {
return sendData("application/xml", xmlData);
}
private static String sendData(String contentType, String data) {
try {
URI uri = new URI("http://localhost:8000/upload");
String host = uri.getHost();
int port = uri.getPort() == -1 ? 80 : uri.getPort();
Socket socket = new Socket(host, port);
String username = "500";
String password = "408";
String auth = username + ":" + password;
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
String request =
"POST " + uri.getPath() + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Content-Type: " + contentType + "\r\n" +
"Content-Length: " + data.getBytes(StandardCharsets.UTF_8).length + "\r\n" +
"Authorization: Basic " + encodedAuth + "\r\n" +
"Connection: close\r\n\r\n" +
data;
String response = socketIo(socket, request);
return "Status Code: " + response.split("\n")[0].split(" ")[1];
} catch (IOException | URISyntaxException e) {
throw new RuntimeException(e);
}
}
private static String socketIo(Socket socket, String request) throws IOException {
OutputStream outputStream = socket.getOutputStream();
outputStream.write(request.getBytes());
outputStream.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line).append("\n");
}
reader.close();
socket.close();
return response.toString();
}
}

View File

@@ -1,4 +1,44 @@
package org.lumijiez.parsers;
public class DarwinParser {
}
public static String extractProductList(String html) {
String divStart = "<div class=\"item-products ga-list\" data-list-name=\"Căutare\">";
String divEnd = "</div>";
int startIndex = html.indexOf(divStart);
if (startIndex == -1) {
return "Product list div not found";
}
int endIndex = -1;
int nestedLevel = 1;
int searchStartIndex = startIndex + divStart.length();
while (nestedLevel > 0 && searchStartIndex < html.length()) {
int nextDivStart = html.indexOf("<div", searchStartIndex);
int nextDivEnd = html.indexOf(divEnd, searchStartIndex);
if (nextDivEnd == -1) {
return "Malformed HTML: couldn't find closing div";
}
if (nextDivStart != -1 && nextDivStart < nextDivEnd) {
nestedLevel++;
searchStartIndex = nextDivStart + 1;
} else {
nestedLevel--;
if (nestedLevel == 0) {
endIndex = nextDivEnd + divEnd.length();
} else {
searchStartIndex = nextDivEnd + 1;
}
}
}
if (endIndex == -1) {
return "Malformed HTML: couldn't find matching closing div";
}
return html.substring(startIndex, endIndex);
}
}

View File

@@ -1,4 +1,68 @@
package org.lumijiez.parsers;
import org.lumijiez.models.Product;
import org.lumijiez.network.TCPClient;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DarwinProductParser {
public static List<Product> parseProducts(String html) {
List<Product> products = new ArrayList<>();
String productPattern = "<div class=\"col-6 col-md-4 col-lg-3 night-mode\">.*?</div>\\s*</figure>\\s*</div>";
Pattern pattern = Pattern.compile(productPattern, Pattern.DOTALL);
Matcher matcher = pattern.matcher(html);
while (matcher.find()) {
String productHtml = matcher.group();
Product product = extractProductInfo(productHtml);
if (product != null) {
products.add(product);
}
}
return products;
}
private static Product extractProductInfo(String productHtml) {
String name = extractWithRegex(productHtml, "title=\"([^\"]+)\"\\s+class=\"ga-item\"");
String imageUrl = extractWithRegex(productHtml, "src=\"([^\"]+)\"");
String specifications = extractWithRegex(productHtml, "<span class=\"specification d-block\">([^<]+)</span>");
String oldPrice = extractWithRegex(productHtml, "<span class=\"last-price\">([^<]+)</span>");
String newPrice = extractWithRegex(productHtml, "<span class=\"price-new\"><b>([^<]+)</b>");
String discount = extractWithRegex(productHtml, "<span class=\"difprice aclas\" title=\"([^\"]+)\">");
String productLink = extractWithRegex(productHtml, "href=\"([^\"]+)\"\\s+title=\"[^\"]+\"\\s+class=\"ga-item\"");
String id = extractId(productLink);
if (name == null || newPrice == null) {
return null;
}
return new Product(id, name, imageUrl, specifications, oldPrice, newPrice, discount, productLink);
}
private static String extractWithRegex(String input, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
return matcher.group(1).trim();
}
return null;
}
private static String extractId(String productLink) {
String body = TCPClient.getHttps(productLink);
String regex = "ID produs:\\s*<strong[^>]*>\\s*(\\d{2}\\.\\d{8}\\.\\d{3})\\s*</strong>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(body);
if (matcher.find()) {
return matcher.group(1);
}
return "0";
}
}

View File

@@ -1,4 +1,81 @@
package org.lumijiez.parsers;
import org.lumijiez.models.FilteredProducts;
import org.lumijiez.models.Product;
import java.text.NumberFormat;
import java.text.ParseException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
public class DarwinProductProcessor {
}
public static FilteredProducts processProducts(List<Product> products, float minPrice, float maxPrice) {
List<Product> filteredProducts = products.stream()
.map(DarwinProductProcessor::convertPricesToEUR)
.filter(product -> isInPriceRange(product, minPrice, maxPrice))
.collect(Collectors.toList());
float totalPrice = filteredProducts.stream()
.map(DarwinProductProcessor::getPrice)
.reduce(0f, Float::sum);
FilteredProducts result = new FilteredProducts();
result.products = filteredProducts;
result.date = Date.from(Instant.now());
result.price = totalPrice;
return result;
}
private static Product convertPricesToEUR(Product product) {
product.oldPrice = convertToEUR(product.oldPrice);
product.newPrice = convertToEUR(product.newPrice);
product.discount = convertToEUR(product.discount);
return product;
}
private static String convertToEUR(String priceInMDL) {
if (priceInMDL == null || priceInMDL.isEmpty()) {
return null;
}
try {
NumberFormat format = NumberFormat.getInstance(Locale.forLanguageTag("ro-RO"));
Number number = format.parse(priceInMDL.replaceAll("[^\\d]", ""));
float price = number.floatValue();
return String.format("%.2f EUR", price / 19);
} catch (ParseException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
return null;
}
}
private static boolean isInPriceRange(Product product, float minPrice, float maxPrice) {
float price = getPrice(product);
return price >= minPrice && price <= maxPrice;
}
private static float getPrice(Product product) {
if (product.newPrice != null) {
return parsePrice(product.newPrice);
}
return 0f;
}
private static float parsePrice(String priceInEUR) {
if (priceInEUR == null) {
return 0f;
}
try {
String numericPart = priceInEUR.replaceAll("[^\\d.]", "");
return Float.parseFloat(numericPart);
} catch (NumberFormatException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
return 0f;
}
}
}

View File

@@ -1,4 +1,32 @@
package org.lumijiez.serializer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
public class JsonFileWriter {
}
public static void saveJsonToFile(Object objectToSerialize, String filePath) throws IllegalAccessException {
String jsonOutput = Lumi.toJson(objectToSerialize);
File file = new File(filePath);
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(jsonOutput);
System.out.println("JSON saved to " + filePath);
} catch (IOException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
}
}
}
}
}

View File

@@ -0,0 +1,217 @@
package org.lumijiez.serializer;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Lumi {
public static String toJson(Object obj) throws IllegalAccessException {
if (!obj.getClass().isAnnotationPresent(LumiSerializable.class)) {
throw new IllegalArgumentException("Class is not marked as LumiSerializable");
}
StringBuilder json = new StringBuilder("{");
Field[] fields = obj.getClass().getDeclaredFields();
List<String> serializedFields = new ArrayList<>();
for (Field field : fields) {
if (field.isAnnotationPresent(LumiSerializeField.class)) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(obj);
serializedFields.add("\"" + fieldName + "\":" + valueToJson(value));
}
}
json.append(String.join(",", serializedFields));
json.append("}");
return json.toString();
}
private static String valueToJson(Object value) {
if (value == null) {
return "null";
} else if (value instanceof String) {
return "\"" + escapeJsonString((String) value) + "\"";
} else if (value instanceof Number || value instanceof Boolean) {
return value.toString();
} else if (value instanceof List) {
return listToJson((List<?>) value);
} else if (value instanceof Date) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
return "\"" + dateFormat.format((Date) value) + "\"";
} else {
try {
return toJson(value);
} catch (IllegalAccessException e) {
return "\"" + value + "\"";
}
}
}
private static String listToJson(List<?> list) {
List<String> jsonItems = new ArrayList<>();
for (Object item : list) {
jsonItems.add(valueToJson(item));
}
return "[" + String.join(",", jsonItems) + "]";
}
private static String escapeJsonString(String input) {
return input.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
public static String toXml(Object obj) throws IllegalAccessException {
if (!obj.getClass().isAnnotationPresent(LumiSerializable.class)) {
throw new IllegalArgumentException("Class is not marked as LumiSerializable");
}
StringBuilder xml = new StringBuilder("<" + obj.getClass().getSimpleName() + ">");
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(LumiSerializeField.class)) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(obj);
xml.append(valueToXml(fieldName, value));
}
}
xml.append("</").append(obj.getClass().getSimpleName()).append(">");
return xml.toString();
}
private static String valueToXml(String fieldName, Object value) {
StringBuilder xml = new StringBuilder("<" + fieldName + ">");
if (value == null) {
xml.append("null");
} else if (value instanceof String || value instanceof Number || value instanceof Boolean) {
xml.append(escapeXmlString(value.toString()));
} else if (value instanceof List) {
xml.append(listToXml((List<?>) value));
} else if (value instanceof Date) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
xml.append(escapeXmlString(dateFormat.format((Date) value)));
} else if (value instanceof java.time.LocalDate) {
xml.append(escapeXmlString(((java.time.LocalDate) value).toString()));
} else if (value instanceof java.time.LocalDateTime) {
xml.append(escapeXmlString(((java.time.LocalDateTime) value).toString()));
} else if (value instanceof java.time.ZonedDateTime) {
xml.append(escapeXmlString(((java.time.ZonedDateTime) value).toString()));
} else {
try {
xml.append(toXml(value));
} catch (IllegalAccessException e) {
xml.append(escapeXmlString(value.toString()));
}
}
xml.append("</").append(fieldName).append(">");
return xml.toString();
}
private static String listToXml(List<?> list) {
StringBuilder xml = new StringBuilder();
for (Object item : list) {
xml.append("<item>");
xml.append(valueToXml("value", item));
xml.append("</item>");
}
return xml.toString();
}
private static String escapeXmlString(String input) {
return input.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;")
.replace("'", "&apos;");
}
public static <T> T fromJson(String json, Class<T> clazz) throws Exception {
if (!clazz.isAnnotationPresent(LumiSerializable.class)) {
throw new IllegalArgumentException("Class is not marked as LumiSerializable");
}
T obj = clazz.getDeclaredConstructor().newInstance();
Pattern pattern = Pattern.compile("\"(\\w+)\"\\s*:\\s*(.+?)(?=,\\s*\"|\\})");
Matcher matcher = pattern.matcher(json);
while (matcher.find()) {
String fieldName = matcher.group(1);
String fieldValue = matcher.group(2).trim();
Field field = getFieldByName(clazz, fieldName);
if (field != null && field.isAnnotationPresent(LumiSerializeField.class)) {
field.setAccessible(true);
field.set(obj, parseValue(fieldValue, field.getType()));
}
}
return obj;
}
public static <T> T fromXml(String xml, Class<T> clazz) throws Exception {
if (!clazz.isAnnotationPresent(LumiSerializable.class)) {
throw new IllegalArgumentException("Class is not marked as LumiSerializable");
}
T obj = clazz.getDeclaredConstructor().newInstance();
Pattern pattern = Pattern.compile("<(\\w+)>(.*?)</\\1>");
Matcher matcher = pattern.matcher(xml);
while (matcher.find()) {
String fieldName = matcher.group(1);
String fieldValue = matcher.group(2);
Field field = getFieldByName(clazz, fieldName);
if (field != null && field.isAnnotationPresent(LumiSerializeField.class)) {
field.setAccessible(true);
field.set(obj, parseValue(fieldValue, field.getType()));
}
}
return obj;
}
private static Field getFieldByName(Class<?> clazz, String fieldName) {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
return null;
}
}
private static Object parseValue(String value, Class<?> type) {
if (type == String.class) {
return value.replaceAll("^\"|\"$", "");
} else if (type == int.class || type == Integer.class) {
return Integer.parseInt(value);
} else if (type == long.class || type == Long.class) {
return Long.parseLong(value);
} else if (type == double.class || type == Double.class) {
return Double.parseDouble(value);
} else if (type == boolean.class || type == Boolean.class) {
return Boolean.parseBoolean(value);
} else if (type == float.class || type == Float.class) {
return Float.parseFloat(value);
}
return value;
}
public static void xmlToFile(Object obj, String fileName) throws IllegalAccessException {
XmlFileWriter.saveXmlToFile(obj, fileName);
}
public static void jsonToFile(Object obj, String fileName) throws IllegalAccessException {
JsonFileWriter.saveJsonToFile(obj, fileName);
}
}

View File

@@ -0,0 +1,10 @@
package org.lumijiez.serializer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface LumiSerializable {}

View File

@@ -0,0 +1,10 @@
package org.lumijiez.serializer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface LumiSerializeField {}

View File

@@ -1,4 +0,0 @@
package org.lumijiez.serializer;
public class LumiSerializer {
}

View File

@@ -0,0 +1,33 @@
package org.lumijiez.serializer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
public class XmlFileWriter {
public static void saveXmlToFile(Object objectToSerialize, String filePath) throws IllegalAccessException {
String xmlOutput = Lumi.toXml(objectToSerialize);
File file = new File(filePath);
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(xmlOutput);
System.out.println("XML saved to " + filePath);
} catch (IOException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
}
}
}
}
}