View Javadoc

1   /*
2    * Created on 27 févr. 2005
3    * 
4    *   Firemox 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.firemox.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.firemox.token.IdTokens;
31  import net.sf.firemox.tools.MToolKit;
32  import net.sf.firemox.xml.XmlConfiguration;
33  import net.sf.firemox.xml.XmlModifier;
34  import net.sf.firemox.xml.XmlParser;
35  import net.sf.firemox.xml.XmlTbs;
36  import net.sf.firemox.xml.XmlTest;
37  import net.sf.firemox.xml.XmlToMDB;
38  import net.sf.firemox.xml.XmlTools;
39  import net.sf.firemox.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>card model</li>
53  	 * </ul>
54  	 * 
55  	 * @param node
56  	 *          the XML card structure
57  	 * @param out
58  	 *          output stream where the card structure will be saved
59  	 * @return the amount of written action in the output.
60  	 * @see net.sf.firemox.clickable.target.card.MCard
61  	 * @throws IOException
62  	 *           error while writing.
63  	 */
64  	public final int buildMdb(Node node, OutputStream out) throws IOException {
65  		// card name
66  		String cardName = node.getAttribute("name");
67  		if (cardName == null || cardName.length() == 0) {
68  			XmlConfiguration.error("Null card name found in '"
69  					+ node.getAttribute("xmlFile") + "'");
70  			cardName = FilenameUtils.getBaseName(node.getAttribute("xmlFile"))
71  					.toLowerCase();
72  		}
73  
74  		String xmlFile = node.getAttribute("xmlFile");
75  		if (xmlFile != null
76  				&& !FilenameUtils.getBaseName(xmlFile).toLowerCase().equalsIgnoreCase(
77  						MToolKit.getKeyName(cardName))) {
78  			XmlConfiguration.error("Card '" + cardName
79  					+ "' should be definied in it's own file, not '"
80  					+ node.getAttribute("xmlFile") + "'");
81  		}
82  
83  		// Write the card name using the pager
84  		XmlTbs.cardPager.addReference(out, cardName);
85  
86  		// credits
87  		final Node credits = node.get("rules-author-comment");
88  		if (credits != null && credits.get(0) != null) {
89  			if (credits.get(0).toString().startsWith("Oracle2Xml")) {
90  				XmlConfiguration.uncompleted();
91  			}
92  			MToolKit.writeString(out, credits.get(0).toString());
93  		} else {
94  			MToolKit.writeString(out, null);
95  		}
96  
97  		// keywords
98  		Node keywords = node.get("keywords");
99  		if (keywords != null && keywords.get(0) != null) {
100 			String[] words = keywords.get(0).toString().split(" ");
101 			out.write(words.length);
102 			for (String keyword : words) {
103 				MToolKit.writeString(out, keyword);
104 			}
105 		} else {
106 			out.write(0);
107 		}
108 
109 		final Node init = node.get("init");
110 		// initialize the additional modifier list
111 		final List<Node> modifierNodes = new ArrayList<Node>();
112 		// registers
113 		byte[] registersBytes = new byte[IdTokens.CARD_REGISTER_SIZE];
114 		if (init != null) {
115 			Node registers = init.get("registers");
116 			if (registers != null) {
117 				final List<Node> list = registers.getNodes("register");
118 				for (Node register : list) {
119 					if (register.getAttribute("value") == null) {
120 						// add this node that should contain a register modifier
121 						modifierNodes.add(register);
122 					} else {
123 						registersBytes[XmlTools.getInt(register.getAttribute("index"))] = (byte) XmlTools
124 								.getInt(register.getAttribute("value"));
125 					}
126 				}
127 			}
128 		}
129 		out.write(registersBytes);
130 
131 		// id card
132 		int idCard = 0;
133 		int decr = 0;
134 		if (init != null) {
135 			Node idcards = init.get("idcards");
136 			if (idcards != null && idcards.get(0) != null) {
137 				String list = ((String) idcards.get(0)).trim();
138 				String[] arrayid = list.split(" ");
139 				for (String id : arrayid) {
140 					if (id.trim().length() > 0) {
141 						idCard |= XmlTools.getIdCard(id);
142 					}
143 				}
144 			}
145 		}
146 		MToolKit.writeInt16(out, idCard);
147 
148 		// color
149 		int idColor = 0;
150 		if (init != null) {
151 			Node colors = init.get("colors");
152 			if (colors != null && colors.get(0) != null) {
153 				String list = ((String) colors.get(0)).trim();
154 				String[] arrayid = list.split(" ");
155 				for (String id : arrayid) {
156 					if (id.trim().length() > 0) {
157 						idColor |= XmlTools.getColor(id);
158 					}
159 				}
160 			}
161 		}
162 		out.write(idColor);
163 
164 		// properties
165 		if (init != null) {
166 			Node properties = init.get("properties");
167 			if (properties == null) {
168 				out.write(0);
169 			} else {
170 				Object strProperties = properties.get(0);
171 				String list = null;
172 				if (strProperties == null) {
173 					list = "";
174 				} else {
175 					list = ((String) strProperties).trim();
176 				}
177 				String[] arrayid = list.split(" ");
178 				decr = 0;
179 				for (int i = arrayid.length; i-- > 0;) {
180 					arrayid[i] = arrayid[i].trim();
181 					if (arrayid[i].length() == 0) {
182 						decr++;
183 					}
184 				}
185 				int[] arrayIdSorted = new int[arrayid.length - decr];
186 				out.write(arrayIdSorted.length);
187 				// get int values associated to properties name
188 				decr = 0;
189 				for (String id : arrayid) {
190 					if (id.length() > 0) {
191 						arrayIdSorted[decr++] = XmlTools.getInt(id);
192 					}
193 				}
194 				// sort the properties values
195 				Arrays.sort(arrayIdSorted);
196 				// write the sorted properties values
197 				for (int id : arrayIdSorted) {
198 					MToolKit.writeInt16(out, id);
199 				}
200 			}
201 		} else {
202 			out.write(0);
203 		}
204 
205 		// actions
206 		Node actions = node.get("actions");
207 		if (actions != null) {
208 			for (Object obj : actions) {
209 				if (obj instanceof Node) {
210 					String ref = ((Node) obj).getAttribute("reference-name");
211 					List<Node> actionList = new ArrayList<Node>();
212 					for (Object actionI : (Node) obj) {
213 						if (actionI instanceof Node) {
214 							// add action to the action list
215 							((Node) actionI)
216 									.addAttribute(new XmlParser.Attribute("name", ref));
217 							actionList.add((Node) actionI);
218 						}
219 					}
220 					// add this reference
221 					if (XmlTbs.referencedActions == null) {
222 						XmlTbs.referencedActions = new HashMap<String, List<Node>>();
223 					}
224 					XmlTbs.referencedActions.put(ref, actionList);
225 				}
226 			}
227 		}
228 
229 		// abilities
230 		Node abilities = node.get("abilities");
231 		if (abilities == null) {
232 			out.write(0);
233 		} else {
234 			out.write(abilities.getNbNodes());
235 			for (Object obj : abilities) {
236 				if (obj instanceof Node) {
237 					Node ability = (Node) obj;
238 					String ref = ability.getAttribute("reference-name");
239 					if (ref != null && ref.length() > 0) {
240 						if (XmlTbs.referencedAbilities == null) {
241 							XmlTbs.referencedAbilities = new HashMap<String, Node>();
242 						}
243 						XmlTbs.referencedAbilities.put(ref, (Node) obj);
244 					}
245 
246 					XmlTbs.getTbsComponent(ability.getTag()).buildMdb(ability, out);
247 					// add this reference
248 				}
249 			}
250 		}
251 
252 		// register indirections
253 		Node modifiers = node.get("modifiers");
254 		if (modifiers == null) {
255 			out.write(modifierNodes.size());
256 		} else {
257 			out.write(modifiers.getNbNodes() + modifierNodes.size());
258 
259 			// explicitly declared modifiers
260 			for (Object obj : modifiers) {
261 				if (obj instanceof Node) {
262 					XmlModifier.getModifier(((Node) obj).getTag()).buildMdb((Node) obj,
263 							out);
264 				}
265 			}
266 		}
267 		if (!modifierNodes.isEmpty()) {
268 			// there are some additional register indirections to add
269 			for (Node nodeModifier : modifierNodes) {
270 				if (nodeModifier.get("value") != null) {
271 					// this indirection has as value a counter
272 					boolean oldValue = XmlTools.defaultOnMeTag;
273 					XmlTools.defaultOnMeTag = false;
274 					XmlModifier.getModifier("register-indirection").buildMdb(
275 							nodeModifier, out);
276 					XmlTools.defaultOnMeTag = oldValue;
277 				} else {
278 					XmlConfiguration
279 							.error("The specified modifier for this register is unknown; "
280 									+ nodeModifier);
281 					return 0;
282 				}
283 			}
284 		}
285 
286 		// attachment
287 		Node attachment = node.get("attachment");
288 		if (attachment == null) {
289 			out.write(0);
290 		} else {
291 			out.write(1);
292 			Node referenceModifiers = null;
293 			if (attachment.getAttribute("ref") != null) {
294 				referenceModifiers = attachment.get("modifiers");
295 				attachment = XmlTbs.getReferencedAttachment(attachment
296 						.getAttribute("ref"));
297 			}
298 			if (attachment == null)
299 				// reference error
300 				return 0;
301 
302 			Node attachmentModifiers = attachment.get("modifiers");
303 			if (referenceModifiers == null) {
304 				if (attachmentModifiers == null) {
305 					out.write(0);
306 				} else {
307 					out.write(attachmentModifiers.getNbNodes());
308 				}
309 			} else {
310 				if (attachmentModifiers == null)
311 					out.write(referenceModifiers.getNbNodes());
312 				else {
313 					out.write(attachmentModifiers.getNbNodes()
314 							+ referenceModifiers.getNbNodes());
315 				}
316 				// macro modifiers
317 				for (Object obj : referenceModifiers) {
318 					if (obj instanceof Node) {
319 						XmlModifier.getModifier(((Node) obj).getTag()).buildMdb((Node) obj,
320 								out);
321 					}
322 				}
323 			}
324 
325 			// explicitly declared modifiers
326 			if (attachmentModifiers != null) {
327 				for (Object obj : attachmentModifiers) {
328 					if (obj instanceof Node) {
329 						XmlModifier.getModifier(((Node) obj).getTag()).buildMdb((Node) obj,
330 								out);
331 					}
332 				}
333 			}
334 			XmlTest.getTest("test").buildMdb(attachment.get("valid-target"), out);
335 			XmlTest.getTest("test").buildMdb(attachment.get("valid-attachment"), out);
336 		}
337 		return 0;
338 	}
339 }