From d7d4d181a1fc9b56f61a35a630d32f38d83325b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Fri, 30 May 2014 01:48:32 +0200 Subject: [PATCH] New: Indirect Ionization (tm) --- .project | 2 +- src/mightypork/utils/Profiler.java | 29 +++ src/mightypork/utils/Reflect.java | 47 ++++ src/mightypork/utils/eventbus/EventBus.java | 17 +- src/mightypork/utils/ion/Ion.java | 235 +++++++++++++----- .../ion/{IonObjBinary.java => IonBinary.java} | 2 +- src/mightypork/utils/ion/IonBundled.java | 26 ++ .../{IonBundle.java => IonDataBundle.java} | 30 +-- src/mightypork/utils/ion/IonInput.java | 61 +++-- src/mightypork/utils/ion/IonMapWrapper.java | 2 +- src/mightypork/utils/ion/IonObjBundled.java | 16 -- src/mightypork/utils/ion/IonOutput.java | 37 ++- .../utils/ion/IonSequenceWrapper.java | 2 +- src/mightypork/utils/ion/IonizerBinary.java | 38 +++ src/mightypork/utils/ion/IonizerBundled.java | 35 +++ src/mightypork/utils/math/algo/Move.java | 19 +- 16 files changed, 433 insertions(+), 165 deletions(-) create mode 100644 src/mightypork/utils/Profiler.java rename src/mightypork/utils/ion/{IonObjBinary.java => IonBinary.java} (95%) create mode 100644 src/mightypork/utils/ion/IonBundled.java rename src/mightypork/utils/ion/{IonBundle.java => IonDataBundle.java} (89%) delete mode 100644 src/mightypork/utils/ion/IonObjBundled.java create mode 100644 src/mightypork/utils/ion/IonizerBinary.java create mode 100644 src/mightypork/utils/ion/IonizerBundled.java diff --git a/.project b/.project index 561482d..a126280 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - mighty_utils + MightyUtils diff --git a/src/mightypork/utils/Profiler.java b/src/mightypork/utils/Profiler.java new file mode 100644 index 0000000..ea61aaf --- /dev/null +++ b/src/mightypork/utils/Profiler.java @@ -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"; + } + +} diff --git a/src/mightypork/utils/Reflect.java b/src/mightypork/utils/Reflect.java index d5f9362..d49a07a 100644 --- a/src/mightypork/utils/Reflect.java +++ b/src/mightypork/utils/Reflect.java @@ -2,6 +2,10 @@ package mightypork.utils; 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); } + + /** + * 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); + } + } diff --git a/src/mightypork/utils/eventbus/EventBus.java b/src/mightypork/utils/eventbus/EventBus.java index b3330f0..9ef7b8c 100644 --- a/src/mightypork/utils/eventbus/EventBus.java +++ b/src/mightypork/utils/eventbus/EventBus.java @@ -1,8 +1,6 @@ package mightypork.utils.eventbus; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import java.util.Collection; import java.util.Collections; import java.util.Set; @@ -112,20 +110,7 @@ final public class EventBus implements Destroyable, BusAccess { private static Class getEventListenerClass(BusEvent event) { - // BEHOLD, MAGIC! - - 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."); + return Reflect.getGenericParameters(event.getClass())[0]; } /** Log detailed messages (debug) */ diff --git a/src/mightypork/utils/ion/Ion.java b/src/mightypork/utils/ion/Ion.java index 4164ce2..3185604 100644 --- a/src/mightypork/utils/ion/Ion.java +++ b/src/mightypork/utils/ion/Ion.java @@ -7,13 +7,13 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; 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> markToClass = new HashMap<>(); private static Map, Integer> classToMark = new HashMap<>(); + private static Map, IonizerBinary> ionizersBinary = new HashMap<>(); + private static Map, IonizerBundled> ionizersBundled = new HashMap<>(); + private static boolean reservedMarkChecking; static { reservedMarkChecking = false; // register built-ins - register(ION_BUNDLE, IonBundle.class); + register(ION_BUNDLE, IonDataBundle.class); register(SEQUENCE_WRAPPER, IonSequenceWrapper.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 */ public static void register(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(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."); + if (!IonBinary.class.isAssignableFrom(objClass)) { + if (!IonBundled.class.isAssignableFrom(objClass)) { + throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass)); } } - // make sure the type has implicit constructor - try { - objClass.getConstructor(); - } catch (NoSuchMethodException | SecurityException e) { - throw new RuntimeException("Class " + objClass + " doesn't have an implicit constructor."); - } + assertHasImplicitConstructor(objClass); - markToClass.put(mark, objClass); - classToMark.put(objClass, mark); + registerUsingMark(mark, objClass); } /** - * 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 */ public static void register(Class objClass) { - try { - final Field fld = objClass.getDeclaredField("ION_MARK"); - - final int modif = fld.getModifiers(); - - if (!Modifier.isFinal(modif) || !Modifier.isStatic(modif)) { - throw new RuntimeException("The ION_MARK field must be static and final."); + if (!IonBinary.class.isAssignableFrom(objClass)) { + if (!IonBundled.class.isAssignableFrom(objClass)) { + throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass)); } + } + + 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); - final int mark = fld.getInt(null); - - register(mark, objClass); + registerUsingMark(mark, objClass); } 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. */ - 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); return ib; } @@ -314,14 +370,14 @@ public class Ion { * @return the object unwrapped * @throws IOException */ - public static T unwrapBundled(IonBundle bundle, Class objClass) throws IOException + public static T unwrapBundled(IonDataBundle bundle, Class objClass) throws IOException { try { final T inst = objClass.newInstance(); inst.load(bundle); return inst; } 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) { 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) { 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) { 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) { - 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) { 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() { final List toRemove = new ArrayList<>(); - for (final Entry> e : markToClass.entrySet()) { - final int mark = e.getKey(); - + + + // remove direct + for (final Integer mark : markToClass.keySet()) { if (!isMarkReserved(mark)) { toRemove.add(mark); } } 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()); + } } diff --git a/src/mightypork/utils/ion/IonObjBinary.java b/src/mightypork/utils/ion/IonBinary.java similarity index 95% rename from src/mightypork/utils/ion/IonObjBinary.java rename to src/mightypork/utils/ion/IonBinary.java index 7824334..0b5bf1e 100644 --- a/src/mightypork/utils/ion/IonObjBinary.java +++ b/src/mightypork/utils/ion/IonBinary.java @@ -10,7 +10,7 @@ import java.io.IOException; * * @author Ondřej Hruška (MightyPork) */ -public interface IonObjBinary { +public interface IonBinary { /** * Load data from the input stream. diff --git a/src/mightypork/utils/ion/IonBundled.java b/src/mightypork/utils/ion/IonBundled.java new file mode 100644 index 0000000..e74d9aa --- /dev/null +++ b/src/mightypork/utils/ion/IonBundled.java @@ -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); +} diff --git a/src/mightypork/utils/ion/IonBundle.java b/src/mightypork/utils/ion/IonDataBundle.java similarity index 89% rename from src/mightypork/utils/ion/IonBundle.java rename to src/mightypork/utils/ion/IonDataBundle.java index 8a84ef3..e6cfdb7 100644 --- a/src/mightypork/utils/ion/IonBundle.java +++ b/src/mightypork/utils/ion/IonDataBundle.java @@ -15,7 +15,7 @@ import java.util.Map; * * @author Ondřej Hruška (MightyPork) */ -public class IonBundle implements IonObjBinary { +public class IonDataBundle implements IonBinary { private final Map backingMap = new HashMap<>(); @@ -26,11 +26,11 @@ public class IonBundle implements IonObjBinary { * @param key key * @param filled bundle to fill */ - public void loadBundle(String key, IonBundle filled) + public void loadBundle(String key, IonDataBundle filled) { if (!containsKey(key)) return; - final IonBundle ib = get(key, new IonBundle()); + final IonDataBundle ib = get(key, new IonDataBundle()); filled.clear(); filled.putAll(ib); @@ -127,9 +127,9 @@ public class IonBundle implements IonObjBinary { * @param loaded loaded object * @return the loaded object */ - public T loadBundled(String key, T loaded) + public 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); loaded.load(bu); @@ -145,9 +145,9 @@ public class IonBundle implements IonObjBinary { * @param key key * @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); put(key, bu); } @@ -184,15 +184,7 @@ public class IonBundle implements IonObjBinary { } - public void put(String key, IonObjBundled 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) + 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); @@ -396,7 +388,7 @@ public class IonBundle implements IonObjBinary { * * @param anotherBundle another bundle */ - public void putAll(IonBundle anotherBundle) + public void putAll(IonDataBundle anotherBundle) { backingMap.putAll(anotherBundle.backingMap); } @@ -424,8 +416,8 @@ public class IonBundle implements IonObjBinary { { if (this == obj) return true; if (obj == null) return false; - if (!(obj instanceof IonBundle)) return false; - final IonBundle other = (IonBundle) obj; + if (!(obj instanceof IonDataBundle)) return false; + final IonDataBundle other = (IonDataBundle) obj; if (backingMap == null) { if (other.backingMap != null) return false; } else if (!backingMap.equals(other.backingMap)) return false; diff --git a/src/mightypork/utils/ion/IonInput.java b/src/mightypork/utils/ion/IonInput.java index 34310ba..6c506c7 100644 --- a/src/mightypork/utils/ion/IonInput.java +++ b/src/mightypork/utils/ion/IonInput.java @@ -235,9 +235,9 @@ public class IonInput implements Closeable { /** * 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); return ib; } @@ -246,7 +246,7 @@ public class IonInput implements Closeable { /** * 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.load(this); @@ -276,16 +276,16 @@ public class IonInput implements Closeable { * * @param def default value. * @return the loaded object - * @throws IOException + * @throws CorruptDataException */ @SuppressWarnings("unchecked") - public T readObject(T def) throws IOException + public T readObject(T def) throws CorruptDataException { try { final Object o = readObject(); return (T) (o == null ? def : o); } 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 { final int mark = readMark(); - if (Ion.isMarkForBinary(mark)) { - IonObjBinary loaded; + + + try { - try { - loaded = (IonObjBinary) Ion.getClassForMark(mark).newInstance(); - } catch (final Exception e) { - throw new RuntimeException("Could not load binary object with mark: " + mark, e); + if (Ion.isMarkForBinary(mark)) { + IonBinary loaded; + + loaded = (IonBinary) Ion.getClassForMark(mark).newInstance(); + + + loaded.load(this); + return loaded; } - loaded.load(this); - return loaded; - } - - if (Ion.isMarkForBundled(mark)) { - IonObjBundled loaded; + if (Ion.isMarkForBundled(mark)) { + IonBundled loaded; + + loaded = (IonBundled) Ion.getClassForMark(mark).newInstance(); + + final IonDataBundle ib = readBundle(); + loaded.load(ib); + return loaded; + } - try { - loaded = (IonObjBundled) Ion.getClassForMark(mark).newInstance(); - } catch (final Exception e) { - throw new RuntimeException("Could not load bundled object with mark: " + mark, e); + if (Ion.isMarkForIndirectBundled(mark)) { + final IonizerBundled ionizer = Ion.getIonizerBundledForClass(Ion.getClassForMark(mark)); + return ionizer.load(readBundle()); } - final IonBundle ib = readBundle(); - loaded.load(ib); - return loaded; + if (Ion.isMarkForIndirectBinary(mark)) { + final IonizerBinary ionizer = Ion.getIonizerBinaryForClass(Ion.getClassForMark(mark)); + return ionizer.load(this); + } + + } catch (final Exception e) { + throw new RuntimeException("Could not load object for mark: " + mark, e); } switch (mark) { diff --git a/src/mightypork/utils/ion/IonMapWrapper.java b/src/mightypork/utils/ion/IonMapWrapper.java index 29bc840..9a21bf6 100644 --- a/src/mightypork/utils/ion/IonMapWrapper.java +++ b/src/mightypork/utils/ion/IonMapWrapper.java @@ -7,7 +7,7 @@ import java.util.Map; @SuppressWarnings({ "rawtypes", "unchecked" }) -class IonMapWrapper implements IonObjBinary { +class IonMapWrapper implements IonBinary { private final Map map; diff --git a/src/mightypork/utils/ion/IonObjBundled.java b/src/mightypork/utils/ion/IonObjBundled.java deleted file mode 100644 index 17b00e6..0000000 --- a/src/mightypork/utils/ion/IonObjBundled.java +++ /dev/null @@ -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); -} diff --git a/src/mightypork/utils/ion/IonOutput.java b/src/mightypork/utils/ion/IonOutput.java index 589e795..51d6bbc 100644 --- a/src/mightypork/utils/ion/IonOutput.java +++ b/src/mightypork/utils/ion/IonOutput.java @@ -195,7 +195,7 @@ public class IonOutput implements Closeable { /** * Write a bundle without a mark */ - public void writeBundle(IonBundle bundle) throws IOException + public void writeBundle(IonDataBundle bundle) throws IOException { bundle.save(this); } @@ -279,26 +279,47 @@ public class IonOutput implements Closeable { return; } - if (obj instanceof IonObjBinary) { - final IonObjBinary iObj = (IonObjBinary) obj; + if (obj instanceof IonBinary) { + final IonBinary iObj = (IonBinary) obj; - writeMark(Ion.getMark(iObj)); + writeMark(Ion.getMark(obj)); iObj.save(this); return; } - if (obj instanceof IonObjBundled) { - final IonObjBundled iObj = (IonObjBundled) obj; + if (obj instanceof IonBundled) { + 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); writeBundle(bundle); 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) { writeMark(Ion.MAP); writeMap((Map) obj); diff --git a/src/mightypork/utils/ion/IonSequenceWrapper.java b/src/mightypork/utils/ion/IonSequenceWrapper.java index 35e17d7..9719c0d 100644 --- a/src/mightypork/utils/ion/IonSequenceWrapper.java +++ b/src/mightypork/utils/ion/IonSequenceWrapper.java @@ -7,7 +7,7 @@ import java.util.Collection; @SuppressWarnings({ "rawtypes", "unchecked" }) -class IonSequenceWrapper implements IonObjBinary { +class IonSequenceWrapper implements IonBinary { private Collection collection = new ArrayList(); diff --git a/src/mightypork/utils/ion/IonizerBinary.java b/src/mightypork/utils/ion/IonizerBinary.java new file mode 100644 index 0000000..0a24a3b --- /dev/null +++ b/src/mightypork/utils/ion/IonizerBinary.java @@ -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 + */ +public abstract class IonizerBinary { + + @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; + +} diff --git a/src/mightypork/utils/ion/IonizerBundled.java b/src/mightypork/utils/ion/IonizerBundled.java new file mode 100644 index 0000000..f4c21b4 --- /dev/null +++ b/src/mightypork/utils/ion/IonizerBundled.java @@ -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 + */ +public abstract class IonizerBundled { + + @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); + +} diff --git a/src/mightypork/utils/math/algo/Move.java b/src/mightypork/utils/math/algo/Move.java index b012780..bbe6332 100644 --- a/src/mightypork/utils/math/algo/Move.java +++ b/src/mightypork/utils/math/algo/Move.java @@ -30,15 +30,9 @@ public class Move { return new Move(x, y); } - private byte x; - private byte y; - - - public Move() - { - // for ion - } - + private final byte x; + private final byte y; + public Move(int x, int y) { @@ -70,11 +64,4 @@ public class Move { { return "(" + x + " ; " + y + ")"; } - - - protected void setTo(byte x, byte y) - { - this.x = x; - this.y = y; - } }