summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorcrast <contact@jamescrasta.com>2013-02-16 14:33:24 -0700
committerTravis Watkins <amaranth@ubuntu.com>2013-04-04 13:20:17 -0500
commit63128012244d05ba1d94cd83febb0faf354cfac4 (patch)
treebf33a754202149eb41635ea635f2c424f81a123a /src
parent073bbd5979f141b293167dafe52d2f95adea6166 (diff)
downloadbukkit-63128012244d05ba1d94cd83febb0faf354cfac4.tar
bukkit-63128012244d05ba1d94cd83febb0faf354cfac4.tar.gz
bukkit-63128012244d05ba1d94cd83febb0faf354cfac4.tar.lz
bukkit-63128012244d05ba1d94cd83febb0faf354cfac4.tar.xz
bukkit-63128012244d05ba1d94cd83febb0faf354cfac4.zip
Refactor common metadata code into base class. Fixes BUKKIT-3624
Implementing the MetadataValue interface is significant work due to having to provide a large amount of conversion stub methods. This commit adds a new optional abstract base class to aid in implementation.
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/bukkit/metadata/LazyMetadataValue.java61
-rw-r--r--src/main/java/org/bukkit/metadata/MetadataValueAdapter.java77
-rw-r--r--src/test/java/org/bukkit/metadata/MetadataValueAdapterTest.java97
3 files changed, 176 insertions, 59 deletions
diff --git a/src/main/java/org/bukkit/metadata/LazyMetadataValue.java b/src/main/java/org/bukkit/metadata/LazyMetadataValue.java
index cc0ba506..57fdc502 100644
--- a/src/main/java/org/bukkit/metadata/LazyMetadataValue.java
+++ b/src/main/java/org/bukkit/metadata/LazyMetadataValue.java
@@ -5,7 +5,6 @@ import java.util.concurrent.Callable;
import org.apache.commons.lang.Validate;
import org.bukkit.plugin.Plugin;
-import org.bukkit.util.NumberConversions;
/**
* The LazyMetadataValue class implements a type of metadata that is not computed until another plugin asks for it.
@@ -14,11 +13,10 @@ import org.bukkit.util.NumberConversions;
* or invalidated at the individual or plugin level. Once invalidated, the LazyMetadataValue will recompute its value
* when asked.
*/
-public class LazyMetadataValue implements MetadataValue {
+public class LazyMetadataValue extends MetadataValueAdapter implements MetadataValue {
private Callable<Object> lazyValue;
private CacheStrategy cacheStrategy;
private SoftReference<Object> internalValue = new SoftReference<Object>(null);
- private Plugin owningPlugin;
private static final Object ACTUALLY_NULL = new Object();
/**
@@ -39,19 +37,14 @@ public class LazyMetadataValue implements MetadataValue {
* @param lazyValue the lazy value assigned to this metadata value.
*/
public LazyMetadataValue(Plugin owningPlugin, CacheStrategy cacheStrategy, Callable<Object> lazyValue) {
- Validate.notNull(owningPlugin, "owningPlugin cannot be null");
+ super(owningPlugin);
Validate.notNull(cacheStrategy, "cacheStrategy cannot be null");
Validate.notNull(lazyValue, "lazyValue cannot be null");
this.lazyValue = lazyValue;
- this.owningPlugin = owningPlugin;
this.cacheStrategy = cacheStrategy;
}
- public Plugin getOwningPlugin() {
- return owningPlugin;
- }
-
public Object value() {
eval();
Object value = internalValue.get();
@@ -61,56 +54,6 @@ public class LazyMetadataValue implements MetadataValue {
return value;
}
- public int asInt() {
- return NumberConversions.toInt(value());
- }
-
- public float asFloat() {
- return NumberConversions.toFloat(value());
- }
-
- public double asDouble() {
- return NumberConversions.toDouble(value());
- }
-
- public long asLong() {
- return NumberConversions.toLong(value());
- }
-
- public short asShort() {
- return NumberConversions.toShort(value());
- }
-
- public byte asByte() {
- return NumberConversions.toByte(value());
- }
-
- public boolean asBoolean() {
- Object value = value();
- if (value instanceof Boolean) {
- return (Boolean) value;
- }
-
- if (value instanceof Number) {
- return ((Number) value).intValue() != 0;
- }
-
- if (value instanceof String) {
- return Boolean.parseBoolean((String) value);
- }
-
- return value != null;
- }
-
- public String asString() {
- Object value = value();
-
- if (value == null) {
- return "";
- }
- return value.toString();
- }
-
/**
* Lazily evaluates the value of this metadata item.
*
diff --git a/src/main/java/org/bukkit/metadata/MetadataValueAdapter.java b/src/main/java/org/bukkit/metadata/MetadataValueAdapter.java
new file mode 100644
index 00000000..c4b8b392
--- /dev/null
+++ b/src/main/java/org/bukkit/metadata/MetadataValueAdapter.java
@@ -0,0 +1,77 @@
+package org.bukkit.metadata;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.util.NumberConversions;
+
+/**
+ * Optional base class for facilitating MetadataValue implementations.
+ *
+ * This provides all the conversion functions for MetadataValue
+ * so that writing an implementation of MetadataValue is as simple
+ * as implementing value() and invalidate().
+ *
+ */
+public abstract class MetadataValueAdapter implements MetadataValue {
+ protected final Plugin owningPlugin;
+
+ protected MetadataValueAdapter(Plugin owningPlugin) {
+ Validate.notNull(owningPlugin, "owningPlugin cannot be null");
+ this.owningPlugin = owningPlugin;
+ }
+
+ public Plugin getOwningPlugin() {
+ return owningPlugin;
+ }
+
+ public int asInt() {
+ return NumberConversions.toInt(value());
+ }
+
+ public float asFloat() {
+ return NumberConversions.toFloat(value());
+ }
+
+ public double asDouble() {
+ return NumberConversions.toDouble(value());
+ }
+
+ public long asLong() {
+ return NumberConversions.toLong(value());
+ }
+
+ public short asShort() {
+ return NumberConversions.toShort(value());
+ }
+
+ public byte asByte() {
+ return NumberConversions.toByte(value());
+ }
+
+ public boolean asBoolean() {
+ Object value = value();
+ if (value instanceof Boolean) {
+ return (Boolean) value;
+ }
+
+ if (value instanceof Number) {
+ return ((Number) value).intValue() != 0;
+ }
+
+ if (value instanceof String) {
+ return Boolean.parseBoolean((String) value);
+ }
+
+ return value != null;
+ }
+
+ public String asString() {
+ Object value = value();
+
+ if (value == null) {
+ return "";
+ }
+ return value.toString();
+ }
+
+}
diff --git a/src/test/java/org/bukkit/metadata/MetadataValueAdapterTest.java b/src/test/java/org/bukkit/metadata/MetadataValueAdapterTest.java
new file mode 100644
index 00000000..7d8a17fe
--- /dev/null
+++ b/src/test/java/org/bukkit/metadata/MetadataValueAdapterTest.java
@@ -0,0 +1,97 @@
+package org.bukkit.metadata;
+
+import static org.junit.Assert.assertEquals;
+
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.TestPlugin;
+import org.junit.Test;
+
+public class MetadataValueAdapterTest {
+ private TestPlugin plugin = new TestPlugin("x");
+
+ @Test
+ public void testAdapterBasics() {
+ IncrementingMetaValue mv = new IncrementingMetaValue(plugin);
+ // check getOwningPlugin
+ assertEquals(mv.getOwningPlugin(), this.plugin);
+
+ // Check value-getting and invalidation.
+ assertEquals(new Integer(1), mv.value());
+ assertEquals(new Integer(2), mv.value());
+ mv.invalidate();
+ assertEquals(new Integer(1), mv.value());
+ }
+
+ @Test
+ public void testAdapterConversions() {
+ IncrementingMetaValue mv = new IncrementingMetaValue(plugin);
+
+ assertEquals(1, mv.asInt());
+ assertEquals(2L, mv.asLong());
+ assertEquals(3.0, mv.asFloat(), 0.001);
+ assertEquals(4, mv.asByte());
+ assertEquals(5.0, mv.asDouble(), 0.001);
+ assertEquals(6, mv.asShort());
+ assertEquals("7", mv.asString());
+ }
+
+ /** Boolean conversion is non-trivial, we want to test it thoroughly. */
+ @Test
+ public void testBooleanConversion() {
+ // null is False.
+ assertEquals(false, simpleValue(null).asBoolean());
+
+ // String to boolean.
+ assertEquals(true, simpleValue("True").asBoolean());
+ assertEquals(true, simpleValue("TRUE").asBoolean());
+ assertEquals(false, simpleValue("false").asBoolean());
+
+ // Number to boolean.
+ assertEquals(true, simpleValue(1).asBoolean());
+ assertEquals(true, simpleValue(5.0).asBoolean());
+ assertEquals(false, simpleValue(0).asBoolean());
+ assertEquals(false, simpleValue(0.1).asBoolean());
+
+ // Boolean as boolean, of course.
+ assertEquals(true, simpleValue(Boolean.TRUE).asBoolean());
+ assertEquals(false, simpleValue(Boolean.FALSE).asBoolean());
+
+ // any object that is not null and not a Boolean, String, or Number is true.
+ assertEquals(true, simpleValue(new Object()).asBoolean());
+ }
+
+ /** Test String conversions return an empty string when given null. */
+ @Test
+ public void testStringConversionNull() {
+ assertEquals("", simpleValue(null).asString());
+ }
+
+ /** Get a fixed value MetadataValue. */
+ private MetadataValue simpleValue(Object value) {
+ return new FixedMetadataValue(plugin, value);
+ }
+
+ /**
+ * A sample non-trivial MetadataValueAdapter implementation.
+ *
+ * The rationale for implementing an incrementing value is to have a value
+ * which changes with every call to value(). This is important for testing
+ * because we want to make sure all the tested conversions are calling the
+ * value() method exactly once and no caching is going on.
+ */
+ class IncrementingMetaValue extends MetadataValueAdapter {
+ private int internalValue = 0;
+
+ protected IncrementingMetaValue(Plugin owningPlugin) {
+ super(owningPlugin);
+ }
+
+ public Object value() {
+ return ++internalValue;
+ }
+
+ public void invalidate() {
+ internalValue = 0;
+ }
+ }
+}