summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java134
1 files changed, 134 insertions, 0 deletions
diff --git a/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java b/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java
index 77b542144..5070be552 100644
--- a/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java
+++ b/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java
@@ -1,6 +1,12 @@
package com.earth2me.essentials.storage;
+import java.beans.IntrospectionException;
+import java.lang.reflect.Field;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -11,8 +17,10 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPluginLoader;
+import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.YAMLException;
+import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.*;
@@ -270,6 +278,132 @@ public class BukkitConstructor extends Constructor
}
return super.construct(node);
}
+
+ protected Object constructJavaBean2ndStep(final MappingNode node, final Object object)
+ {
+ Map<Class<? extends Object>, TypeDescription> typeDefinitions;
+ try
+ {
+ final Field typeDefField = Constructor.class.getDeclaredField("typeDefinitions");
+ typeDefField.setAccessible(true);
+ typeDefinitions = (Map<Class<? extends Object>, TypeDescription>)typeDefField.get((Constructor)BukkitConstructor.this);
+ if (typeDefinitions == null) {
+ throw new NullPointerException();
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new YAMLException(ex);
+ }
+ flattenMapping(node);
+ final Class<? extends Object> beanType = node.getType();
+ final List<NodeTuple> nodeValue = node.getValue();
+ for (NodeTuple tuple : nodeValue)
+ {
+ ScalarNode keyNode;
+ if (tuple.getKeyNode() instanceof ScalarNode)
+ {
+ // key must be scalar
+ keyNode = (ScalarNode)tuple.getKeyNode();
+ }
+ else
+ {
+ throw new YAMLException("Keys must be scalars but found: " + tuple.getKeyNode());
+ }
+ final Node valueNode = tuple.getValueNode();
+ // keys can only be Strings
+ keyNode.setType(String.class);
+ final String key = (String)constructObject(keyNode);
+ try
+ {
+ Property property;
+ try
+ {
+ property = getProperty(beanType, key);
+ }
+ catch (YAMLException e)
+ {
+ continue;
+ }
+ valueNode.setType(property.getType());
+ final TypeDescription memberDescription = typeDefinitions.get(beanType);
+ boolean typeDetected = false;
+ if (memberDescription != null)
+ {
+ switch (valueNode.getNodeId())
+ {
+ case sequence:
+ final SequenceNode snode = (SequenceNode)valueNode;
+ final Class<? extends Object> memberType = memberDescription.getListPropertyType(key);
+ if (memberType != null)
+ {
+ snode.setListType(memberType);
+ typeDetected = true;
+ }
+ else if (property.getType().isArray())
+ {
+ snode.setListType(property.getType().getComponentType());
+ typeDetected = true;
+ }
+ break;
+ case mapping:
+ final MappingNode mnode = (MappingNode)valueNode;
+ final Class<? extends Object> keyType = memberDescription.getMapKeyType(key);
+ if (keyType != null)
+ {
+ mnode.setTypes(keyType, memberDescription.getMapValueType(key));
+ typeDetected = true;
+ }
+ break;
+ }
+ }
+ if (!typeDetected && valueNode.getNodeId() != NodeId.scalar)
+ {
+ // only if there is no explicit TypeDescription
+ final Class<?>[] arguments = property.getActualTypeArguments();
+ if (arguments != null)
+ {
+ // type safe (generic) collection may contain the
+ // proper class
+ if (valueNode.getNodeId() == NodeId.sequence)
+ {
+ final Class<?> t = arguments[0];
+ final SequenceNode snode = (SequenceNode)valueNode;
+ snode.setListType(t);
+ }
+ else if (valueNode.getTag().equals(Tag.SET))
+ {
+ final Class<?> t = arguments[0];
+ final MappingNode mnode = (MappingNode)valueNode;
+ mnode.setOnlyKeyType(t);
+ mnode.setUseClassConstructor(true);
+ }
+ else if (property.getType().isAssignableFrom(Map.class))
+ {
+ final Class<?> ketType = arguments[0];
+ final Class<?> valueType = arguments[1];
+ final MappingNode mnode = (MappingNode)valueNode;
+ mnode.setTypes(ketType, valueType);
+ mnode.setUseClassConstructor(true);
+ }
+ else
+ {
+ // the type for collection entries cannot be
+ // detected
+ }
+ }
+ }
+ final Object value = constructObject(valueNode);
+ property.set(object, value);
+ }
+ catch (Exception e)
+ {
+ throw new YAMLException("Cannot create property=" + key + " for JavaBean="
+ + object + "; " + e.getMessage(), e);
+ }
+ }
+ return object;
+ }
}
@Override