Spliting Game into GameId and Game with full info about the state of the game
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 30 Aug 2009 14:37:47 +0200
changeset 4869e897fe8140
parent 47 2b6c104e6a59
child 49 75074e02f345
Spliting Game into GameId and Game with full info about the state of the game
.hgignore
freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/FreemarkerProcessor.java
freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java
freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt
freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt
quoridor/src/main/java/cz/xelfi/quoridor/Board.java
quoridor/src/test/java/cz/xelfi/quoridor/SerializeTest.java
webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java
webidor/src/main/java/cz/xelfi/quoridor/webidor/GameId.java
webidor/src/main/java/cz/xelfi/quoridor/webidor/GameResult.java
webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Games.java
webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java
webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java
     1.1 --- a/.hgignore	Sat Aug 29 16:15:20 2009 +0200
     1.2 +++ b/.hgignore	Sun Aug 30 14:37:47 2009 +0200
     1.3 @@ -1,1 +1,4 @@
     1.4  .*/target/.*
     1.5 +.*orig$
     1.6 +.*~$
     1.7 +
     2.1 --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/FreemarkerProcessor.java	Sat Aug 29 16:15:20 2009 +0200
     2.2 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/FreemarkerProcessor.java	Sun Aug 30 14:37:47 2009 +0200
     2.3 @@ -34,8 +34,6 @@
     2.4  import java.io.OutputStreamWriter;
     2.5  import java.io.Writer;
     2.6  import java.util.Map;
     2.7 -import java.util.logging.Level;
     2.8 -import java.util.logging.Logger;
     2.9  import javax.script.Bindings;
    2.10  import javax.script.ScriptContext;
    2.11  import javax.script.ScriptEngine;
    2.12 @@ -88,6 +86,7 @@
    2.13          try {
    2.14              eng.eval(r);
    2.15          } catch (ScriptException ex) {
    2.16 +            System.err.println("dump data: " + model);
    2.17              ex.printStackTrace();
    2.18              throw new IOException(ex);
    2.19          }
     3.1 --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java	Sat Aug 29 16:15:20 2009 +0200
     3.2 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java	Sun Aug 30 14:37:47 2009 +0200
     3.3 @@ -60,6 +60,7 @@
     3.4  import org.codehaus.jettison.json.JSONArray;
     3.5  import org.codehaus.jettison.json.JSONException;
     3.6  import org.codehaus.jettison.json.JSONObject;
     3.7 +import org.w3c.dom.Document;
     3.8  
     3.9  /**
    3.10   *
    3.11 @@ -173,10 +174,6 @@
    3.12      }
    3.13  
    3.14  
    3.15 -    private static Object getJson(WebResource res) throws JSONException {
    3.16 -        return convert(res.accept(MediaType.APPLICATION_JSON_TYPE).get(JSONArray.class));
    3.17 -    }
    3.18 -
    3.19      private static Object convert(Object obj) throws JSONException {
    3.20          if (obj instanceof JSONArray) {
    3.21              JSONArray arr = (JSONArray)obj;
    3.22 @@ -226,7 +223,8 @@
    3.23      }
    3.24  
    3.25      private Viewable welcomeImpl() throws JSONException {
    3.26 -        Object obj = getJson(base.path("games"));
    3.27 +        final Object got = base.path("games").accept(MediaType.TEXT_XML_TYPE).get(Document.class);
    3.28 +        Map<?,?> obj = (Map<?, ?>)convert(got);
    3.29          return new Viewable("index.fmt", obj);
    3.30      }
    3.31  
     4.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt	Sat Aug 29 16:15:20 2009 +0200
     4.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt	Sun Aug 30 14:37:47 2009 +0200
     4.3 @@ -6,6 +6,7 @@
     4.4    </head>
     4.5    <body>
     4.6        <h1>Game</h1>
     4.7 +      <h3>${id.white} vs. ${id.black}</h3>
     4.8        <form action="move">
     4.9            <input type="hidden" name="type" value="fence" readonly="readonly"/>
    4.10            <select name="column">
    4.11 @@ -51,6 +52,6 @@
    4.12            </select>
    4.13            <input type="submit" value="Move!" />
    4.14        </form>
    4.15 -      <pre>${model}</pre>
    4.16 +      <pre>${board}</pre>
    4.17    </body>
    4.18  </html>
    4.19 \ No newline at end of file
     5.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt	Sat Aug 29 16:15:20 2009 +0200
     5.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt	Sun Aug 30 14:37:47 2009 +0200
     5.3 @@ -8,7 +8,7 @@
     5.4        <h1>Quoridor Community Server</h1>
     5.5  
     5.6        <ol>
     5.7 -      <#list model as item>
     5.8 +      <#list gameId as item>
     5.9          <li>${item.white} vs. ${item.black} <a href="games/${item.id}/">board</a></li>
    5.10        </#list>
    5.11        </ol>
     6.1 --- a/quoridor/src/main/java/cz/xelfi/quoridor/Board.java	Sat Aug 29 16:15:20 2009 +0200
     6.2 +++ b/quoridor/src/main/java/cz/xelfi/quoridor/Board.java	Sun Aug 30 14:37:47 2009 +0200
     6.3 @@ -31,6 +31,7 @@
     6.4  import java.io.EOFException;
     6.5  import java.io.IOException;
     6.6  import java.io.Reader;
     6.7 +import java.io.StringReader;
     6.8  import java.io.StringWriter;
     6.9  import java.io.Writer;
    6.10  import java.util.ArrayList;
    6.11 @@ -293,6 +294,15 @@
    6.12      //
    6.13  
    6.14      private static final Pattern northSouthPattern = Pattern.compile("(\\+(\\|*)(\\*)?-+\\+)");
    6.15 +
    6.16 +    /** Reads the board from a reader. Opposite operation to {@link #write(java.io.Writer)}.
    6.17 +     *
    6.18 +     * @param r the reader
    6.19 +     * @return the read board
    6.20 +     * @throws IOException if I/O error occurs
    6.21 +     * @throws IllegalPositionException if the reader does not contain description
    6.22 +     *   of the board
    6.23 +     */
    6.24      public static Board read(Reader r) throws IOException, IllegalPositionException {
    6.25          BufferedReader b = new BufferedReader(r);
    6.26          for (;;) {
    6.27 @@ -307,6 +317,24 @@
    6.28          }
    6.29      }
    6.30  
    6.31 +    /** Translates the string into board, if possible. String created by
    6.32 +     * use of {@link #toString()} is accepted, more information about the
    6.33 +     * format is avaliable in the description of {@link #write(java.io.Writer)}
    6.34 +     * method.
    6.35 +     *
    6.36 +     * @param board string to analyze
    6.37 +     * @return board object, if the string can be read
    6.38 +     * @throws IllegalPositionException if the string does not represent the board
    6.39 +     */
    6.40 +    public static Board valueOf(String board) throws IllegalPositionException {
    6.41 +        try {
    6.42 +            return read(new StringReader(board));
    6.43 +        } catch (IOException ex) {
    6.44 +            // shall not happen, StringReader does not throw IOException
    6.45 +            throw (IllegalPositionException)new IllegalPositionException(ex.getMessage()).initCause(ex);
    6.46 +        }
    6.47 +    }
    6.48 +
    6.49      private static int assertChar(String s, int pos, char... ch) throws IOException {
    6.50          if (s.length() >= pos) {
    6.51              for (int i = 0; i < ch.length; i++) {
    6.52 @@ -635,6 +663,12 @@
    6.53          return false;
    6.54      }
    6.55  
    6.56 +    /** Converts the board into string representation. For more information
    6.57 +     * about the format see {@link #write(java.io.Writer)}. To read the
    6.58 +     * string back use {@link #valueOf(java.lang.String)}.
    6.59 +     *
    6.60 +     * @return string representing the board
    6.61 +     */
    6.62      @Override
    6.63      public String toString() {
    6.64          StringWriter w = new StringWriter();
     7.1 --- a/quoridor/src/test/java/cz/xelfi/quoridor/SerializeTest.java	Sat Aug 29 16:15:20 2009 +0200
     7.2 +++ b/quoridor/src/test/java/cz/xelfi/quoridor/SerializeTest.java	Sun Aug 30 14:37:47 2009 +0200
     7.3 @@ -72,7 +72,7 @@
     7.4          StringWriter w = new StringWriter();
     7.5          b.write(w);
     7.6          w.close();
     7.7 -        return Board.read(new StringReader(w.toString()));
     7.8 +        return Board.valueOf(w.toString());
     7.9      }
    7.10  
    7.11  }
     8.1 --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java	Sat Aug 29 16:15:20 2009 +0200
     8.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java	Sun Aug 30 14:37:47 2009 +0200
     8.3 @@ -32,12 +32,13 @@
     8.4  import cz.xelfi.quoridor.Player;
     8.5  import java.util.ArrayList;
     8.6  import java.util.List;
     8.7 -import java.util.UUID;
     8.8  import javax.xml.bind.annotation.XmlAccessType;
     8.9  import javax.xml.bind.annotation.XmlAccessorType;
    8.10  import javax.xml.bind.annotation.XmlAttribute;
    8.11 -import javax.xml.bind.annotation.XmlID;
    8.12 +import javax.xml.bind.annotation.XmlElement;
    8.13  import javax.xml.bind.annotation.XmlRootElement;
    8.14 +import javax.xml.bind.annotation.adapters.XmlAdapter;
    8.15 +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    8.16  
    8.17  /**
    8.18   *
    8.19 @@ -45,45 +46,31 @@
    8.20   */
    8.21  @XmlRootElement
    8.22  @XmlAccessorType(XmlAccessType.FIELD)
    8.23 -public final class Game {
    8.24 +public final class Game extends Object {
    8.25 +    @XmlElement
    8.26 +    private GameId id;
    8.27      @XmlAttribute
    8.28 -    private String white;
    8.29 -    @XmlAttribute
    8.30 -    private String black;
    8.31 -    @XmlID
    8.32 -    private String id;
    8.33 -
    8.34 -    private transient Board board;
    8.35 -    private transient List<Move> moves;
    8.36 +    @XmlJavaTypeAdapter(BoardAdapter.class)
    8.37 +    private Board board;
    8.38 +    @XmlElement
    8.39 +    @XmlJavaTypeAdapter(MoveAdapter.class)
    8.40 +    private List<Move> moves;
    8.41  
    8.42      Game() {
    8.43      }
    8.44  
    8.45      public Game(String first, String second) {
    8.46 -        this(
    8.47 -            UUID.randomUUID().toString(),
    8.48 -            first, second
    8.49 -        );
    8.50 +        this.id = new GameId(first, second);
    8.51      }
    8.52  
    8.53 -    public Game(String id, String first, String second) {
    8.54 -        this.white = first;
    8.55 -        this.black = second;
    8.56 +    public Game(GameId id) {
    8.57          this.id = id;
    8.58      }
    8.59  
    8.60 -    public String getId() {
    8.61 +    public GameId getId() {
    8.62          return id;
    8.63      }
    8.64 -
    8.65 -    public String getWhite() {
    8.66 -        return white;
    8.67 -    }
    8.68 -
    8.69 -    public String getBlack() {
    8.70 -        return black;
    8.71 -    }
    8.72 -
    8.73 +    
    8.74      public Board getBoard() {
    8.75          if (board == null) {
    8.76              board = Board.empty();
    8.77 @@ -93,10 +80,10 @@
    8.78  
    8.79      public void apply(String player, Move m) throws IllegalPositionException {
    8.80          Player p = null;
    8.81 -        if (getWhite().equals(player)) {
    8.82 +        if (id.getWhite().equals(player)) {
    8.83              p = getBoard().getPlayers().get(0);
    8.84          } else {
    8.85 -            if (getBlack().equals(player)) {
    8.86 +            if (id.getBlack().equals(player)) {
    8.87                  p = getBoard().getPlayers().get(1);
    8.88              }
    8.89          }
    8.90 @@ -114,4 +101,38 @@
    8.91          }
    8.92          return moves;
    8.93      }
    8.94 +
    8.95 +    private static final class MoveAdapter extends XmlAdapter<String[],List<Move>> {
    8.96 +        @Override
    8.97 +        public List<Move> unmarshal(String[] arr) throws Exception {
    8.98 +            List<Move> res = new ArrayList<Move>();
    8.99 +            for (String v : arr) {
   8.100 +                res.add(Move.valueOf(v));
   8.101 +            }
   8.102 +            return res;
   8.103 +        }
   8.104 +
   8.105 +        @Override
   8.106 +        public String[] marshal(List<Move> arr) throws Exception {
   8.107 +            List<String> res = new ArrayList<String>();
   8.108 +            for (Move m : arr) {
   8.109 +                res.add(m.toString()); 
   8.110 +            }
   8.111 +            return res.toArray(new String[0]);
   8.112 +        }
   8.113 +    } // end of MoveAdapter
   8.114 +
   8.115 +    private static final class BoardAdapter extends XmlAdapter<String,Board> {
   8.116 +
   8.117 +        @Override
   8.118 +        public Board unmarshal(String v) throws Exception {
   8.119 +            return Board.valueOf(v);
   8.120 +        }
   8.121 +
   8.122 +        @Override
   8.123 +        public String marshal(Board v) throws Exception {
   8.124 +            return v.toString();
   8.125 +        }
   8.126 +
   8.127 +    }
   8.128  }
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/GameId.java	Sun Aug 30 14:37:47 2009 +0200
     9.3 @@ -0,0 +1,92 @@
     9.4 +/*
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * The contents of this file are subject to the terms of either the GNU
     9.8 + * General Public License Version 2 only ("GPL") or the Common
     9.9 + * Development and Distribution License("CDDL") (collectively, the
    9.10 + * "License"). You may not use this file except in compliance with the
    9.11 + * License. You can obtain a copy of the License at
    9.12 + * http://www.netbeans.org/cddl-gplv2.html
    9.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.14 + * specific language governing permissions and limitations under the
    9.15 + * License.  When distributing the software, include this License Header
    9.16 + * Notice in each file and include the License file at
    9.17 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    9.18 + * particular file as subject to the "Classpath" exception as provided
    9.19 + * by Sun in the GPL Version 2 section of the License file that
    9.20 + * accompanied this code. If applicable, add the following below the
    9.21 + * License Header, with the fields enclosed by brackets [] replaced by
    9.22 + * your own identifying information:
    9.23 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.24 + *
    9.25 + * Contributor(s):
    9.26 + *
    9.27 + * Portions Copyrighted 2009 Jaroslav Tulach
    9.28 + */
    9.29 +
    9.30 +package cz.xelfi.quoridor.webidor;
    9.31 +
    9.32 +import java.util.Date;
    9.33 +import java.util.UUID;
    9.34 +import javax.xml.bind.annotation.XmlAccessType;
    9.35 +import javax.xml.bind.annotation.XmlAccessorType;
    9.36 +import javax.xml.bind.annotation.XmlAttribute;
    9.37 +import javax.xml.bind.annotation.XmlID;
    9.38 +import javax.xml.bind.annotation.XmlRootElement;
    9.39 +
    9.40 +/** Basic identification of a game.
    9.41 + *
    9.42 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    9.43 + */
    9.44 +@XmlRootElement
    9.45 +@XmlAccessorType(XmlAccessType.FIELD)
    9.46 +public class GameId {
    9.47 +    @XmlAttribute
    9.48 +    private String white;
    9.49 +    @XmlAttribute
    9.50 +    private String black;
    9.51 +    @XmlAttribute
    9.52 +    private Date started;
    9.53 +    @XmlAttribute
    9.54 +    private GameResult result;
    9.55 +    @XmlID
    9.56 +    private String id;
    9.57 +
    9.58 +    GameId() {
    9.59 +    }
    9.60 +
    9.61 +    public GameId(String first, String second) {
    9.62 +        this(
    9.63 +            UUID.randomUUID().toString(),
    9.64 +            first, second, new Date(), GameResult.IN_PROGRESS
    9.65 +        );
    9.66 +    }
    9.67 +
    9.68 +    public GameId(String id, String first, String second, Date started, GameResult result) {
    9.69 +        this.white = first;
    9.70 +        this.black = second;
    9.71 +        this.id = id;
    9.72 +        this.started = started;
    9.73 +        this.result = result;
    9.74 +    }
    9.75 +
    9.76 +    public String getId() {
    9.77 +        return id;
    9.78 +    }
    9.79 +
    9.80 +    public String getWhite() {
    9.81 +        return white;
    9.82 +    }
    9.83 +
    9.84 +    public String getBlack() {
    9.85 +        return black;
    9.86 +    }
    9.87 +
    9.88 +    public Date getStarted() {
    9.89 +        return started;
    9.90 +    }
    9.91 +
    9.92 +    public GameResult getResult() {
    9.93 +        return result;
    9.94 +    }
    9.95 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/GameResult.java	Sun Aug 30 14:37:47 2009 +0200
    10.3 @@ -0,0 +1,35 @@
    10.4 +/*
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * The contents of this file are subject to the terms of either the GNU
    10.8 + * General Public License Version 2 only ("GPL") or the Common
    10.9 + * Development and Distribution License("CDDL") (collectively, the
   10.10 + * "License"). You may not use this file except in compliance with the
   10.11 + * License. You can obtain a copy of the License at
   10.12 + * http://www.netbeans.org/cddl-gplv2.html
   10.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   10.14 + * specific language governing permissions and limitations under the
   10.15 + * License.  When distributing the software, include this License Header
   10.16 + * Notice in each file and include the License file at
   10.17 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   10.18 + * particular file as subject to the "Classpath" exception as provided
   10.19 + * by Sun in the GPL Version 2 section of the License file that
   10.20 + * accompanied this code. If applicable, add the following below the
   10.21 + * License Header, with the fields enclosed by brackets [] replaced by
   10.22 + * your own identifying information:
   10.23 + * "Portions Copyrighted [year] [name of copyright owner]"
   10.24 + *
   10.25 + * Contributor(s):
   10.26 + *
   10.27 + * Portions Copyrighted 2009 Jaroslav Tulach
   10.28 + */
   10.29 +
   10.30 +package cz.xelfi.quoridor.webidor;
   10.31 +
   10.32 +/** Possible results of the game.
   10.33 + *
   10.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.35 + */
   10.36 +public enum GameResult {
   10.37 +    IN_PROGRESS, WHITE_WON, BLACK_WON;
   10.38 +}
    11.1 --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Games.java	Sat Aug 29 16:15:20 2009 +0200
    11.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Games.java	Sun Aug 30 14:37:47 2009 +0200
    11.3 @@ -37,11 +37,8 @@
    11.4  import java.io.IOException;
    11.5  import java.io.PrintWriter;
    11.6  import java.util.ArrayList;
    11.7 -import java.util.Arrays;
    11.8 -import java.util.HashMap;
    11.9 +import java.util.Date;
   11.10  import java.util.List;
   11.11 -import java.util.Map;
   11.12 -import java.util.TreeMap;
   11.13  import java.util.logging.Level;
   11.14  import java.util.logging.Logger;
   11.15  import javax.ws.rs.GET;
   11.16 @@ -52,14 +49,13 @@
   11.17  import javax.ws.rs.Produces;
   11.18  import javax.ws.rs.QueryParam;
   11.19  import javax.ws.rs.core.MediaType;
   11.20 -import org.codehaus.jettison.json.JSONObject;
   11.21  
   11.22  /**
   11.23   *
   11.24   * @author Jaroslav Tulach <jtulach@netbeans.org>
   11.25   */
   11.26  public final class Games {
   11.27 -    private List<Game> games = new ArrayList<Game>();
   11.28 +    private final List<Game> games = new ArrayList<Game>();
   11.29      private final File dir;
   11.30      private static final Logger LOG = Logger.getLogger(Games.class.getName());
   11.31  
   11.32 @@ -79,11 +75,11 @@
   11.33      }
   11.34  
   11.35      @POST
   11.36 -    @Produces(MediaType.APPLICATION_JSON)
   11.37 -    public Game createGame(
   11.38 +    @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
   11.39 +    public GameId createGame(
   11.40          @QueryParam("white") String white,
   11.41          @QueryParam("black") String black
   11.42 -    ) {
   11.43 +    ) throws IOException {
   11.44          if (white == null) {
   11.45              throw new IllegalArgumentException("Must specify white");
   11.46          }
   11.47 @@ -91,8 +87,9 @@
   11.48              throw new IllegalArgumentException("Must specify black");
   11.49          }
   11.50          Game g = new Game(white, black);
   11.51 +        storeGame(g);
   11.52          games.add(g);
   11.53 -        return g;
   11.54 +        return g.getId();
   11.55      }
   11.56  
   11.57      @GET
   11.58 @@ -108,22 +105,19 @@
   11.59  
   11.60      @GET
   11.61      @Path("{id}")
   11.62 -    @Produces(MediaType.APPLICATION_JSON)
   11.63 -    public Object getBoardInfo(@PathParam("id") String id) {
   11.64 +    @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
   11.65 +    public Game getBoardInfo(@PathParam("id") String id) {
   11.66          Game g = findGame(id);
   11.67          if (g == null) {
   11.68              throw new IllegalArgumentException("Unknown game " + id);
   11.69          }
   11.70 -        Map<String,Object> data = new HashMap<String, Object>();
   11.71 -        data.put("board", g.getBoard().toString());
   11.72 -        data.put("game", g);
   11.73 -        return data;
   11.74 +        return g;
   11.75      }
   11.76  
   11.77      @PUT
   11.78      @Path("{id}")
   11.79 -    @Produces(MediaType.APPLICATION_JSON)
   11.80 -    public Game applyMove(
   11.81 +    @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
   11.82 +    public GameId applyMove(
   11.83          @PathParam("id") String id,
   11.84          @QueryParam("player") String player,
   11.85          @QueryParam("move") String move
   11.86 @@ -139,18 +133,26 @@
   11.87          } catch (IOException ex) {
   11.88              LOG.log(Level.WARNING, "Cannot store game " + id, ex);
   11.89          }
   11.90 -        return g;
   11.91 +        return g.getId();
   11.92      }
   11.93  
   11.94      @GET
   11.95 -    @Produces(MediaType.APPLICATION_JSON)
   11.96 +    @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
   11.97 +    public List<GameId> listGames() {
   11.98 +        List<GameId> arr = new ArrayList<GameId>(games.size());
   11.99 +        for (Game g : games) {
  11.100 +            arr.add(g.getId());
  11.101 +        }
  11.102 +        return arr;
  11.103 +    }
  11.104 +
  11.105      public List<Game> getGames() {
  11.106          return games;
  11.107      }
  11.108  
  11.109      private Game findGame(String id) {
  11.110          for (Game g : games) {
  11.111 -            if (g.getId().equals(id)) {
  11.112 +            if (g.getId().getId().equals(id)) {
  11.113                  return g;
  11.114              }
  11.115          }
  11.116 @@ -165,7 +167,7 @@
  11.117          for (;;) {
  11.118              String line = r.readLine();
  11.119              if (line == null) {
  11.120 -                break;
  11.121 +                line = "finish";
  11.122              }
  11.123              line = line.trim();
  11.124              if (line.length() == 0) {
  11.125 @@ -186,7 +188,11 @@
  11.126                  throw new IOException("Missing white and black identification in " + f);
  11.127              }
  11.128              if (g == null) {
  11.129 -                g = new Game(f.getName(), white, black);
  11.130 +                GameId id = new GameId(f.getName(), white, black, new Date(f.lastModified()), GameResult.IN_PROGRESS);
  11.131 +                g = new Game(id);
  11.132 +            }
  11.133 +            if (line.equals("finish")) {
  11.134 +                break;
  11.135              }
  11.136              String[] moves = line.split(" ");
  11.137              if (moves.length == 0) {
  11.138 @@ -212,10 +218,11 @@
  11.139  
  11.140      private void storeGame(Game g) throws IOException {
  11.141          dir.mkdirs();
  11.142 -        File f = new File(dir, g.getId());
  11.143 +        File f = new File(dir, g.getId().getId());
  11.144          PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(f)));
  11.145 -        pw.println("# white: " + g.getWhite());
  11.146 -        pw.println("# black: " + g.getBlack());
  11.147 +        pw.println("# white: " + g.getId().getWhite());
  11.148 +        pw.println("# black: " + g.getId().getBlack());
  11.149 +        pw.println("# status: " + g.getId().getResult());
  11.150          int cnt = 0;
  11.151          for (Move m : g.getMoves()) {
  11.152              pw.print(m.toString());
    12.1 --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java	Sat Aug 29 16:15:20 2009 +0200
    12.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java	Sun Aug 30 14:37:47 2009 +0200
    12.3 @@ -33,8 +33,6 @@
    12.4  import com.sun.net.httpserver.HttpServer;
    12.5  import java.io.File;
    12.6  import java.io.IOException;
    12.7 -import java.util.HashMap;
    12.8 -import java.util.Map;
    12.9  import javax.ws.rs.Path;
   12.10  
   12.11  /**
    13.1 --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java	Sat Aug 29 16:15:20 2009 +0200
    13.2 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java	Sun Aug 30 14:37:47 2009 +0200
    13.3 @@ -33,14 +33,12 @@
    13.4  import cz.xelfi.quoridor.Board;
    13.5  import cz.xelfi.quoridor.Move;
    13.6  import cz.xelfi.quoridor.webidor.resources.Games;
    13.7 -import cz.xelfi.quoridor.webidor.resources.Quoridor;
    13.8  import java.io.File;
    13.9  import java.io.FileReader;
   13.10  import java.io.IOException;
   13.11  import java.util.List;
   13.12  import java.util.Map;
   13.13  import javax.ws.rs.core.MediaType;
   13.14 -import org.codehaus.jettison.json.JSONObject;
   13.15  import org.junit.Test;
   13.16  import static org.junit.Assert.*;
   13.17  
   13.18 @@ -94,33 +92,33 @@
   13.19  
   13.20      @Test public void testCreateAGame() throws Exception {
   13.21          webResource = webResource.path("api");
   13.22 -        Game s = webResource.path("games").queryParam("white", "Jarda")
   13.23 -                .queryParam("black", "Jirka").post(Game.class);
   13.24 +        GameId s = webResource.path("games").queryParam("white", "Jarda")
   13.25 +                .queryParam("black", "Jirka").post(GameId.class);
   13.26  
   13.27          String msg = webResource.path("games").get(String.class);
   13.28          //List<Game> games =  webResource.path("games").get(new GenericType<List<Game>>() {});
   13.29  
   13.30 -        GenericType<List<Game>> gType = new GenericType<List<Game>>() {};
   13.31 +        GenericType<List<GameId>> gType = new GenericType<List<GameId>>() {};
   13.32  
   13.33 -        List<Game> games = webResource.path("games").accept("application/json").get(gType);
   13.34 +        List<GameId> games = webResource.path("games").accept("application/json").get(gType);
   13.35          assertEquals("One game", 1, games.size());
   13.36          assertEquals("Same white", "Jarda", games.get(0).getWhite());
   13.37          assertEquals("Same black", "Jirka", games.get(0).getBlack());
   13.38  
   13.39 -        Game s1 = webResource.path("games/" + s.getId()).queryParam("player", "Jarda").queryParam("move", "N").put(Game.class);
   13.40 +        GameId s1 = webResource.path("games/" + s.getId()).queryParam("player", "Jarda").queryParam("move", "N").put(GameId.class);
   13.41          try {
   13.42 -            Game s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jarda").queryParam("move", "N").put(Game.class);
   13.43 +            GameId s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jarda").queryParam("move", "N").put(GameId.class);
   13.44              fail("Not Jarda's turn, previous call shall fail");
   13.45          } catch (UniformInterfaceException ex) {
   13.46              // OK
   13.47          }
   13.48          try {
   13.49 -            Game s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jirka").queryParam("move", "NONSENCE").put(Game.class);
   13.50 +            GameId s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jirka").queryParam("move", "NONSENCE").put(GameId.class);
   13.51              fail("Invalid move");
   13.52          } catch (UniformInterfaceException ex) {
   13.53              // OK
   13.54          }
   13.55 -        Game s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jirka").queryParam("move", "S").put(Game.class);
   13.56 +        GameId s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jirka").queryParam("move", "S").put(GameId.class);
   13.57          assertNotNull("Successful move", s2);
   13.58  
   13.59          File game = new File(new File(dir, "games"), s2.getId());
   13.60 @@ -144,22 +142,24 @@
   13.61          Games read = new Games(new File(dir, "games"));
   13.62          List<Game> readGames = read.getGames();
   13.63          assertEquals("One game read", 1, readGames.size());
   13.64 -        Board board = read.getGames().get(0).getBoard();
   13.65 +        Board board = readGames.get(0).getBoard();
   13.66          assertEquals(1, board.getPlayers().get(0).getRow());
   13.67          assertEquals(7, board.getPlayers().get(1).getRow());
   13.68 -        assertEquals(Move.NORTH, read.getGames().get(0).getMoves().get(0));
   13.69 -        assertEquals(Move.SOUTH, read.getGames().get(0).getMoves().get(1));
   13.70 +        assertEquals(Move.NORTH, readGames.get(0).getMoves().get(0));
   13.71 +        assertEquals(Move.SOUTH, readGames.get(0).getMoves().get(1));
   13.72  
   13.73          class GMap extends GenericType<Map<String,Object>>{}
   13.74 -        JSONObject map = webResource.path("games").path(s.getId()).accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
   13.75 -        assertNotNull("Map really returned", map);
   13.76 -        String txtBoard = (String) map.get("board");
   13.77 -        assertNotNull("Contains its textual form", txtBoard);
   13.78 -        assertEquals("It is same as text of our game", board.toString(), txtBoard);
   13.79 +        String text = webResource.path("games").path(s.getId()).accept(MediaType.TEXT_PLAIN).get(String.class);
   13.80 +        if (text.indexOf("-----") == -1) {
   13.81 +            fail("Expecting board:\n" + text);
   13.82 +        }
   13.83 +        Game readGame = webResource.path("games").path(s.getId()).accept(MediaType.TEXT_XML).get(Game.class);
   13.84 +        assertNotNull("Game really returned", readGame);
   13.85 +        assertEquals("Same game as in text representation", readGame.getBoard(), Board.valueOf(text));
   13.86 +        assertEquals("It is same as text of our game", readGame.getBoard().toString(), text);
   13.87  
   13.88 -        Object og = map.getJSONObject("game");
   13.89 -        assertTrue("Instance of JSON: " + og, og instanceof JSONObject);
   13.90 -        JSONObject jg = (JSONObject)og;
   13.91 +        assertEquals(Move.NORTH, readGame.getMoves().get(0));
   13.92 +        assertEquals(Move.SOUTH, readGame.getMoves().get(1));
   13.93      }
   13.94  
   13.95  }