Making list of activeTweeters really a list. It is easier to observe its changes.
1.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Mon Apr 08 18:26:11 2013 +0200
1.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Mon Apr 08 19:30:22 2013 +0200
1.3 @@ -48,7 +48,6 @@
1.4 import javax.lang.model.element.TypeElement;
1.5 import javax.lang.model.element.VariableElement;
1.6 import javax.lang.model.type.ArrayType;
1.7 -import javax.lang.model.type.DeclaredType;
1.8 import javax.lang.model.type.MirroredTypeException;
1.9 import javax.lang.model.type.TypeKind;
1.10 import javax.lang.model.type.TypeMirror;
1.11 @@ -596,7 +595,7 @@
1.12 }
1.13 w.write(" try {\n");
1.14 w.write(" locked = true;\n");
1.15 - w.write(" return " + e.getEnclosingElement().getSimpleName() + '.' + e.getSimpleName() + "(");
1.16 + w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
1.17 String sep = "";
1.18 for (int i = 1; i <= arg; i++) {
1.19 w.write(sep);
2.1 --- a/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java Mon Apr 08 18:26:11 2013 +0200
2.2 +++ b/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java Mon Apr 08 19:30:22 2013 +0200
2.3 @@ -31,7 +31,7 @@
2.4 @Page(xhtml="index.html", className="TwitterModel", properties={
2.5 @Property(name="savedLists", type=TwitterClient.Twttrs.class, array = true),
2.6 @Property(name="activeTweetersName", type=String.class),
2.7 - @Property(name="activeTweeters", type=TwitterClient.Twttrs.class),
2.8 + @Property(name="activeTweeters", type=String.class, array = true),
2.9 @Property(name="userNameToAdd", type=String.class),
2.10 @Property(name="currentTweets", type=TwitterClient.Twt.class, array = true)
2.11 })
2.12 @@ -50,6 +50,28 @@
2.13 @Property(name = "created_at", type = String.class),
2.14 })
2.15 static final class Twt {
2.16 + @ComputedProperty static String html(String text) {
2.17 + StringBuilder sb = new StringBuilder(320);
2.18 + for (int pos = 0;;) {
2.19 + int http = text.indexOf("http", pos);
2.20 + if (http == -1) {
2.21 + sb.append(text.substring(pos));
2.22 + return sb.toString();
2.23 + }
2.24 + int spc = text.indexOf(' ', http);
2.25 + if (spc == -1) {
2.26 + spc = text.length();
2.27 + }
2.28 + sb.append(text.substring(pos, http));
2.29 + String url = text.substring(http, spc);
2.30 + sb.append("<a href='").append(url).append("'>").append(url).append("</a>");
2.31 + pos = spc;
2.32 + }
2.33 + }
2.34 +
2.35 + @ComputedProperty static String userUrl(String from_user) {
2.36 + return "http://twitter.com/" + from_user;
2.37 + }
2.38 }
2.39 @Model(className = "TwitterQuery", properties = {
2.40 @Property(array = true, name = "results", type = Twt.class)
2.41 @@ -66,34 +88,32 @@
2.42 @OnPropertyChange("activeTweetersName")
2.43 static void changeTweetersList(TwitterModel model) {
2.44 Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName());
2.45 - model.setActiveTweeters(people.clone());
2.46 + model.getActiveTweeters().clear();
2.47 + model.getActiveTweeters().addAll(people.getUserNames());
2.48 }
2.49
2.50 - @OnPropertyChange("activeTweeters")
2.51 + @OnPropertyChange({ "activeTweeters", "activeTweetersCount" })
2.52 static void refreshTweets(TwitterModel model) {
2.53 - Tweeters people = model.getActiveTweeters();
2.54 - if (people != null) {
2.55 - StringBuilder sb = new StringBuilder();
2.56 - sb.append("rpp=25&q=");
2.57 - String sep = "";
2.58 - for (String p : people.getUserNames()) {
2.59 - sb.append(sep);
2.60 - sb.append("from:");
2.61 - sb.append(p);
2.62 - sep = " OR ";
2.63 - }
2.64 - model.queryTweets("http://search.twitter.com", sb.toString());
2.65 + StringBuilder sb = new StringBuilder();
2.66 + sb.append("rpp=25&q=");
2.67 + String sep = "";
2.68 + for (String p : model.getActiveTweeters()) {
2.69 + sb.append(sep);
2.70 + sb.append("from:");
2.71 + sb.append(p);
2.72 + sep = " OR ";
2.73 }
2.74 + model.queryTweets("http://search.twitter.com", sb.toString());
2.75 }
2.76
2.77 static {
2.78 final TwitterModel model = new TwitterModel();
2.79 final List<Tweeters> svdLst = model.getSavedLists();
2.80 - svdLst.add(tweeters("API Design", "JaroslavTulach"));
2.81 - svdLst.add(tweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
2.82 - svdLst.add(tweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
2.83 - svdLst.add(tweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans"));
2.84 - svdLst.add(tweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
2.85 + svdLst.add(newTweeters("API Design", "JaroslavTulach"));
2.86 + svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
2.87 + svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
2.88 + svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka"));
2.89 + svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
2.90
2.91 model.setActiveTweetersName("NetBeans");
2.92
2.93 @@ -101,27 +121,32 @@
2.94 }
2.95
2.96 @ComputedProperty
2.97 - static boolean hasUnsavedChanges(Tweeters activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
2.98 + static boolean hasUnsavedChanges(List<String> activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
2.99 Tweeters tw = findByName(savedLists, activeTweetersName);
2.100 if (activeTweeters == null) {
2.101 return false;
2.102 }
2.103 - return !tw.equals(activeTweeters);
2.104 + return !tw.getUserNames().equals(activeTweeters);
2.105 + }
2.106 +
2.107 + @ComputedProperty
2.108 + static int activeTweetersCount(List<String> activeTweeters) {
2.109 + return activeTweeters.size();
2.110 }
2.111
2.112 @ComputedProperty
2.113 static boolean userNameToAddIsValid(
2.114 - String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, Tweeters activeTweeters
2.115 + String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, List<String> activeTweeters
2.116 ) {
2.117 - return activeTweeters != null && userNameToAdd != null &&
2.118 + return userNameToAdd != null &&
2.119 userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
2.120 - !activeTweeters.getUserNames().contains(userNameToAdd);
2.121 + !activeTweeters.contains(userNameToAdd);
2.122 }
2.123
2.124 @OnFunction
2.125 static void deleteList(TwitterModel model) {
2.126 final List<Tweeters> sl = model.getSavedLists();
2.127 - sl.remove(model.getActiveTweeters());
2.128 + sl.remove(findByName(sl, model.getActiveTweetersName()));
2.129 if (sl.isEmpty()) {
2.130 final Tweeters t = new Tweeters();
2.131 t.setName("New");
2.132 @@ -135,20 +160,20 @@
2.133 Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
2.134 int indx = model.getSavedLists().indexOf(t);
2.135 if (indx != -1) {
2.136 - model.getSavedLists().set(indx, model.getActiveTweeters());
2.137 - } else {
2.138 - model.getSavedLists().add(model.getActiveTweeters());
2.139 + t.setName(model.getActiveTweetersName());
2.140 + t.getUserNames().clear();
2.141 + t.getUserNames().addAll(model.getActiveTweeters());
2.142 }
2.143 }
2.144
2.145 @OnFunction
2.146 static void addUser(TwitterModel model) {
2.147 String n = model.getUserNameToAdd();
2.148 - model.getActiveTweeters().getUserNames().add(n);
2.149 + model.getActiveTweeters().add(n);
2.150 }
2.151 @OnFunction
2.152 static void removeUser(String data, TwitterModel model) {
2.153 - model.getActiveTweeters().getUserNames().remove(data);
2.154 + model.getActiveTweeters().remove(data);
2.155 }
2.156
2.157 private static Tweeters findByName(List<Tweeters> list, String name) {
2.158 @@ -160,11 +185,10 @@
2.159 return list.isEmpty() ? new Tweeters() : list.get(0);
2.160 }
2.161
2.162 - private static Tweeters tweeters(String listName, String... userNames) {
2.163 + private static Tweeters newTweeters(String listName, String... userNames) {
2.164 Tweeters t = new Tweeters();
2.165 t.setName(listName);
2.166 t.getUserNames().addAll(Arrays.asList(userNames));
2.167 return t;
2.168 }
2.169 -
2.170 }
3.1 --- a/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html Mon Apr 08 18:26:11 2013 +0200
3.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html Mon Apr 08 19:30:22 2013 +0200
3.3 @@ -44,7 +44,7 @@
3.4 This code based on original <a href="http://knockoutjs.com/examples/twitter.html">knockout.js Twitter example</a> and
3.5 uses almost unmodified HTML code. It just changes the model. It
3.6 is written in Java language and it is executed using <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
3.7 - virtual machine. The Java source code has about 170 lines and is available
3.8 + virtual machine. The Java source code has about 190 lines and is available
3.9 <a href="http://source.apidesign.org/hg/bck2brwsr/file/3bd43aa6f08d/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java">here</a>
3.10 - in fact it may even be more dense than the original JavaScript model.
3.11 </p>
3.12 @@ -52,14 +52,14 @@
3.13 <div class='liveExample'>
3.14 <div class='configuration'>
3.15 <div class='listChooser'>
3.16 - <button data-bind='click: deleteList, enable: activeTweeters.name'>Delete</button>
3.17 + <button data-bind='click: deleteList, enable: activeTweetersName'>Delete</button>
3.18 <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button>
3.19 <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
3.20 </div>
3.21
3.22 - <p>Currently viewing <span data-bind='text: activeTweeters().userNames().length'> </span> user(s):</p>
3.23 - <div class='currentUsers' data-bind='with: activeTweeters'>
3.24 - <ul data-bind='foreach: userNames'>
3.25 + <p>Currently viewing <span data-bind='text: activeTweetersCount'> </span> user(s):</p>
3.26 + <div class='currentUsers' >
3.27 + <ul data-bind='foreach: activeTweeters'>
3.28 <li>
3.29 <button data-bind='click: $root.removeUser'>Remove</button>
3.30 <div data-bind='text: $data'> </div>
3.31 @@ -79,8 +79,8 @@
3.32 <tr>
3.33 <td><img data-bind='attr: { src: profile_image_url }' /></td>
3.34 <td>
3.35 - <a href='http://twitter.com/${ from_user }' class='twitterUser' data-bind='attr: { href: "http://twitter.com/" + from_user }, text: from_user'> </a>
3.36 - <span data-bind='text: text'> </span>
3.37 + <a class='twitterUser' data-bind='attr: { href: userUrl }, text: from_user'> </a>
3.38 + <span data-bind='html: html'> </span>
3.39 <div class='tweetInfo' data-bind='text: created_at'> </div>
3.40 </td>
3.41 </tr>
4.1 --- a/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java Mon Apr 08 18:26:11 2013 +0200
4.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java Mon Apr 08 19:30:22 2013 +0200
4.3 @@ -17,6 +17,7 @@
4.4 */
4.5 package org.apidesign.bck2brwsr.demo.twitter;
4.6
4.7 +import java.util.List;
4.8 import static org.testng.Assert.*;
4.9 import org.testng.annotations.BeforeMethod;
4.10 import org.testng.annotations.Test;
4.11 @@ -46,11 +47,10 @@
4.12 assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
4.13 assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
4.14
4.15 - Tweeters mod = model.getActiveTweeters();
4.16 - assertNotNull(mod, "Modified list is not filled in");
4.17 + List<String> mod = model.getActiveTweeters();
4.18 assertTrue(model.isHasUnsavedChanges(), "We have modifications");
4.19 - assertEquals(mod.getUserNames().size(), 1, "One element in the list");
4.20 - assertEquals(mod.getUserNames().get(0), "Joe", "Its name is Joe");
4.21 + assertEquals(mod.size(), 1, "One element in the list");
4.22 + assertEquals(mod.get(0), "Joe", "Its name is Joe");
4.23
4.24 assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
4.25
4.26 @@ -58,8 +58,10 @@
4.27 assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
4.28
4.29 assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
4.30 -
4.31 - assertFalse(model.getSavedLists().contains(t), "No longer contains old list");
4.32 }
4.33
4.34 + @Test public void httpAtTheEnd() {
4.35 + String res = TwitterClient.Twt.html("Ahoj http://kuk");
4.36 + assertEquals(res, "Ahoj <a href='http://kuk'>http://kuk</a>");
4.37 + }
4.38 }