Switch to a Json Serializer
This commit is contained in:
parent
df9525fca6
commit
642044a15a
13 changed files with 262 additions and 527 deletions
|
@ -1,4 +1,4 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
package dev.zontreck.ariaslib.json;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialization or Deserialization has completed.
|
* Serialization or Deserialization has completed.
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
package dev.zontreck.ariaslib.json;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used on a class to indicate that it is serializable by the dynamic serializer.
|
* Used on a class to indicate that it is serializable by the dynamic serializer.
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
package dev.zontreck.ariaslib.json;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
@ -18,8 +18,7 @@ public class DynamicDeserializer
|
||||||
*/
|
*/
|
||||||
public static <T> T doDeserialize(Class<T> clazz, byte[] data) throws Exception {
|
public static <T> T doDeserialize(Class<T> clazz, byte[] data) throws Exception {
|
||||||
ByteArrayInputStream BAIS = new ByteArrayInputStream ( data );
|
ByteArrayInputStream BAIS = new ByteArrayInputStream ( data );
|
||||||
XmlDeserializer deserial = new XmlDeserializer ( BAIS );
|
return deserialize( ( Map<String, Object> ) JsonObject.parseJSON ( BAIS ).getMap() , clazz);
|
||||||
return deserialize( ( Map<String, Object> ) deserial.readSettings () , clazz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> T deserialize(Map<String, Object> map, Class<T> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
private static <T> T deserialize(Map<String, Object> map, Class<T> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||||
|
@ -32,7 +31,7 @@ public class DynamicDeserializer
|
||||||
Field field :
|
Field field :
|
||||||
fields
|
fields
|
||||||
) {
|
) {
|
||||||
if(XmlStreamWriter.isSerializableType ( field.getType () ))
|
if( !( field.getType ().isAnnotationPresent ( DynSerial.class ) ))
|
||||||
{
|
{
|
||||||
field.set ( object, map.get ( field.getName () ) );
|
field.set ( object, map.get ( field.getName () ) );
|
||||||
}else {
|
}else {
|
|
@ -0,0 +1,72 @@
|
||||||
|
package dev.zontreck.ariaslib.json;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DynamicSerializer {
|
||||||
|
/**
|
||||||
|
* Serializes the object instance
|
||||||
|
*
|
||||||
|
* @param inst The class object to serialize
|
||||||
|
* @return A byte array of serialized data
|
||||||
|
*/
|
||||||
|
public static byte[] doSerialize ( Object inst ) throws InvocationTargetException, IllegalAccessException {
|
||||||
|
Map<String, Object> ret = serialize ( inst );
|
||||||
|
|
||||||
|
JsonObject js = new JsonObject ( ret );
|
||||||
|
|
||||||
|
return js.toJSONString ( ).getBytes ( );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> serialize ( Object inst ) throws InvocationTargetException, IllegalAccessException {
|
||||||
|
Class<?> clazz = inst.getClass ( );
|
||||||
|
if ( ! clazz.isAnnotationPresent ( DynSerial.class ) )
|
||||||
|
return null;
|
||||||
|
Method[] mth = clazz.getDeclaredMethods ( );
|
||||||
|
Method onComplete = null;
|
||||||
|
for (
|
||||||
|
Method mt :
|
||||||
|
mth
|
||||||
|
) {
|
||||||
|
if ( mt.isAnnotationPresent ( PreSerialize.class ) ) {
|
||||||
|
mt.invoke ( inst );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mt.isAnnotationPresent ( Completed.class ) )
|
||||||
|
onComplete = mt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field[] fields = clazz.getDeclaredFields ( );
|
||||||
|
Map<String, Object> ret = new HashMap<> ( );
|
||||||
|
for (
|
||||||
|
Field field :
|
||||||
|
fields
|
||||||
|
) {
|
||||||
|
if ( field.isAnnotationPresent ( IgnoreSerialization.class ) )
|
||||||
|
continue;
|
||||||
|
Object fieldVal = field.get ( inst );
|
||||||
|
|
||||||
|
String fieldName = field.getName ( );
|
||||||
|
|
||||||
|
if ( ! ( fieldVal.getClass ( ).isAnnotationPresent ( DynSerial.class ) ) ) {
|
||||||
|
ret.put ( fieldName , fieldVal );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Map<String, Object> TMP = serialize ( fieldVal );
|
||||||
|
ret.put ( fieldName , TMP );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( onComplete != null )
|
||||||
|
onComplete.invoke ( inst , false );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
package dev.zontreck.ariaslib.json;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks an element to be ignored completely by the serializer or deserializer.
|
* Marks an element to be ignored completely by the serializer or deserializer.
|
183
src/main/java/dev/zontreck/ariaslib/json/JsonObject.java
Normal file
183
src/main/java/dev/zontreck/ariaslib/json/JsonObject.java
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
package dev.zontreck.ariaslib.json;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class JsonObject {
|
||||||
|
private Map<String, Object> data;
|
||||||
|
|
||||||
|
public JsonObject() {
|
||||||
|
data = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject(Map<String, Object> dat)
|
||||||
|
{
|
||||||
|
data = new HashMap<> ( dat );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String key, Object value) {
|
||||||
|
data.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(String key) {
|
||||||
|
return data.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void merge(Map<String,Object> ret)
|
||||||
|
{
|
||||||
|
data.putAll ( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getMap()
|
||||||
|
{
|
||||||
|
return new HashMap<> ( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(String key, Object value) {
|
||||||
|
if (data.containsKey(key)) {
|
||||||
|
Object existingValue = data.get(key);
|
||||||
|
if (existingValue instanceof List) {
|
||||||
|
((List<Object>) existingValue).add(value);
|
||||||
|
} else {
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
list.add(existingValue);
|
||||||
|
list.add(value);
|
||||||
|
data.put(key, list);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJSONString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{");
|
||||||
|
|
||||||
|
boolean first = true;
|
||||||
|
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||||
|
if (!first) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
sb.append("\"");
|
||||||
|
sb.append(escape(entry.getKey()));
|
||||||
|
sb.append("\":");
|
||||||
|
sb.append(toJSONValue(entry.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escape(String str) {
|
||||||
|
// Add necessary escape characters (e.g., double quotes, backslashes)
|
||||||
|
// You can implement this method based on your specific requirements.
|
||||||
|
// This is a simplified version for demonstration purposes.
|
||||||
|
return str.replace("\"", "\\\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toJSONValue(Object value) {
|
||||||
|
if (value instanceof String) {
|
||||||
|
return "\"" + escape(value.toString()) + "\"";
|
||||||
|
} else if (value instanceof JsonObject js) {
|
||||||
|
return js.toJSONString();
|
||||||
|
} else if (value instanceof List) {
|
||||||
|
return toJSONList((List<Object>) value);
|
||||||
|
} else {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toJSONList(List<Object> list) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("[");
|
||||||
|
|
||||||
|
boolean first = true;
|
||||||
|
for (Object item : list) {
|
||||||
|
if (!first) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
sb.append(toJSONValue(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonObject parseJSON( InputStream inputStream) throws IOException {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader (inputStream));
|
||||||
|
StringBuilder jsonString = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
jsonString.append(line);
|
||||||
|
}
|
||||||
|
return parseJsonObject(jsonString.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonObject parseJsonObject(String jsonString) {
|
||||||
|
JsonObject jsonObject = new JsonObject();
|
||||||
|
jsonString = jsonString.trim();
|
||||||
|
if (jsonString.startsWith("{") && jsonString.endsWith("}")) {
|
||||||
|
jsonString = jsonString.substring(1, jsonString.length() - 1);
|
||||||
|
String[] keyValuePairs = jsonString.split(",");
|
||||||
|
for (String pair : keyValuePairs) {
|
||||||
|
String[] keyValue = pair.split(":");
|
||||||
|
if (keyValue.length == 2) {
|
||||||
|
String key = keyValue[0].trim().replace("\"", "");
|
||||||
|
String value = keyValue[1].trim();
|
||||||
|
jsonObject.put(key, parseValue(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object parseValue(String value) {
|
||||||
|
if (value.startsWith("{") && value.endsWith("}")) {
|
||||||
|
return parseJsonObject(value);
|
||||||
|
} else if (value.startsWith("[") && value.endsWith("]")) {
|
||||||
|
return parseJSONArray(value);
|
||||||
|
} else if (value.startsWith("\"") && value.endsWith("\"")) {
|
||||||
|
return value.substring(1, value.length() - 1);
|
||||||
|
} else if (value.equalsIgnoreCase("true")) {
|
||||||
|
return true;
|
||||||
|
} else if (value.equalsIgnoreCase("false")) {
|
||||||
|
return false;
|
||||||
|
} else if (value.equalsIgnoreCase("null")) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
try {
|
||||||
|
return Double.parseDouble(value);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Object> parseJSONArray(String jsonArray) {
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
jsonArray = jsonArray.trim();
|
||||||
|
if (jsonArray.startsWith("[") && jsonArray.endsWith("]")) {
|
||||||
|
jsonArray = jsonArray.substring(1, jsonArray.length() - 1);
|
||||||
|
String[] elements = jsonArray.split(",");
|
||||||
|
for (String element : elements) {
|
||||||
|
list.add(parseValue(element.trim()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
package dev.zontreck.ariaslib.json;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be set on a method, and will invoke that method prior to serialization beginning.
|
* To be set on a method, and will invoke that method prior to serialization beginning.
|
|
@ -1,73 +0,0 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class DynamicSerializer {
|
|
||||||
/**
|
|
||||||
* Serializes the object instance
|
|
||||||
*
|
|
||||||
* @param inst The class object to serialize
|
|
||||||
* @return A byte array of serialized data
|
|
||||||
*/
|
|
||||||
public static byte[] doSerialize(Object inst) throws InvocationTargetException, IllegalAccessException {
|
|
||||||
Map<String, Object> ret = serialize(inst);
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream ( );
|
|
||||||
XmlSerializer ser = new XmlSerializer ( baos );
|
|
||||||
ser.writeValue ( ret );
|
|
||||||
|
|
||||||
return baos.toByteArray ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<String,Object> serialize ( Object inst ) throws InvocationTargetException, IllegalAccessException {
|
|
||||||
Class<?> clazz = inst.getClass ( );
|
|
||||||
if(!clazz.isAnnotationPresent ( DynSerial.class ))
|
|
||||||
return null;
|
|
||||||
Method[] mth = clazz.getDeclaredMethods ( );
|
|
||||||
Method onComplete = null;
|
|
||||||
for (
|
|
||||||
Method mt :
|
|
||||||
mth
|
|
||||||
) {
|
|
||||||
if ( mt.isAnnotationPresent ( PreSerialize.class ) ) {
|
|
||||||
mt.invoke ( inst );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mt.isAnnotationPresent ( Completed.class ))
|
|
||||||
onComplete = mt;
|
|
||||||
}
|
|
||||||
|
|
||||||
Field[] fields = clazz.getDeclaredFields ();
|
|
||||||
Map<String,Object> ret = new HashMap<> ( );
|
|
||||||
for (
|
|
||||||
Field field :
|
|
||||||
fields
|
|
||||||
) {
|
|
||||||
if(field.isAnnotationPresent ( IgnoreSerialization.class )) continue;
|
|
||||||
Object fieldVal = field.get ( inst );
|
|
||||||
|
|
||||||
String fieldName = field.getName ();
|
|
||||||
|
|
||||||
if(XmlStreamWriter.isSerializableType ( fieldVal ))
|
|
||||||
{
|
|
||||||
ret.put ( fieldName, fieldVal );
|
|
||||||
}else {
|
|
||||||
Map<String,Object> TMP = serialize(fieldVal);
|
|
||||||
ret.put ( fieldName, TMP );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(onComplete != null)
|
|
||||||
onComplete.invoke ( inst, false );
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
|
||||||
|
|
||||||
|
|
||||||
import dev.zontreck.ariaslib.xmlrpc.XmlRpcStreamReader;
|
|
||||||
|
|
||||||
import javax.xml.stream.XMLStreamException;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public class XmlDeserializer {
|
|
||||||
private XmlStreamReader xmlStreamReader;
|
|
||||||
|
|
||||||
public XmlDeserializer ( InputStream inputStream ) throws Exception {
|
|
||||||
xmlStreamReader = new XmlStreamReader ( inputStream );
|
|
||||||
}
|
|
||||||
public String skipXmlHeader(String xml) {
|
|
||||||
int startIndex = xml.indexOf("<?xml");
|
|
||||||
if (startIndex >= 0) {
|
|
||||||
int endIndex = xml.indexOf("?>", startIndex);
|
|
||||||
if (endIndex >= 0) {
|
|
||||||
return xml.substring(endIndex + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return xml;
|
|
||||||
}
|
|
||||||
public XmlDeserializer ( String xml ) throws Exception {
|
|
||||||
byte[] xmlBytes = xml.getBytes ( );
|
|
||||||
ByteArrayInputStream inputStream = new ByteArrayInputStream ( xmlBytes );
|
|
||||||
xmlStreamReader = new XmlStreamReader ( inputStream );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object readSettings()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return xmlStreamReader.readSettings ();
|
|
||||||
} catch ( XMLStreamException e ) {
|
|
||||||
throw new RuntimeException ( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close ( ) throws Exception {
|
|
||||||
xmlStreamReader.close ( );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
|
||||||
|
|
||||||
|
|
||||||
public class XmlException extends Exception {
|
|
||||||
public XmlException ( int code , String message ) {
|
|
||||||
super ( message );
|
|
||||||
FaultCode = code;
|
|
||||||
FaultString = message;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String FaultString;
|
|
||||||
public final int FaultCode;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString ( ) {
|
|
||||||
StringBuilder sb = new StringBuilder ( );
|
|
||||||
sb.append ( "Code: " +FaultCode);
|
|
||||||
sb.append ( "\nMessage: " +FaultString);
|
|
||||||
sb.append ( "\n\n" );
|
|
||||||
|
|
||||||
return sb.toString ();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
|
||||||
|
|
||||||
|
|
||||||
import dev.zontreck.ariaslib.xmlrpc.XmlRpcStreamWriter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class XmlSerializer {
|
|
||||||
private XmlStreamWriter writer;
|
|
||||||
|
|
||||||
public XmlSerializer ( OutputStream outputStream ) {
|
|
||||||
this.writer = new XmlStreamWriter ( outputStream );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeValue(Object value)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
writer.writeSettings ( value );
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
throw new RuntimeException ( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close ( ) throws IOException {
|
|
||||||
writer.close ( );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,174 +0,0 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
|
||||||
|
|
||||||
import javax.xml.stream.XMLInputFactory;
|
|
||||||
import javax.xml.stream.XMLStreamConstants;
|
|
||||||
import javax.xml.stream.XMLStreamException;
|
|
||||||
import javax.xml.stream.XMLStreamReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class XmlStreamReader {
|
|
||||||
private XMLStreamReader xmlStreamReader;
|
|
||||||
|
|
||||||
public XmlStreamReader ( InputStream inputStream ) throws XMLStreamException {
|
|
||||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance ( );
|
|
||||||
xmlStreamReader = inputFactory.createXMLStreamReader ( inputStream );
|
|
||||||
}
|
|
||||||
|
|
||||||
private String CURRENT_TAG_NAME;
|
|
||||||
private int ELEM_TYPE;
|
|
||||||
|
|
||||||
public boolean nextTag ( ) throws XMLStreamException {
|
|
||||||
while ( xmlStreamReader.hasNext ( ) ) {
|
|
||||||
int eventType = xmlStreamReader.next ( );
|
|
||||||
if ( eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT ) {
|
|
||||||
CURRENT_TAG_NAME = getLocalName ( );
|
|
||||||
ELEM_TYPE = xmlStreamReader.getEventType ( );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object readSettings() throws XMLStreamException {
|
|
||||||
nextTag ();
|
|
||||||
require ( XMLStreamConstants.START_ELEMENT, null, "settings" );
|
|
||||||
return deserializeValue ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLocalName ( ) {
|
|
||||||
return xmlStreamReader.getLocalName ( );
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getElementText ( ) throws XMLStreamException {
|
|
||||||
return xmlStreamReader.getElementText ( );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void require ( int type , String namespaceURI , String localName ) throws XMLStreamException {
|
|
||||||
xmlStreamReader.require ( type , namespaceURI , localName );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object deserializeValue ( ) throws XMLStreamException {
|
|
||||||
nextTag ( );
|
|
||||||
|
|
||||||
|
|
||||||
int eventType = xmlStreamReader.getEventType ( );
|
|
||||||
if ( eventType == XMLStreamConstants.CHARACTERS || eventType == XMLStreamConstants.CDATA ) {
|
|
||||||
return xmlStreamReader.getText ( );
|
|
||||||
}
|
|
||||||
else if ( eventType == XMLStreamConstants.START_ELEMENT ) {
|
|
||||||
String localName = xmlStreamReader.getLocalName ( );
|
|
||||||
switch ( localName ) {
|
|
||||||
case "string":
|
|
||||||
return deserializeString ( );
|
|
||||||
case "i4":
|
|
||||||
return deserializeByte ();
|
|
||||||
case "int":
|
|
||||||
return deserializeInt ( );
|
|
||||||
case "double":
|
|
||||||
return deserializeDouble ( );
|
|
||||||
case "bool":
|
|
||||||
return deserializeBoolean ( );
|
|
||||||
case "array":
|
|
||||||
return deserializeArray ( );
|
|
||||||
case "struct":
|
|
||||||
return deserializeStruct ( );
|
|
||||||
case "nil":
|
|
||||||
return null;
|
|
||||||
case "i8":
|
|
||||||
return deserializeLong ( );
|
|
||||||
case "float":
|
|
||||||
return deserializeFloat();
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException ( "Unsupported element: " + localName );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalArgumentException ( "Unexpected event type: " + eventType );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String deserializeString ( ) throws XMLStreamException {
|
|
||||||
return getElementText ( );
|
|
||||||
}
|
|
||||||
|
|
||||||
private int deserializeInt ( ) throws XMLStreamException {
|
|
||||||
return Integer.parseInt ( getElementText ( ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte deserializeByte ( ) throws XMLStreamException {
|
|
||||||
return Byte.parseByte ( getElementText ( ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private long deserializeLong ( ) throws XMLStreamException {
|
|
||||||
return Long.parseLong ( getElementText ( ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private float deserializeFloat() throws XMLStreamException {
|
|
||||||
return Float.parseFloat ( getElementText () );
|
|
||||||
}
|
|
||||||
|
|
||||||
private double deserializeDouble ( ) throws XMLStreamException {
|
|
||||||
return Double.parseDouble ( getElementText ( ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean deserializeBoolean ( ) throws XMLStreamException {
|
|
||||||
return Boolean.parseBoolean ( getElementText ( ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object[] deserializeArray ( ) throws XMLStreamException {
|
|
||||||
List<Object> arr = new ArrayList<> ( );
|
|
||||||
while ( nextTag ( ) ) {
|
|
||||||
if ( CURRENT_TAG_NAME.equals ( "data" ) && ELEM_TYPE == XMLStreamConstants.END_ELEMENT ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if ( CURRENT_TAG_NAME.equals ( "value" ) && ELEM_TYPE == XMLStreamConstants.START_ELEMENT ) {
|
|
||||||
arr.add ( deserializeValue ( ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr.toArray ( );
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, Object> deserializeStruct ( ) throws XMLStreamException {
|
|
||||||
Map<String, Object> struct = new HashMap<> ( );
|
|
||||||
String name = null;
|
|
||||||
while ( nextTag ( ) ) {
|
|
||||||
if ( xmlStreamReader.getLocalName ( ).equals ( "member" ) ) {
|
|
||||||
name = null;
|
|
||||||
}
|
|
||||||
else if ( xmlStreamReader.getLocalName ( ).equals ( "name" ) ) {
|
|
||||||
name = getElementText ( );
|
|
||||||
}
|
|
||||||
else if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.START_ELEMENT ) {
|
|
||||||
if ( name != null ) {
|
|
||||||
Object value = deserializeValue ( );
|
|
||||||
struct.put ( name , value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( CURRENT_TAG_NAME.equals ( "struct" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.END_ELEMENT ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return struct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String skipXmlHeader ( String xml ) {
|
|
||||||
int startIndex = xml.indexOf ( "<?xml" );
|
|
||||||
if ( startIndex >= 0 ) {
|
|
||||||
int endIndex = xml.indexOf ( "?>" , startIndex );
|
|
||||||
if ( endIndex >= 0 ) {
|
|
||||||
return xml.substring ( endIndex + 2 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return xml;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void close ( ) throws XMLStreamException {
|
|
||||||
xmlStreamReader.close ( );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,175 +0,0 @@
|
||||||
package dev.zontreck.ariaslib.xml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class XmlStreamWriter {
|
|
||||||
private static final String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
|
||||||
private static final String METHOD_CALL_START_TAG = "<methodCall>";
|
|
||||||
private static final String METHOD_CALL_END_TAG = "</methodCall>";
|
|
||||||
private static final String METHOD_NAME_START_TAG = "<methodName>";
|
|
||||||
private static final String METHOD_NAME_END_TAG = "</methodName>";
|
|
||||||
private static final String METHOD_RESPONSE_START_TAG = "<methodResponse>";
|
|
||||||
private static final String METHOD_RESPONSE_END_TAG = "</methodResponse>";
|
|
||||||
private static final String PARAMS_START_TAG = "<params>";
|
|
||||||
private static final String PARAMS_END_TAG = "</params>";
|
|
||||||
private static final String PARAM_START_TAG = "<param>";
|
|
||||||
private static final String PARAM_END_TAG = "</param>";
|
|
||||||
private static final String VALUE_START_TAG = "<value>";
|
|
||||||
private static final String VALUE_END_TAG = "</value>";
|
|
||||||
private static final String ARRAY_START_TAG = "<array>";
|
|
||||||
private static final String ARRAY_END_TAG = "</array>";
|
|
||||||
private static final String DATA_START_TAG = "<data>";
|
|
||||||
private static final String DATA_END_TAG = "</data>";
|
|
||||||
private static final String STRUCT_START_TAG = "<struct>";
|
|
||||||
private static final String STRUCT_END_TAG = "</struct>";
|
|
||||||
private static final String MEMBER_START_TAG = "<member>";
|
|
||||||
private static final String MEMBER_END_TAG = "</member>";
|
|
||||||
private static final String NAME_START_TAG = "<name>";
|
|
||||||
private static final String NAME_END_TAG = "</name>";
|
|
||||||
|
|
||||||
private static final String SETTINGS_START_TAG = "<settings>";
|
|
||||||
private static final String SETTINGS_END_TAG = "</settings>";
|
|
||||||
|
|
||||||
private Writer writer;
|
|
||||||
|
|
||||||
public XmlStreamWriter ( OutputStream outputStream ) {
|
|
||||||
this.writer = new OutputStreamWriter ( outputStream );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isSerializableType ( Object value ) {
|
|
||||||
|
|
||||||
return isSerializableType ( value.getClass () );
|
|
||||||
}
|
|
||||||
public static boolean isSerializableType ( Class<?> clazz ) {
|
|
||||||
|
|
||||||
List<Class<?>> valid = new ArrayList<> ( );
|
|
||||||
valid.add ( null );
|
|
||||||
valid.add ( String.class );
|
|
||||||
valid.add ( Integer.class );
|
|
||||||
valid.add ( Long.class );
|
|
||||||
valid.add ( Double.class );
|
|
||||||
valid.add ( Boolean.class );
|
|
||||||
valid.add ( List.class );
|
|
||||||
valid.add ( Map.class );
|
|
||||||
valid.add ( Byte.class );
|
|
||||||
valid.add ( Float.class );
|
|
||||||
|
|
||||||
if(valid.contains ( clazz ))return true;
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeSettings(Object value) throws IOException {
|
|
||||||
writer.write ( XML_VERSION );
|
|
||||||
writer.write ( SETTINGS_START_TAG );
|
|
||||||
writeValue ( value );
|
|
||||||
writer.write ( SETTINGS_END_TAG );
|
|
||||||
writer.flush ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeValue ( Object value ) throws IOException {
|
|
||||||
if ( value == null ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<nil/>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof String ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<string>" );
|
|
||||||
writer.write ( escapeXml ( ( String ) value ) );
|
|
||||||
writer.write ( "</string>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof Integer ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<i4>" );
|
|
||||||
writer.write ( value.toString ( ) );
|
|
||||||
writer.write ( "</i4>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof Long ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<i8>" );
|
|
||||||
writer.write ( value.toString ( ) ); // Save it as a int for now due to unclear handling
|
|
||||||
writer.write ( "</i8>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof Double ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<double>" );
|
|
||||||
writer.write ( value.toString ( ) );
|
|
||||||
writer.write ( "</double>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof Boolean ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<bool>" );
|
|
||||||
writer.write ( value.toString ( ) );
|
|
||||||
writer.write ( "</bool>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof List ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( ARRAY_START_TAG );
|
|
||||||
writer.write ( DATA_START_TAG );
|
|
||||||
List<?> list = ( List<?> ) value;
|
|
||||||
for ( Object item : list ) {
|
|
||||||
writeValue ( item );
|
|
||||||
}
|
|
||||||
writer.write ( DATA_END_TAG );
|
|
||||||
writer.write ( ARRAY_END_TAG );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof Map ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( STRUCT_START_TAG );
|
|
||||||
Map<?, ?> map = ( Map<?, ?> ) value;
|
|
||||||
for ( Map.Entry<?, ?> entry : map.entrySet ( ) ) {
|
|
||||||
writer.write ( MEMBER_START_TAG );
|
|
||||||
writer.write ( NAME_START_TAG );
|
|
||||||
writer.write ( escapeXml ( entry.getKey ( ).toString ( ) ) );
|
|
||||||
writer.write ( NAME_END_TAG );
|
|
||||||
writeValue ( entry.getValue ( ) );
|
|
||||||
writer.write ( MEMBER_END_TAG );
|
|
||||||
}
|
|
||||||
writer.write ( STRUCT_END_TAG );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if ( value instanceof Byte ) {
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<i1>" );
|
|
||||||
writer.write ( value.toString ( ) ); // Treat as a integer for now
|
|
||||||
writer.write ( "</i1>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else if(value instanceof Float)
|
|
||||||
{
|
|
||||||
writer.write ( VALUE_START_TAG );
|
|
||||||
writer.write ( "<float>" );
|
|
||||||
writer.write ( value.toString () );
|
|
||||||
writer.write ( "</float>" );
|
|
||||||
writer.write ( VALUE_END_TAG );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalArgumentException ( "Unsupported data type: " + value.getClass ( ).getName ( ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String escapeXml ( String value ) {
|
|
||||||
return value
|
|
||||||
.replace ( "&" , "&" )
|
|
||||||
.replace ( "<" , "<" )
|
|
||||||
.replace ( ">" , ">" )
|
|
||||||
.replace ( "\"" , """ )
|
|
||||||
.replace ( "'" , "'" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close ( ) throws IOException {
|
|
||||||
writer.close ( );
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue