View Javadoc

1   /*
2    * Created on 27 févr. 2005
3    * 
4    *   Magic-Project is a turn based strategy simulator
5    *   Copyright (C) 2003-2007 Fabrice Daugan
6    *
7    *   This program is free software; you can redistribute it and/or modify it 
8    * under the terms of the GNU General Public License as published by the Free 
9    * Software Foundation; either version 2 of the License, or (at your option) any
10   * later version.
11   *
12   *   This program is distributed in the hope that it will be useful, but WITHOUT 
13   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
15   * details.
16   *
17   *   You should have received a copy of the GNU General Public License along  
18   * with this program; if not, write to the Free Software Foundation, Inc., 
19   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   */
21  package net.sf.magicproject.xml.tbs;
22  
23  import java.io.IOException;
24  import java.io.OutputStream;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.HashMap;
28  import java.util.List;
29  
30  import net.sf.magicproject.token.IdTokens;
31  import net.sf.magicproject.tools.MToolKit;
32  import net.sf.magicproject.xml.XmlConfiguration;
33  import net.sf.magicproject.xml.XmlModifier;
34  import net.sf.magicproject.xml.XmlParser;
35  import net.sf.magicproject.xml.XmlTbs;
36  import net.sf.magicproject.xml.XmlTest;
37  import net.sf.magicproject.xml.XmlToMDB;
38  import net.sf.magicproject.xml.XmlTools;
39  import net.sf.magicproject.xml.XmlParser.Node;
40  
41  import org.apache.commons.io.FilenameUtils;
42  
43  /***
44   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
45   * @since 0.82
46   */
47  public class Card implements XmlToMDB {
48  
49  	/***
50  	 * <ul>
51  	 * Structure of stream : Data[size]
52  	 * <li>art author [String]</li>
53  	 * <li>rules author [String]</li>
54  	 * <li>keywords [String[]]</li>
55  	 * <li>registers [IdTokenCard.CARD_REGISTER_SIZE]</li>
56  	 * <li>idCard [int16]</li>
57  	 * <li>idColor [int]</li>
58  	 * <li>abilities [Ability[]]</li>
59  	 * <li>sorted properties [int16[]]</li>
60  	 * <li>modifiers [ModifierModel[]]</li>
61  	 * <li>attachement [boolean]</li>
62  	 * <li>attachement condition [Test[]]</li>
63  	 * </ul>
64  	 * 
65  	 * @param node
66  	 *          the XML card structure
67  	 * @param out
68  	 *          outputstream where the card structure will be saved
69  	 * @return the amount of written action in the output.
70  	 * @see net.sf.magicproject.clickable.targetable.card.MCard
71  	 * @throws IOException
72  	 *           error while writting.
73  	 */
74  	public final int buildMdb(Node node, OutputStream out) throws IOException {
75  		// card name
76  		String cardName = node.getAttribute("name");
77  		if (cardName == null || cardName.length() == 0) {
78  			XmlConfiguration.error++;
79  			System.out.println("\t>> Null card name found in '"
80  					+ node.getAttribute("xmlFile") + "'");
81  			cardName = FilenameUtils.getBaseName(node.getAttribute("xmlFile"))
82  					.toLowerCase();
83  		}
84  
85  		String xmlFile = node.getAttribute("xmlFile");
86  		if (xmlFile != null
87  				&& !FilenameUtils.getBaseName(xmlFile).toLowerCase().equalsIgnoreCase(
88  						MToolKit.getKeyName(cardName))) {
89  			XmlConfiguration.error++;
90  			System.out.println("\t>> Card '" + cardName
91  					+ "' should be definied in it's own file, not '"
92  					+ node.getAttribute("xmlFile") + "'");
93  		}
94  
95  		// Write the card name using the pager
96  		XmlTbs.cardPager.addReference(out, cardName);
97  
98  		// credits
99  		Node credits = node.get("rules-author-comment");
100 		if (credits != null && credits.get(0) != null) {
101 			if (credits.get(0).toString().startsWith("Oracle2Xml")) {
102 				XmlConfiguration.uncompleted++;
103 				System.out.println("\t... uncompleted card");
104 			}
105 			MToolKit.writeString(out, credits.get(0).toString());
106 		} else {
107 			MToolKit.writeString(out, null);
108 		}
109 
110 		// keywords
111 		Node keywords = node.get("keywords");
112 		if (keywords != null && keywords.get(0) != null) {
113 			String[] words = keywords.get(0).toString().split(" ");
114 			out.write(words.length);
115 			for (String keyword : words) {
116 				MToolKit.writeString(out, keyword);
117 			}
118 		} else {
119 			out.write(0);
120 		}
121 
122 		Node init = node.get("init");
123 		// init the additional modifier list
124 		List<Node> modifierNodes = new ArrayList<Node>();
125 		// registers
126 		byte[] registersBytes = new byte[IdTokens.CARD_REGISTER_SIZE];
127 		if (init != null) {
128 			Node registers = init.get("registers");
129 			if (registers != null) {
130 				final List<Node> list = registers.getNodes("register");
131 				for (Node register : list) {
132 					if (register.getAttribute("value") == null) {
133 						// add this node that should contain a registermodifier
134 						modifierNodes.add(register);
135 					} else {
136 						registersBytes[XmlTools.getInt(register.getAttribute("index"))] = (byte) XmlTools
137 								.getInt(register.getAttribute("value"));
138 					}
139 				}
140 			}
141 		}
142 		out.write(registersBytes);
143 
144 		// idcard
145 		int idCard = 0;
146 		int decr = 0;
147 		if (init != null) {
148 			Node idcards = init.get("idcards");
149 			if (idcards != null && idcards.get(0) != null) {
150 				String list = ((String) idcards.get(0)).trim();
151 				String[] arrayid = list.split(" ");
152 				for (String id : arrayid) {
153 					if (id.trim().length() > 0) {
154 						idCard |= XmlTools.getIdCard(id);
155 					}
156 				}
157 			}
158 		}
159 		MToolKit.writeInt16(out, idCard);
160 
161 		// color
162 		int idColor = 0;
163 		if (init != null) {
164 			Node colors = init.get("colors");
165 			if (colors != null && colors.get(0) != null) {
166 				String list = ((String) colors.get(0)).trim();
167 				String[] arrayid = list.split(" ");
168 				for (String id : arrayid) {
169 					if (id.trim().length() > 0) {
170 						idColor |= XmlTools.getColor(id);
171 					}
172 				}
173 			}
174 		}
175 		out.write(idColor);
176 
177 		// actions
178 		Node actions = node.get("actions");
179 		if (actions != null) {
180 			for (Object obj : actions) {
181 				if (obj instanceof Node) {
182 					String ref = ((Node) obj).getAttribute("reference-name");
183 					List<Node> actionList = new ArrayList<Node>();
184 					for (Object actionI : (Node) obj) {
185 						if (actionI instanceof Node) {
186 							// add action to the action list
187 							((Node) actionI)
188 									.addAttribute(new XmlParser.Attribute("name", ref));
189 							actionList.add((Node) actionI);
190 						}
191 					}
192 					// add this reference
193 					if (XmlTbs.referencedActions == null) {
194 						XmlTbs.referencedActions = new HashMap<String, List<Node>>();
195 					}
196 					XmlTbs.referencedActions.put(ref, actionList);
197 				}
198 			}
199 		}
200 
201 		// abilities
202 		Node abilities = node.get("abilities");
203 		if (abilities == null) {
204 			out.write(0);
205 		} else {
206 			out.write(abilities.getNbNodes());
207 			for (Object obj : abilities) {
208 				if (obj instanceof Node) {
209 					Node ability = (Node) obj;
210 					String ref = ability.getAttribute("reference-name");
211 					if (ref != null && ref.length() > 0) {
212 						if (XmlTbs.referencedAbilities == null) {
213 							XmlTbs.referencedAbilities = new HashMap<String, Node>();
214 						}
215 						XmlTbs.referencedAbilities.put(ref, (Node) obj);
216 					}
217 
218 					XmlTbs.getTbsComponent(ability.getTag()).buildMdb(ability, out);
219 					// add this reference
220 				}
221 			}
222 		}
223 
224 		// properties
225 		if (init != null) {
226 			Node properties = init.get("properties");
227 			if (properties == null) {
228 				out.write(0);
229 			} else {
230 				Object strProperties = properties.get(0);
231 				String list = null;
232 				if (strProperties == null) {
233 					list = "";
234 				} else {
235 					list = ((String) strProperties).trim();
236 				}
237 				String[] arrayid = list.split(" ");
238 				decr = 0;
239 				for (int i = arrayid.length; i-- > 0;) {
240 					arrayid[i] = arrayid[i].trim();
241 					if (arrayid[i].length() == 0) {
242 						decr++;
243 					}
244 				}
245 				int[] arrayIdSorted = new int[arrayid.length - decr];
246 				out.write(arrayIdSorted.length);
247 				// get int values associated to properties name
248 				decr = 0;
249 				for (String id : arrayid) {
250 					if (id.length() > 0) {
251 						arrayIdSorted[decr++] = XmlTools.getInt(id);
252 					}
253 				}
254 				// sort the properties values
255 				Arrays.sort(arrayIdSorted);
256 				// write the sorted properties values
257 				for (int id : arrayIdSorted) {
258 					MToolKit.writeInt16(out, id);
259 				}
260 			}
261 		} else {
262 			out.write(0);
263 		}
264 
265 		// registerindirections
266 		Node modifiers = node.get("modifiers");
267 		if (modifiers == null) {
268 			out.write(modifierNodes.size());
269 		} else {
270 			out.write(modifiers.getNbNodes() + modifierNodes.size());
271 
272 			// explicitly declared modifiers
273 			for (Object obj : modifiers) {
274 				if (obj instanceof Node) {
275 					XmlModifier.getModifier(((Node) obj).getTag()).buildMdb((Node) obj,
276 							out);
277 				}
278 			}
279 		}
280 		if (!modifierNodes.isEmpty()) {
281 			// there are some additional register indirections to add
282 			for (Node nodeModifier : modifierNodes) {
283 				if (nodeModifier.get("value") != null) {
284 					// this indirection has as value a counter
285 					boolean oldValue = XmlTools.defaultOnMeTag;
286 					XmlTools.defaultOnMeTag = false;
287 					XmlModifier.getModifier("register-indirection").buildMdb(
288 							nodeModifier, out);
289 					XmlTools.defaultOnMeTag = oldValue;
290 				} else {
291 					XmlConfiguration.error++;
292 					System.out
293 							.println("\t>>The specified modifier for this register is unknown; "
294 									+ nodeModifier);
295 					return 0;
296 				}
297 			}
298 		}
299 
300 		// attachment
301 		Node attachment = node.get("attachment");
302 		if (attachment == null) {
303 			out.write(0);
304 		} else {
305 			out.write(1);
306 			Node referenceModifiers = null;
307 			if (attachment.getAttribute("ref") != null) {
308 				referenceModifiers = attachment.get("modifiers");
309 				attachment = XmlTbs.getReferencedAttachment(attachment
310 						.getAttribute("ref"));
311 			}
312 			if (attachment == null)
313 				// reference error
314 				return 0;
315 
316 			Node attachementModifiers = attachment.get("modifiers");
317 			if (referenceModifiers == null) {
318 				if (attachementModifiers == null) {
319 					out.write(0);
320 				} else {
321 					out.write(attachementModifiers.getNbNodes());
322 				}
323 			} else {
324 				if (attachementModifiers == null)
325 					out.write(referenceModifiers.getNbNodes());
326 				else {
327 					out.write(attachementModifiers.getNbNodes()
328 							+ referenceModifiers.getNbNodes());
329 				}
330 				// macro modifiers
331 				for (Object obj : referenceModifiers) {
332 					if (obj instanceof Node) {
333 						XmlModifier.getModifier(((Node) obj).getTag()).buildMdb((Node) obj,
334 								out);
335 					}
336 				}
337 			}
338 
339 			// explicitly declared modifiers
340 			if (attachementModifiers != null) {
341 				for (Object obj : attachementModifiers) {
342 					if (obj instanceof Node) {
343 						XmlModifier.getModifier(((Node) obj).getTag()).buildMdb((Node) obj,
344 								out);
345 					}
346 				}
347 			}
348 			XmlTest.getTest("test").buildMdb(attachment.get("valid-target"), out);
349 			XmlTest.getTest("test").buildMdb(attachment.get("valid-attachment"), out);
350 		}
351 		return 0;
352 	}
353 }