DocumentParser.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package com.l2jserver.gameserver.engines;
  16. import java.io.File;
  17. import java.util.logging.Logger;
  18. import javax.xml.parsers.DocumentBuilder;
  19. import javax.xml.parsers.DocumentBuilderFactory;
  20. import org.w3c.dom.Document;
  21. import org.w3c.dom.NamedNodeMap;
  22. import org.w3c.dom.Node;
  23. import org.xml.sax.ErrorHandler;
  24. import org.xml.sax.SAXParseException;
  25. import com.l2jserver.Config;
  26. import com.l2jserver.util.file.filter.XMLFilter;
  27. /**
  28. * Abstract class for XML parsers.<br>
  29. * It's in <i>beta</i> state, so it's expected to change over time.
  30. * @author Zoey76
  31. */
  32. public abstract class DocumentParser
  33. {
  34. protected final Logger _log = Logger.getLogger(getClass().getName());
  35. private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
  36. private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
  37. private static final XMLFilter xmlFilter = new XMLFilter();
  38. /**
  39. * This method can be used to load/reload the data.<br>
  40. * It's highly recommended to clear the data storage, either the list or map.
  41. */
  42. public abstract void load();
  43. /**
  44. * Wrapper for {@link #parseFile(File)} method.
  45. * @param path the relative path to the datapack root of the XML file to parse.
  46. */
  47. protected void parseDatapackFile(String path)
  48. {
  49. parseFile(new File(Config.DATAPACK_ROOT, path));
  50. }
  51. /**
  52. * Parses a single XML file.<br>
  53. * If the file was successfully parsed, call {@link #parseDocument(Document)} for the parsed document.
  54. * Validation is enforced.
  55. * @param f the XML file to parse.
  56. */
  57. protected void parseFile(File f)
  58. {
  59. if (!xmlFilter.accept(f))
  60. {
  61. _log.warning(getClass().getSimpleName() + ": Could not parse " + f.getName() + " is not a file or it doesn't exist!");
  62. return;
  63. }
  64. final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  65. dbf.setNamespaceAware(true);
  66. dbf.setValidating(true);
  67. dbf.setIgnoringComments(true);
  68. Document doc = null;
  69. try
  70. {
  71. dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
  72. final DocumentBuilder db = dbf.newDocumentBuilder();
  73. db.setErrorHandler(new XMLErrorHandler());
  74. doc = db.parse(f);
  75. }
  76. catch (Exception e)
  77. {
  78. _log.warning(getClass().getSimpleName() + ": Could not parse " + f.getName() + " file: " + e.getMessage());
  79. return;
  80. }
  81. parseDocument(doc);
  82. }
  83. /**
  84. * Wrapper for {@link #parseDirectory(File)}.
  85. * @param path the path to the directory where the XML files are.
  86. * @return {@code false} if it fails to find the directory, {@code true} otherwise.
  87. */
  88. protected boolean parseDirectory(String path)
  89. {
  90. return parseDirectory(new File(path));
  91. }
  92. /**
  93. * Loads all XML files from {@code path} and calls {@link #parseFile(File)} for each one of them.
  94. * @param dir the directory object to scan.
  95. * @return {@code false} if it fails to find the directory, {@code true} otherwise.
  96. */
  97. protected boolean parseDirectory(File dir)
  98. {
  99. if (!dir.exists())
  100. {
  101. _log.warning(getClass().getSimpleName() + ": Folder " + dir.getAbsolutePath() + " doesn't exist!");
  102. return false;
  103. }
  104. final File[] listOfFiles = dir.listFiles(xmlFilter);
  105. for (File f : listOfFiles)
  106. {
  107. parseFile(f);
  108. }
  109. return true;
  110. }
  111. /**
  112. * Abstract method that when implemented will parse a document.<br>
  113. * Is expected to be call from {@link #parseFile(File)}.
  114. * @param doc the document to parse.
  115. */
  116. protected abstract void parseDocument(Document doc);
  117. /**
  118. * @param n the named node map.
  119. * @param name the attribute name.
  120. * @return a parsed integer.
  121. */
  122. protected static int parseInt(NamedNodeMap n, String name)
  123. {
  124. return Integer.parseInt(n.getNamedItem(name).getNodeValue());
  125. }
  126. /**
  127. * @param n the named node map.
  128. * @param name the attribute name.
  129. * @return a parsed integer object.
  130. */
  131. protected static Integer parseInteger(NamedNodeMap n, String name)
  132. {
  133. return Integer.valueOf(n.getNamedItem(name).getNodeValue());
  134. }
  135. /**
  136. * @param n the node to parse.
  137. * @return the parsed integer.
  138. */
  139. protected static int parseInt(Node n)
  140. {
  141. return Integer.parseInt(n.getNodeValue());
  142. }
  143. /**
  144. * @param n the node to parse.
  145. * @return the parsed integer object.
  146. */
  147. protected static Integer parseInteger(Node n)
  148. {
  149. return Integer.valueOf(n.getNodeValue());
  150. }
  151. /**
  152. * @param n the named node map.
  153. * @param name the attribute name.
  154. * @return a parsed integer.
  155. */
  156. protected static Long parseLong(NamedNodeMap n, String name)
  157. {
  158. return Long.valueOf(n.getNamedItem(name).getNodeValue());
  159. }
  160. /**
  161. * @param n the named node map.
  162. * @param name the attribute name.
  163. * @return {@code true} if the attribute exists and it's value is {@code true}, {@code false} otherwise.
  164. */
  165. protected static boolean parseBoolean(NamedNodeMap n, String name)
  166. {
  167. final Node b = n.getNamedItem(name);
  168. return (b != null) && Boolean.parseBoolean(b.getNodeValue());
  169. }
  170. /**
  171. * Simple XML error handler.
  172. * @author Zoey76
  173. */
  174. protected class XMLErrorHandler implements ErrorHandler
  175. {
  176. @Override
  177. public void warning(SAXParseException e) throws SAXParseException
  178. {
  179. throw e;
  180. }
  181. @Override
  182. public void error(SAXParseException e) throws SAXParseException
  183. {
  184. throw e;
  185. }
  186. @Override
  187. public void fatalError(SAXParseException e) throws SAXParseException
  188. {
  189. throw e;
  190. }
  191. }
  192. }