1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.magicproject.database;
20
21 import java.awt.Graphics;
22 import java.awt.Image;
23 import java.awt.image.ImageProducer;
24 import java.net.MalformedURLException;
25 import java.net.URL;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30
31 import net.sf.magicproject.clickable.targetable.card.AbstractCard;
32 import net.sf.magicproject.clickable.targetable.card.CardModel;
33 import net.sf.magicproject.clickable.targetable.card.MCard;
34 import net.sf.magicproject.database.data.TranslatableData;
35 import net.sf.magicproject.deckbuilder.MdbLoader;
36 import net.sf.magicproject.management.MonitorListener;
37 import net.sf.magicproject.management.MonitoredCheckContent;
38 import net.sf.magicproject.tools.MToolKit;
39 import net.sf.magicproject.tools.Picture;
40 import net.sf.magicproject.xml.XmlParser;
41 import net.sf.magicproject.xml.XmlParser.Node;
42 import sun.awt.image.FileImageSource;
43
44 /***
45 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
46 * @since 0.90
47 */
48 public class DatabaseCard {
49
50 private Map<String, TranslatableData> data = new HashMap<String, TranslatableData>(
51 5);
52
53 /***
54 * The proxy used to build this object.
55 */
56 private final Proxy dataProxy;
57
58 /***
59 * The proxy used to display picture of this object. If is null,
60 * <code>dataProxy</code> will be used.
61 */
62 private Proxy[] pictureProxies;
63
64 /***
65 * The currently associated image of this card. Is <code>null</code> while
66 * not loaded.
67 */
68 private MonitoredCheckContent image;
69
70 /***
71 * The currently associated scaled image of this card. Is <code>null</code>
72 * while not loaded.
73 */
74 private Image scaledImage;
75
76 /***
77 * The card model of this card.
78 */
79 private final CardModel cardModel;
80
81 /***
82 * The consistence of this database.
83 */
84 private boolean consistent;
85
86 /***
87 * Create new instance of DatabaseCard.
88 *
89 * @param cardModel
90 * the card model containing card name used as id
91 * @param dataProxy
92 * the proxy where this data came from. If is <code>null</code>,
93 * the picture would be get using the default art URL.
94 * @param pictureProxies
95 * the proxies used to get image. If is <code>null</code>,
96 * <code>dataProxy</code> would be used.
97 */
98 public DatabaseCard(CardModel cardModel, Proxy dataProxy,
99 Proxy... pictureProxies) {
100 this.cardModel = cardModel;
101 this.dataProxy = dataProxy;
102 setPictureProxies(pictureProxies);
103 }
104
105 /***
106 * Return the card model of this card.
107 *
108 * @return the card model of this card.
109 */
110 public CardModel getCardModel() {
111 return cardModel;
112 }
113
114 /***
115 * Return the proxy used to build this object.
116 *
117 * @return the proxy used to build this object.
118 */
119 public Proxy getDataProxy() {
120 return dataProxy;
121 }
122
123 /***
124 * Return the proxy used to display picture of this object. If is null,
125 * <code>dataProxy</code> will be used.
126 *
127 * @return the proxy used to display picture of this object. If is null,
128 * <code>dataProxy</code> will be used.
129 */
130 public Proxy getPictureProxy() {
131 return pictureProxies[0];
132 }
133
134 /***
135 * Return the proxies used to display picture of this object. If is null,
136 * <code>dataProxy</code> will be used.
137 *
138 * @return the proxies used to display picture of this object. If is null,
139 * <code>dataProxy</code> will be used.
140 */
141 public Proxy[] getPictureProxies() {
142 return pictureProxies;
143 }
144
145 /***
146 * The card name. Is considered as id. Return the english name, not the
147 * localized one.
148 *
149 * @return the card name. Is considered as id.
150 * @see net.sf.magicproject.clickable.targetable.card.CardModel#getCardName()
151 */
152 public String getCardName() {
153 return cardModel.getCardName();
154 }
155
156 /***
157 * Return the localized card's name.
158 *
159 * @return the localized card's name.
160 * @see net.sf.magicproject.clickable.targetable.card.CardModel#getLocalName()
161 */
162 public String getLocalName() {
163 return cardModel.getLocalName();
164 }
165
166 /***
167 * Return XML rule designer of the card.
168 *
169 * @return XML rule designer of the card.
170 * @see net.sf.magicproject.clickable.targetable.card.CardModel#getRulesCredit()
171 */
172 public String getRulesCredit() {
173 return cardModel.getRulesCredit();
174 }
175
176 /***
177 * Add a translatable data to this database.
178 *
179 * @param data
180 * translatable data to add.
181 */
182 public void add(TranslatableData data) {
183 if ("local-name".equalsIgnoreCase(data.getValue())) {
184 cardModel.setLocalName(data.getValue());
185 }
186 this.data.put(data.getPropertyName(), data);
187 }
188
189 /***
190 * Return the card's picture as it would be displayed in the board.
191 *
192 * @param card
193 * the card requesting it's picture.
194 * @return the card's picture as it would be displayed in the board.
195 */
196 public Image getImage(AbstractCard card) {
197 if (card.visibility == null || !card.visibility.isVisibleForYou()) {
198 return DatabaseFactory.backImage;
199 }
200 return getImage((MonitorListener) card);
201 }
202
203 /***
204 * Return the scaled card's picture as it would be displayed in the board.
205 *
206 * @param card
207 * the card requesting it's picture.
208 * @return the scaled card's picture as it would be displayed in the board.
209 */
210 public Image getScaledImage(AbstractCard card) {
211 if (card.visibility == null || !card.visibility.isVisibleForYou()) {
212 return DatabaseFactory.scaledBackImage;
213 }
214 return getScaledImage((MonitorListener) card);
215 }
216
217 /***
218 * Return the card's picture as it would be displayed in the board.
219 *
220 * @param listener
221 * the listener to notify when the picture will be completely loaded.
222 * @return the card's picture as it would be displayed in the board.
223 */
224 public Image getImage(MonitorListener listener) {
225 if (image == null) {
226 loadDatabasePicture(null, listener);
227 } else if (!image.isFinished()) {
228 image.addListener(listener);
229 }
230 return image.getContent();
231 }
232
233 /***
234 * Return the scaled card's picture as it would be displayed in the board.
235 *
236 * @param listener
237 * the listener to notify when the picture will be completely loaded.
238 * @return the scaled card's picture as it would be displayed in the board.
239 */
240 public Image getScaledImage(MonitorListener listener) {
241 if (scaledImage == null) {
242 if (image == null) {
243 getImage(listener);
244 }
245 if (!image.isFinished()) {
246 return image.getContent();
247 }
248 scaledImage = Picture.getScaledImage(image.getContent());
249 }
250 return scaledImage;
251 }
252
253 /***
254 * Return the stream description used to build the picture by this database
255 * object.
256 *
257 * @return the stream description used to buid the picture by this database
258 * object.
259 */
260 public String getPictureStream() {
261 if (image != null && DatabaseFactory.sourceFile != null
262 && image.getContent() != null) {
263 final ImageProducer imageProducer = image.getContent().getSource();
264 if (imageProducer instanceof FileImageSource) {
265 try {
266 return DatabaseFactory.sourceFile.get(imageProducer).toString();
267 } catch (Exception e) {
268 return "unvailable stream";
269 }
270 }
271 }
272
273 return "unvailable stream";
274 }
275
276 /***
277 * Load the image considering proxy, properties and the given picture name. If
278 * no proxy is set for this database, the picture is loaded from the
279 * 'tbs/${tbs.name}/images' directory. The picture fielname is either the
280 * specified <param>pictureName</param> if not null, either the built from
281 * the card name. The looked for picture type is '.jpg'.<br>
282 * If a proxy is set, then the proxy will build the URL where the picture can
283 * been found first locally, then remotly from the proxy web-site.
284 *
285 * @param pictureName
286 * the alternative picture name.
287 * @param listener
288 * the card requesting this picture.
289 */
290 private synchronized void loadDatabasePicture(String pictureName,
291 MonitorListener listener) {
292 if (image != null) {
293
294 if (!image.isFinished())
295 image.addListener(listener);
296 return;
297 }
298 try {
299 if (pictureProxies == null) {
300
301
302
303
304 if (pictureName != null) {
305
306 image = Picture.loadImage(MToolKit
307 .getTbsPicture(pictureName + ".jpg"), null);
308 } else {
309
310 image = Picture.loadImage(MToolKit.getTbsPicture(cardModel
311 .getKeyName()
312 + ".jpg", false), new URL(MdbLoader.artURL + "/"
313 + cardModel.getKeyName() + ".jpg"));
314 }
315 } else {
316
317
318
319
320
321
322
323 List<String> localPaths = new ArrayList<String>();
324 for (Proxy pictureProxy : pictureProxies) {
325 for (String path : pictureProxy.getLocalPictures(cardModel, data)) {
326 if (path != null) {
327 image = Picture.loadImage(path, null);
328 if (image != null) {
329 return;
330 }
331 }
332 localPaths.add(path);
333 }
334 }
335
336 List<String> remotePaths = new ArrayList<String>();
337 for (Proxy pictureProxy : pictureProxies) {
338 remotePaths.addAll(pictureProxy.getRemotePictures(cardModel, data));
339 }
340
341
342 if (pictureName != null) {
343
344 image = Picture.loadImage(MToolKit
345 .getTbsPicture(pictureName + ".jpg"), null);
346 } else {
347
348 localPaths.add(MToolKit.getTbsPicture(
349 cardModel.getKeyName() + ".jpg", false));
350 remotePaths.add(MdbLoader.artURL + "/" + cardModel.getKeyName()
351 + ".jpg");
352 }
353
354 if (image == null) {
355 image = new MonitoredCheckContent(localPaths, remotePaths, listener);
356 image.start();
357 }
358 }
359 } catch (MalformedURLException e) {
360 try {
361 image = Picture.loadImage(MToolKit.getTbsPicture(cardModel.getKeyName()
362 + ".jpg"), null);
363 } catch (MalformedURLException ex) {
364
365 }
366 }
367
368 if (image == null) {
369
370 image = new MonitoredCheckContent(DatabaseFactory.backImage);
371 }
372
373 }
374
375 /***
376 * Create a node representing this data inside the given node.
377 *
378 * @param inNode
379 * the node where data would be added to.
380 */
381 void updateCache(Node inNode) {
382
383
384 XmlParser.Attribute[] attributes = new XmlParser.Attribute[2];
385 attributes[0] = new XmlParser.Attribute("local-name", getLocalName());
386 attributes[1] = new XmlParser.Attribute("proxy", dataProxy.getName());
387
388
389 Node node = new XmlParser.Node(inNode, cardModel.getKeyName(), null);
390 node.aAttrs = attributes;
391
392
393 for (String datString : data.keySet()) {
394 XmlParser.Attribute[] values = new XmlParser.Attribute[2];
395 TranslatableData dataIt = data.get(datString);
396 values[0] = new XmlParser.Attribute("name", dataIt.getPropertyName());
397 values[1] = new XmlParser.Attribute("value", dataIt.getValue());
398 Node property = new XmlParser.Node(node, "property", null);
399 property.aAttrs = values;
400 node.add(0, property);
401 }
402 inNode.aList.add(0, node);
403 }
404
405 /***
406 * Create a new instance of DatabaseCard with a picture different form the
407 * standard one (relative to card name). No proxy would be used for this new
408 * instance.<br>
409 * The given picture is immediatly loaded.
410 *
411 * @param pictureName
412 * the picture to use with this DatabaseCard
413 * @return a clone of this instance, without proxy and with the specified
414 * picture loaded immediatly.
415 */
416 public DatabaseCard clone(String pictureName) {
417 final DatabaseCard clone = new DatabaseCard(cardModel, null);
418 clone.loadDatabasePicture(pictureName, null);
419 return clone;
420 }
421
422 @Override
423 public DatabaseCard clone() {
424 return clone(cardModel);
425 }
426
427 /***
428 * Return a clone of this object from the given card model.
429 *
430 * @param cardModel
431 * @return a clone of this object from the given card model.
432 */
433 public DatabaseCard clone(CardModel cardModel) {
434 final DatabaseCard clone = new DatabaseCard(cardModel, dataProxy,
435 pictureProxies);
436 return clone;
437 }
438
439 /***
440 * Return the translated data associated to the named property.
441 *
442 * @param property
443 * the property name.
444 * @return the translated data associated to the named property.
445 */
446 public String getProperty(String property) {
447 final TranslatableData data = this.data.get(property);
448 if (data != null) {
449 return data.getTranslatedValue(dataProxy);
450 }
451 return "-";
452 }
453
454 /***
455 * Set the proxy used to display picture of this object. If is null,
456 * <code>dataProxy</code> will be used.
457 *
458 * @param pictureProxies
459 * the new proxies used for picture. Order corresponds to
460 * prefereence.
461 */
462 public void setPictureProxies(Proxy... pictureProxies) {
463 if (this.pictureProxies != pictureProxies) {
464 if (pictureProxies == null) {
465 this.pictureProxies = new Proxy[] { dataProxy };
466 } else {
467 this.pictureProxies = pictureProxies;
468 }
469 image = null;
470 }
471 }
472
473 @Override
474 public String toString() {
475 return cardModel.toString();
476 }
477
478 /***
479 * Set the consistence of this database.
480 *
481 * @param consistent
482 * the new consistence of this database.
483 */
484 public void setConsistent(boolean consistent) {
485 this.consistent = consistent;
486 }
487
488 /***
489 * Return the new score of this database.
490 *
491 * @return true if this database is consistent.
492 */
493 public boolean isConsistent() {
494 return consistent;
495 }
496
497 /***
498 * This method update and paint on the given card, the progressbar of task of
499 * the image attached to this model.
500 *
501 * @param card
502 * the listener to manage.
503 * @param g
504 * the graphics used to paint the progressbar.
505 */
506 public void updatePaintNotification(MCard card, Graphics g) {
507 if (image == null || !image.isFinished()) {
508
509 if (image != null
510 && (card.visibility != null && card.visibility.isVisibleForYou())) {
511 image.paintNotification(g);
512 }
513 } else if (image.isFinished()) {
514 image.acknowledgeFinished(card);
515 }
516 }
517
518 /***
519 * This method update and paint on the given listener, the progressbar of task
520 * of the image attached to this model.
521 *
522 * @param listener
523 * the listener to manage.
524 * @param g
525 * the graphics used to paint the progressbar.
526 */
527 public void updatePaintNotification(MonitorListener listener, Graphics g) {
528 if (image == null || !image.isFinished()) {
529
530 if (image != null) {
531 image.paintNotification(g);
532 }
533 } else if (image.isFinished()) {
534 image.acknowledgeFinished(listener);
535 }
536 }
537
538 /***
539 * Reset the bufferised data.
540 */
541 public void updateMUI() {
542 scaledImage = null;
543 }
544
545 }