Bukkit  1.4.7-R1.0
 All Classes Namespaces Files Functions Variables Enumerator Pages
ConfigurationSerialization.java
Go to the documentation of this file.
1 package org.bukkit.configuration.serialization;
2 
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Modifier;
7 import java.util.HashMap;
8 import java.util.Map;
9 import java.util.logging.Level;
10 import java.util.logging.Logger;
11 
12 import org.apache.commons.lang.Validate;
13 import org.bukkit.Color;
14 import org.bukkit.FireworkEffect;
15 import org.bukkit.configuration.Configuration;
16 import org.bukkit.inventory.ItemStack;
17 import org.bukkit.potion.PotionEffect;
18 import org.bukkit.util.BlockVector;
19 import org.bukkit.util.Vector;
20 
25  public static final String SERIALIZED_TYPE_KEY = "==";
26  private final Class<? extends ConfigurationSerializable> clazz;
27  private static Map<String, Class<? extends ConfigurationSerializable>> aliases = new HashMap<String, Class<? extends ConfigurationSerializable>>();
28 
29  static {
30  registerClass(Vector.class);
32  registerClass(ItemStack.class);
33  registerClass(Color.class);
36  }
37 
38  protected ConfigurationSerialization(Class<? extends ConfigurationSerializable> clazz) {
39  this.clazz = clazz;
40  }
41 
42  protected Method getMethod(String name, boolean isStatic) {
43  try {
44  Method method = clazz.getDeclaredMethod(name, Map.class);
45 
46  if (!ConfigurationSerializable.class.isAssignableFrom(method.getReturnType())) {
47  return null;
48  }
49  if (Modifier.isStatic(method.getModifiers()) != isStatic) {
50  return null;
51  }
52 
53  return method;
54  } catch (NoSuchMethodException ex) {
55  return null;
56  } catch (SecurityException ex) {
57  return null;
58  }
59  }
60 
61  protected Constructor<? extends ConfigurationSerializable> getConstructor() {
62  try {
63  return clazz.getConstructor(Map.class);
64  } catch (NoSuchMethodException ex) {
65  return null;
66  } catch (SecurityException ex) {
67  return null;
68  }
69  }
70 
71  protected ConfigurationSerializable deserializeViaMethod(Method method, Map<String, Object> args) {
72  try {
73  ConfigurationSerializable result = (ConfigurationSerializable) method.invoke(null, args);
74 
75  if (result == null) {
76  Logger.getLogger(ConfigurationSerialization.class.getName()).log(Level.SEVERE, "Could not call method '" + method.toString() + "' of " + clazz + " for deserialization: method returned null");
77  } else {
78  return result;
79  }
80  } catch (Throwable ex) {
81  Logger.getLogger(ConfigurationSerialization.class.getName()).log(
82  Level.SEVERE,
83  "Could not call method '" + method.toString() + "' of " + clazz + " for deserialization",
84  ex instanceof InvocationTargetException ? ex.getCause() : ex);
85  }
86 
87  return null;
88  }
89 
90  protected ConfigurationSerializable deserializeViaCtor(Constructor<? extends ConfigurationSerializable> ctor, Map<String, Object> args) {
91  try {
92  return ctor.newInstance(args);
93  } catch (Throwable ex) {
94  Logger.getLogger(ConfigurationSerialization.class.getName()).log(
95  Level.SEVERE,
96  "Could not call constructor '" + ctor.toString() + "' of " + clazz + " for deserialization",
97  ex instanceof InvocationTargetException ? ex.getCause() : ex);
98  }
99 
100  return null;
101  }
102 
103  public ConfigurationSerializable deserialize(Map<String, Object> args) {
104  Validate.notNull(args, "Args must not be null");
105 
106  ConfigurationSerializable result = null;
107  Method method = null;
108 
109  if (result == null) {
110  method = getMethod("deserialize", true);
111 
112  if (method != null) {
113  result = deserializeViaMethod(method, args);
114  }
115  }
116 
117  if (result == null) {
118  method = getMethod("valueOf", true);
119 
120  if (method != null) {
121  result = deserializeViaMethod(method, args);
122  }
123  }
124 
125  if (result == null) {
126  Constructor<? extends ConfigurationSerializable> constructor = getConstructor();
127 
128  if (constructor != null) {
129  result = deserializeViaCtor(constructor, args);
130  }
131  }
132 
133  return result;
134  }
135 
149  public static ConfigurationSerializable deserializeObject(Map<String, Object> args, Class<? extends ConfigurationSerializable> clazz) {
150  return new ConfigurationSerialization(clazz).deserialize(args);
151  }
152 
165  public static ConfigurationSerializable deserializeObject(Map<String, Object> args) {
166  Class<? extends ConfigurationSerializable> clazz = null;
167 
168  if (args.containsKey(SERIALIZED_TYPE_KEY)) {
169  try {
170  String alias = (String) args.get(SERIALIZED_TYPE_KEY);
171 
172  if (alias == null) {
173  throw new IllegalArgumentException("Cannot have null alias");
174  }
175  clazz = getClassByAlias(alias);
176  if (clazz == null) {
177  throw new IllegalArgumentException("Specified class does not exist ('" + alias + "')");
178  }
179  } catch (ClassCastException ex) {
180  ex.fillInStackTrace();
181  throw ex;
182  }
183  } else {
184  throw new IllegalArgumentException("Args doesn't contain type key ('" + SERIALIZED_TYPE_KEY + "')");
185  }
186 
187  return new ConfigurationSerialization(clazz).deserialize(args);
188  }
189 
195  public static void registerClass(Class<? extends ConfigurationSerializable> clazz) {
196  DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class);
197 
198  if (delegate == null) {
199  registerClass(clazz, getAlias(clazz));
200  registerClass(clazz, clazz.getName());
201  }
202  }
203 
211  public static void registerClass(Class<? extends ConfigurationSerializable> clazz, String alias) {
212  aliases.put(alias, clazz);
213  }
214 
220  public static void unregisterClass(String alias) {
221  aliases.remove(alias);
222  }
223 
229  public static void unregisterClass(Class<? extends ConfigurationSerializable> clazz) {
230  while (aliases.values().remove(clazz)) {
231  ;
232  }
233  }
234 
241  public static Class<? extends ConfigurationSerializable> getClassByAlias(String alias) {
242  return aliases.get(alias);
243  }
244 
251  public static String getAlias(Class<? extends ConfigurationSerializable> clazz) {
252  DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class);
253 
254  if (delegate != null) {
255  if ((delegate.value() == null) || (delegate.value() == clazz)) {
256  delegate = null;
257  } else {
258  return getAlias(delegate.value());
259  }
260  }
261 
262  if (delegate == null) {
263  SerializableAs alias = clazz.getAnnotation(SerializableAs.class);
264 
265  if ((alias != null) && (alias.value() != null)) {
266  return alias.value();
267  }
268  }
269 
270  return clazz.getName();
271  }
272 }