package ring.persistence; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import javax.xml.bind.JAXBException; import org.xmldb.api.base.Collection; import org.xmldb.api.base.XMLDBException; import org.xmldb.api.modules.XMLResource; import ring.entities.Entity; import ring.items.Item; import ring.mobiles.Mobile; import ring.movement.Room; import ring.movement.Zone; import ring.nrapi.business.BusinessObject; import ring.players.Player; import ring.players.PlayerCharacter; public class ExistDBStore implements DataStore { //XMLDB mappings public static final String XML_RESOURCE_TYPE = "XMLResource"; //Collection mappings public static final String STATIC_COLLECTION = "static"; public static final String GAME_COLLECTION = "game"; public static final String PLAYERS_COLLECTION = "players"; //Loadpoint: Whether to do default load method, load explictly from game, //or explicitly from static. private Loadpoint loadpoint; private static String LOAD_QUERY = ""; static { //Retrieve the XQuery for loading resources. InputStream xqStream = ExistDBStore.class.getClassLoader().getResourceAsStream("ring/persistence/resourceloader.xq"); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(xqStream)); String line = ""; while ((line = reader.readLine()) != null) { LOAD_QUERY += line + "\n"; } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } @Override /** * Explicitly pulls from the players collection. */ public Player retrievePlayer(String id) { try { return retrieveResource(id, Player.class, Loadpoint.PLAYERS); } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public PlayerCharacter retrievePlayerCharacter(String id) { try { return retrieveResource(id, PlayerCharacter.class, Loadpoint.PLAYERS); } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public Room retrieveRoom(String id) { try { return retrieveResource(id, Room.class, getLoadpoint()); } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public Entity retrieveEntity(String id) { try { return retrieveResource(id, Entity.class, getLoadpoint()); } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public Zone retrieveZone(String id) { try { return retrieveResource(id, Zone.class, getLoadpoint()); } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public Item retrieveItem(String id) { try { return retrieveResource(id, Item.class, getLoadpoint()); } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public Mobile retrieveMobile(String id) { try { return retrieveResource(id, Mobile.class, getLoadpoint()); } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } private void closeConnection(Collection col) { assert(col != null); try { col.close(); } catch (XMLDBException e) { e.printStackTrace(); } } @Override /** * Updates the parent document this Persistable is tied to. * Due to the nature of this method, other changes to the * parent document will be committed as well. */ public boolean storePersistable(Persistable p) { ExistDB db = new ExistDB(); Collection col = null; try { if (p.getRoot().getDocumentName() == null) { p.getRoot().setDocumentName(p.getID() + ".xml"); } //TODO implement update lock checking: all parts of a document must be ready for update. Could be good use of AspectJ? if (p instanceof Player || p instanceof PlayerCharacter) { col = db.getCollection(PLAYERS_COLLECTION); } else { col = db.getCollection(GAME_COLLECTION); } assert(col != null); //Find the existing document, or create a new one. XMLResource doc = null; if (p.getDocumentName() != null) { doc = (XMLResource)col.getResource(p.getDocumentName()); if (doc == null) { doc = createXMLResource(col, p.getID()); } } else { doc = createXMLResource(col, p.getID()); } //Now update the document's content with all of the //info that the root of p has.f doc.setContent(p.toXMLDocument()); col.storeResource(doc); return true; } catch (XMLDBException e) { e.printStackTrace(); return false; } finally { if (col != null) { closeConnection(col); } } } protected <T extends BusinessObject> T retrieveResource(String id, Class<T> type, Loadpoint point) throws XMLDBException, JAXBException { //Ghetto prepared statements! String query = LOAD_QUERY.replace("$id", id); XQuery xq = new XQuery(query); xq.setLoadpoint(point); List<T> results = xq.execute(type); if (results.size() > 0) { return results.get(0); } else { return null; } } private XMLResource createXMLResource(Collection col, String id) throws XMLDBException { return (XMLResource) col.createResource(id, XML_RESOURCE_TYPE); } @Override public boolean importDocument(File file) { ExistDB db = new ExistDB(); Collection col = null; try { col = db.getCollection(STATIC_COLLECTION); String name = file.getName(); if (!name.endsWith(".xml")) name += ".xml"; XMLResource res = createXMLResource(col, name); res.setContent(file); col.storeResource(res); return true; } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } finally { if (col != null) { closeConnection(col); } } } @Override public boolean removeDocument(String docID) { ExistDB db = new ExistDB(); Collection col = null; try { col = db.getCollection(STATIC_COLLECTION); XMLResource res = (XMLResource)col.getResource(docID); if (res != null) { col.removeResource(res); return true; } else { return false; } } catch (XMLDBException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } finally { if (col != null) { closeConnection(col); } } } @Override public Loadpoint getLoadpoint() { if (loadpoint != null) { return loadpoint; } else { return Loadpoint.DEFAULT; } } @Override public void setLoadpoint(Loadpoint point) { loadpoint = point; } }