@SuppressWarnings("unchecked") static void unmarshalElement(Element baseElement, Map<String, Object> map) { List<Element> childElements = baseElement.elements(); for (Element childElement : childElements) { String name = childElement.getName(); Attribute itemMetaAttribute = childElement.attribute("itemmeta"); Object value; if (itemMetaAttribute != null && Boolean.valueOf(itemMetaAttribute.getValue()).booleanValue()) { Map<String, Object> metaMap = Maps.newHashMap(); unmarshalElement(childElement, metaMap); Material material = Material.valueOf((String) map.get("type")); ItemMeta metaDummy = Bukkit.getItemFactory().getItemMeta(material); Class<?> deserializationClass = metaDummy.getClass(); do { if (!deserializationClass.isAnnotationPresent(DelegateDeserialization.class)) { break; } DelegateDeserialization annotation = deserializationClass.getAnnotation(DelegateDeserialization.class); deserializationClass = annotation.value(); } while (true); ItemMeta meta; try { Method method = deserializationClass.getMethod("deserialize", Map.class); meta = (ItemMeta) method.invoke(null, metaMap); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new IllegalStateException("Cannot deserialize item meta", e); } value = meta; } else { value = deserializeObject(childElement); } map.put(name, value); } }