1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.magicproject.xml;
20
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.FilenameFilter;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31
32 import net.sf.magicproject.annotation.XmlTestElement;
33 import net.sf.magicproject.token.IdConst;
34 import net.sf.magicproject.tools.MToolKit;
35 import net.sf.magicproject.tools.PairStringInt;
36 import net.sf.magicproject.xml.XmlParser.Node;
37
38 import org.apache.commons.io.filefilter.FileFilterUtils;
39 import org.apache.commons.lang.StringUtils;
40 import org.apache.commons.lang.WordUtils;
41 import org.xml.sax.SAXException;
42 import org.xml.sax.SAXParseException;
43
44 /***
45 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
46 */
47 public class XmlConfiguration {
48
49 /***
50 * Is schema validation is activated.
51 */
52 public static boolean validationOn = false;
53
54 /***
55 * Constructor.
56 *
57 * @param configuration
58 * An input stream containing a complete e.g. configuration file
59 * @exception SAXException
60 * parsing error.
61 * @exception IOException
62 * writing error.
63 */
64 public XmlConfiguration(InputStream configuration) throws SAXException,
65 IOException {
66 initParser();
67 synchronized (parser) {
68 config = parser.parse(configuration);
69 }
70 }
71
72 /***
73 *
74 */
75 private static synchronized void initParser() {
76 if (parser != null) {
77 return;
78 }
79 parser = new XmlParser();
80 }
81
82 /***
83 * Create a new object and configure it. A new object is created and
84 * configured.
85 *
86 * @param xmlFile
87 * the xml source file.
88 * @param workingDir
89 * the working dir.
90 * @param output
91 * the output strem of mdb file.
92 */
93 public void newInstance(String xmlFile, String workingDir, OutputStream output) {
94 try {
95 if (XmlTools.aliasMap == null) {
96 XmlTools.aliasMap = new HashMap<String, Integer>(newIncludeInstance());
97 }
98 String tagName = config.getTag();
99 config.addAttribute(new XmlParser.Attribute("workingDir", workingDir));
100 config.addAttribute(new XmlParser.Attribute("xmlFile", xmlFile.replace(
101 '//', '/')));
102 XmlTbs.getTbsComponent(tagName).buildMdb(config, output);
103 } catch (Exception e) {
104 e.printStackTrace();
105 }
106 }
107
108 /***
109 * Return the method name corresponding to the specified TAG.
110 *
111 * @param tagName
112 * @return the method name corresponding to the specified TAG.
113 */
114 static XmlToMDB getXmlClass(String tagName, Map<String, XmlToMDB> instances,
115 Class<?> nameSpaceCall) {
116 if (!nameSpaceCall.getSimpleName().startsWith("Xml"))
117 throw new InternalError("Caller should be an Xml class : "
118 + nameSpaceCall);
119
120 XmlToMDB nodeClass = instances.get(tagName);
121 if (nodeClass != null) {
122 return nodeClass;
123 }
124
125 String simpleClassName = StringUtils
126 .capitalize(tagName.replaceAll("-", ""));
127 String packageName = nameSpaceCall.getPackage().getName();
128 String namespace = nameSpaceCall.getSimpleName().substring(3).toLowerCase();
129 String className = packageName + "." + namespace + "." + simpleClassName;
130 XmlToMDB result;
131 try {
132 result = (XmlToMDB) Class.forName(className).newInstance();
133 } catch (Throwable e) {
134 try {
135 Class<?> mdbClass = null;
136 simpleClassName = WordUtils.capitalize(tagName.replaceAll("-", " "))
137 .replaceAll(" ", "");
138 className = StringUtils.chomp(packageName, ".xml") + "." + namespace
139 + "." + simpleClassName;
140 mdbClass = Class.forName(className);
141 result = getAnnotedBuilder(mdbClass, tagName, packageName, namespace);
142 } catch (Throwable ei2) {
143 XmlConfiguration.error++;
144 System.out.println("\t>> Unsupported " + namespace + " '" + tagName
145 + "'");
146 result = DummyBuilder.instance();
147 }
148 }
149 instances.put(tagName, result);
150 return result;
151 }
152
153 /***
154 * @param mdbClass
155 * @throws IllegalAccessException
156 * @throws InstantiationException
157 * @throws ClassNotFoundException
158 */
159 private static XmlToMDB getAnnotedBuilder(Class<?> mdbClass, String tagName,
160 String packageName, String namespace) throws InstantiationException,
161 IllegalAccessException, ClassNotFoundException {
162 if (!mdbClass.isAnnotationPresent(XmlTestElement.class)) {
163 XmlConfiguration.error++;
164 System.out.println("\t>> Unsupported annoted " + namespace + " '"
165 + tagName + "'");
166 return DummyBuilder.instance();
167 }
168 XmlTestElement xmlElement = mdbClass.getAnnotation(XmlTestElement.class);
169 XmlAnnoted annotedInstance = (XmlAnnoted) Class.forName(
170 packageName + "." + namespace + ".XmlAnnoted").newInstance();
171 annotedInstance.setXmlElement(xmlElement);
172 annotedInstance.setAnnotedClass(mdbClass);
173 return annotedInstance;
174 }
175
176 /***
177 * Create a new object and configure it. A new object is created and
178 * configured.
179 *
180 * @return The newly created configured object.
181 */
182 private Map<String, Integer> newIncludeInstance() {
183
184 exportedProperties.clear();
185 exportedTypes.clear();
186 exportedPhases.clear();
187 propertyPictures.clear();
188
189 Node aliases = XmlTools.getExternalizableNode(config, "aliases");
190 Map<String, Integer> aliasMap = new HashMap<String, Integer>();
191
192 aliasMap.put("nocare", IdConst.NO_CARE);
193 for (Node alias : aliases.getNodes("alias")) {
194 aliasMap.put(alias.getAttribute("name"), Integer.parseInt(alias
195 .getAttribute("value")));
196 final String exportation = alias.getAttribute("export");
197 if ("properties".equals(exportation)) {
198 exportedProperties.add(new PairStringInt(alias.getAttribute("name"),
199 Integer.parseInt(alias.getAttribute("value"))));
200
201 final String picture = alias.getAttribute("picture");
202 if (picture != null) {
203 propertyPictures.put(Integer.parseInt(alias.getAttribute("value")),
204 picture);
205 }
206 } else if ("damage-types".equals(exportation)) {
207 exportedDamageTypes.add(new PairStringInt(alias.getAttribute("name"),
208 Integer.parseInt(alias.getAttribute("value"))));
209 } else if ("types".equals(exportation)) {
210 exportedTypes.add(new PairStringInt(alias.getAttribute("name"), Integer
211 .parseInt(alias.getAttribute("value"))));
212 } else if ("phases".equals(exportation)) {
213 exportedPhases.add(new PairStringInt(alias.getAttribute("name"),
214 Integer.parseInt(alias.getAttribute("value"))));
215 }
216 }
217 return aliasMap;
218 }
219
220 /***
221 * <ul>
222 * 2 modes:
223 * <li>Update the a MDB for specified TBS against the XML files (main file,
224 * cards and fragments). Arguments are : TBS_NAME</li>
225 * <li>Rebuild completely the MDB for specified TBS. Arguments are : -full
226 * TBS_NAME</li>
227 * </ul>
228 *
229 * @param args
230 * main arguments.
231 */
232 public static void main(String... args) {
233 String res = "";
234 warning = 0;
235 uncompleted = 0;
236 error = 0;
237 for (String arg : args) {
238 res += ", " + arg;
239 }
240 long start = System.currentTimeMillis();
241 XmlTools.initHashMaps();
242 try {
243 if (args.length >= 2 && args[0].startsWith("-full")) {
244 validationOn = !args[0].equalsIgnoreCase("-fullO");
245 MToolKit.tbsName = args[args.length - 1];
246
247 noPayMana = args.length > 2 && "-nopaymana".equals(args[1]);
248 final File recycledDir = new File(IdConst.TBS_DIR + "/"
249 + MToolKit.tbsName + "/recycled");
250 if (!recycledDir.exists() || !recycledDir.isDirectory()) {
251 recycledDir.mkdir();
252 }
253
254 String xmlFile = IdConst.TBS_DIR + "/" + MToolKit.tbsName + ".xml";
255
256 new XmlConfiguration(MToolKit.getResourceAsStream(xmlFile))
257 .newInstance(xmlFile, IdConst.TBS_DIR + "/" + MToolKit.tbsName
258 + "/recycled", new FileOutputStream(MToolKit.getTbsFile(
259 MToolKit.tbsName + ".mdb", false)));
260 } else if (args.length == 3 && args[0].startsWith("-update")) {
261
262 MToolKit.tbsName = args[1];
263 String xmlFile = IdConst.TBS_DIR + "/" + MToolKit.tbsName + ".xml";
264 long lastModifiedMdb = Long.parseLong(args[2]);
265 boolean update = false;
266
267 if (new File(xmlFile).lastModified() > lastModifiedMdb) {
268
269 System.out.println("MDB is out of date, " + xmlFile + " is newer");
270 update = true;
271 } else {
272 final File fragmentDir = new File(IdConst.TBS_DIR + "/"
273 + MToolKit.tbsName);
274 for (File frament : fragmentDir
275 .listFiles((FilenameFilter) FileFilterUtils.andFileFilter(
276 FileFilterUtils.suffixFileFilter("xml"), FileFilterUtils
277 .prefixFileFilter("fragment-")))) {
278 if (frament.lastModified() > lastModifiedMdb) {
279
280 System.out
281 .println("MDB is out of date, at least one fragment found : "
282 + frament.getName());
283 update = true;
284 break;
285 }
286 }
287 if (!update) {
288
289 final File recycledDir = new File(IdConst.TBS_DIR + "/"
290 + MToolKit.tbsName + "/recycled");
291 if (!recycledDir.exists() || !recycledDir.isDirectory()) {
292 recycledDir.mkdir();
293 }
294 if (recycledDir.lastModified() > lastModifiedMdb) {
295
296 System.out
297 .println("MDB is out of date, the recycled directory is new");
298 update = true;
299 } else {
300 for (File card : recycledDir
301 .listFiles((FilenameFilter) FileFilterUtils.andFileFilter(
302 FileFilterUtils.suffixFileFilter("xml"), FileFilterUtils
303 .notFileFilter(FileFilterUtils
304 .suffixFileFilter(IdConst.FILE_DATABASE_SAVED))))) {
305 if (card.lastModified() > lastModifiedMdb) {
306
307 System.out
308 .println("MDB is out of date, at least one new card found : "
309 + card);
310 update = true;
311 break;
312 }
313 }
314 }
315 }
316 }
317 if (!update) {
318 return;
319 }
320
321 new XmlConfiguration(MToolKit.getResourceAsStream(xmlFile))
322 .newInstance(xmlFile, IdConst.TBS_DIR + "/" + MToolKit.tbsName
323 + "/recycled", new FileOutputStream(IdConst.TBS_DIR + "/"
324 + MToolKit.tbsName + "/" + MToolKit.tbsName + ".mdb"));
325 } else {
326
327 for (String arg : args) {
328 new XmlConfiguration(MToolKit.getResourceAsStream(arg)).newInstance(
329 arg, MToolKit.getFile(arg).getParentFile().getCanonicalPath(),
330 new FileOutputStream(MToolKit.getFile(arg + ".mdb")));
331 }
332 }
333 } catch (SAXParseException e) {
334
335 } catch (Exception e) {
336 e.printStackTrace();
337 }
338 if (warning > 0) {
339 System.out
340 .println("\t" + warning + " warning" + (warning > 1 ? "s" : ""));
341 }
342 if (error > 0) {
343 System.out.println("\t" + error + " error" + (error > 1 ? "s" : ""));
344 System.out.println("Some cards have not been built correctly. Fix them.");
345 } else {
346 System.out.println("\tSuccessfull build");
347 }
348 System.out.println("\tTime : " + (System.currentTimeMillis() - start)
349 / 1000 + " s");
350 }
351
352 /***
353 *
354 */
355 private static XmlParser parser;
356
357 /***
358 *
359 */
360 private XmlParser.Node config;
361
362 /***
363 * Exported properties
364 */
365 public static List<PairStringInt> exportedProperties = new ArrayList<PairStringInt>();
366
367 /***
368 * Exported properties
369 */
370 public static Map<Integer, String> propertyPictures = new HashMap<Integer, String>();
371
372 /***
373 * Exported types
374 */
375 public static List<PairStringInt> exportedTypes = new ArrayList<PairStringInt>();
376
377 /***
378 * Exported phases
379 */
380 public static List<PairStringInt> exportedPhases = new ArrayList<PairStringInt>();
381
382 /***
383 * Exported damage types
384 */
385 public static List<PairStringInt> exportedDamageTypes = new ArrayList<PairStringInt>();
386
387 /***
388 * Indicates that the next 'paymana' actions would be played the parameter
389 * 'colorless="0"'
390 */
391 public static boolean noPayMana;
392
393 /***
394 * Found errors
395 */
396 public static int error;
397
398 /***
399 * Found warnings
400 */
401 public static int warning;
402
403 /***
404 * Found uncompleted cards
405 */
406 public static int uncompleted;
407
408 /***
409 * Indicates the debug data are saved in the mdb.
410 *
411 * @return true if the debug data are saved in the mdb.
412 */
413 public static boolean isDebugEnable() {
414 return true;
415 }
416 }