New: Indirect Ionization (tm)

master
Ondřej Hruška 10 years ago
parent a5bcb22ef2
commit d7d4d181a1
  1. 2
      .project
  2. 29
      src/mightypork/utils/Profiler.java
  3. 47
      src/mightypork/utils/Reflect.java
  4. 17
      src/mightypork/utils/eventbus/EventBus.java
  5. 235
      src/mightypork/utils/ion/Ion.java
  6. 2
      src/mightypork/utils/ion/IonBinary.java
  7. 26
      src/mightypork/utils/ion/IonBundled.java
  8. 30
      src/mightypork/utils/ion/IonDataBundle.java
  9. 61
      src/mightypork/utils/ion/IonInput.java
  10. 2
      src/mightypork/utils/ion/IonMapWrapper.java
  11. 16
      src/mightypork/utils/ion/IonObjBundled.java
  12. 37
      src/mightypork/utils/ion/IonOutput.java
  13. 2
      src/mightypork/utils/ion/IonSequenceWrapper.java
  14. 38
      src/mightypork/utils/ion/IonizerBinary.java
  15. 35
      src/mightypork/utils/ion/IonizerBundled.java
  16. 19
      src/mightypork/utils/math/algo/Move.java

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>mighty_utils</name> <name>MightyUtils</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>

@ -0,0 +1,29 @@
package mightypork.utils;
public class Profiler {
public static long begin()
{
return System.currentTimeMillis();
}
public static double end(long begun)
{
return endLong(begun) / 1000D;
}
public static long endLong(long begun)
{
return System.currentTimeMillis() - begun;
}
public static String endStr(long begun)
{
return Support.str(end(begun)) + " s";
}
}

@ -2,6 +2,10 @@ package mightypork.utils;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/** /**
@ -36,4 +40,47 @@ public class Reflect {
return tested.getClass().isAnnotationPresent(annotation); return tested.getClass().isAnnotationPresent(annotation);
} }
/**
* Get generic parameters of a class
*
* @param clazz the examined class
* @return parameter types
*/
public static Class<?>[] getGenericParameters(Class<?> clazz)
{
// BEHOLD, MAGIC!
final Type evtc = clazz.getGenericSuperclass();
if (evtc instanceof ParameterizedType) {
final Type[] types = ((ParameterizedType) evtc).getActualTypeArguments();
final Class<?>[] classes = new Class<?>[types.length];
for (int i = 0; i < types.length; i++) {
classes[i] = (Class<?>) types[i];
}
return classes;
}
throw new RuntimeException(Support.str(clazz) + " is not generic.");
}
public static Object getConstantFieldValue(Class<?> objClass, String fieldName) throws ReflectiveOperationException
{
final Field fld = objClass.getDeclaredField(fieldName);
final int modif = fld.getModifiers();
if (!Modifier.isFinal(modif) || !Modifier.isStatic(modif)) {
throw new RuntimeException("The " + fieldName + " field of " + Support.str(objClass) + " field must be static and final!");
}
fld.setAccessible(true);
return fld.get(null);
}
} }

