View Javadoc

1   // START LICENSE
2   // JSet - a Java JSet card board game implementation
3   // Copyright (C) 2004 Jerome Lacoste
4   //
5   // This program is free software; you can redistribute it and/or modify
6   // it under the terms of the GNU General Public License as published by
7   // the Free Software Foundation; either version 2 of the License, or (at
8   // your option) any later version.
9   //
10  // This program is distributed in the hope that it will be useful, but
11  // WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // General Public License for more details.
14  //
15  // You should have received a copy of the GNU General Public License
16  // along with this program; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  // END LICENSE
19  
20  package org.cb.jset.client.model;
21  
22  import org.apache.log4j.Logger;
23  import org.cb.jset.JSetCard;
24  import org.cb.jset.CardProperties;
25  import org.cb.jset.CardSet;
26  import org.cb.jset.BoardException;
27  import org.cb.cardboard.AbstractCardBoardModel;
28  import org.cb.cardboard.Card;
29  import org.cb.cardboard.CardBoardEvent;
30  
31  import java.util.Collections;
32  import java.util.List;
33  import java.util.ArrayList;
34  import java.io.Serializable;
35  
36  
37  /***
38   * A client BoardImpl is a special board that also keeps track of card layout, especially the empty spaces.
39   *
40   *
41   * Note: implementation not yet multithread safe (FIXME)
42   * @author jerome@coffeebreaks.org - last modified by $LastChangedBy: jerome $
43   * @version $Id: JSetClientBoardModel.java 129 2004-04-15 05:00:43Z jerome $
44   */
45  public class JSetClientBoardModel extends AbstractCardBoardModel implements SetGameClientBoard, Serializable
46  {
47    private transient final Logger _logger = Logger.getLogger(JSetClientBoardModel.class);
48  
49    /*** A List of JSetCard elements representing the cards on the board. */
50    private final List _cards = new ArrayList();
51  
52    /***
53     * Clear the board.
54     */
55    public void clear()
56    {
57      int size = _cards.size();
58      _cards.clear();
59  //    _selectedCards.clear();
60      fireIntervalRemoved(0, size - 1);
61    }
62  
63    /***
64     * @return the number of spaces used by cards on the board. Unused spaces are taken into account.
65     * @see #getNbCards() for the exact number of cards on the board.
66     */
67    public int getSize()
68    {
69      return _cards.size();
70    }
71  
72    /***
73     * Return the Card element specified by the index on the board.
74     * @param index
75     * @return the Card element or <code>null</code> if the space on the board is empty at that position.
76     */
77    public Card getElementAt(final int index)
78    {
79      return (Card) _cards.get(index);
80    }
81  
82    /***
83     * @return The cards in the board. May contain some <code>null</code> to represent the empty spaces.
84     */
85    public List getElements()
86    {
87      return Collections.unmodifiableList(_cards);
88    }
89  
90    /***
91     * @return the number of cards on the board.
92     * @see #getSize() which takes into account the number of cards plus the empty spaces.
93     */
94    public int getNbCards()
95    {
96      int lNbCards = 0;
97      for (int i = 0; i < _cards.size(); i++)
98      {
99        final Card card = (Card) _cards.get(i);
100       if (card != null)
101       {
102         lNbCards++;
103       }
104     }
105     return lNbCards;
106   }
107 
108   /***
109    * Add the specified cards onto the board.
110    * @param cards the cards to add.
111    * @throws NullPointerException if <code>cards</code> is <code>null</code> or if an element in the array is <code>null</code>.
112    */
113   public void addCards(final CardProperties[] cards)
114   {
115     logCards("before adding: " + CardProperties.toString(cards));
116 
117     int indexOfCardsToAdd = 0;
118     int indexInCardsList = 0; // FIXME we could cache this one.
119 
120 
121     final List indexesOfCardsChanged = new ArrayList();
122     cardsToAdd:
123     // card.addCardListener(_eventHandler);
124     for (; indexInCardsList < _cards.size() && indexOfCardsToAdd < cards.length; indexInCardsList++)
125     {
126       final JSetCard oldCard = (JSetCard) _cards.get(indexInCardsList);
127       if (oldCard == null)
128       {
129         final CardProperties cardProperties = cards[indexOfCardsToAdd++];
130         final Card newCard = new org.cb.jset.JSetCard(cardProperties);
131         _cards.set(indexInCardsList, newCard);
132         indexesOfCardsChanged.add(new Integer(indexInCardsList));
133         continue cardsToAdd;
134       }
135     }
136     if (indexesOfCardsChanged.size() > 0)
137     {
138       fireContentsChanged(indexesOfCardsChanged);
139     }
140     if (indexOfCardsToAdd < cards.length)
141     {
142       final int firstListIndex = indexInCardsList;
143       int lastListIndex = 0;
144       for (; indexOfCardsToAdd < cards.length; indexOfCardsToAdd++)
145       {
146         final CardProperties cardProperties = cards[indexOfCardsToAdd];
147         final Card card = new org.cb.jset.JSetCard(cardProperties);
148         _cards.add(indexInCardsList++, card);
149         lastListIndex = indexInCardsList;
150       }
151       fireIntervalAdded(firstListIndex, (lastListIndex - 1));
152     }
153     logCards("after adding: " + CardProperties.toString(cards));
154   }
155 
156   /***
157    * Remove the specified matching set from the board.
158    * @param set the set to remove
159    * @throws BoardException when something fails
160    */
161   public void removeSet(final CardSet set) throws BoardException
162   {
163     logCards("before matching: "  + CardProperties.toString(set.getCards()));
164     final CardProperties[] cards = set.getCards();
165 
166     final int[] indexesOnBoard = new int[cards.length];
167     for (int i = 0; i < indexesOnBoard.length; i++)
168     {
169       final int index = _cards.indexOf(new org.cb.jset.JSetCard(CardProperties.findCard(cards[i])));
170       if (index == -1)
171       {
172         _logger.debug("JSetCard " + cards[i] + " not found. Listing contents of board...");
173         logCards("");
174         throw new BoardException("JSetCard " + cards[i] + " not found.");
175       }
176       indexesOnBoard[i] = index;
177     }
178 
179     for (int i = 0; i < indexesOnBoard.length; i++)
180     {
181       final int lIndex = indexesOnBoard[i];
182       _cards.set(lIndex, null);
183       fireIntervalRemoved(lIndex, lIndex);
184     }
185     logCards("after matching: "  + CardProperties.toString(set.getCards()));
186   }
187 
188   private void logCards(final String message)
189   {
190     _logger.debug("Logging cards: " + message);
191     for (int j = 0; j < _cards.size(); j++)
192     {
193       final org.cb.jset.JSetCard card = (org.cb.jset.JSetCard) _cards.get(j);
194       _logger.debug("[" + j + "]:" + card);
195     }
196   }
197 
198   private void fireContentsChanged(final List indexes)
199   {
200     final CardBoardEvent event = new CardBoardEvent(this, indexes);
201     fireContentsChanged(event);
202   }
203 
204   private void fireIntervalAdded(final int firstIndex, final int lastIndex)
205   {
206     final CardBoardEvent event = new CardBoardEvent(this, CardBoardEvent.INTERVAL_ADDED, firstIndex, lastIndex);
207     fireIntervalAdded(event);
208   }
209 
210   private void fireIntervalRemoved(final int firstIndex, final int lastIndex)
211   {
212     final CardBoardEvent event = new CardBoardEvent(this, CardBoardEvent.INTERVAL_REMOVED, firstIndex, lastIndex);
213     fireIntervalRemoved(event);
214   }
215 
216 //  class EventHandler implements SetGameClientCardListener
217 //  {
218 //    public void notifyCardEvent(CardEvent card)
219 //    {
220 //      if (card.getType() == CardEvent.SELECTED)
221 //      {
222 //        _selectedCards.add(card.getSource());
223 //      }
224 //      else
225 //      {
226 //        _selectedCards.remove(card.getSource());
227 //      }
228 //    }
229 //  }
230 }