package ring.nrapi.xml; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.python.core.PyObject; import org.python.util.PythonInterpreter; import ring.persistence.Persistable; /** * A tool for converting Jython-based Persistable objects to XML that the engine can understand. * This stores a list of Persistables, and when requested, calls the toXML() method on each one. * This tool is mainly to be used by world builders who do not wish to code data in XML by hand. * Instead, the compiler will use this to construct the XML for them. The only downside is that * game objects must be added to this object manually. * @author projectmoon * */ public class XMLConverter { private static List<Persistable> persistables = new ArrayList<Persistable>(); /** * Adds a Persistable to the XML converter for later use. * @param p */ public static void add(Persistable p) { persistables.add(p); } /** * Adds a list of Persistables for later use. * @param ps */ public static void add(List<Persistable> ps) { persistables.addAll(ps); } /** * Adds a python dictionary or list containing only Persistables to the list of * objects to be converted to XML. This method performs basic type checking to * ensure that the PyObject received is either a dict or a list. If the passed object * is neither a list nor a dict, the method will assume that the object being added * is an individual Persistable and will try to convert it to that. If all of these * fail, an IllegalArgumentException will be thrown. * <br/><br/> * When adding a list or dict, it will iterate over all values without regards to their * actual data type, so it is still possible to get a ClassCastException. * @param p */ public static void add(PyObject p) { if (p.getType().getName().equals("dict")) { Map<?, Persistable> map = (Map<?, Persistable>)p.__tojava__(Map.class); persistables.addAll(map.values()); } else if (p.getType().getName().equals("list")) { List<Persistable> list = (List<Persistable>) p.__tojava__(List.class); persistables.addAll(list); } else { try { Persistable persistable = (Persistable)p.__tojava__(Persistable.class); persistables.add(persistable); } catch (Exception e) { throw new IllegalArgumentException("Type \"" + p.getType().getName() + "\" is invalid in this context."); } } } /** * Adds a Map containing Persistables to the XML Converter for later use. * The keys may be of any type, as the XMLConverter is only concerned with the values. * @param map */ public static void add(Map<?, Persistable> map) { persistables.addAll(map.values()); } /** * Converts all stored persistables to XML and returns their XML strings in a List. * @return The converted XML. */ public static List<String> getXML() { List<String> xml = new ArrayList<String>(persistables.size()); for (Persistable p : persistables) { xml.add(p.toXML()); } return xml; } public static List<Persistable> getPersistables() { return persistables; } /** * Clears the list of stored persistables. */ public static void clear() { persistables.clear(); } /** * The preferred way to create a Persistable that will be converted to XML. This returns a * new instance of the desired Persistable type, and adds it to the list of Persistables. * @param type The Java class object for which to create this Persistable. From Jython, this is retrieved * as "ClassName". There is no need to add .class to the end. * @return A new instance of the desired type. * @throws InstantiationException * @throws IllegalAccessException */ public static <P extends Persistable> P create(Class<P> type) throws InstantiationException, IllegalAccessException { P inst = type.newInstance(); persistables.add(inst); return inst; } }