@ -1,8 +1,6 @@
package mightypork.utils.eventbus; package mightypork.utils.eventbus;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@ -112,20 +110,7 @@ final public class EventBus implements Destroyable, BusAccess {
private static Class<?> getEventListenerClass(BusEvent<?> event) private static Class<?> getEventListenerClass(BusEvent<?> event)
{ {
// BEHOLD, MAGIC! return Reflect.getGenericParameters(event.getClass())[0];
final Type evtc = event.getClass().getGenericSuperclass();
if (evtc instanceof ParameterizedType) {
if (((ParameterizedType) evtc).getRawType() == BusEvent.class) {
final Type[] types = ((ParameterizedType) evtc).getActualTypeArguments();
for (final Type genericType : types) {
return (Class<?>) genericType;
}
}
}
throw new RuntimeException("Could not detect event listener type.");
} }
/** Log detailed messages (debug) */ /** Log detailed messages (debug) */

@ -7,13 +7,13 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import mightypork.utils.Reflect;
import mightypork.utils.Support;
/** /**
@ -90,13 +90,16 @@ public class Ion {
private static Map<Integer, Class<?>> markToClass = new HashMap<>(); private static Map<Integer, Class<?>> markToClass = new HashMap<>();
private static Map<Class<?>, Integer> classToMark = new HashMap<>(); private static Map<Class<?>, Integer> classToMark = new HashMap<>();
private static Map<Class<?>, IonizerBinary<?>> ionizersBinary = new HashMap<>();
private static Map<Class<?>, IonizerBundled<?>> ionizersBundled = new HashMap<>();
private static boolean reservedMarkChecking; private static boolean reservedMarkChecking;
static { static {
reservedMarkChecking = false; reservedMarkChecking = false;
// register built-ins // register built-ins
register(ION_BUNDLE, IonBundle.class); register(ION_BUNDLE, IonDataBundle.class);
register(SEQUENCE_WRAPPER, IonSequenceWrapper.class); register(SEQUENCE_WRAPPER, IonSequenceWrapper.class);
register(MAP_WRAPPER, IonMapWrapper.class); register(MAP_WRAPPER, IonMapWrapper.class);
@ -105,70 +108,123 @@ public class Ion {
/** /**
* Register new {@link IonObjBinary} class for writing/loading. * Register a type for writing/loading.
* *
* @param mark mark to be used 50..255, unless internal * @param mark binary ION mark
* @param objClass class of the registered object * @param objClass class of the registered object
*/ */
public static void register(int mark, Class<?> objClass) public static void register(int mark, Class<?> objClass)
{ {
// negative marks are allowed. if (!IonBinary.class.isAssignableFrom(objClass)) {
if (mark > RANGE_HIGH) throw new IllegalArgumentException("Mark must be < 256."); if (!IonBundled.class.isAssignableFrom(objClass)) {
if (mark < RANGE_LOW) throw new IllegalArgumentException("Mark must be positive."); throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass));
if (reservedMarkChecking && isMarkReserved(mark)) {
throw new IllegalArgumentException("Marks " + RESERVED_LOW + ".." + RESERVED_HIGH + " are reserved.");
}
if (markToClass.containsKey(objClass)) {
throw new IllegalArgumentException("Mark " + mark + " is already in use.");
}
if (classToMark.containsKey(objClass)) {
throw new IllegalArgumentException(objClass + " is already registered.");
}
if (!IonObjBundled.class.isAssignableFrom(objClass)) {
if (!IonObjBinary.class.isAssignableFrom(objClass)) {
throw new IllegalArgumentException(objClass + " cannot be registered to Ion.");
} }
} }
// make sure the type has implicit constructor assertHasImplicitConstructor(objClass);
try {
objClass.getConstructor();
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException("Class " + objClass + " doesn't have an implicit constructor.");
}
markToClass.put(mark, objClass); registerUsingMark(mark, objClass);
classToMark.put(objClass, mark);
} }
/** /**
* Try to register the type using a static final ION_MARK int field. * Try to register a type using a static final ION_MARK int field.
* *
* @param objClass type class * @param objClass type class
*/ */
public static void register(Class<?> objClass) public static void register(Class<?> objClass)
{ {
try { if (!IonBinary.class.isAssignableFrom(objClass)) {
final Field fld = objClass.getDeclaredField("ION_MARK"); if (!IonBundled.class.isAssignableFrom(objClass)) {
throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass));
final int modif = fld.getModifiers();
if (!Modifier.isFinal(modif) || !Modifier.isStatic(modif)) {
throw new RuntimeException("The ION_MARK field must be static and final.");
} }
}
assertHasImplicitConstructor(objClass);
registerUsingConstant(objClass);
}
private static void registerUsingMark(int mark, Class<?> objClass)
{
assertMarkAvailable(mark, objClass);
markToClass.put(mark, objClass);
classToMark.put(objClass, mark);
}
public static void registerUsingConstant(Class<?> objClass)
{
try {
final int mark = ((Number) Reflect.getConstantFieldValue(objClass, "ION_MARK")).intValue();
fld.setAccessible(true); registerUsingMark(mark, objClass);
final int mark = fld.getInt(null);
register(mark, objClass);
} catch (final Exception e) { } catch (final Exception e) {
throw new RuntimeException("Could not register " + objClass + " using an ION_MARK field.", e); throw new RuntimeException("Could not register " + Support.str(objClass) + " using an ION_MARK field.", e);
}
}
/**
* Register new binary ionizer.
*
* @param mark binary ION mark
* @param ionizer ionizer
*/
public static void registerIndirect(int mark, IonizerBinary<?> ionizer)
{
final Class<?> objClass = Reflect.getGenericParameters(ionizer.getClass())[0];
registerUsingMark(mark, objClass);
ionizersBinary.put(objClass, ionizer);
}
/**
* Register new bundled ionizer.
*
* @param mark binary ION mark
* @param ionizer ionizer
*/
public static void registerIndirect(int mark, IonizerBundled<?> ionizer)
{
final Class<?> objClass = Reflect.getGenericParameters(ionizer.getClass())[0];
registerUsingMark(mark, objClass);
ionizersBundled.put(objClass, ionizer);
}
private static void assertHasImplicitConstructor(Class<?> objClass)
{
try {
objClass.getConstructor();
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException("Class " + objClass + " doesn't have an implicit constructor.");
}
}
private static void assertMarkAvailable(int mark, Class<?> objClass)
{
// negative marks are allowed.
if (mark > RANGE_HIGH) throw new IllegalArgumentException("Mark must be < 256.");
if (mark < RANGE_LOW) throw new IllegalArgumentException("Mark must be positive.");
if (reservedMarkChecking && isMarkReserved(mark)) {
throw new IllegalArgumentException("Marks " + RESERVED_LOW + ".." + RESERVED_HIGH + " are reserved.");
}
if (markToClass.containsKey(mark)) {
throw new IllegalArgumentException("Mark " + mark + " is already in use.");
}
if (classToMark.containsKey(objClass)) {
throw new IllegalArgumentException(Support.str(objClass) + " is already registered.");
} }
} }
@ -297,9 +353,9 @@ public class Ion {
/** /**
* Create new bundle and write the object to it. * Create new bundle and write the object to it.
*/ */
public static IonBundle wrapBundled(IonObjBundled content) throws IOException public static IonDataBundle wrapBundled(IonBundled content) throws IOException
{ {
final IonBundle ib = new IonBundle(); final IonDataBundle ib = new IonDataBundle();
content.save(ib); content.save(ib);
return ib; return ib;
} }
@ -314,14 +370,14 @@ public class Ion {
* @return the object unwrapped * @return the object unwrapped
* @throws IOException * @throws IOException
*/ */
public static <T extends IonObjBundled> T unwrapBundled(IonBundle bundle, Class<? extends T> objClass) throws IOException public static <T extends IonBundled> T unwrapBundled(IonDataBundle bundle, Class<? extends T> objClass) throws IOException
{ {
try { try {
final T inst = objClass.newInstance(); final T inst = objClass.newInstance();
inst.load(bundle); inst.load(bundle);
return inst; return inst;
} catch (InstantiationException | IllegalAccessException e) { } catch (InstantiationException | IllegalAccessException e) {
throw new IOException("Could not instantiate " + objClass + "."); throw new IOException("Could not instantiate " + Support.str(objClass) + ".");
} }
} }
@ -332,6 +388,18 @@ public class Ion {
} }
static IonizerBinary<?> getIonizerBinaryForClass(Class<?> clz)
{
return ionizersBinary.get(clz);
}
static IonizerBundled<?> getIonizerBundledForClass(Class<?> clz)
{
return ionizersBundled.get(clz);
}
public static int getMark(Object object) public static int getMark(Object object)
{ {
assertRegistered(object); assertRegistered(object);
@ -341,24 +409,48 @@ public class Ion {
/** /**
* @return true if the mark is for a registered {@link IonObjBinary} object * @return true if the mark is for a registered {@link IonBinary} object
*/ */
static boolean isMarkForBinary(int mark) static boolean isMarkForBinary(int mark)
{ {
if (!markToClass.containsKey(mark)) return false; if (!markToClass.containsKey(mark)) return false;
return IonObjBinary.class.isAssignableFrom(markToClass.get(mark)); return IonBinary.class.isAssignableFrom(markToClass.get(mark));
} }
/** /**
* @return true if the mark is for a registered {@link IonObjBinary} object * @return true if the mark is for a registered {@link IonBinary} object
*/ */
static boolean isMarkForBundled(int mark) static boolean isMarkForBundled(int mark)
{ {
if (!markToClass.containsKey(mark)) return false; if (!markToClass.containsKey(mark)) return false;
return IonObjBundled.class.isAssignableFrom(markToClass.get(mark)); return IonBundled.class.isAssignableFrom(markToClass.get(mark));
}
/**
* @return true if the mark is for a registered indirectly saved binary
* object
*/
static boolean isMarkForIndirectBinary(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return ionizersBinary.containsKey(markToClass.get(mark));
}
/**
* @return true if the mark is for a registered indirectly saved bundled
* object
*/
static boolean isMarkForIndirectBundled(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return ionizersBundled.containsKey(markToClass.get(mark));
} }
@ -372,11 +464,14 @@ public class Ion {
/** /**
* @return true if the mark is for a registered {@link IonObjBinary} object * @return true if the mark is for a registered {@link IonBinary} object
*/ */
static boolean isRegistered(Object object) static boolean isRegistered(Object object)
{ {
return classToMark.containsKey(object.getClass()); final Class<?> clazz = object.getClass();
if (classToMark.containsKey(clazz)) return true;
return false;
} }
@ -388,7 +483,7 @@ public class Ion {
static void assertRegistered(Object obj) static void assertRegistered(Object obj)
{ {
if (!isRegistered(obj)) { if (!isRegistered(obj)) {
throw new RuntimeException("Type not registered: " + (obj.getClass())); throw new RuntimeException("Type not registered: " + Support.str(obj.getClass()));
} }
} }
@ -400,16 +495,34 @@ public class Ion {
public static void reset() public static void reset()
{ {
final List<Integer> toRemove = new ArrayList<>(); final List<Integer> toRemove = new ArrayList<>();
for (final Entry<Integer, Class<?>> e : markToClass.entrySet()) {
final int mark = e.getKey();
// remove direct
for (final Integer mark : markToClass.keySet()) {
if (!isMarkReserved(mark)) { if (!isMarkReserved(mark)) {
toRemove.add(mark); toRemove.add(mark);
} }
} }
for (final int i : toRemove) { for (final int i : toRemove) {
classToMark.remove(markToClass.remove(i));
final Class<?> clz = markToClass.remove(i);
classToMark.remove(clz);
ionizersBinary.remove(clz);
ionizersBundled.remove(clz);
} }
} }
public static boolean isObjectIndirectBundled(Object obj)
{
return ionizersBundled.containsKey(obj.getClass());
}
public static boolean isObjectIndirectBinary(Object obj)
{
return ionizersBinary.containsKey(obj.getClass());
}
} }

@ -10,7 +10,7 @@ import java.io.IOException;
* *
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public interface IonObjBinary { public interface IonBinary {
/** /**
* Load data from the input stream. * Load data from the input stream.

@ -0,0 +1,26 @@
package mightypork.utils.ion;
/**
* Bundled ion object. If a class implements both binary and bundled, then
* binary will be preferred by both IonInput and IonOutput.
*
* @author Ondřej Hruška (MightyPork)
*/
public interface IonBundled {
/**
* Load this object from the data bundle
*
* @param in bundle to load from
*/
void load(IonDataBundle in);
/**
* Save this object to the data bundle
*
* @param out bundle to save into
*/
void save(IonDataBundle out);
}

@ -15,7 +15,7 @@ import java.util.Map;
* *
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class IonBundle implements IonObjBinary { public class IonDataBundle implements IonBinary {
private final Map<String, Object> backingMap = new HashMap<>(); private final Map<String, Object> backingMap = new HashMap<>();
@ -26,11 +26,11 @@ public class IonBundle implements IonObjBinary {
* @param key key * @param key key
* @param filled bundle to fill * @param filled bundle to fill
*/ */
public void loadBundle(String key, IonBundle filled) public void loadBundle(String key, IonDataBundle filled)
{ {
if (!containsKey(key)) return; if (!containsKey(key)) return;
final IonBundle ib = get(key, new IonBundle()); final IonDataBundle ib = get(key, new IonDataBundle());
filled.clear(); filled.clear();
filled.putAll(ib); filled.putAll(ib);
@ -127,9 +127,9 @@ public class IonBundle implements IonObjBinary {
* @param loaded loaded object * @param loaded loaded object
* @return the loaded object * @return the loaded object
*/ */
public <T extends IonObjBundled> T loadBundled(String key, T loaded) public <T extends IonBundled> T loadBundled(String key, T loaded)
{ {
final IonBundle bu = get(key, null); final IonDataBundle bu = get(key, null);
if (bu == null) throw new RuntimeException("No such key: " + key); if (bu == null) throw new RuntimeException("No such key: " + key);
loaded.load(bu); loaded.load(bu);
@ -145,9 +145,9 @@ public class IonBundle implements IonObjBinary {
* @param key key * @param key key
* @param saved saved object * @param saved saved object
*/ */
public void putBundled(String key, IonObjBundled saved) public void putBundled(String key, IonBundled saved)
{ {
final IonBundle bu = new IonBundle(); final IonDataBundle bu = new IonDataBundle();
saved.save(bu); saved.save(bu);
put(key, bu); put(key, bu);
} }
@ -184,15 +184,7 @@ public class IonBundle implements IonObjBinary {
} }
public void put(String key, IonObjBundled value) public void put(String key, Object value)
{
if (key == null || value == null) return;
if (!Ion.isRegistered(value)) throw new IllegalArgumentException("Cannot add to bundle, not registered: " + value);
backingMap.put(key, value);
}
public void put(String key, IonObjBinary value)
{ {
if (key == null || value == null) return; if (key == null || value == null) return;
if (!Ion.isRegistered(value)) throw new IllegalArgumentException("Cannot add to bundle, not registered: " + value); if (!Ion.isRegistered(value)) throw new IllegalArgumentException("Cannot add to bundle, not registered: " + value);
@ -396,7 +388,7 @@ public class IonBundle implements IonObjBinary {
* *
* @param anotherBundle another bundle * @param anotherBundle another bundle
*/ */
public void putAll(IonBundle anotherBundle) public void putAll(IonDataBundle anotherBundle)
{ {
backingMap.putAll(anotherBundle.backingMap); backingMap.putAll(anotherBundle.backingMap);
} }
@ -424,8 +416,8 @@ public class IonBundle implements IonObjBinary {
{ {
if (this == obj) return true; if (this == obj) return true;
if (obj == null) return false; if (obj == null) return false;
if (!(obj instanceof IonBundle)) return false; if (!(obj instanceof IonDataBundle)) return false;
final IonBundle other = (IonBundle) obj; final IonDataBundle other = (IonDataBundle) obj;
if (backingMap == null) { if (backingMap == null) {
if (other.backingMap != null) return false; if (other.backingMap != null) return false;
} else if (!backingMap.equals(other.backingMap)) return false; } else if (!backingMap.equals(other.backingMap)) return false;

@ -235,9 +235,9 @@ public class IonInput implements Closeable {
/** /**
* Read bundle without a mark * Read bundle without a mark
*/ */
public IonBundle readBundle() throws IOException public IonDataBundle readBundle() throws IOException
{ {
final IonBundle ib = new IonBundle(); final IonDataBundle ib = new IonDataBundle();
ib.load(this); ib.load(this);
return ib; return ib;
} }
@ -246,7 +246,7 @@ public class IonInput implements Closeable {
/** /**
* Read bundle without a mark, load into a provided one * Read bundle without a mark, load into a provided one
*/ */
public void readBundle(IonBundle filled) throws IOException public void readBundle(IonDataBundle filled) throws IOException
{ {
filled.clear(); filled.clear();
filled.load(this); filled.load(this);
@ -276,16 +276,16 @@ public class IonInput implements Closeable {
* *
* @param def default value. * @param def default value.
* @return the loaded object * @return the loaded object
* @throws IOException * @throws CorruptDataException
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T readObject(T def) throws IOException public <T> T readObject(T def) throws CorruptDataException
{ {
try { try {
final Object o = readObject(); final Object o = readObject();
return (T) (o == null ? def : o); return (T) (o == null ? def : o);
} catch (final Exception e) { } catch (final Exception e) {
throw new IOException("Could not load object.", e); throw new CorruptDataException("Could not load object.", e);
} }
} }
@ -299,31 +299,42 @@ public class IonInput implements Closeable {
public Object readObject() throws IOException public Object readObject() throws IOException
{ {
final int mark = readMark(); final int mark = readMark();
if (Ion.isMarkForBinary(mark)) {
IonObjBinary loaded;
try {
try { if (Ion.isMarkForBinary(mark)) {
loaded = (IonObjBinary) Ion.getClassForMark(mark).newInstance(); IonBinary loaded;
} catch (final Exception e) {
throw new RuntimeException("Could not load binary object with mark: " + mark, e); loaded = (IonBinary) Ion.getClassForMark(mark).newInstance();
loaded.load(this);
return loaded;
} }
loaded.load(this); if (Ion.isMarkForBundled(mark)) {
return loaded; IonBundled loaded;
}
loaded = (IonBundled) Ion.getClassForMark(mark).newInstance();
if (Ion.isMarkForBundled(mark)) {
IonObjBundled loaded; final IonDataBundle ib = readBundle();
loaded.load(ib);
return loaded;
}
try { if (Ion.isMarkForIndirectBundled(mark)) {
loaded = (IonObjBundled) Ion.getClassForMark(mark).newInstance(); final IonizerBundled<?> ionizer = Ion.getIonizerBundledForClass(Ion.getClassForMark(mark));
} catch (final Exception e) { return ionizer.load(readBundle());
throw new RuntimeException("Could not load bundled object with mark: " + mark, e);
} }
final IonBundle ib = readBundle(); if (Ion.isMarkForIndirectBinary(mark)) {
loaded.load(ib); final IonizerBinary<?> ionizer = Ion.getIonizerBinaryForClass(Ion.getClassForMark(mark));
return loaded; return ionizer.load(this);
}
} catch (final Exception e) {
throw new RuntimeException("Could not load object for mark: " + mark, e);
} }
switch (mark) { switch (mark) {

@ -7,7 +7,7 @@ import java.util.Map;
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
class IonMapWrapper implements IonObjBinary { class IonMapWrapper implements IonBinary {
private final Map map; private final Map map;

@ -1,16 +0,0 @@
package mightypork.utils.ion;
/**
* Bundled ion object. If a class implements both binary and bundled, then
* binary will be preferred by both IonInput and IonOutput.
*
* @author Ondřej Hruška (MightyPork)
*/
public interface IonObjBundled {
void load(IonBundle in);
void save(IonBundle out);
}

@ -195,7 +195,7 @@ public class IonOutput implements Closeable {
/** /**
* Write a bundle without a mark * Write a bundle without a mark
*/ */
public void writeBundle(IonBundle bundle) throws IOException public void writeBundle(IonDataBundle bundle) throws IOException
{ {
bundle.save(this); bundle.save(this);
} }
@ -279,26 +279,47 @@ public class IonOutput implements Closeable {
return; return;
} }
if (obj instanceof IonObjBinary) { if (obj instanceof IonBinary) {
final IonObjBinary iObj = (IonObjBinary) obj; final IonBinary iObj = (IonBinary) obj;
writeMark(Ion.getMark(iObj)); writeMark(Ion.getMark(obj));
iObj.save(this); iObj.save(this);
return; return;
} }
if (obj instanceof IonObjBundled) { if (obj instanceof IonBundled) {
final IonObjBundled iObj = (IonObjBundled) obj; final IonBundled iObj = (IonBundled) obj;
writeMark(Ion.getMark(iObj)); writeMark(Ion.getMark(obj));
final IonBundle bundle = new IonBundle(); final IonDataBundle bundle = new IonDataBundle();
iObj.save(bundle); iObj.save(bundle);
writeBundle(bundle); writeBundle(bundle);
return; return;
} }
if (Ion.isObjectIndirectBundled(obj)) {
final IonizerBundled<?> ionizer = Ion.getIonizerBundledForClass(obj.getClass());
writeMark(Ion.getMark(obj));
final IonDataBundle bundle = new IonDataBundle();
ionizer._save(obj, bundle);
writeBundle(bundle);
return;
}
if (Ion.isObjectIndirectBinary(obj)) {
final IonizerBinary<?> ionizer = Ion.getIonizerBinaryForClass(obj.getClass());
writeMark(Ion.getMark(obj));
ionizer._save(obj, this);
return;
}
if (obj instanceof Map) { if (obj instanceof Map) {
writeMark(Ion.MAP); writeMark(Ion.MAP);
writeMap((Map<?, ?>) obj); writeMap((Map<?, ?>) obj);

@ -7,7 +7,7 @@ import java.util.Collection;
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
class IonSequenceWrapper implements IonObjBinary { class IonSequenceWrapper implements IonBinary {
private Collection collection = new ArrayList(); private Collection collection = new ArrayList();

@ -0,0 +1,38 @@
package mightypork.utils.ion;
import java.io.IOException;
/**
* External ionizer using a IonOutput / IonInput - can be used if the data type
* cannot be modified to implement the proper interface
*
* @author Ondřej Hruška (MightyPork)
* @param <T>
*/
public abstract class IonizerBinary<T> {
@SuppressWarnings("unchecked")
final void _save(Object object, IonOutput out) throws IOException{
save((T)object, out);
}
/**
* Save an object to ion output
*
* @param object object to save
* @param out ion output
* @throws IOException
*/
public abstract void save(T object, IonOutput out) throws IOException;
/**
* Load an object from ion input
*
* @param in ion input
* @return the loaded object
*/
public abstract T load(IonInput in) throws IOException;
}

@ -0,0 +1,35 @@
package mightypork.utils.ion;
/**
* External ionizer using a data bundle - can be used if the data type cannot be
* modified to implement the proper interface
*
* @author Ondřej Hruška (MightyPork)
* @param <T>
*/
public abstract class IonizerBundled<T> {
@SuppressWarnings("unchecked")
final void _save(Object object, IonDataBundle out) {
save((T)object, out);
}
/**
* Save an object to data bundle
*
* @param object object to save
* @param out bundle to save to
*/
public abstract void save(T object, IonDataBundle out);
/**
* Load an object from a bundle
*
* @param in bundle to load from
* @return the loaded object
*/
public abstract T load(IonDataBundle in);
}

@ -30,15 +30,9 @@ public class Move {
return new Move(x, y); return new Move(x, y);
} }
private byte x; private final byte x;
private byte y; private final byte y;
public Move()
{
// for ion
}
public Move(int x, int y) public Move(int x, int y)
{ {
@ -70,11 +64,4 @@ public class Move {
{ {
return "(" + x + " ; " + y + ")"; return "(" + x + " ; " + y + ")";
} }
protected void setTo(byte x, byte y)
{
this.x = x;
this.y = y;
}
} }

Loading…
Cancel
Save