Some refactoring and cleaning, string utils.

master
Ondřej Hruška 11 years ago
parent 272fb63168
commit 33696050d4
  1. 60
      src/mightypork/utils/Convert.java
  2. 34
      src/mightypork/utils/MapSort.java
  3. 38
      src/mightypork/utils/Reflect.java
  4. 231
      src/mightypork/utils/Str.java
  5. 153
      src/mightypork/utils/Support.java
  6. 2
      src/mightypork/utils/annotations/Alias.java
  7. 2
      src/mightypork/utils/annotations/FactoryMethod.java
  8. 90
      src/mightypork/utils/config/SimpleConfig.java
  9. 36
      src/mightypork/utils/config/propmgr/Property.java
  10. 96
      src/mightypork/utils/config/propmgr/PropertyManager.java
  11. 30
      src/mightypork/utils/config/propmgr/PropertyStore.java
  12. 10
      src/mightypork/utils/config/propmgr/properties/BooleanProperty.java
  13. 10
      src/mightypork/utils/config/propmgr/properties/DoubleProperty.java
  14. 10
      src/mightypork/utils/config/propmgr/properties/IntegerProperty.java
  15. 10
      src/mightypork/utils/config/propmgr/properties/StringProperty.java
  16. 52
      src/mightypork/utils/config/propmgr/store/PropertyFile.java
  17. 102
      src/mightypork/utils/config/propmgr/store/SortedProperties.java
  18. 41
      src/mightypork/utils/eventbus/BusEvent.java
  19. 208
      src/mightypork/utils/eventbus/EventBus.java
  20. 78
      src/mightypork/utils/eventbus/EventChannel.java
  21. 30
      src/mightypork/utils/eventbus/clients/BusNode.java
  22. 18
      src/mightypork/utils/eventbus/clients/ClientHub.java
  23. 2
      src/mightypork/utils/eventbus/clients/ClientList.java
  24. 8
      src/mightypork/utils/eventbus/clients/DelegatingClient.java
  25. 30
      src/mightypork/utils/eventbus/clients/DelegatingList.java
  26. 4
      src/mightypork/utils/eventbus/clients/ToggleableClient.java
  27. 2
      src/mightypork/utils/eventbus/events/DestroyEvent.java
  28. 10
      src/mightypork/utils/eventbus/events/UpdateEvent.java
  29. 2
      src/mightypork/utils/eventbus/events/flags/DelayedEvent.java
  30. 2
      src/mightypork/utils/eventbus/events/flags/NonConsumableEvent.java
  31. 2
      src/mightypork/utils/eventbus/events/flags/NonRejectableEvent.java
  32. 16
      src/mightypork/utils/exceptions/CorruptDataException.java
  33. 16
      src/mightypork/utils/exceptions/IllegalValueException.java
  34. 16
      src/mightypork/utils/exceptions/KeyAlreadyExistsException.java
  35. 18
      src/mightypork/utils/files/FileSuffixFilter.java
  36. 88
      src/mightypork/utils/files/FileTreeDiff.java
  37. 194
      src/mightypork/utils/files/FileUtil.java
  38. 14
      src/mightypork/utils/files/InstanceLock.java
  39. 52
      src/mightypork/utils/files/OsUtils.java
  40. 36
      src/mightypork/utils/files/WorkDir.java
  41. 46
      src/mightypork/utils/files/zip/ZipBuilder.java
  42. 66
      src/mightypork/utils/files/zip/ZipUtils.java
  43. 2
      src/mightypork/utils/interfaces/Destroyable.java
  44. 6
      src/mightypork/utils/interfaces/Enableable.java
  45. 6
      src/mightypork/utils/interfaces/Hideable.java
  46. 12
      src/mightypork/utils/interfaces/Pauseable.java
  47. 2
      src/mightypork/utils/interfaces/Pollable.java
  48. 2
      src/mightypork/utils/interfaces/Updateable.java
  49. 218
      src/mightypork/utils/ion/Ion.java
  50. 6
      src/mightypork/utils/ion/IonBinary.java
  51. 6
      src/mightypork/utils/ion/IonBundled.java
  52. 180
      src/mightypork/utils/ion/IonDataBundle.java
  53. 212
      src/mightypork/utils/ion/IonInput.java
  54. 28
      src/mightypork/utils/ion/IonMapWrapper.java
  55. 204
      src/mightypork/utils/ion/IonOutput.java
  56. 28
      src/mightypork/utils/ion/IonSequenceWrapper.java
  57. 12
      src/mightypork/utils/ion/IonizerBinary.java
  58. 12
      src/mightypork/utils/ion/IonizerBundled.java
  59. 144
      src/mightypork/utils/logging/Log.java
  60. 22
      src/mightypork/utils/logging/monitors/LogMonitor.java
  61. 4
      src/mightypork/utils/logging/monitors/LogMonitorStdout.java
  62. 4
      src/mightypork/utils/logging/writers/ArchivingLog.java
  63. 28
      src/mightypork/utils/logging/writers/LogWriter.java
  64. 72
      src/mightypork/utils/logging/writers/SimpleLog.java
  65. 144
      src/mightypork/utils/math/Calc.java
  66. 74
      src/mightypork/utils/math/Polar.java
  67. 92
      src/mightypork/utils/math/Range.java
  68. 78
      src/mightypork/utils/math/algo/Coord.java
  69. 32
      src/mightypork/utils/math/algo/Move.java
  70. 28
      src/mightypork/utils/math/algo/Moves.java
  71. 44
      src/mightypork/utils/math/algo/floodfill/FloodFill.java
  72. 2
      src/mightypork/utils/math/algo/pathfinding/Heuristic.java
  73. 126
      src/mightypork/utils/math/algo/pathfinding/PathFinder.java
  74. 28
      src/mightypork/utils/math/algo/pathfinding/PathFinderProxy.java
  75. 2
      src/mightypork/utils/math/algo/pathfinding/heuristics/DiagonalHeuristic.java
  76. 2
      src/mightypork/utils/math/algo/pathfinding/heuristics/ManhattanHeuristic.java
  77. 12
      src/mightypork/utils/math/angles/Angles.java
  78. 46
      src/mightypork/utils/math/angles/Deg.java
  79. 30
      src/mightypork/utils/math/angles/Rad.java
  80. 78
      src/mightypork/utils/math/animation/Animator.java
  81. 26
      src/mightypork/utils/math/animation/AnimatorBounce.java
  82. 20
      src/mightypork/utils/math/animation/AnimatorRewind.java
  83. 134
      src/mightypork/utils/math/animation/Easing.java
  84. 170
      src/mightypork/utils/math/animation/NumAnimated.java
  85. 20
      src/mightypork/utils/math/animation/NumAnimatedDeg.java
  86. 20
      src/mightypork/utils/math/animation/NumAnimatedRad.java
  87. 116
      src/mightypork/utils/math/animation/VectAnimated.java
  88. 126
      src/mightypork/utils/math/color/Color.java
  89. 24
      src/mightypork/utils/math/color/ColorAlphaAdjuster.java
  90. 30
      src/mightypork/utils/math/color/ColorHsb.java
  91. 24
      src/mightypork/utils/math/color/ColorRgb.java
  92. 6
      src/mightypork/utils/math/color/Grad.java
  93. 2
      src/mightypork/utils/math/color/GradH.java
  94. 2
      src/mightypork/utils/math/color/GradV.java
  95. 6
      src/mightypork/utils/math/color/pal/CGA.java
  96. 2
      src/mightypork/utils/math/color/pal/CMDR.java
  97. 10
      src/mightypork/utils/math/color/pal/PAL16.java
  98. 12
      src/mightypork/utils/math/color/pal/RGB.java
  99. 6
      src/mightypork/utils/math/color/pal/ZX.java
  100. 18
      src/mightypork/utils/math/constraints/CachedConstraint.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -8,7 +8,7 @@ package mightypork.utils;
