Removing anything related to JSON from the HTML layer, using natural freemarker's W3C DOM processing capabilities
1.1 --- a/.hgignore Sun Aug 30 16:15:37 2009 +0200
1.2 +++ b/.hgignore Mon Aug 31 22:44:47 2009 +0200
1.3 @@ -1,3 +1,4 @@
1.4 +target/.*
1.5 .*/target/.*
1.6 .*orig$
1.7 .*~$
2.1 --- a/freemarkerdor/pom.xml Sun Aug 30 16:15:37 2009 +0200
2.2 +++ b/freemarkerdor/pom.xml Mon Aug 31 22:44:47 2009 +0200
2.3 @@ -46,6 +46,11 @@
2.4 <version>4.5</version>
2.5 <scope>test</scope>
2.6 </dependency>
2.7 + <dependency>
2.8 + <groupId>freemarker</groupId>
2.9 + <artifactId>freemarker</artifactId>
2.10 + <version>2.3.8</version>
2.11 + </dependency>
2.12 </dependencies>
2.13 <build>
2.14 <plugins>
2.15 @@ -65,3 +70,8 @@
2.16
2.17
2.18
2.19 +
2.20 +
2.21 +
2.22 +
2.23 +
3.1 --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/FreemarkerProcessor.java Sun Aug 30 16:15:37 2009 +0200
3.2 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/FreemarkerProcessor.java Mon Aug 31 22:44:47 2009 +0200
3.3 @@ -41,6 +41,7 @@
3.4 import javax.script.ScriptException;
3.5 import javax.ws.rs.ext.Provider;
3.6 import org.openide.filesystems.FileUtil;
3.7 +import org.w3c.dom.Document;
3.8
3.9 /**
3.10 *
3.11 @@ -68,7 +69,11 @@
3.12 if (model instanceof Map) {
3.13 bind.putAll((Map<? extends String, ? extends Object>)model);
3.14 }
3.15 - bind.put("model", model);
3.16 + if (model instanceof Document) {
3.17 + bind.put("doc", model);
3.18 + } else {
3.19 + bind.put("model", model);
3.20 + }
3.21
3.22 Writer w = new OutputStreamWriter(out);
3.23
4.1 --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Sun Aug 30 16:15:37 2009 +0200
4.2 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Mon Aug 31 22:44:47 2009 +0200
4.3 @@ -38,11 +38,6 @@
4.4 import java.io.FileInputStream;
4.5 import java.io.IOException;
4.6 import java.net.URI;
4.7 -import java.util.ArrayList;
4.8 -import java.util.HashMap;
4.9 -import java.util.Iterator;
4.10 -import java.util.List;
4.11 -import java.util.Map;
4.12 import java.util.Properties;
4.13 import java.util.concurrent.Callable;
4.14 import javax.ws.rs.DefaultValue;
4.15 @@ -58,9 +53,6 @@
4.16 import javax.ws.rs.core.MediaType;
4.17 import javax.ws.rs.core.NewCookie;
4.18 import javax.ws.rs.core.Response;
4.19 -import org.codehaus.jettison.json.JSONArray;
4.20 -import org.codehaus.jettison.json.JSONException;
4.21 -import org.codehaus.jettison.json.JSONObject;
4.22 import org.w3c.dom.Document;
4.23
4.24 /**
4.25 @@ -94,7 +86,11 @@
4.26 ) throws Exception {
4.27 File f = new File(new File(new File(System.getProperty("user.home")), ".quoridor"), "passwd");
4.28 Properties p = new Properties();
4.29 - p.load(new FileInputStream(f));
4.30 + try {
4.31 + p.load(new FileInputStream(f));
4.32 + } catch (IOException ex) {
4.33 + ex.printStackTrace();
4.34 + }
4.35 if (name != null && password.equals(p.getProperty(name))) {
4.36 return Response.seeOther(new URI("/")).cookie(new NewCookie("login", name)).entity(welcomeImpl()).build();
4.37 } else {
4.38 @@ -105,7 +101,7 @@
4.39
4.40 @GET
4.41 @Produces(MediaType.TEXT_HTML)
4.42 - public Viewable welcome() throws JSONException {
4.43 + public Viewable welcome() {
4.44 Viewable v = checkLogin();
4.45 if (v != null) {
4.46 return v;
4.47 @@ -116,15 +112,13 @@
4.48 @GET
4.49 @Path("games/{id}/")
4.50 @Produces(MediaType.TEXT_HTML)
4.51 - public Viewable board(@PathParam("id") String id) throws JSONException {
4.52 + public Viewable board(@PathParam("id") String id) {
4.53 Viewable v = checkLogin();
4.54 if (v != null) {
4.55 return v;
4.56 }
4.57 - Map<?,?> obj = (Map<?,?>)convert(base.path("games").path(id).accept(MediaType.APPLICATION_JSON_TYPE).get(JSONObject.class));
4.58 -
4.59 -
4.60 - return new Viewable("game.fmt", obj);
4.61 + Document doc = base.path("games").path(id).accept(MediaType.TEXT_XML).get(Document.class);
4.62 + return new Viewable("game.fmt", doc);
4.63 }
4.64
4.65 @GET
4.66 @@ -137,7 +131,7 @@
4.67 @QueryParam("direction-next") @DefaultValue("") String directionNext,
4.68 @QueryParam("column") @DefaultValue("") String column,
4.69 @QueryParam("row") @DefaultValue("") String row
4.70 - ) throws JSONException {
4.71 + ) {
4.72 Viewable v = checkLogin();
4.73 if (v != null) {
4.74 return v;
4.75 @@ -160,41 +154,20 @@
4.76 public Viewable create(
4.77 @QueryParam("white") String white,
4.78 @QueryParam("black") String black
4.79 - ) throws JSONException {
4.80 + ) {
4.81 Viewable v = checkLogin();
4.82 if (v != null) {
4.83 return v;
4.84 }
4.85 - Object obj = convert(
4.86 + Object obj =
4.87 base.path("games").queryParam("white", white).
4.88 - queryParam("black", black).post(JSONObject.class)
4.89 - );
4.90 - Map<?,?> map = (Map<?,?>)obj;
4.91 - String id = (String)map.get("id");
4.92 - return board(id);
4.93 + queryParam("black", black).post(Document.class);
4.94 + return welcome();
4.95 }
4.96
4.97 -
4.98 - private static Object convert(Object obj) throws JSONException {
4.99 - if (obj instanceof JSONArray) {
4.100 - JSONArray arr = (JSONArray)obj;
4.101 - final int length = arr.length();
4.102 - List<Object> res = new ArrayList<Object>(length);
4.103 - for (int i = 0; i < length; i++) {
4.104 - res.add(convert(arr.get(i)));
4.105 - }
4.106 - return res;
4.107 - } else if (obj instanceof JSONObject) {
4.108 - JSONObject json = (JSONObject)obj;
4.109 - Map<Object,Object> map = new HashMap<Object,Object>(json.length() * 2 / 3);
4.110 - for (Iterator it = json.keys(); it.hasNext();) {
4.111 - String key = (String)it.next();
4.112 - map.put(key, convert(json.get(key)));
4.113 - }
4.114 - return map;
4.115 - } else {
4.116 - return obj;
4.117 - }
4.118 + private Viewable welcomeImpl() {
4.119 + final Object got = base.path("games").accept(MediaType.TEXT_XML).get(Document.class);
4.120 + return new Viewable("index.fmt", got);
4.121 }
4.122
4.123 //
4.124 @@ -236,10 +209,4 @@
4.125 return server;
4.126 }
4.127
4.128 - private Viewable welcomeImpl() throws JSONException {
4.129 - final Object got = base.path("games").accept(MediaType.APPLICATION_JSON_TYPE).get(JSONArray.class);
4.130 - List<?> obj = (List<?>)convert(got);
4.131 - return new Viewable("index.fmt", obj);
4.132 - }
4.133 -
4.134 }
5.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Sun Aug 30 16:15:37 2009 +0200
5.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Mon Aug 31 22:44:47 2009 +0200
5.3 @@ -6,7 +6,7 @@
5.4 </head>
5.5 <body>
5.6 <h1>Game</h1>
5.7 - <h3>${id.white} vs. ${id.black}</h3>
5.8 + <h3>${doc.game.id.@white} vs. ${doc.game.id.@black}</h3>
5.9 <form action="move">
5.10 <input type="hidden" name="type" value="fence" readonly="readonly"/>
5.11 <select name="column">
5.12 @@ -52,6 +52,6 @@
5.13 </select>
5.14 <input type="submit" value="Move!" />
5.15 </form>
5.16 - <pre>${board}</pre>
5.17 + <pre>${doc.game.board}</pre>
5.18 </body>
5.19 </html>
5.20 \ No newline at end of file
6.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt Sun Aug 30 16:15:37 2009 +0200
6.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt Mon Aug 31 22:44:47 2009 +0200
6.3 @@ -6,10 +6,11 @@
6.4 </head>
6.5 <body>
6.6 <h1>Quoridor Community Server</h1>
6.7 -
6.8 <ol>
6.9 - <#list model as item>
6.10 - <li>${item.white} vs. ${item.black} <a href="games/${item.id}/">board</a></li>
6.11 + <#list doc.gameIds.* as g>
6.12 + <li>
6.13 + ${g.@white} vs. ${g.@black} <a href="games/${g.@id}/">board</a>
6.14 + </li>
6.15 </#list>
6.16 </ol>
6.17 <form action="games/create">
7.1 --- a/freemarkerdor/src/test/java/cz/xelfi/quoridor/freemarkerdor/UITest.java Sun Aug 30 16:15:37 2009 +0200
7.2 +++ b/freemarkerdor/src/test/java/cz/xelfi/quoridor/freemarkerdor/UITest.java Mon Aug 31 22:44:47 2009 +0200
7.3 @@ -104,6 +104,9 @@
7.4 if (res.indexOf("action=\"login\"") == -1) {
7.5 fail("Wrong index.html:\n" + res);
7.6 }
7.7 + if (res.toLowerCase().indexOf("error") != -1) {
7.8 + fail("There was an error:\n" + res);
7.9 + }
7.10 res = webResource.cookie(Cookie.valueOf("login=jarda")).accept("text/html").get(String.class);
7.11 if (res.indexOf("action=\"games/create\"") == -1) {
7.12 fail(res);
8.1 --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java Sun Aug 30 16:15:37 2009 +0200
8.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java Mon Aug 31 22:44:47 2009 +0200
8.3 @@ -49,7 +49,7 @@
8.4 public final class Game extends Object {
8.5 @XmlElement
8.6 private GameId id;
8.7 - @XmlAttribute
8.8 + @XmlElement
8.9 @XmlJavaTypeAdapter(BoardAdapter.class)
8.10 private Board board;
8.11 @XmlElement
9.1 --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/GameId.java Sun Aug 30 16:15:37 2009 +0200
9.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/GameId.java Mon Aug 31 22:44:47 2009 +0200
9.3 @@ -49,7 +49,7 @@
9.4 private Date started;
9.5 @XmlAttribute
9.6 private GameResult result;
9.7 - @XmlID
9.8 + @XmlID @XmlAttribute
9.9 private String id;
9.10
9.11 GameId() {
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/W3CDocumentReader.java Mon Aug 31 22:44:47 2009 +0200
10.3 @@ -0,0 +1,46 @@
10.4 +/*
10.5 + * To change this template, choose Tools | Templates
10.6 + * and open the template in the editor.
10.7 + */
10.8 +
10.9 +package cz.xelfi.quoridor.webidor;
10.10 +
10.11 +import java.io.IOException;
10.12 +import java.io.InputStream;
10.13 +import java.lang.annotation.Annotation;
10.14 +import java.lang.reflect.Type;
10.15 +import javax.ws.rs.Consumes;
10.16 +import javax.ws.rs.WebApplicationException;
10.17 +import javax.ws.rs.core.MediaType;
10.18 +import javax.ws.rs.core.MultivaluedMap;
10.19 +import javax.ws.rs.ext.Provider;
10.20 +import javax.xml.parsers.DocumentBuilder;
10.21 +import javax.xml.parsers.DocumentBuilderFactory;
10.22 +import javax.xml.parsers.ParserConfigurationException;
10.23 +import org.w3c.dom.Document;
10.24 +import org.xml.sax.SAXException;
10.25 +
10.26 +/**
10.27 + *
10.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
10.29 + */
10.30 +@Provider
10.31 +@Consumes(MediaType.TEXT_XML)
10.32 +public class W3CDocumentReader implements javax.ws.rs.ext.MessageBodyReader<Document> {
10.33 + public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
10.34 + return type == Document.class;
10.35 + }
10.36 +
10.37 + public Document readFrom(Class<Document> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
10.38 + try {
10.39 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
10.40 + DocumentBuilder builder = factory.newDocumentBuilder();
10.41 + return builder.parse(entityStream);
10.42 + } catch (ParserConfigurationException ex) {
10.43 + throw new WebApplicationException(ex);
10.44 + } catch (SAXException ex) {
10.45 + throw new WebApplicationException(ex);
10.46 + }
10.47 + }
10.48 +
10.49 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/webidor/src/main/resources/META-INF/services/javax.ws.rs.ext.MessageBodyReader Mon Aug 31 22:44:47 2009 +0200
11.3 @@ -0,0 +1,1 @@
11.4 +cz.xelfi.quoridor.webidor.W3CDocumentReader
12.1 --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Sun Aug 30 16:15:37 2009 +0200
12.2 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Mon Aug 31 22:44:47 2009 +0200
12.3 @@ -40,6 +40,7 @@
12.4 import java.util.Map;
12.5 import javax.ws.rs.core.MediaType;
12.6 import org.junit.Test;
12.7 +import org.w3c.dom.Document;
12.8 import static org.junit.Assert.*;
12.9
12.10 /**
12.11 @@ -100,6 +101,10 @@
12.12
12.13 GenericType<List<GameId>> gType = new GenericType<List<GameId>>() {};
12.14
12.15 + Document doc = webResource.path("games").accept("text/xml").get(Document.class);
12.16 + assertNotNull("Can read games in form of XML", doc);
12.17 + assertEquals("Name is correct", "gameIds", doc.getDocumentElement().getNodeName());
12.18 + assertEquals("One child", 1, doc.getDocumentElement().getChildNodes().getLength());
12.19 List<GameId> games = webResource.path("games").accept("application/json").get(gType);
12.20 assertEquals("One game", 1, games.size());
12.21 assertEquals("Same white", "Jarda", games.get(0).getWhite());