* @author Ondřej Hruška (MightyPork)
*/
public class Convert {
/**
* Get INTEGER
*
@ -26,8 +26,8 @@ public class Convert {
} catch (final NumberFormatException e) {}
return def;
}
/**
* Get DOUBLE
*
@ -45,8 +45,8 @@ public class Convert {
} catch (final NumberFormatException e) {}
return def;
}
/**
* Get FLOAT
*
@ -62,8 +62,8 @@ public class Convert {
} catch (final NumberFormatException e) {}
return def;
}
/**
* Get BOOLEAN
*
@ -76,7 +76,7 @@ public class Convert {
if (o == null) return def;
if (o instanceof Boolean) return ((Boolean) o).booleanValue();
if (o instanceof Number) return ((Number) o).intValue() != 0;
if (o instanceof String) {
final String s = ((String) o).trim().toLowerCase();
if (s.equals("0")) return false;
@ -85,23 +85,23 @@ public class Convert {
final double n = Double.parseDouble(s);
return n != 0;
} catch (final NumberFormatException e) {}
if (s.equals("true")) return true;
if (s.equals("yes")) return true;
if (s.equals("y")) return true;
if (s.equals("a")) return true;
if (s.equals("enabled")) return true;
if (s.equals("false")) return false;
if (s.equals("no")) return false;
if (s.equals("n")) return false;
if (s.equals("disabled")) return true;
}
return def;
}
/**
* Get STRING
*
@ -113,19 +113,19 @@ public class Convert {
{
if (o == null) return def;
if (o instanceof String) return ((String) o);
if (o instanceof Float) return Support.str((float) o);
if (o instanceof Double) return Support.str((double) o);
if (o instanceof Float) return Str.val((float) o);
if (o instanceof Double) return Str.val((double) o);
if (o instanceof Class<?>) {
return Support.str(o);
return Str.val(o);
}
return o.toString();
}
/**
* Get INTEGER
*
@ -136,8 +136,8 @@ public class Convert {
{
return toInteger(o, 0);
}
/**
* Get DOUBLE
*
@ -148,8 +148,8 @@ public class Convert {
{
return toDouble(o, 0d);
}
/**
* Get FLOAT
*
@ -160,8 +160,8 @@ public class Convert {
{
return toFloat(o, 0f);
}
/**
* Get BOOLEAN
*
@ -172,8 +172,8 @@ public class Convert {
{
return toBoolean(o, false);
}
/**
* Get STRING
*

@ -16,7 +16,7 @@ import java.util.Map.Entry;
* @author Ondřej Hruška (MightyPork)
*/
public class MapSort {
/**
* Sort a map by keys, maintaining key-value pairs, using natural order.
*
@ -28,8 +28,8 @@ public class MapSort {
{
return byKeys(map, null);
}
/**
* Sort a map by keys, maintaining key-value pairs.
*
@ -41,10 +41,10 @@ public class MapSort {
public static <K, V> LinkedHashMap<K, V> byKeys(Map<K, V> map, Comparator<K> comparator)
{
final List<K> keys = new LinkedList<>(map.keySet());
if (comparator == null) {
comparator = new Comparator<K>() {
@Override
public int compare(K arg0, K arg1)
{
@ -52,18 +52,18 @@ public class MapSort {
}
};
}
Collections.sort(keys, comparator);
final LinkedHashMap<K, V> sortedMap = new LinkedHashMap<>();
for (final K key : keys) {
sortedMap.put(key, map.get(key));
}
return sortedMap;
}
/**
* Sort a map by values, maintaining key-value pairs, using natural order.
*
@ -75,8 +75,8 @@ public class MapSort {
{
return byValues(map, null);
}
/**
* Sort a map by values, maintaining key-value pairs.
*
@ -87,9 +87,9 @@ public class MapSort {
public static <K, V> LinkedHashMap<K, V> byValues(Map<K, V> map, final Comparator<V> comparator)
{
final List<Map.Entry<K, V>> entries = new LinkedList<>(map.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<K, V>>() {
@SuppressWarnings("unchecked")
@Override
public int compare(Entry<K, V> o1, Entry<K, V> o2)
@ -98,13 +98,13 @@ public class MapSort {
return comparator.compare(o1.getValue(), o2.getValue());
}
});
final LinkedHashMap<K, V> sortedMap = new LinkedHashMap<>();
for (final Map.Entry<K, V> entry : entries) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
}

@ -14,7 +14,7 @@ import java.lang.reflect.Type;
* @author Ondřej Hruška (MightyPork)
*/
public class Reflect {
/**
* Get annotation of given type from an object
*
@ -26,8 +26,8 @@ public class Reflect {
{
return tested.getClass().getAnnotation(annotation);
}
/**
* Check if an object has an annotation of given trype
*
@ -39,8 +39,8 @@ public class Reflect {
{
return tested.getClass().isAnnotationPresent(annotation);
}
/**
* Get generic parameters of a class
*
@ -50,25 +50,25 @@ public class Reflect {
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.");
throw new RuntimeException(Str.val(clazz) + " is not generic.");
}
/**
* Get value of a public static final field. If the modifiers don't match,
* an exception is thrown.
@ -82,15 +82,15 @@ public class Reflect {
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 ReflectiveOperationException("The " + fieldName + " field of " + Support.str(objClass) + " must be static and final!");
throw new ReflectiveOperationException("The " + fieldName + " field of " + Str.val(objClass) + " must be static and final!");
}
fld.setAccessible(true);
return fld.get(null);
}
}

@ -0,0 +1,231 @@
package mightypork.utils;
import mightypork.utils.annotations.Alias;
import mightypork.utils.math.AlignX;
/**
* General purpose string utilities
*
* @author Ondřej Hruška (MightyPork)
*/
public class Str {
public static String fromLastDot(String s)
{
return fromLast(s, '.');
}
public static String toLastDot(String s)
{
return toLast(s, '.');
}
public static String fromLast(String s, char c)
{
if (s == null) return null;
if (s.lastIndexOf(c) == -1) return "";
return s.substring(s.lastIndexOf(c) + 1, s.length());
}
public static String toLast(String s, char c)
{
if (s == null) return null;
if (s.lastIndexOf(c) == -1) return s;
return s.substring(0, s.lastIndexOf(c));
}
public static String fromFirst(String s, char c)
{
if (s == null) return null;
if (s.indexOf(c) == -1) return "";
return s.substring(s.indexOf(c) + 1, s.length());
}
public static String toFirst(String s, char c)
{
if (s == null) return null;
if (s.indexOf(c) == -1) return s;
return s.substring(0, s.indexOf(c));
}
public static String fromEnd(String s, int chars)
{
return s.substring(s.length() - chars, s.length());
}
public static String fromStart(String s, int chars)
{
return s.substring(0, chars);
}
public static String pad(String s, int length)
{
return pad(s, length, AlignX.LEFT);
}
public static String pad(String s, int length, AlignX align)
{
return pad(s, length, align, ' ');
}
public static String pad(String s, int length, AlignX align, char fill)
{
final String filling = repeat("" + fill, length);
switch (align) {
case LEFT:
s += filling;
return fromStart(s, length);
case RIGHT:
s += filling;
return fromEnd(s, length);
case CENTER:
if (s.length() >= length) return s;
s = filling + s + filling;
final int cut = (int) (s.length() / 2D - length / 2D);
return s.substring(cut, s.length() - cut);
}
throw new IllegalArgumentException("Impossible error.");
}
/**
* Repeat a string
*
* @param repeated string
* @param count
* @return output
*/
public static String repeat(String repeated, int count)
{
String s = "";
for (int i = 0; i < count; i++)
s += repeated;
return s;
}
public static boolean isValidFilenameChar(char ch)
{
return isValidFilenameString(Character.toString(ch));
}
public static boolean isValidFilenameString(String filename)
{
return filename.matches("[a-zA-Z0-9 +\\-.,_%@#!]+");
}
public static String ellipsisStart(String orig, int length)
{
if (orig.length() > length) {
orig = "\u2026" + orig.substring(length, orig.length());
}
return orig;
}
public static String ellipsisEnd(String orig, int length)
{
if (orig.length() > length) {
orig = orig.substring(0, length - 1) + "\u2026";
}
return orig;
}
/**
* Convert a class to string, preserving name and outer class, but excluding
* path.
*
* @param cls the class
* @return class name
*/
public static String val(Class<?> cls)
{
final Alias ln = cls.getAnnotation(Alias.class);
if (ln != null) {
return ln.name();
}
String name = cls.getName();
String sep = "";
if (name.contains("$")) {
name = name.substring(name.lastIndexOf("$") + 1);
sep = "$";
} else {
name = name.substring(name.lastIndexOf(".") + 1);
sep = ".";
}
final Class<?> enclosing = cls.getEnclosingClass();
return (enclosing == null ? "" : Str.val(enclosing) + sep) + name;
}
/**
* Convert double to string, remove the mess at the end.
*
* @param d double
* @return string
*/
public static String val(Double d)
{
String s = d.toString();
s = s.replace(',', '.');
s = s.replaceAll("([0-9]+\\.[0-9]+)00+[0-9]+", "$1");
s = s.replaceAll("0+$", "");
s = s.replaceAll("\\.$", "");
return s;
}
/**
* Convert object to string. If the object overrides toString(), it is
* caled. Otherwise it's class name is converted to string.
*
* @param o object
* @return string representation
*/
public static String val(Object o)
{
if (o == null) return "<null>";
boolean hasToString = false;
try {
hasToString = (o.getClass().getMethod("toString").getDeclaringClass() != Object.class);
} catch (final Throwable t) {
// oh well..
}
if (hasToString) {
return o.toString();
} else {
return val(o.getClass());
}
}
}

@ -9,8 +9,6 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import mightypork.utils.annotations.Alias;
/**
* Miscelanous utilities
@ -18,7 +16,7 @@ import mightypork.utils.annotations.Alias;
* @author Ondřej Hruška (MightyPork)
*/
public final class Support {
/**
* Create a new thread of the runnable, and start it.
*
@ -31,8 +29,8 @@ public final class Support {
t.start();
return t;
}
/**
* Pick first non-null option
*
@ -44,11 +42,11 @@ public final class Support {
for (final Object o : options) {
if (o != null) return o;
}
return null; // all null
}
/**
* Get current time/date for given format.
*
@ -59,8 +57,8 @@ public final class Support {
{
return (new SimpleDateFormat(format)).format(new Date());
}
/**
* Parse array of vararg key, value pairs to a LinkedHashMap.<br>
* Example:
@ -85,11 +83,11 @@ public final class Support {
public static <K, V> Map<K, V> parseVarArgs(Object... args) throws ClassCastException, IllegalArgumentException
{
final LinkedHashMap<K, V> attrs = new LinkedHashMap<>();
if (args.length % 2 != 0) {
throw new IllegalArgumentException("Odd number of elements in varargs map!");
}
K key = null;
for (final Object o : args) {
if (key == null) {
@ -100,11 +98,11 @@ public final class Support {
key = null;
}
}
return attrs;
}
/**
* Get if an Object is in array (using equals)
*
@ -119,8 +117,8 @@ public final class Support {
}
return false;
}
/**
* Get if string is in array
*
@ -140,8 +138,8 @@ public final class Support {
return false;
}
}
/**
* Make enumeration iterable
*
@ -152,7 +150,7 @@ public final class Support {
{
return new IterableEnumerationWrapper<>(enumeration);
}
/**
* Helper class for iterationg over an {@link Enumeration}
*
@ -160,10 +158,10 @@ public final class Support {
* @param <T> target element type (will be cast)
*/
private static class IterableEnumerationWrapper<T> implements Iterable<T> {
private final Enumeration<? extends T> enumeration;
/**
* @param enumeration the iterated enumeration
*/
@ -171,27 +169,27 @@ public final class Support {
{
this.enumeration = enumeration;
}
@Override
public Iterator<T> iterator()
{
return new Iterator<T>() {
@Override
public boolean hasNext()
{
return enumeration.hasMoreElements();
}
@Override
public T next()
{
return enumeration.nextElement();
}
@Override
public void remove()
{
@ -199,99 +197,6 @@ public final class Support {
}
};
}
}
/**
* Convert a class to string, preserving name and outer class, but excluding
* path.
*
* @param cls the class
* @return class name
*/
public static String str(Class<?> cls)
{
final Alias ln = cls.getAnnotation(Alias.class);
if (ln != null) {
return ln.name();
}
String name = cls.getName();
String sep = "";
if (name.contains("$")) {
name = name.substring(name.lastIndexOf("$") + 1);
sep = "$";
} else {
name = name.substring(name.lastIndexOf(".") + 1);
sep = ".";
}
final Class<?> enclosing = cls.getEnclosingClass();
return (enclosing == null ? "" : Support.str(enclosing) + sep) + name;
}
/**
* Convert double to string, remove the mess at the end.
*
* @param d double
* @return string
*/
public static String str(Double d)
{
String s = d.toString();
s = s.replace(',', '.');
s = s.replaceAll("([0-9]+\\.[0-9]+)00+[0-9]+", "$1");
s = s.replaceAll("0+$", "");
s = s.replaceAll("\\.$", "");
return s;
}
/**
* Convert float to string, remove the mess at the end.
*
* @param f float
* @return string
*/
public static String str(Float f)
{
String s = f.toString();
s = s.replaceAll("([0-9]+\\.[0-9]+)00+[0-9]+", "$1");
s = s.replaceAll("0+$", "");
s = s.replaceAll("\\.$", "");
return s;
}
/**
* Convert object to string. If the object overrides toString(), it is
* caled. Otherwise it's class name is converted to string.
*
* @param o object
* @return string representation
*/
public static String str(Object o)
{
if (o == null) return "<null>";
boolean hasToString = false;
try {
hasToString = (o.getClass().getMethod("toString").getDeclaringClass() != Object.class);
} catch (final Throwable t) {
// oh well..
}
if (hasToString) {
return o.toString();
} else {
return str(o.getClass());
}
}
}

@ -20,6 +20,6 @@ import java.lang.annotation.Target;
@Documented
@Target(ElementType.TYPE)
public @interface Alias {
String name();
}

@ -18,5 +18,5 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Documented
public @interface FactoryMethod {
}

@ -23,7 +23,7 @@ import mightypork.utils.logging.Log;
* @author Ondřej Hruška (MightyPork)
*/
public class SimpleConfig {
/**
* Load list from file
*
@ -34,11 +34,11 @@ public class SimpleConfig {
public static List<String> listFromFile(File file) throws IOException
{
final String fileText = FileUtil.fileToString(file);
return listFromString(fileText);
}
/**
* Load map from file
*
@ -49,11 +49,11 @@ public class SimpleConfig {
public static Map<String, String> mapFromFile(File file) throws IOException
{
final String fileText = FileUtil.fileToString(file);
return mapFromString(fileText);
}
/**
* Load list from string
*
@ -63,27 +63,27 @@ public class SimpleConfig {
public static List<String> listFromString(String text)
{
final List<String> list = new ArrayList<>();
final String[] groupsLines = text.split("\n");
for (String s : groupsLines) {
// ignore invalid lines
if (s.length() == 0) continue;
if (s.startsWith("#") || s.startsWith("//")) continue;
// NULL value
if (s.equalsIgnoreCase("NULL")) s = null;
if (s != null) s = s.replace("\\n", "\n");
// save extracted key-value pair
list.add(s);
}
return list;
}
/**
* Load map from string
*
@ -93,51 +93,51 @@ public class SimpleConfig {
public static Map<String, String> mapFromString(String text)
{
final LinkedHashMap<String, String> pairs = new LinkedHashMap<>();
final String[] groupsLines = text.split("\n");
for (final String s : groupsLines) {
// ignore invalid lines
if (s.length() == 0) continue;
if (s.startsWith("#") || s.startsWith("//")) continue;
if (!s.contains("=")) continue;
// split and trim
String[] parts = s.split("=");
for (int i = 0; i < parts.length; i++) {
parts[i] = parts[i].trim();
}
// check if both parts are valid
if (parts.length == 0) {
Log.w("Bad line in config file: " + s);
continue;
}
if (parts.length == 1) {
parts = new String[] { parts[0], "" };
}
if (parts.length != 2) {
Log.w("Bad line in config file: " + s);
continue;
}
// NULL value
if (parts[0].equalsIgnoreCase("NULL")) parts[0] = null;
if (parts[1].equalsIgnoreCase("NULL")) parts[1] = null;
if (parts[0] != null) parts[0] = parts[0].replace("\\n", "\n");
if (parts[1] != null) parts[1] = parts[1].replace("\\n", "\n");
// save extracted key-value pair
pairs.put(parts[0], parts[1]);
}
return pairs;
}
/**
* Save map to file
*
@ -149,35 +149,35 @@ public class SimpleConfig {
public static void mapToFile(File target, Map<String, String> data, boolean allowNulls) throws IOException
{
final List<String> lines = new ArrayList<>();
for (final Entry<String, String> e : data.entrySet()) {
String key = e.getKey();
String value = e.getValue();
if (!allowNulls && (key == null || value == null || key.length() == 0 || value.length() == 0)) continue;
if (key == null) key = "NULL";
if (value == null) value = "NULL";
key = key.replace("\n", "\\n");
value = value.replace("\n", "\\n");
lines.add(key + " = " + value);
}
String text = ""; // # File written by SimpleConfig
for (final String s : lines) {
if (text.length() > 0) text += "\n";
text += s;
}
FileUtil.stringToFile(target, text);
}
/**
* Save list to file
*
@ -188,18 +188,18 @@ public class SimpleConfig {
public static void listToFile(File target, List<String> data) throws IOException
{
String text = ""; // # File written by SimpleConfig
for (String s : data) {
if (text.length() > 0) text += "\n";
if (s == null) s = "NULL";
s = s.replace("\n", "\\n");
text += s;
}
FileUtil.stringToFile(target, text);
}
}

@ -14,14 +14,14 @@ import mightypork.utils.annotations.Stub;
* @param <T> property type
*/
public abstract class Property<T> {
protected final String comment;
protected final String key;
protected T value;
protected final T defaultValue;
/**
* Create a property without comment
*
@ -33,8 +33,8 @@ public abstract class Property<T> {
{
this(key, defaultValue, null);
}
/**
* Create a property with a comment
*
@ -51,8 +51,8 @@ public abstract class Property<T> {
this.value = defaultValue;
this.defaultValue = defaultValue;
}
/**
* Parse a string representation of the value into this property. If the
* value cannot be decoded, use the default value instead.
@ -60,8 +60,8 @@ public abstract class Property<T> {
* @param string property value as string
*/
public abstract void fromString(String string);
/**
* Get property value as string (compatible with `fromString())
*
@ -73,8 +73,8 @@ public abstract class Property<T> {
{
return Convert.toString(value, Convert.toString(defaultValue));
}
/**
* Get the current property value
*
@ -84,8 +84,8 @@ public abstract class Property<T> {
{
return value;
}
/**
* Set property value.<br>
* Uses Object to allow setValue(Object) method in {@link PropertyManager}
@ -98,8 +98,8 @@ public abstract class Property<T> {
{
this.value = (T) value;
}
/**
* Get property comment.
*
@ -109,8 +109,8 @@ public abstract class Property<T> {
{
return comment;
}
/**
* Get property key
*

@ -22,12 +22,12 @@ import mightypork.utils.logging.Log;
* @author Ondřej Hruška (MightyPork)
*/
public class PropertyManager {
private final TreeMap<String, Property<?>> entries = new TreeMap<>();
private final TreeMap<String, String> renameTable = new TreeMap<>();
private final PropertyStore props;
/**
* Create property manager from file path and a header comment.<br>
* This is the same as using a {@link PropertyFile} store.
@ -39,8 +39,8 @@ public class PropertyManager {
{
this(new PropertyFile(file, comment));
}
/**
* Create property manager based on provided {@link PropertyStore}
*
@ -51,61 +51,61 @@ public class PropertyManager {
{
this.props = props;
}
/**
* Load from file
*/
public void load()
{
props.load();
// rename keys (useful if keys change but value is to be kept)
for (final Entry<String, String> entry : renameTable.entrySet()) {
final String value = props.getProperty(entry.getKey());
if (value == null) continue;
final String oldKey = entry.getKey();
final String newKey = entry.getValue();
props.removeProperty(oldKey);
props.setProperty(newKey, value, entries.get(newKey).getComment());
}
for (final Property<?> entry : entries.values()) {
entry.fromString(props.getProperty(entry.getKey()));
}
}
public void save()
{
try {
final ArrayList<String> keyList = new ArrayList<>();
// validate entries one by one, replace with default when needed
for (final Property<?> entry : entries.values()) {
keyList.add(entry.getKey());
props.setProperty(entry.getKey(), entry.toString(), entry.getComment());
}
// removed unused props
for (final String key : props.keys()) {
if (!keyList.contains(key)) {
props.removeProperty(key);
}
}
props.save();
} catch (final IOException ioe) {
ioe.printStackTrace();
}
}
/**
* Get a property entry (rarely used)
*
@ -121,8 +121,8 @@ public class PropertyManager {
return null;
}
}
/**
* Get boolean property
*
@ -133,8 +133,8 @@ public class PropertyManager {
{
return Convert.toBoolean(getProperty(k).getValue());
}
/**
* Get numeric property
*
@ -145,8 +145,8 @@ public class PropertyManager {
{
return Convert.toInteger(getProperty(k).getValue());
}
/**
* Get numeric property as double
*
@ -157,8 +157,8 @@ public class PropertyManager {
{
return Convert.toDouble(getProperty(k).getValue());
}
/**
* Get string property
*
@ -169,8 +169,8 @@ public class PropertyManager {
{
return Convert.toString(getProperty(k).getValue());
}
/**
* Get arbitrary property. Make sure it's of the right type!
*
@ -186,8 +186,8 @@ public class PropertyManager {
return null;
}
}
/**
* Add a boolean property
*
@ -199,8 +199,8 @@ public class PropertyManager {
{
addProperty(new BooleanProperty(k, d, comment));
}
/**
* Add a numeric property (double)
*
@ -212,8 +212,8 @@ public class PropertyManager {
{
addProperty(new DoubleProperty(k, d, comment));
}
/**
* Add a numeric property
*
@ -225,8 +225,8 @@ public class PropertyManager {
{
addProperty(new IntegerProperty(k, d, comment));
}
/**
* Add a string property
*
@ -238,8 +238,8 @@ public class PropertyManager {
{
addProperty(new StringProperty(k, d, comment));
}
/**
* Add a generic property (can be used with custom property types)
*
@ -249,8 +249,8 @@ public class PropertyManager {
{
entries.put(prop.getKey(), prop);
}
/**
* Rename key before loading; value is preserved
*
@ -262,8 +262,8 @@ public class PropertyManager {
renameTable.put(oldKey, newKey);
return;
}
/**
* Set value saved to certain key.
*
@ -274,8 +274,8 @@ public class PropertyManager {
{
getProperty(key).setValue(value);
}
/**
* Set heading comment of the property store.
*
@ -285,5 +285,5 @@ public class PropertyManager {
{
props.setComment(fileComment);
}
}

@ -13,30 +13,30 @@ import java.util.Collection;
* @author Ondřej Hruška (MightyPork)
*/
public interface PropertyStore {
/**
* Set a header comment
*
* @param comment the comment text (can be multi-line)
*/
void setComment(String comment);
/**
* Load properties from the file / store. If the file does not exist or is
* inaccessible, nothing is loaded.
*/
void load();
/**
* Save properties to the file / store.
*
* @throws IOException if the file cannot be created or written.
*/
void save() throws IOException;
/**
* Get a property value
*
@ -44,8 +44,8 @@ public interface PropertyStore {
* @return value retrieved from the file, or null if none found.
*/
String getProperty(String key);
/**
* Set a property value
*
@ -54,22 +54,22 @@ public interface PropertyStore {
* @param comment property comment. Can be null.
*/
void setProperty(String key, String value, String comment);
/**
* Remove a property from the list.
*
* @param key property key to remove
*/
void removeProperty(String key);
/**
* Clear the property list
*/
void clear();
/**
* Get keys collection (can be used for iterating)
*

@ -11,19 +11,19 @@ import mightypork.utils.config.propmgr.Property;
* @author Ondřej Hruška (MightyPork)
*/
public class BooleanProperty extends Property<Boolean> {
public BooleanProperty(String key, Boolean defaultValue)
{
super(key, defaultValue);
}
public BooleanProperty(String key, Boolean defaultValue, String comment)
{
super(key, defaultValue, comment);
}
@Override
public void fromString(String string)
{

@ -11,19 +11,19 @@ import mightypork.utils.config.propmgr.Property;
* @author Ondřej Hruška (MightyPork)
*/
public class DoubleProperty extends Property<Double> {
public DoubleProperty(String key, Double defaultValue)
{
super(key, defaultValue);
}
public DoubleProperty(String key, Double defaultValue, String comment)
{
super(key, defaultValue, comment);
}
@Override
public void fromString(String string)
{

@ -11,19 +11,19 @@ import mightypork.utils.config.propmgr.Property;
* @author Ondřej Hruška (MightyPork)
*/
public class IntegerProperty extends Property<Integer> {
public IntegerProperty(String key, Integer defaultValue)
{
super(key, defaultValue);
}
public IntegerProperty(String key, Integer defaultValue, String comment)
{
super(key, defaultValue, comment);
}
@Override
public void fromString(String string)
{

@ -11,19 +11,19 @@ import mightypork.utils.config.propmgr.Property;
* @author Ondřej Hruška (MightyPork)
*/
public class StringProperty extends Property<String> {
public StringProperty(String key, String defaultValue)
{
super(key, defaultValue);
}
public StringProperty(String key, String defaultValue, String comment)
{
super(key, defaultValue, comment);
}
@Override
public void fromString(String string)
{

@ -17,48 +17,48 @@ import mightypork.utils.config.propmgr.PropertyStore;
* @author Ondřej Hruška (MightyPork)
*/
public class PropertyFile implements PropertyStore {
private String comment;
private final File file;
private final SortedProperties props;
public PropertyFile(File file)
{
this.file = file;
this.comment = null;
this.props = new SortedProperties();
}
public PropertyFile(File file, String comment)
{
this.file = file;
this.comment = comment;
this.props = new SortedProperties();
}
@Override
public void setComment(String comment)
{
this.comment = comment;
}
@Override
public void load()
{
if (!file.exists()) return;
try(FileInputStream in = new FileInputStream(file)) {
props.load(in);
} catch (final IOException e) {
// ignore
}
}
@Override
public void save() throws IOException
{
@ -67,55 +67,55 @@ public class PropertyFile implements PropertyStore {
throw new IOException("Cound not create config file.");
}
}
try(FileOutputStream out = new FileOutputStream(file)) {
props.store(out, comment);
}
}
@Override
public String getProperty(String key)
{
return props.getProperty(key);
}
@Override
public void setProperty(String key, String value, String comment)
{
props.setProperty(key, value);
props.setKeyComment(key, comment);
}
@Override
public void removeProperty(String key)
{
props.remove(key);
}
@Override
public void clear()
{
props.clear();
}
@SuppressWarnings("unchecked")
@Override
public Collection<String> keys()
{
// Set<String> keys = new HashSet<>();
// for (Object o : props.keySet()) {
// keys.add((String) o);
// }
// return keys;
// we know it is strings.
return (Collection<String>) (Collection<?>) props.keySet();
}
}

@ -23,15 +23,15 @@ import java.util.Vector;
* @author Ondřej Hruška (MightyPork)
*/
class SortedProperties extends java.util.Properties {
/** Comments for individual keys */
private final Hashtable<String, String> keyComments = new Hashtable<>();
private static void writeComments(BufferedWriter bw, String comm) throws IOException
{
final String comments = comm.replace("\n\n", "\n \n");
final int len = comments.length();
int current = 0;
int last = 0;
@ -44,7 +44,7 @@ class SortedProperties extends java.util.Properties {
if (last != current) {
bw.write("# " + comments.substring(last, current));
}
if (c > '\u00ff') {
uu[2] = hexDigit(c, 12);
uu[3] = hexDigit(c, 8);
@ -64,13 +64,13 @@ class SortedProperties extends java.util.Properties {
if (last != current) {
bw.write("# " + comments.substring(last, current));
}
bw.newLine();
bw.newLine();
bw.newLine();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public synchronized Enumeration keys()
@ -83,8 +83,8 @@ class SortedProperties extends java.util.Properties {
Collections.sort(keyList); //sort!
return keyList.elements();
}
private static String saveConvert(String theString, boolean escapeSpace, boolean escapeUnicode)
{
final int len = theString.length();
@ -93,10 +93,10 @@ class SortedProperties extends java.util.Properties {
bufLen = Integer.MAX_VALUE;
}
final StringBuffer result = new StringBuffer(bufLen);
for (int x = 0; x < len; x++) {
final char ch = theString.charAt(x);
// Handle common case first, selecting largest block that
// avoids the specials below
if ((ch > 61) && (ch < 127)) {
@ -108,7 +108,7 @@ class SortedProperties extends java.util.Properties {
result.append(ch);
continue;
}
switch (ch) {
case ' ':
if (x == 0 || escapeSpace) {
@ -116,27 +116,27 @@ class SortedProperties extends java.util.Properties {
}
result.append(' ');
break;
case '\t':
result.append('\\');
result.append('t');
break;
case '\n':
result.append('\\');
result.append('n');
break;
case '\r':
result.append('\\');
result.append('r');
break;
case '\f':
result.append('\\');
result.append('f');
break;
case '=': // Fall through
case ':': // Fall through
case '#': // Fall through
@ -144,7 +144,7 @@ class SortedProperties extends java.util.Properties {
result.append('\\');
result.append(ch);
break;
default:
if (((ch < 0x0020) || (ch > 0x007e)) & escapeUnicode) {
result.append('\\');
@ -158,11 +158,11 @@ class SortedProperties extends java.util.Properties {
}
}
}
return result.toString();
}
/**
* Set additional comment to a key
*
@ -173,75 +173,75 @@ class SortedProperties extends java.util.Properties {
{
keyComments.put(key, comment);
}
@SuppressWarnings("rawtypes")
@Override
public void store(OutputStream out, String comments) throws IOException
{
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
final boolean escUnicode = false;
boolean firstEntry = true;
String lastSectionBeginning = "";
if (comments != null) {
writeComments(bw, comments);
}
synchronized (this) {
for (final Enumeration e = keys(); e.hasMoreElements();) {
boolean wasNewLine = false;
String key = (String) e.nextElement();
String val = (String) get(key);
key = saveConvert(key, true, escUnicode);
val = saveConvert(val, false, escUnicode);
// separate sections
if (!lastSectionBeginning.equals(key.split("[.]")[0])) {
if (!firstEntry) {
bw.newLine();
bw.newLine();
}
wasNewLine = true;
lastSectionBeginning = key.split("[.]")[0];
}
if (keyComments.containsKey(key)) {
String cm = keyComments.get(key);
cm = cm.replace("\r", "\n");
cm = cm.replace("\r\n", "\n");
cm = cm.replace("\n\n", "\n \n");
final String[] cmlines = cm.split("\n");
// newline before comments
if (!wasNewLine && !firstEntry) {
bw.newLine();
}
for (final String cmline : cmlines) {
bw.write("# " + cmline);
bw.newLine();
}
}
bw.write(key + " = " + val);
bw.newLine();
firstEntry = false;
}
}
bw.flush();
}
private static String escapifyStr(String str)
{
final StringBuilder result = new StringBuilder();
final int len = str.length();
for (int x = 0; x < len; x++) {
final char ch = str.charAt(x);
@ -249,7 +249,7 @@ class SortedProperties extends java.util.Properties {
result.append(ch);
continue;
}
result.append('\\');
result.append('u');
result.append(hexDigit(ch, 12));
@ -259,26 +259,26 @@ class SortedProperties extends java.util.Properties {
}
return result.toString();
}
private static char hexDigit(char ch, int offset)
{
final int val = (ch >> offset) & 0xF;
if (val <= 9) {
return (char) ('0' + val);
}
return (char) ('A' + val - 10);
}
@Override
public synchronized void load(InputStream is) throws IOException
{
load(is, "utf-8");
}
public void load(InputStream is, String encoding) throws IOException
{
final StringBuilder sb = new StringBuilder();
@ -288,18 +288,18 @@ class SortedProperties extends java.util.Properties {
if (temp < 0) {
break;
}
final char c = (char) temp;
sb.append(c);
}
// discard comments
final String read = sb.toString().replaceAll("(#|;|//|--)[^\n]*\n", "\n");
final String inputString = escapifyStr(read);
final byte[] bs = inputString.getBytes("ISO-8859-1");
final ByteArrayInputStream bais = new ByteArrayInputStream(bs);
super.load(bais);
}
}

@ -1,6 +1,7 @@
package mightypork.utils.eventbus;
import mightypork.utils.annotations.Stub;
import mightypork.utils.eventbus.events.flags.DelayedEvent;
import mightypork.utils.eventbus.events.flags.DirectEvent;
import mightypork.utils.eventbus.events.flags.NonConsumableEvent;
@ -31,19 +32,19 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
* @param <HANDLER> handler type
*/
public abstract class BusEvent<HANDLER> {
private boolean consumed;
private boolean served;
/**
* Ask handler to handle this message.
*
* @param handler handler instance
*/
protected abstract void handleBy(HANDLER handler);
/**
* Consume the event, so no other clients will receive it.
*
@ -53,17 +54,15 @@ public abstract class BusEvent<HANDLER> {
public final void consume()
{
if (consumed) throw new IllegalStateException("Already consumed.");
if (getClass().isAnnotationPresent(NonConsumableEvent.class)) {
throw new UnsupportedOperationException("Not consumable.");
}
(new Throwable()).printStackTrace();
consumed = true;
}
/**
* Deliver to a handler using the handleBy method.
*
@ -72,17 +71,17 @@ public abstract class BusEvent<HANDLER> {
final void deliverTo(HANDLER handler)
{
handleBy(handler);
if (!served) {
if (getClass().isAnnotationPresent(SingleReceiverEvent.class)) {
consumed = true;
}
served = true;
}
}
/**
* Check if the event is consumed. When an event is consumed, no other
* clients will receive it.
@ -93,8 +92,8 @@ public abstract class BusEvent<HANDLER> {
{
return consumed;
}
/**
* @return true if the event was served to at least 1 client
*/
@ -102,8 +101,8 @@ public abstract class BusEvent<HANDLER> {
{
return served;
}
/**
* Clear "served" and "consumed" flags before dispatching.
*/
@ -112,14 +111,16 @@ public abstract class BusEvent<HANDLER> {
served = false;
consumed = false;
}
/**
* Called after all clients have received the event.
*
* @param bus event bus instance
*/
@Stub
public void onDispatchComplete(EventBus bus)
{
//
}
}

@ -10,7 +10,7 @@ import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import mightypork.utils.Reflect;
import mightypork.utils.Support;
import mightypork.utils.Str;
import mightypork.utils.eventbus.clients.DelegatingClient;
import mightypork.utils.eventbus.events.flags.DelayedEvent;
import mightypork.utils.eventbus.events.flags.DirectEvent;
@ -26,73 +26,73 @@ import mightypork.utils.logging.Log;
* @author Ondřej Hruška (MightyPork)
*/
final public class EventBus implements Destroyable {
/**
* Queued event holder
*/
private class DelayQueueEntry implements Delayed {
private final long due;
private final BusEvent<?> evt;
public DelayQueueEntry(double seconds, BusEvent<?> event)
{
super();
this.due = System.currentTimeMillis() + (long) (seconds * 1000);
this.evt = event;
}
@Override
public int compareTo(Delayed o)
{
return Long.valueOf(getDelay(TimeUnit.MILLISECONDS)).compareTo(o.getDelay(TimeUnit.MILLISECONDS));
}
@Override
public long getDelay(TimeUnit unit)
{
return unit.convert(due - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
public BusEvent<?> getEvent()
{
return evt;
}
}
/**
* Thread handling queued events
*/
private class QueuePollingThread extends Thread {
public volatile boolean stopped = false;
public QueuePollingThread()
{
super("Queue Polling Thread");
}
@Override
public void run()
{
DelayQueueEntry evt;
while (!stopped) {
evt = null;
try {
evt = sendQueue.take();
} catch (final InterruptedException ignored) {
//
}
if (evt != null) {
try {
dispatch(evt.getEvent());
@ -102,36 +102,36 @@ final public class EventBus implements Destroyable {
}
}
}
}
static final String logMark = "(bus) ";
private static Class<?> getEventListenerClass(BusEvent<?> event)
{
return Reflect.getGenericParameters(event.getClass())[0];
}
/** Log detailed messages (debug) */
public boolean detailedLogging = false;
/** Queue polling thread */
private final QueuePollingThread busThread;
/** Registered clients */
private final Set<Object> clients = Collections.newSetFromMap(new ConcurrentHashMap<Object, Boolean>());
/** Whether the bus was destroyed */
private boolean dead = false;
/** Message channels */
private final Set<EventChannel<?, ?>> channels = Collections.newSetFromMap(new ConcurrentHashMap<EventChannel<?, ?>, Boolean>());
/** Messages queued for delivery */
private final DelayQueue<DelayQueueEntry> sendQueue = new DelayQueue<>();
/**
* Make a new bus and start it's queue thread.
*/
@ -141,8 +141,8 @@ final public class EventBus implements Destroyable {
busThread.setDaemon(true);
busThread.start();
}
/**
* Halt bus thread and reject any future events.
*/
@ -150,12 +150,12 @@ final public class EventBus implements Destroyable {
public void destroy()
{
assertLive();
busThread.stopped = true;
dead = true;
}
/**
* Send based on annotation
*
@ -164,22 +164,22 @@ final public class EventBus implements Destroyable {
public void send(BusEvent<?> event)
{
assertLive();
final DelayedEvent adelay = Reflect.getAnnotation(event, DelayedEvent.class);
if (adelay != null) {
sendDelayed(event, adelay.delay());
return;
}
if (Reflect.hasAnnotation(event, DirectEvent.class)) {
sendDirect(event);
return;
}
sendQueued(event);
}
/**
* Add event to a queue
*
@ -188,11 +188,11 @@ final public class EventBus implements Destroyable {
public void sendQueued(BusEvent<?> event)
{
assertLive();
sendDelayed(event, 0);
}
/**
* Add event to a queue, scheduled for given time.
*
@ -202,17 +202,17 @@ final public class EventBus implements Destroyable {
public void sendDelayed(BusEvent<?> event, double delay)
{
assertLive();
final DelayQueueEntry dm = new DelayQueueEntry(delay, event);
if (shallLog(event)) {
Log.f3(logMark + "Qu [" + Support.str(event) + "]" + (delay == 0 ? "" : (", delay: " + delay + "s")));
Log.f3(logMark + "Qu [" + Str.val(event) + "]" + (delay == 0 ? "" : (", delay: " + delay + "s")));
}
sendQueue.add(dm);
}
/**
* Send immediately.<br>
* Should be used for real-time events that require immediate response, such
@ -223,23 +223,23 @@ final public class EventBus implements Destroyable {
public void sendDirect(BusEvent<?> event)
{
assertLive();
if (shallLog(event)) Log.f3(logMark + "Di [" + Support.str(event) + "]");
if (shallLog(event)) Log.f3(logMark + "Di [" + Str.val(event) + "]");
dispatch(event);
}
public void sendDirectToChildren(DelegatingClient delegatingClient, BusEvent<?> event)
{
assertLive();
if (shallLog(event)) Log.f3(logMark + "Di->sub [" + Support.str(event) + "]");
if (shallLog(event)) Log.f3(logMark + "Di->sub [" + Str.val(event) + "]");
doDispatch(delegatingClient.getChildClients(), event);
}
/**
* Connect a client to the bus. The client will be connected to all current
* and future channels, until removed from the bus.
@ -249,15 +249,15 @@ final public class EventBus implements Destroyable {
public void subscribe(Object client)
{
assertLive();
if (client == null) return;
clients.add(client);
if (detailedLogging) Log.f3(logMark + "Client joined: " + Support.str(client));
if (detailedLogging) Log.f3(logMark + "Client joined: " + Str.val(client));
}
/**
* Disconnect a client from the bus.
*
@ -266,47 +266,47 @@ final public class EventBus implements Destroyable {
public void unsubscribe(Object client)
{
assertLive();
clients.remove(client);
if (detailedLogging) Log.f3(logMark + "Client left: " + Support.str(client));
if (detailedLogging) Log.f3(logMark + "Client left: " + Str.val(client));
}
@SuppressWarnings("unchecked")
private boolean addChannelForEvent(BusEvent<?> event)
{
try {
if (detailedLogging) {
Log.f3(logMark + "Setting up channel for new event type: " + Support.str(event.getClass()));
Log.f3(logMark + "Setting up channel for new event type: " + Str.val(event.getClass()));
}
final Class<?> listener = getEventListenerClass(event);
final EventChannel<?, ?> ch = EventChannel.create(event.getClass(), listener);
if (ch.canBroadcast(event)) {
channels.add(ch);
//channels.flush();
if (detailedLogging) {
Log.f3(logMark + "Created new channel: " + Support.str(event.getClass()) + " -> " + Support.str(listener));
Log.f3(logMark + "Created new channel: " + Str.val(event.getClass()) + " -> " + Str.val(listener));
}
return true;
} else {
Log.w(logMark + "Could not create channel for event " + Support.str(event.getClass()));
Log.w(logMark + "Could not create channel for event " + Str.val(event.getClass()));
}
} catch (final Throwable t) {
Log.w(logMark + "Error while trying to add channel for event.", t);
}
return false;
}
/**
* Make sure the bus is not destroyed.
*
@ -316,8 +316,8 @@ final public class EventBus implements Destroyable {
{
if (dead) throw new IllegalStateException("EventBus is dead.");
}
/**
* Send immediately.<br>
* Should be used for real-time events that require immediate response, such
@ -328,12 +328,12 @@ final public class EventBus implements Destroyable {
private synchronized void dispatch(BusEvent<?> event)
{
assertLive();
doDispatch(clients, event);
event.onDispatchComplete(this);
}
/**
* Send to a set of clients
*
@ -343,36 +343,36 @@ final public class EventBus implements Destroyable {
private synchronized void doDispatch(Collection<?> clients, BusEvent<?> event)
{
boolean accepted = false;
event.clearFlags();
for (int i = 0; i < 2; i++) { // two tries.
for (final EventChannel<?, ?> b : channels) {
if (b.canBroadcast(event)) {
accepted = true;
b.broadcast(event, clients);
}
if (event.isConsumed()) break;
}
if (!accepted) if (addChannelForEvent(event)) continue;
break;
}
if (!accepted) Log.e(logMark + "Not accepted by any channel: " + Support.str(event));
if (!event.wasServed() && shallLog(event)) Log.w(logMark + "Not delivered: " + Support.str(event));
if (!accepted) Log.e(logMark + "Not accepted by any channel: " + Str.val(event));
if (!event.wasServed() && shallLog(event)) Log.w(logMark + "Not delivered: " + Str.val(event));
}
private boolean shallLog(BusEvent<?> event)
{
if (!detailedLogging) return false;
if (Reflect.hasAnnotation(event, NotLoggedEvent.class)) return false;
return true;
}
}

@ -5,7 +5,7 @@ import java.util.Collection;
import java.util.HashSet;
import mightypork.utils.Reflect;
import mightypork.utils.Support;
import mightypork.utils.Str;
import mightypork.utils.eventbus.clients.DelegatingClient;
import mightypork.utils.eventbus.clients.ToggleableClient;
import mightypork.utils.eventbus.events.flags.NonRejectableEvent;
@ -20,11 +20,11 @@ import mightypork.utils.logging.Log;
* @param <CLIENT> client (subscriber) type
*/
class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
private final Class<CLIENT> clientClass;
private final Class<EVENT> eventClass;
/**
* Create a channel
*
@ -33,16 +33,16 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
*/
public EventChannel(Class<EVENT> eventClass, Class<CLIENT> clientClass)
{
if (eventClass == null || clientClass == null) {
throw new NullPointerException("Null Event or Client class.");
}
this.clientClass = clientClass;
this.eventClass = eventClass;
}
/**
* Try to broadcast a event.<br>
* If event is of wrong type, <code>false</code> is returned.
@ -53,11 +53,11 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
public void broadcast(BusEvent<?> event, Collection<?> clients)
{
if (!canBroadcast(event)) return;
doBroadcast(eventClass.cast(event), clients, new HashSet<>());
}
/**
* Send the event
*
@ -68,46 +68,46 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
private void doBroadcast(final EVENT event, final Collection<?> clients, final Collection<Object> processed)
{
for (final Object client : clients) {
// exclude obvious non-clients
if (!isClientValid(client)) {
continue;
}
// avoid executing more times
if (processed.contains(client)) {
Log.w(EventBus.logMark + "Client already served: " + Support.str(client));
Log.w(EventBus.logMark + "Client already served: " + Str.val(client));
continue;
}
processed.add(client);
final boolean must_deliver = Reflect.hasAnnotation(event, NonRejectableEvent.class);
// opt-out
if (client instanceof ToggleableClient) {
if (!must_deliver && !((ToggleableClient) client).isListening()) continue;
}
sendTo(client, event);
if (event.isConsumed()) return;
// pass on to delegated clients
if (client instanceof DelegatingClient) {
if (must_deliver || ((DelegatingClient) client).doesDelegate()) {
final Collection<?> children = ((DelegatingClient) client).getChildClients();
if (children != null && children.size() > 0) {
doBroadcast(event, children, processed);
}
}
}
}
}
/**
* Send an event to a client.
*
@ -121,8 +121,8 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
((BusEvent<CLIENT>) event).deliverTo((CLIENT) client);
}
}
/**
* Check if the given event can be broadcasted by this channel
*
@ -133,8 +133,8 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
{
return event != null && eventClass.isInstance(event);
}
/**
* Create an instance for given types
*
@ -146,8 +146,8 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
{
return new EventChannel<>(eventClass, clientClass);
}
/**
* Check if client is of channel type
*
@ -158,8 +158,8 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
{
return clientClass.isInstance(client);
}
/**
* Check if the channel is compatible with given
*
@ -170,8 +170,8 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
{
return isClientOfChannelType(client) || (client instanceof DelegatingClient);
}
@Override
public int hashCode()
{
@ -181,8 +181,8 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
result = prime * result + ((eventClass == null) ? 0 : eventClass.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
@ -198,11 +198,11 @@ class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
} else if (!eventClass.equals(other.eventClass)) return false;
return true;
}
@Override
public String toString()
{
return "{ " + Support.str(eventClass) + " => " + Support.str(clientClass) + " }";
return "{ " + Str.val(eventClass) + " => " + Str.val(clientClass) + " }";
}
}

@ -15,33 +15,33 @@ import mightypork.utils.eventbus.EventBus;
* @author Ondřej Hruška (MightyPork)
*/
public abstract class BusNode implements ClientHub {
private final Set<Object> clients = new LinkedHashSet<>();
private boolean listening = true;
private boolean delegating = true;
@Override
public Collection<Object> getChildClients()
{
return clients;
}
@Override
public boolean doesDelegate()
{
return delegating;
}
@Override
public boolean isListening()
{
return listening;
}
/**
* Add a child subscriber to the {@link EventBus}.<br>
*
@ -52,8 +52,8 @@ public abstract class BusNode implements ClientHub {
{
clients.add(client);
}
/**
* Remove a child subscriber
*
@ -66,8 +66,8 @@ public abstract class BusNode implements ClientHub {
clients.remove(client);
}
}
/**
* Set whether events should be received.
*
@ -77,8 +77,8 @@ public abstract class BusNode implements ClientHub {
{
this.listening = listening;
}
/**
* Set whether events should be passed on to child nodes
*

@ -12,27 +12,27 @@ import mightypork.utils.eventbus.EventBus;
* @author Ondřej Hruška (MightyPork)
*/
public interface ClientHub extends DelegatingClient, ToggleableClient {
@Override
public boolean doesDelegate();
@Override
public Collection<Object> getChildClients();
@Override
public boolean isListening();
/**
* Add a child subscriber to the {@link EventBus}.<br>
*
* @param client
*/
public void addChildClient(Object client);
/**
* Remove a child subscriber
*

@ -11,7 +11,7 @@ import java.util.ArrayList;
* @author Ondřej Hruška (MightyPork)
*/
public class ClientList extends ArrayList<Object> {
public ClientList(Object... clients)
{
for (final Object c : clients) {

@ -12,16 +12,16 @@ import java.util.Collection;
* @author Ondřej Hruška (MightyPork)
*/
public interface DelegatingClient {
/**
* @return collection of child clients. Can not be null.
*/
public Collection<?> getChildClients();
/**
* @return true if delegating is active
*/
public boolean doesDelegate();
}

@ -12,10 +12,10 @@ import mightypork.utils.interfaces.Enableable;
* @author Ondřej Hruška (MightyPork)
*/
public class DelegatingList extends ClientList implements DelegatingClient, Enableable, ToggleableClient {
private boolean enabled = true;
/**
* Delegating list with initial clients
*
@ -25,44 +25,44 @@ public class DelegatingList extends ClientList implements DelegatingClient, Enab
{
super(clients);
}
/**
* Empty delegating list.
*/
public DelegatingList()
{
}
@Override
public Collection<?> getChildClients()
{
return this;
}
@Override
public boolean doesDelegate()
{
return isEnabled();
}
@Override
public boolean isListening()
{
return isEnabled();
}
@Override
public void setEnabled(boolean yes)
{
enabled = yes;
}
@Override
public boolean isEnabled()
{

@ -7,10 +7,10 @@ package mightypork.utils.eventbus.clients;
* @author Ondřej Hruška (MightyPork)
*/
public interface ToggleableClient {
/**
* @return true if the client wants to receive messages
*/
public boolean isListening();
}

@ -4,6 +4,7 @@ package mightypork.utils.eventbus.events;
import mightypork.utils.eventbus.BusEvent;
import mightypork.utils.eventbus.events.flags.DirectEvent;
import mightypork.utils.eventbus.events.flags.NonConsumableEvent;
import mightypork.utils.eventbus.events.flags.NonRejectableEvent;
import mightypork.utils.interfaces.Destroyable;
@ -14,6 +15,7 @@ import mightypork.utils.interfaces.Destroyable;
*/
@DirectEvent
@NonConsumableEvent
@NonRejectableEvent
public class DestroyEvent extends BusEvent<Destroyable> {
@Override

@ -17,10 +17,10 @@ import mightypork.utils.interfaces.Updateable;
@DirectEvent
@NonConsumableEvent
public class UpdateEvent extends BusEvent<Updateable> {
private final double deltaTime;
/**
* @param deltaTime time since last update (sec)
*/
@ -28,8 +28,8 @@ public class UpdateEvent extends BusEvent<Updateable> {
{
this.deltaTime = deltaTime;
}
@Override
public void handleBy(Updateable handler)
{

@ -19,7 +19,7 @@ import java.lang.annotation.Target;
@Inherited
@Documented
public @interface DelayedEvent {
/**
* @return event dispatch delay [seconds]
*/

@ -17,5 +17,5 @@ import java.lang.annotation.Target;
@Documented
@Target(ElementType.TYPE)
public @interface NonConsumableEvent {
}

@ -17,5 +17,5 @@ import java.lang.annotation.Target;
@Documented
@Target(ElementType.TYPE)
public @interface NonRejectableEvent {
}

@ -10,28 +10,28 @@ import java.io.IOException;
* @author Ondřej Hruška (MightyPork)
*/
public class CorruptDataException extends IOException {
public CorruptDataException()
{
super();
}
public CorruptDataException(String message, Throwable cause)
{
super(message, cause);
}
public CorruptDataException(String message)
{
super(message);
}
public CorruptDataException(Throwable cause)
{
super(cause);
}
}

@ -8,27 +8,27 @@ package mightypork.utils.exceptions;
* @author Ondřej Hruška (MightyPork)
*/
public class IllegalValueException extends RuntimeException {
public IllegalValueException()
{
}
public IllegalValueException(String message)
{
super(message);
}
public IllegalValueException(Throwable cause)
{
super(cause);
}
public IllegalValueException(String message, Throwable cause)
{
super(message, cause);
}
}

@ -7,28 +7,28 @@ package mightypork.utils.exceptions;
* @author Ondřej Hruška (MightyPork)
*/
public class KeyAlreadyExistsException extends RuntimeException {
public KeyAlreadyExistsException()
{
super();
}
public KeyAlreadyExistsException(String message, Throwable cause)
{
super(message, cause);
}
public KeyAlreadyExistsException(String message)
{
super(message);
}
public KeyAlreadyExistsException(Throwable cause)
{
super(cause);
}
}

@ -11,11 +11,11 @@ import java.io.FileFilter;
* @author Ondřej Hruška (MightyPork)
*/
public class FileSuffixFilter implements FileFilter {
/** Array of allowed suffixes */
private String[] suffixes = null;
/**
* Suffix filter
*
@ -25,22 +25,22 @@ public class FileSuffixFilter implements FileFilter {
{
this.suffixes = suffixes;
}
@Override
public boolean accept(File pathname)
{
if (!pathname.isFile()) return false;
final String fname = pathname.getName().toLowerCase().trim();
for (final String suffix : suffixes) {
if (fname.endsWith(suffix.toLowerCase().trim())) {
return true;
}
}
return false;
}
}

@ -16,138 +16,138 @@ import mightypork.utils.logging.Log;
public class FileTreeDiff {
private static final byte[] BUFFER = new byte[2048];
private final Checksum ck1 = new Adler32();
private final Checksum ck2 = new Adler32();
private boolean logging = true;
private final List<Tuple<File>> compared = new ArrayList<>();
private final Comparator<File> fileFirstSorter = new Comparator<File>() {
@Override
public int compare(File o1, File o2)
{
if (!o1.isDirectory() && o2.isDirectory()) return -1;
if (o1.isDirectory() && !o2.isDirectory()) return 1;
return o1.getName().compareTo(o2.getName());
}
};
public void enableLogging(boolean state)
{
logging = state;
}
public boolean areEqual(File dir1, File dir2)
{
if (logging) Log.f3("Comparing directory trees:\n 1. " + dir1 + "\n 2. " + dir2);
try {
compared.clear();
buildList(dir1, dir2);
calcChecksum();
if (logging) Log.f3("No difference found.");
return true;
} catch (final NotEqualException e) {
if (logging) Log.f3("Difference found:\n" + e.getMessage());
return false;
}
}
private void calcChecksum() throws NotEqualException
{
for (final Tuple<File> pair : compared) {
ck1.reset();
ck2.reset();
try(FileInputStream in1 = new FileInputStream(pair.a);
FileInputStream in2 = new FileInputStream(pair.b)) {
FileInputStream in2 = new FileInputStream(pair.b)) {
try(CheckedInputStream cin1 = new CheckedInputStream(in1, ck1);
CheckedInputStream cin2 = new CheckedInputStream(in2, ck2)) {
CheckedInputStream cin2 = new CheckedInputStream(in2, ck2)) {
while (true) {
final int read1 = cin1.read(BUFFER);
final int read2 = cin2.read(BUFFER);
if (read1 != read2 || ck1.getValue() != ck2.getValue()) {
throw new NotEqualException("Bytes differ:\n" + pair.a + "\n" + pair.b);
}
if (read1 == -1) break;
}
}
} catch (final IOException e) {
// ignore
}
}
}
private void buildList(File f1, File f2) throws NotEqualException
{
if (f1.isDirectory() != f2.isDirectory()) throw new NotEqualException("isDirectory differs:\n" + f1 + "\n" + f2);
if (f1.isFile() && f2.isFile()) {
if (f1.length() != f2.length()) throw new NotEqualException("Sizes differ:\n" + f1 + "\n" + f2);
}
if (f1.isDirectory()) {
final File[] children1 = f1.listFiles();
final File[] children2 = f2.listFiles();
Arrays.sort(children1, fileFirstSorter);
Arrays.sort(children2, fileFirstSorter);
if (children1.length != children2.length) throw new NotEqualException("Child counts differ:\n" + f1 + "\n" + f2);
for (int i = 0; i < children1.length; i++) {
final File ch1 = children1[i];
final File ch2 = children2[i];
if (!ch1.getName().equals(ch2.getName())) throw new NotEqualException("Filenames differ:\n" + ch1 + "\n" + ch2);
buildList(ch1, ch2);
}
} else {
compared.add(new Tuple<>(f1, f2));
}
}
private class NotEqualException extends Exception {
public NotEqualException(String msg)
{
super(msg);
}
}
private class Tuple<T> {
public T a;
public T b;
public Tuple(T a, T b)
{
this.a = a;
this.b = b;
}
}
}

@ -17,14 +17,14 @@ import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import mightypork.utils.Str;
import mightypork.utils.logging.Log;
import mightypork.utils.string.StringUtil;
import mightypork.utils.string.validation.StringFilter;
public class FileUtil {
/**
* Copy directory recursively.
*
@ -36,8 +36,8 @@ public class FileUtil {
{
copyDirectory(source, target, null, null);
}
/**
* Copy directory recursively - advanced variant.
*
@ -50,28 +50,28 @@ public class FileUtil {
public static void copyDirectory(File source, File target, FileFilter filter, List<File> filesCopied) throws IOException
{
if (!source.exists()) return;
if (source.isDirectory()) {
if (!target.exists() && !target.mkdir()) {
throw new IOException("Could not open destination directory.");
}
final String[] children = source.list();
for (final String element : children) {
copyDirectory(new File(source, element), new File(target, element), filter, filesCopied);
}
} else {
if (filter != null && !filter.accept(source)) {
return;
}
if (filesCopied != null) filesCopied.add(target);
copyFile(source, target);
}
}
/**
* List directory recursively
*
@ -87,17 +87,17 @@ public class FileUtil {
for (final String element : children) {
listDirectoryRecursive(new File(source, element), filter, files);
}
} else {
if (filter != null && !filter.isValid(source.getAbsolutePath())) {
return;
}
files.add(source);
}
}
/**
* Copy file using streams. Make sure target directory exists!
*
@ -107,15 +107,15 @@ public class FileUtil {
*/
public static void copyFile(File source, File target) throws IOException
{
try(InputStream in = new FileInputStream(source);
OutputStream out = new FileOutputStream(target)) {
OutputStream out = new FileOutputStream(target)) {
copyStream(in, out);
}
}
/**
* Copy bytes from input to output stream, leaving out stream open
*
@ -128,19 +128,19 @@ public class FileUtil {
if (in == null) {
throw new NullPointerException("Input stream is null");
}
if (out == null) {
throw new NullPointerException("Output stream is null");
}
final byte[] buf = new byte[2048];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
/**
* Improved delete
*
@ -153,18 +153,18 @@ public class FileUtil {
if (!path.exists()) {
return true;
}
if (!recursive || !path.isDirectory()) return path.delete();
final String[] list = path.list();
for (int i = 0; i < list.length; i++) {
if (!delete(new File(path, list[i]), true)) return false;
}
return path.delete();
}
/**
* Read entire file to a string.
*
@ -175,12 +175,12 @@ public class FileUtil {
public static String fileToString(File file) throws IOException
{
try(FileInputStream fin = new FileInputStream(file)) {
return streamToString(fin);
}
}
/**
* Get files in a folder (create folder if needed)
*
@ -191,8 +191,8 @@ public class FileUtil {
{
return FileUtil.listDirectory(dir, null);
}
/**
* Get files in a folder (create folder if needed)
*
@ -203,17 +203,17 @@ public class FileUtil {
public static List<File> listDirectory(File dir, FileFilter filter)
{
dir.mkdir();
final List<File> list = new ArrayList<>();
for (final File f : dir.listFiles(filter)) {
list.add(f);
}
return list;
}
/**
* Remove extension.
*
@ -224,20 +224,20 @@ public class FileUtil {
{
return getFilenameParts(file.getName());
}
public static String getExtension(File file)
{
return getExtension(file.getName());
}
public static String getExtension(String file)
{
return StringUtil.fromLastChar(file, '.');
return Str.fromLast(file, '.');
}
/**
* Remove extension.
*
@ -247,24 +247,24 @@ public class FileUtil {
public static String[] getFilenameParts(String filename)
{
String ext, name;
try {
ext = StringUtil.fromLastDot(filename);
ext = Str.fromLastDot(filename);
} catch (final StringIndexOutOfBoundsException e) {
ext = "";
}
try {
name = StringUtil.toLastDot(filename);
name = Str.toLastDot(filename);
} catch (final StringIndexOutOfBoundsException e) {
name = "";
Log.w("Error extracting extension from file " + filename);
}
return new String[] { name, ext };
}
/**
* Read entire input stream to a string, and close it.
*
@ -275,8 +275,8 @@ public class FileUtil {
{
return streamToString(in, -1);
}
/**
* Read input stream to a string, and close it.
*
@ -290,10 +290,10 @@ public class FileUtil {
Log.e(new NullPointerException("Null stream to be converted to String."));
return ""; // to avoid NPE's
}
BufferedReader br = null;
final StringBuilder sb = new StringBuilder();
String line;
try {
int cnt = 0;
@ -302,11 +302,11 @@ public class FileUtil {
sb.append(line + "\n");
cnt++;
}
if (cnt == lines && lines > 0) {
sb.append("--- end of preview ---\n");
}
} catch (final IOException e) {
Log.e(e);
} finally {
@ -316,15 +316,15 @@ public class FileUtil {
// ignore
}
}
return sb.toString();
}
public static InputStream stringToStream(String text)
{
if (text == null) return null;
try {
return new ByteArrayInputStream(text.getBytes("UTF-8"));
} catch (final UnsupportedEncodingException e) {
@ -332,38 +332,38 @@ public class FileUtil {
return null;
}
}
public static InputStream getResource(String path)
{
final InputStream in = FileUtil.class.getResourceAsStream(path);
if (in != null) return in;
try {
return new FileInputStream(new File(".", path));
} catch (final FileNotFoundException e) {
} catch (final FileNotFoundException e) {
try {
return new FileInputStream(WorkDir.getFile(path));
} catch (final FileNotFoundException e2) {
Log.w("Could not open resource stream, file not found: " + path);
return null;
}
}
}
public static String getResourceAsString(String path)
{
return streamToString(getResource(path));
}
/**
* Save string to file
*
@ -374,44 +374,44 @@ public class FileUtil {
public static void stringToFile(File file, String text) throws IOException
{
try(PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) {
out.print(text);
out.flush();
}
}
public static void deleteEmptyDirs(File base) throws IOException
{
for (final File f : listDirectory(base)) {
if (!f.isDirectory()) continue;
deleteEmptyDirs(f);
final List<File> children = listDirectory(f);
if (children.size() == 0) {
if (!f.delete()) throw new IOException("Could not delete a directory: " + f);
continue;
}
}
}
public static String getBasename(String name)
{
return StringUtil.toLastChar(StringUtil.fromLastChar(name, '/'), '.');
return Str.toLast(Str.fromLast(name, '/'), '.');
}
public static String getFilename(String name)
{
return StringUtil.fromLastChar(name, '/');
return Str.fromLast(name, '/');
}
/**
* Copy resource to file
*
@ -422,14 +422,14 @@ public class FileUtil {
public static void resourceToFile(String resname, File file) throws IOException
{
try(InputStream in = FileUtil.getResource(resname);
OutputStream out = new FileOutputStream(file)) {
OutputStream out = new FileOutputStream(file)) {
FileUtil.copyStream(in, out);
}
}
/**
* Get resource as string, safely closing streams.
*

@ -13,19 +13,19 @@ import java.nio.channels.FileLock;
* @author Ondřej Hruška (MightyPork)
*/
public class InstanceLock {
@SuppressWarnings("resource")
public static boolean onFile(final File lockFile)
{
try {
lockFile.getParentFile().mkdirs();
final RandomAccessFile randomAccessFile = new RandomAccessFile(lockFile, "rw");
final FileLock fileLock = randomAccessFile.getChannel().tryLock();
if (fileLock != null) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run()
{
@ -39,10 +39,10 @@ public class InstanceLock {
}
}
});
return true;
}
return false;
} catch (final IOException e) {
System.err.println("IO error while obtaining lock.");
@ -50,5 +50,5 @@ public class InstanceLock {
return false;
}
}
}

@ -5,90 +5,90 @@ import java.io.File;
public class OsUtils {
public static enum EnumOS
{
linux, macos, solaris, unknown, windows;
public boolean isLinux()
{
return this == linux || this == solaris;
}
public boolean isMac()
{
return this == macos;
}
public boolean isWindows()
{
return this == windows;
}
}
private static EnumOS cachedOs;
public static File getHomeWorkDir(String dirname)
{
final String userhome = System.getProperty("user.home", ".");
File file;
switch (getOs()) {
case linux:
case solaris:
file = new File(userhome, dirname + '/');
break;
case windows:
final String appdata = System.getenv("APPDATA");
if (appdata != null) {
file = new File(appdata, dirname + '/');
} else {
file = new File(userhome, dirname + '/');
}
break;
case macos:
file = new File(userhome, "Library/Application Support/" + dirname);
break;
default:
file = new File(userhome, dirname + "/");
break;
}
return file;
}
public static EnumOS getOs()
{
if (cachedOs != null) return cachedOs;
final String s = System.getProperty("os.name").toLowerCase();
if (s.contains("win")) {
cachedOs = EnumOS.windows;
} else if (s.contains("mac")) {
cachedOs = EnumOS.macos;
} else if (s.contains("linux") || s.contains("unix")) {
cachedOs = EnumOS.linux;
} else if (s.contains("solaris") || s.contains("sunos")) {
cachedOs = EnumOS.solaris;
} else {
cachedOs = EnumOS.unknown;
}
return cachedOs;
}
}

@ -14,11 +14,11 @@ import mightypork.utils.logging.Log;
* @author Ondřej Hruška (MightyPork)
*/
public class WorkDir {
private static File baseDir = new File(".");
private static Map<String, String> namedPaths = new HashMap<>();
/**
* Initialize the workdir for the given root path
*
@ -28,8 +28,8 @@ public class WorkDir {
{
WorkDir.baseDir = workdir;
}
/**
* Add a path alias (dir or file), relative to the workdir.
*
@ -40,8 +40,8 @@ public class WorkDir {
{
namedPaths.put(alias, path);
}
/**
* Get workdir folder, create if not exists.
*
@ -51,18 +51,18 @@ public class WorkDir {
public static File getDir(String path)
{
if (namedPaths.containsKey(path)) path = namedPaths.get(path);
final File f = new File(baseDir, path);
if (!f.exists()) {
if (!f.mkdirs()) {
Log.w("Could not create a directory: " + f + " (path: " + path + ")");
}
}
return f;
}
/**
* Get workdir file, create parent if not exists.
*
@ -72,19 +72,19 @@ public class WorkDir {
public static File getFile(String path)
{
if (namedPaths.containsKey(path)) path = namedPaths.get(path);
final File f = new File(baseDir, path);
// create the parent dir
if (!f.getParent().equals(baseDir)) {
f.getParentFile().mkdirs();
}
return f;
}
/**
* @return the workdir File
*/
@ -92,5 +92,5 @@ public class WorkDir {
{
return baseDir;
}
}

@ -20,25 +20,25 @@ import mightypork.utils.logging.Log;
* @author Ondřej Hruška (MightyPork)
*/
public class ZipBuilder {
private final ZipOutputStream out;
private final HashSet<String> included = new HashSet<>();
/**
* @param target target zip file
* @throws IOException if the file is directory or cannot be created
*/
public ZipBuilder(File target) throws IOException
{
if (!target.getParentFile().mkdirs()) throw new IOException("Could not create output directory.");
final FileOutputStream dest = new FileOutputStream(target);
out = new ZipOutputStream(new BufferedOutputStream(dest));
}
/**
* Add stream to a path
*
@ -54,13 +54,13 @@ public class ZipBuilder {
return; // ignore
}
included.add(path);
out.putNextEntry(new ZipEntry(path));
FileUtil.copyStream(in, out);
}
/**
* Add string as a file
*
@ -73,15 +73,15 @@ public class ZipBuilder {
path = preparePath(path);
if (included.contains(path)) return; // ignore
included.add(path);
out.putNextEntry(new ZipEntry(path));
try(InputStream in = FileUtil.stringToStream(text)) {
FileUtil.copyStream(in, out);
}
}
/**
* Add resource obtained via FileUtils.getResource()
*
@ -94,15 +94,15 @@ public class ZipBuilder {
path = preparePath(path);
if (included.contains(path)) return; // ignore
included.add(path);
out.putNextEntry(new ZipEntry(path));
try(InputStream in = FileUtil.getResource(resPath)) {
FileUtil.copyStream(in, out);
}
}
/**
* Normalize path
*
@ -112,13 +112,13 @@ public class ZipBuilder {
private static String preparePath(String path)
{
path = path.replace("\\", "/");
if (path.charAt(0) == '/') path = path.substring(1);
return path;
}
/**
* Close the zip stream
*

@ -24,10 +24,10 @@ import mightypork.utils.string.validation.StringFilter;
* @author Ondřej Hruška (MightyPork)
*/
public class ZipUtils {
private static final int BUFFER_SIZE = 2048;
/**
* Extract zip file to target directory
*
@ -43,8 +43,8 @@ public class ZipUtils {
return extractZip(zip, outputDir, filter);
}
}
/**
* Extract zip file to target directory
*
@ -57,35 +57,35 @@ public class ZipUtils {
public static List<String> extractZip(ZipFile zip, File outputDir, StringFilter filter) throws IOException
{
final ArrayList<String> files = new ArrayList<>();
if (!outputDir.mkdirs()) throw new IOException("Could not create output directory.");
final Enumeration<? extends ZipEntry> zipFileEntries = zip.entries();
// process each entry
while (zipFileEntries.hasMoreElements()) {
final ZipEntry entry = zipFileEntries.nextElement();
// parse filename and path
final String entryPath = entry.getName();
final File destFile = new File(outputDir, entryPath);
final File destinationParent = destFile.getParentFile();
if (entry.isDirectory() || (filter != null && !filter.isValid(entryPath))) continue;
// make sure directories exist
if (!destinationParent.mkdirs()) throw new IOException("Could not create directory.");
if (!entry.isDirectory()) {
extractZipEntry(zip, entry, destFile);
files.add(entryPath);
}
}
return files;
}
/**
* Read zip entries and add their paths to a list
*
@ -99,8 +99,8 @@ public class ZipUtils {
return listZip(zip);
}
}
/**
* Read zip entries and add their paths to a list
*
@ -111,22 +111,22 @@ public class ZipUtils {
public static List<String> listZip(ZipFile zip) throws IOException
{
final ArrayList<String> files = new ArrayList<>();
final Enumeration<? extends ZipEntry> zipFileEntries = zip.entries();
// process each entry
while (zipFileEntries.hasMoreElements()) {
final ZipEntry entry = zipFileEntries.nextElement();
if (!entry.isDirectory()) {
files.add(entry.getName());
}
}
return files;
}
/**
* Extract one zip entry to target file
*
@ -138,17 +138,17 @@ public class ZipUtils {
public static void extractZipEntry(ZipFile zip, ZipEntry entry, File destFile) throws IOException
{
if (!destFile.getParentFile().mkdirs()) throw new IOException("Could not create output directory.");
try(InputStream in = zip.getInputStream(entry);
BufferedInputStream is = new BufferedInputStream(in);
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
BufferedInputStream is = new BufferedInputStream(in);
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
FileUtil.copyStream(is, dest);
}
}
/**
* Load zip entry to String
*
@ -172,8 +172,8 @@ public class ZipUtils {
}
}
}
public static boolean entryExists(File selectedFile, String string)
{
try(ZipFile zf = new ZipFile(selectedFile)) {
@ -182,6 +182,6 @@ public class ZipUtils {
Log.w("Error reading zip.", e);
return false;
}
}
}

@ -7,7 +7,7 @@ package mightypork.utils.interfaces;
* @author Ondřej Hruška (MightyPork)
*/
public interface Destroyable {
/**
* Destroy this object
*/

@ -9,15 +9,15 @@ package mightypork.utils.interfaces;
* @author Ondřej Hruška (MightyPork)
*/
public interface Enableable {
/**
* Change enabled state
*
* @param yes enabled
*/
public void setEnabled(boolean yes);
/**
* @return true if enabled
*/

@ -7,9 +7,9 @@ package mightypork.utils.interfaces;
* @author Ondřej Hruška (MightyPork)
*/
public interface Hideable {
void setVisible(boolean yes);
boolean isVisible();
}

@ -7,22 +7,22 @@ package mightypork.utils.interfaces;
* @author Ondřej Hruška (MightyPork)
*/
public interface Pauseable {
/**
* Pause operation
*/
public void pause();
/**
* Resume operation
*/
public void resume();
/**
* @return paused state
*/
public boolean isPaused();
}

@ -7,7 +7,7 @@ package mightypork.utils.interfaces;
* @author Ondřej Hruška (MightyPork)
*/
public interface Pollable {
/**
* Update internal state
*/

@ -7,7 +7,7 @@ package mightypork.utils.interfaces;
* @author Ondřej Hruška (MightyPork)
*/
public interface Updateable {
/**
* Update item state based on elapsed time
*

@ -13,7 +13,7 @@ import java.util.List;
import java.util.Map;
import mightypork.utils.Reflect;
import mightypork.utils.Support;
import mightypork.utils.Str;
/**
@ -22,13 +22,13 @@ import mightypork.utils.Support;
* @author Ondřej Hruška (MightyPork)
*/
public class Ion {
private static final int RESERVED_LOW = 0;
private static final int RESERVED_HIGH = 49;
private static final int RANGE_LOW = 0;
private static final int RANGE_HIGH = 255;
// marks for object saving
/** Null mark */
static final int NULL = 0;
@ -84,28 +84,28 @@ public class Ion {
public static final int MAP = 25;
/** Array of arbitrary objects */
public static final int OBJECT_ARRAY = 26;
/** Ionizables<Mark, Class> */
private static Map<Integer, Class<?>> markToClass = 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;
static {
reservedMarkChecking = false;
// register built-ins
register(ION_BUNDLE, IonDataBundle.class);
register(SEQUENCE_WRAPPER, IonSequenceWrapper.class);
register(MAP_WRAPPER, IonMapWrapper.class);
reservedMarkChecking = true;
}
/**
* Register a type for writing/loading.
*
@ -116,16 +116,16 @@ public class Ion {
{
if (!IonBinary.class.isAssignableFrom(objClass)) {
if (!IonBundled.class.isAssignableFrom(objClass)) {
throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass));
throw new IllegalArgumentException("Cannot register directly: " + Str.val(objClass));
}
}
assertHasImplicitConstructor(objClass);
registerUsingMark(mark, objClass);
}
/**
* Try to register a type using a static final ION_MARK int field.
*
@ -135,37 +135,37 @@ public class Ion {
{
if (!IonBinary.class.isAssignableFrom(objClass)) {
if (!IonBundled.class.isAssignableFrom(objClass)) {
throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass));
throw new IllegalArgumentException("Cannot register directly: " + Str.val(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();
registerUsingMark(mark, objClass);
} catch (final Exception e) {
throw new RuntimeException("Could not register " + Support.str(objClass) + " using an ION_MARK field.", e);
throw new RuntimeException("Could not register " + Str.val(objClass) + " using an ION_MARK field.", e);
}
}
/**
* Register new binary ionizer.
*
@ -175,13 +175,13 @@ public class Ion {
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.
*
@ -191,13 +191,13 @@ public class Ion {
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 {
@ -206,28 +206,28 @@ public class Ion {
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.");
throw new IllegalArgumentException(Str.val(objClass) + " is already registered.");
}
}
/**
* Load binary from file and cast.
*/
@ -235,8 +235,8 @@ public class Ion {
{
return fromFile(new File(path));
}
/**
* Load binary from file and cast.
*/
@ -246,8 +246,8 @@ public class Ion {
return fromStream(in);
}
}
/**
* Write binary to file with mark.
*/
@ -255,24 +255,24 @@ public class Ion {
{
toFile(new File(path), obj);
}
/**
* Write binary to file with mark.
*/
public static void toFile(File file, Object obj) throws IOException
{
try(OutputStream out = new FileOutputStream(file)) {
toStream(out, obj);
out.flush();
} catch (final Exception e) {
throw new IOException("Error writing to ION file.", e);
}
}
/**
* Load object from stream based on mark, try to cast.
*/
@ -282,8 +282,8 @@ public class Ion {
return (T) inp.readObject();
}
}
/**
* Write object to output with a mark.
*/
@ -293,8 +293,8 @@ public class Ion {
iout.writeObject(obj);
}
}
/**
* Get ion input
*
@ -306,8 +306,8 @@ public class Ion {
{
return getInput(new File(path));
}
/**
* Get ion input
*
@ -320,8 +320,8 @@ public class Ion {
{
return new IonInput(new FileInputStream(file));
}
/**
* Get ion output
*
@ -333,8 +333,8 @@ public class Ion {
{
return getOutput(new File(path));
}
/**
* Get ion output
*
@ -347,8 +347,8 @@ public class Ion {
{
return new IonOutput(new FileOutputStream(file));
}
/**
* Create new bundle and write the object to it.
*/
@ -358,8 +358,8 @@ public class Ion {
content.save(ib);
return ib;
}
/**
* Try to unwrap an object from bundle. The object class must have implicit
* accessible constructor.
@ -376,59 +376,59 @@ public class Ion {
inst.load(bundle);
return inst;
} catch (InstantiationException | IllegalAccessException e) {
throw new IOException("Could not instantiate " + Support.str(objClass) + ".");
throw new IOException("Could not instantiate " + Str.val(objClass) + ".");
}
}
static Class<?> getClassForMark(int mark)
{
return markToClass.get(mark);
}
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);
return classToMark.get(object.getClass());
}
/**
* @return true if the mark is for a registered {@link IonBinary} object
*/
static boolean isMarkForBinary(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return IonBinary.class.isAssignableFrom(markToClass.get(mark));
}
/**
* @return true if the mark is for a registered {@link IonBinary} object
*/
static boolean isMarkForBundled(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return IonBundled.class.isAssignableFrom(markToClass.get(mark));
}
/**
* @return true if the mark is for a registered indirectly saved binary
* object
@ -436,11 +436,11 @@ public class Ion {
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
@ -448,11 +448,11 @@ public class Ion {
static boolean isMarkForIndirectBundled(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return ionizersBundled.containsKey(markToClass.get(mark));
}
/**
* @return true if the mark is reserved for internal use
*/
@ -460,8 +460,8 @@ public class Ion {
{
return mark >= RESERVED_LOW && mark <= RESERVED_HIGH;
}
/**
* @return true if the mark is for a registered {@link IonBinary} object
*/
@ -469,11 +469,11 @@ public class Ion {
{
final Class<?> clazz = object.getClass();
if (classToMark.containsKey(clazz)) return true;
return false;
}
/**
* Make sure object is registered in the table.
*
@ -482,11 +482,11 @@ public class Ion {
static void assertRegistered(Object obj)
{
if (!isRegistered(obj)) {
throw new RuntimeException("Type not registered: " + Support.str(obj.getClass()));
throw new RuntimeException("Type not registered: " + Str.val(obj.getClass()));
}
}
/**
* For get all external registered types - just like if the class was
* freshly loaded. Can be used for unit tests.
@ -494,31 +494,31 @@ public class Ion {
public static void reset()
{
final List<Integer> toRemove = new ArrayList<>();
// remove direct
for (final Integer mark : markToClass.keySet()) {
if (!isMarkReserved(mark)) {
toRemove.add(mark);
}
}
for (final int i : toRemove) {
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());

@ -11,7 +11,7 @@ import java.io.IOException;
* @author Ondřej Hruška (MightyPork)
*/
public interface IonBinary {
/**
* Load data from the input stream.
*
@ -19,8 +19,8 @@ public interface IonBinary {
* @throws IOException
*/
void load(IonInput in) throws IOException;
/**
* Store data to output stream (in such way that the load method will later
* be able to read it).

@ -8,15 +8,15 @@ package mightypork.utils.ion;
* @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
*

@ -16,10 +16,10 @@ import java.util.Map;
* @author Ondřej Hruška (MightyPork)
*/
public class IonDataBundle implements IonBinary {
private final Map<String, Object> backingMap = new HashMap<>();
/**
* Clear & fill a provided bundle with elements from a bundle value
*
@ -29,14 +29,14 @@ public class IonDataBundle implements IonBinary {
public void loadBundle(String key, IonDataBundle filled)
{
if (!containsKey(key)) return;
final IonDataBundle ib = get(key, new IonDataBundle());
filled.clear();
filled.putAll(ib);
}
/**
* Check if a key is used in the bundle
*
@ -47,8 +47,8 @@ public class IonDataBundle implements IonBinary {
{
return backingMap.containsKey(key);
}
/**
* Check if a value is contained in the bundle
*
@ -59,8 +59,8 @@ public class IonDataBundle implements IonBinary {
{
return backingMap.containsValue(value);
}
/**
* Get a map value
*
@ -71,8 +71,8 @@ public class IonDataBundle implements IonBinary {
{
return loadMap(key, new LinkedHashMap<K, V>());
}
/**
* Clear & fill the provided map with elements from a map value
*
@ -87,8 +87,8 @@ public class IonDataBundle implements IonBinary {
imw.fill(filled);
return filled;
}
/**
* Get a sequence value
*
@ -99,8 +99,8 @@ public class IonDataBundle implements IonBinary {
{
return loadSequence(key, new ArrayList<E>());
}
/**
* Clear & fill the provided Collection with elements from a sequence value
*
@ -114,11 +114,11 @@ public class IonDataBundle implements IonBinary {
if (isw == null) throw new RuntimeException("No such key: " + key);
filled.clear();
isw.fill(filled);
return filled;
}
/**
* Load a bundled object from a bundle value.<br>
* The object does not have to be registered.
@ -131,13 +131,13 @@ public class IonDataBundle implements IonBinary {
{
final IonDataBundle bu = get(key, null);
if (bu == null) throw new RuntimeException("No such key: " + key);
loaded.load(bu);
return loaded;
}
/**
* Save a bundled object to a bundle value.<br>
* The object does not have to be registered.
@ -151,8 +151,8 @@ public class IonDataBundle implements IonBinary {
saved.save(bu);
put(key, bu);
}
/**
* Get value, or fallback (if none found of with bad type).
*
@ -170,8 +170,8 @@ public class IonDataBundle implements IonBinary {
return fallback;
}
}
/**
* Get value, or null (if none found of with bad type).
*
@ -182,124 +182,124 @@ public class IonDataBundle implements IonBinary {
{
return get(key, (T) null);
}
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, boolean value)
{
backingMap.put(key, value);
}
public void put(String key, byte value)
{
backingMap.put(key, value);
}
public void put(String key, char value)
{
backingMap.put(key, value);
}
public void put(String key, short value)
{
backingMap.put(key, value);
}
public void put(String key, int value)
{
backingMap.put(key, value);
}
public void put(String key, long value)
{
backingMap.put(key, value);
}
public void put(String key, double value)
{
backingMap.put(key, value);
}
public void put(String key, float value)
{
backingMap.put(key, value);
}
public void put(String key, String value)
{
backingMap.put(key, value);
}
public void put(String key, boolean[] value)
{
backingMap.put(key, value);
}
public void put(String key, char[] value)
{
backingMap.put(key, value);
}
public void put(String key, short[] value)
{
backingMap.put(key, value);
}
public void put(String key, int[] value)
{
backingMap.put(key, value);
}
public void put(String key, long[] value)
{
backingMap.put(key, value);
}
public void put(String key, double[] value)
{
backingMap.put(key, value);
}
public void put(String key, float[] value)
{
backingMap.put(key, value);
}
public void put(String key, String[] value)
{
backingMap.put(key, value);
}
public void put(String key, Object[] value)
{
backingMap.put(key, value);
}
/**
* Put a sequence to the bundle.
*
@ -311,8 +311,8 @@ public class IonDataBundle implements IonBinary {
{
backingMap.put(key, new IonSequenceWrapper(c));
}
/**
* Put a map to the bundle.
*
@ -324,22 +324,22 @@ public class IonDataBundle implements IonBinary {
{
backingMap.put(key, new IonMapWrapper(m));
}
@Override
public void load(IonInput in) throws IOException
{
in.readMap(backingMap);
}
@Override
public void save(IonOutput out) throws IOException
{
out.writeMap(backingMap);
}
/**
* Get number of elements in the bundle
*
@ -349,8 +349,8 @@ public class IonDataBundle implements IonBinary {
{
return backingMap.size();
}
/**
* Check whether the bundle is empty
*
@ -360,8 +360,8 @@ public class IonDataBundle implements IonBinary {
{
return backingMap.isEmpty();
}
/**
* Remove all elements
*/
@ -369,8 +369,8 @@ public class IonDataBundle implements IonBinary {
{
backingMap.clear();
}
/**
* Remove a value by key
*
@ -381,8 +381,8 @@ public class IonDataBundle implements IonBinary {
{
return backingMap.remove(key);
}
/**
* Put all from another bundle
*
@ -392,15 +392,15 @@ public class IonDataBundle implements IonBinary {
{
backingMap.putAll(anotherBundle.backingMap);
}
@Override
public String toString()
{
return backingMap.toString();
}
@Override
public int hashCode()
{
@ -409,8 +409,8 @@ public class IonDataBundle implements IonBinary {
result = prime * result + ((backingMap == null) ? 0 : backingMap.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{

@ -23,25 +23,25 @@ import mightypork.utils.exceptions.CorruptDataException;
* @author Ondřej Hruška (MightyPork)
*/
public class IonInput implements Closeable {
private final DataInput in;
private final InputStream stream;
@SuppressWarnings("resource")
public IonInput(File inFile) throws FileNotFoundException
{
this(new FileInputStream(inFile));
}
public IonInput(InputStream in)
{
this.stream = in;
this.in = new DataInputStream(in);
}
/**
* Read int 0-255. Suitable when the int was written using
* <code>writeIntByte()</code> method.
@ -53,8 +53,8 @@ public class IonInput implements Closeable {
{
return in.readUnsignedByte();
}
/**
* Read an int 0-65535. Suitable when the int was written using
* <code>writeIntShort()</code> method.
@ -66,62 +66,62 @@ public class IonInput implements Closeable {
{
return in.readUnsignedShort();
}
public boolean readBoolean() throws IOException
{
return in.readBoolean();
}
public byte readByte() throws IOException
{
return in.readByte();
}
public short readShort() throws IOException
{
return in.readShort();
}
public char readChar() throws IOException
{
return in.readChar();
}
public int readInt() throws IOException
{
return in.readInt();
}
public long readLong() throws IOException
{
return in.readLong();
}
public float readFloat() throws IOException
{
return in.readFloat();
}
public double readDouble() throws IOException
{
return in.readDouble();
}
public String readString() throws IOException
{
return in.readUTF();
}
public boolean[] readBooleans() throws IOException
{
final int length = readLength();
@ -131,8 +131,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public byte[] readBytes() throws IOException
{
final int length = readLength();
@ -142,8 +142,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public char[] readChars() throws IOException
{
final int length = readLength();
@ -153,8 +153,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public short[] readShorts() throws IOException
{
final int length = readLength();
@ -164,8 +164,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public int[] readInts() throws IOException
{
final int length = readLength();
@ -175,8 +175,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public long[] readLongs() throws IOException
{
final int length = readLength();
@ -186,8 +186,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public float[] readFloats() throws IOException
{
final int length = readLength();
@ -197,8 +197,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public double[] readDoubles() throws IOException
{
final int length = readLength();
@ -208,8 +208,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public String[] readStrings() throws IOException
{
final int length = readLength();
@ -219,8 +219,8 @@ public class IonInput implements Closeable {
}
return arr;
}
public Object[] readObjects() throws IOException
{
final int length = readLength();
@ -230,8 +230,8 @@ public class IonInput implements Closeable {
}
return arr;
}
/**
* Read bundle without a mark
*/
@ -241,8 +241,8 @@ public class IonInput implements Closeable {
ib.load(this);
return ib;
}
/**
* Read bundle without a mark, load into a provided one
*/
@ -251,20 +251,20 @@ public class IonInput implements Closeable {
filled.clear();
filled.load(this);
}
private int readMark() throws IOException
{
return readIntByte();
}
private int readLength() throws IOException
{
return readInt();
}
/**
* <p>
* Read object based on mark; if null mark is found, returns default value.
@ -288,8 +288,8 @@ public class IonInput implements Closeable {
throw new CorruptDataException("Could not load object.", e);
}
}
/**
* Read single object, preceded by a mark.
*
@ -299,115 +299,115 @@ public class IonInput implements Closeable {
public Object readObject() throws IOException
{
final int mark = readMark();
try {
if (Ion.isMarkForBinary(mark)) {
IonBinary loaded;
loaded = (IonBinary) Ion.getClassForMark(mark).newInstance();
loaded.load(this);
return loaded;
}
if (Ion.isMarkForBundled(mark)) {
IonBundled loaded;
loaded = (IonBundled) Ion.getClassForMark(mark).newInstance();
final IonDataBundle ib = readBundle();
loaded.load(ib);
return loaded;
}
if (Ion.isMarkForIndirectBundled(mark)) {
final IonizerBundled<?> ionizer = Ion.getIonizerBundledForClass(Ion.getClassForMark(mark));
return ionizer.load(readBundle());
}
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) {
case Ion.NULL:
return null;
case Ion.BOOLEAN:
return readBoolean();
case Ion.BYTE:
return readByte();
case Ion.CHAR:
return readChar();
case Ion.SHORT:
return readShort();
case Ion.INT:
return readInt();
case Ion.LONG:
return readLong();
case Ion.FLOAT:
return readFloat();
case Ion.DOUBLE:
return readDouble();
case Ion.STRING:
return readString();
case Ion.BOOLEAN_ARRAY:
return readBooleans();
case Ion.BYTE_ARRAY:
return readBytes();
case Ion.CHAR_ARRAY:
return readChars();
case Ion.SHORT_ARRAY:
return readShorts();
case Ion.INT_ARRAY:
return readInts();
case Ion.LONG_ARRAY:
return readLongs();
case Ion.FLOAT_ARRAY:
return readFloats();
case Ion.DOUBLE_ARRAY:
return readDoubles();
case Ion.STRING_ARRAY:
return readStrings();
case Ion.OBJECT_ARRAY:
return readObjects();
case Ion.MAP:
return readMap();
case Ion.SEQUENCE:
return readSequence();
default:
throw new CorruptDataException("Invalid mark: " + mark);
}
}
/**
* Reads mark and returns true if the mark is ENTRY, false if the mark is
* END. Throws an exception otherwise.
@ -420,11 +420,11 @@ public class IonInput implements Closeable {
final int mark = readMark();
if (mark == Ion.ENTRY) return true;
if (mark == Ion.END) return false;
throw new CorruptDataException("Unexpected mark in sequence: " + mark);
}
/**
* Read a sequence of elements into an ArrayList
*
@ -435,8 +435,8 @@ public class IonInput implements Closeable {
{
return readSequence(new ArrayList<T>());
}
/**
* Load entries into a collection. The collection is cleaned first.
*
@ -457,8 +457,8 @@ public class IonInput implements Closeable {
throw new CorruptDataException("Unexpected element type in sequence.", e);
}
}
/**
* Read element pairs into a HashMap
*
@ -469,8 +469,8 @@ public class IonInput implements Closeable {
{
return readMap(new HashMap<K, V>());
}
/**
* Load data into a map. The map is cleaned first.
*
@ -486,7 +486,7 @@ public class IonInput implements Closeable {
while (hasNextEntry()) {
final K key = (K) readObject();
final V value = (V) readObject();
filled.put(key, value);
}
return filled;
@ -494,8 +494,8 @@ public class IonInput implements Closeable {
throw new CorruptDataException("Unexpected element type in map.", e);
}
}
@Override
public void close() throws IOException
{

@ -8,47 +8,47 @@ import java.util.Map;
@SuppressWarnings({ "rawtypes", "unchecked" })
class IonMapWrapper implements IonBinary {
private final Map map;
public IonMapWrapper()
{
map = new LinkedHashMap<>();
}
public IonMapWrapper(Map saved)
{
map = saved;
}
@Override
public void load(IonInput in) throws IOException
{
map.clear();
in.readMap(map);
}
@Override
public void save(IonOutput out) throws IOException
{
out.writeMap(map);
}
public void fill(Map o)
{
o.clear();
o.putAll(map);
}
public Map getMap()
{
return map;
}
}

@ -20,97 +20,97 @@ import java.util.Map.Entry;
* @author Ondřej Hruška (MightyPork)
*/
public class IonOutput implements Closeable {
private final DataOutput out;
private final OutputStream stream;
@SuppressWarnings("resource")
public IonOutput(File outFile) throws FileNotFoundException
{
this(new FileOutputStream(outFile));
}
public IonOutput(OutputStream out)
{
this.stream = out;
this.out = new DataOutputStream(out);
}
public void writeBoolean(boolean a) throws IOException
{
out.writeBoolean(a);
}
public void writeByte(int a) throws IOException
{
out.writeByte(a);
}
public void writeShort(int a) throws IOException
{
out.writeShort(a);
}
public void writeChar(int a) throws IOException
{
out.writeChar(a);
}
public void writeInt(int a) throws IOException
{
out.writeInt(a);
}
public void writeIntShort(int a) throws IOException
{
out.writeShort(a);
}
public void writeIntByte(int a) throws IOException
{
out.writeByte(a);
}
public void writeLong(long a) throws IOException
{
out.writeLong(a);
}
public void writeFloat(float a) throws IOException
{
out.writeFloat(a);
}
public void writeDouble(double a) throws IOException
{
out.writeDouble(a);
}
public void writeBytes(String a) throws IOException
{
out.writeBytes(a);
}
public void writeString(String a) throws IOException
{
out.writeUTF(a);
}
public void writeBooleans(boolean[] arr) throws IOException
{
writeLength(arr.length);
@ -118,8 +118,8 @@ public class IonOutput implements Closeable {
out.writeBoolean(a);
}
}
public void writeBytes(byte[] arr) throws IOException
{
writeLength(arr.length);
@ -127,8 +127,8 @@ public class IonOutput implements Closeable {
out.writeByte(a);
}
}
public void writeChars(char[] arr) throws IOException
{
writeLength(arr.length);
@ -136,8 +136,8 @@ public class IonOutput implements Closeable {
out.writeChar(a);
}
}
public void writeShorts(short[] arr) throws IOException
{
writeLength(arr.length);
@ -145,8 +145,8 @@ public class IonOutput implements Closeable {
out.writeShort(a);
}
}
public void writeInts(int[] arr) throws IOException
{
writeLength(arr.length);
@ -154,8 +154,8 @@ public class IonOutput implements Closeable {
out.writeInt(a);
}
}
public void writeLongs(long[] arr) throws IOException
{
writeLength(arr.length);
@ -163,8 +163,8 @@ public class IonOutput implements Closeable {
out.writeLong(a);
}
}
public void writeFloats(float[] arr) throws IOException
{
writeLength(arr.length);
@ -172,8 +172,8 @@ public class IonOutput implements Closeable {
out.writeFloat(a);
}
}
public void writeDoubles(double[] arr) throws IOException
{
writeLength(arr.length);
@ -181,8 +181,8 @@ public class IonOutput implements Closeable {
out.writeDouble(a);
}
}
public void writeStrings(String[] arr) throws IOException
{
writeLength(arr.length);
@ -190,8 +190,8 @@ public class IonOutput implements Closeable {
out.writeUTF(a);
}
}
/**
* Write a bundle without a mark
*/
@ -199,8 +199,8 @@ public class IonOutput implements Closeable {
{
bundle.save(this);
}
/**
* Write array of objects. Works with all that is supported by writeObject()
*
@ -214,8 +214,8 @@ public class IonOutput implements Closeable {
writeObject(a);
}
}
public <T> void writeSequence(Collection<T> sequence) throws IOException
{
for (final T element : sequence) {
@ -224,47 +224,47 @@ public class IonOutput implements Closeable {
}
endSequence();
}
public <K, V> void writeMap(Map<K, V> map) throws IOException
{
for (final Entry<K, V> e : map.entrySet()) {
if (e.getValue() == null) {
continue;
}
startEntry();
writeObject(e.getKey());
writeObject(e.getValue());
}
endSequence();
}
public void endSequence() throws IOException
{
writeMark(Ion.END);
}
public void startEntry() throws IOException
{
writeMark(Ion.ENTRY);
}
private void writeMark(int mark) throws IOException
{
writeIntByte(mark);
}
private void writeLength(int length) throws IOException
{
writeInt(length);
}
/**
* Write an object. Supported are built-in types and types registered to
* Ion.
@ -278,177 +278,177 @@ public class IonOutput implements Closeable {
writeMark(Ion.NULL);
return;
}
if (obj instanceof IonBinary) {
final IonBinary iObj = (IonBinary) obj;
writeMark(Ion.getMark(obj));
iObj.save(this);
return;
}
if (obj instanceof IonBundled) {
final IonBundled iObj = (IonBundled) obj;
writeMark(Ion.getMark(obj));
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);
return;
}
if (obj instanceof Collection) {
writeMark(Ion.SEQUENCE);
writeSequence((Collection<?>) obj);
return;
}
if (obj instanceof Boolean) {
writeMark(Ion.BOOLEAN);
writeBoolean((Boolean) obj);
return;
}
if (obj instanceof Byte) {
writeMark(Ion.BYTE);
writeByte((Byte) obj);
return;
}
if (obj instanceof Character) {
writeMark(Ion.CHAR);
writeChar((Character) obj);
return;
}
if (obj instanceof Short) {
writeMark(Ion.SHORT);
writeShort((Short) obj);
return;
}
if (obj instanceof Integer) {
writeMark(Ion.INT);
writeInt((Integer) obj);
return;
}
if (obj instanceof Long) {
writeMark(Ion.LONG);
writeLong((Long) obj);
return;
}
if (obj instanceof Float) {
writeMark(Ion.FLOAT);
writeFloat((Float) obj);
return;
}
if (obj instanceof Double) {
writeMark(Ion.DOUBLE);
writeDouble((Double) obj);
return;
}
if (obj instanceof String) {
writeMark(Ion.STRING);
writeString((String) obj);
return;
}
if (obj instanceof boolean[]) {
writeMark(Ion.BOOLEAN_ARRAY);
writeBooleans((boolean[]) obj);
return;
}
if (obj instanceof byte[]) {
writeMark(Ion.BYTE_ARRAY);
writeBytes((byte[]) obj);
return;
}
if (obj instanceof char[]) {
writeMark(Ion.CHAR_ARRAY);
writeChars((char[]) obj);
return;
}
if (obj instanceof short[]) {
writeMark(Ion.SHORT_ARRAY);
writeShorts((short[]) obj);
return;
}
if (obj instanceof int[]) {
writeMark(Ion.INT_ARRAY);
writeInts((int[]) obj);
return;
}
if (obj instanceof long[]) {
writeMark(Ion.LONG_ARRAY);
writeLongs((long[]) obj);
return;
}
if (obj instanceof float[]) {
writeMark(Ion.FLOAT_ARRAY);
writeFloats((float[]) obj);
return;
}
if (obj instanceof double[]) {
writeMark(Ion.DOUBLE_ARRAY);
writeDoubles((double[]) obj);
return;
}
if (obj instanceof String[]) {
writeMark(Ion.STRING_ARRAY);
writeStrings((String[]) obj);
return;
}
if (obj instanceof Object[]) {
writeMark(Ion.OBJECT_ARRAY);
writeObjects((Object[]) obj);
return;
}
throw new IOException("Object " + obj + " could not be be written to stream.");
}
@Override
public void close() throws IOException
{

@ -8,47 +8,47 @@ import java.util.Collection;
@SuppressWarnings({ "rawtypes", "unchecked" })
class IonSequenceWrapper implements IonBinary {
private Collection collection = new ArrayList();
public IonSequenceWrapper()
{
collection = new ArrayList();
}
public IonSequenceWrapper(Collection saved)
{
collection = saved;
}
@Override
public void load(IonInput in) throws IOException
{
collection.clear();
in.readSequence(collection);
}
@Override
public void save(IonOutput out) throws IOException
{
out.writeSequence(collection);
}
public void fill(Collection o)
{
o.clear();
o.addAll(collection);
}
public Collection getSequence()
{
return collection;
}
}

@ -12,14 +12,14 @@ import java.io.IOException;
* @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
*
@ -28,8 +28,8 @@ public abstract class IonizerBinary<T> {
* @throws IOException
*/
public abstract void save(T object, IonOutput out) throws IOException;
/**
* Load an object from ion input
*
@ -37,5 +37,5 @@ public abstract class IonizerBinary<T> {
* @return the loaded object
*/
public abstract T load(IonInput in) throws IOException;
}

@ -9,14 +9,14 @@ package mightypork.utils.ion;
* @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
*
@ -24,8 +24,8 @@ public abstract class IonizerBundled<T> {
* @param out bundle to save to
*/
public abstract void save(T object, IonDataBundle out);
/**
* Load an object from a bundle
*
@ -33,5 +33,5 @@ public abstract class IonizerBundled<T> {
* @return the loaded object
*/
public abstract T load(IonDataBundle in);
}

@ -7,13 +7,13 @@ import java.io.StringWriter;
import java.util.HashMap;
import java.util.logging.Level;
import mightypork.utils.Str;
import mightypork.utils.annotations.FactoryMethod;
import mightypork.utils.logging.monitors.LogMonitor;
import mightypork.utils.logging.monitors.LogMonitorStdout;
import mightypork.utils.logging.writers.ArchivingLog;
import mightypork.utils.logging.writers.LogWriter;
import mightypork.utils.logging.writers.SimpleLog;
import mightypork.utils.string.StringUtil;
/**
@ -22,15 +22,15 @@ import mightypork.utils.string.StringUtil;
* @author Ondřej Hruška (MightyPork)
*/
public class Log {
private static LogWriter main = null;
private static boolean enabled = true;
private static final LogMonitorStdout sysoMonitor = new LogMonitorStdout();
private static final long start_ms = System.currentTimeMillis();
private static HashMap<String, SimpleLog> logs = new HashMap<>();
/**
* Create a logger. If another with the name already exists, it'll be
* retrieved instead of creating a new one.
@ -44,16 +44,16 @@ public class Log {
public static synchronized LogWriter create(String logName, File logFile, int oldLogsCount)
{
if (logs.containsKey(logName)) return logs.get(logName);
final ArchivingLog log = new ArchivingLog(logName, logFile, oldLogsCount);
log.init();
logs.put(logName, log);
return log;
}
/**
* Create a logger. If another with the name already exists, it'll be
* retrieved instead of creating a new one.
@ -66,50 +66,50 @@ public class Log {
public static synchronized LogWriter create(String logName, File logFile)
{
if (logs.containsKey(logName)) return logs.get(logName);
final SimpleLog log = new SimpleLog(logName, logFile);
log.init();
logs.put(logName, log);
return log;
}
public static void setMainLogger(LogWriter log)
{
main = log;
}
public static LogWriter getMainLogger()
{
return main;
}
public static void addMonitor(LogMonitor mon)
{
assertInited();
main.addMonitor(mon);
}
public static void removeMonitor(LogMonitor mon)
{
assertInited();
main.removeMonitor(mon);
}
private static void assertInited()
{
if (main == null) throw new IllegalStateException("Main logger not initialized.");
}
/**
* Log a message
*
@ -120,14 +120,14 @@ public class Log {
{
if (enabled) {
sysoMonitor.onMessageLogged(level, formatMessage(level, msg, null, start_ms));
if (main != null) {
main.log(level, msg);
}
}
}
/**
* Log a message
*
@ -139,14 +139,14 @@ public class Log {
{
if (enabled) {
sysoMonitor.onMessageLogged(level, formatMessage(level, msg, t, start_ms));
if (main != null) {
main.log(level, msg, t);
}
}
}
/**
* Log FINE message
*
@ -156,8 +156,8 @@ public class Log {
{
log(Level.FINE, msg);
}
/**
* Log FINER message
*
@ -167,8 +167,8 @@ public class Log {
{
log(Level.FINER, msg);
}