# HG changeset patch # User Jaroslav Tulach # Date 1372089044 -7200 # Node ID 73c0973e8e0a7fcedf637c7ec7ed2e5372a7d70a # Parent 7189e9abb928ac3dc26bda53da50ecdbede58f60 Moving all knockout related code under the 'ko' directory diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype-test/pom.xml --- a/ko-archetype-test/pom.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ - - - 4.0.0 - - org.apidesign - html - 0.4-SNAPSHOT - - org.apidesign.html - ko-archetype-test - 0.4-SNAPSHOT - Knockout 4 Java Archetype Test - http://maven.apache.org - Verifies the Knockout & net.java.html.json archetype behaves properly. - - UTF-8 - - - - ${project.groupId} - knockout4j-archetype - 0.4-SNAPSHOT - - - org.testng - testng - test - - - org.apache.maven.shared - maven-verifier - 1.4 - test - - - ${project.groupId} - ko-fx - ${project.version} - provided - - - ${project.groupId} - ko-bck2brwsr - ${project.version} - provided - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.archetype.test; - -import java.io.IOException; -import java.net.URL; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; -import javax.xml.xpath.XPathFactoryConfigurationException; -import org.testng.annotations.Test; -import static org.testng.Assert.*; -import org.testng.annotations.BeforeClass; -import org.w3c.dom.Document; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -/** - * - * @author Jaroslav Tulach - */ -public class ArchetypeVersionTest { - private String version; - - public ArchetypeVersionTest() { - } - - @BeforeClass public void readCurrentVersion() throws Exception { - version = findCurrentVersion(); - assertFalse(version.isEmpty(), "There should be some version string"); - } - - - @Test public void testComparePomDepsVersions() throws Exception { - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); - URL r = l.getResource("archetype-resources/pom.xml"); - assertNotNull(r, "Archetype pom found"); - - final XPathFactory fact = XPathFactory.newInstance(); - XPathExpression xp2 = fact.newXPath().compile( - "//properties/net.java.html.version/text()" - ); - - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); - String arch = (String) xp2.evaluate(dom, XPathConstants.STRING); - - assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version"); - } - - @Test public void testCheckLauncher() throws Exception { - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); - URL r = l.getResource("archetype-resources/pom.xml"); - assertNotNull(r, "Archetype pom found"); - - final XPathFactory fact = XPathFactory.newInstance(); - XPathExpression xp2 = fact.newXPath().compile( - "//properties/bck2brwsr.launcher.version/text()" - ); - - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); - String arch = (String) xp2.evaluate(dom, XPathConstants.STRING); - - - assertTrue(arch.matches("[0-9\\.]+"), "launcher version seems valid: " + arch); - } - - @Test public void testCheckBck2Brwsr() throws Exception { - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); - URL r = l.getResource("archetype-resources/pom.xml"); - assertNotNull(r, "Archetype pom found"); - - final XPathFactory fact = XPathFactory.newInstance(); - XPathExpression xp2 = fact.newXPath().compile( - "//properties/bck2brwsr.version/text()" - ); - - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); - String arch = (String) xp2.evaluate(dom, XPathConstants.STRING); - - assertTrue(arch.matches("[0-9\\.]+"), "bck2brwsr version seems valid: " + arch); - } - - @Test public void testNbActions() throws Exception { - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); - URL r = l.getResource("archetype-resources/nbactions.xml"); - assertNotNull(r, "Archetype nb file found"); - - final XPathFactory fact = XPathFactory.newInstance(); - XPathExpression xp2 = fact.newXPath().compile( - "//goal/text()" - ); - - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); - NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET); - - for (int i = 0; i < goals.getLength(); i++) { - String s = goals.item(i).getTextContent(); - if (s.contains("apidesign")) { - assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s); - } - } - } - - static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException { - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); - URL u = l.getResource("META-INF/maven/org.apidesign.html/knockout4j-archetype/pom.xml"); - assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path")); - - final XPathFactory fact = XPathFactory.newInstance(); - fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - - XPathExpression xp = fact.newXPath().compile("project/version/text()"); - - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream()); - return xp.evaluate(dom); - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.archetype.test; - -import java.io.File; -import java.util.Properties; -import java.util.zip.ZipFile; -import org.apache.maven.it.Verifier; -import org.testng.annotations.Test; -import static org.testng.Assert.*; - -/** - * - * @author Jaroslav Tulach - */ -public class VerifyArchetypeTest { - @Test public void fxBrwsrCompiles() throws Exception { - final File dir = new File("target/tests/fxcompile/").getAbsoluteFile(); - generateFromArchetype(dir); - - File created = new File(dir, "o-a-test"); - assertTrue(created.isDirectory(), "Project created"); - assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there"); - - Verifier v = new Verifier(created.getAbsolutePath()); - v.executeGoal("verify"); - - v.verifyErrorFreeLog(); - - for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) { - if (l.contains("j2js")) { - fail("No pre-compilaton:\n" + l); - } - } - - v.verifyTextInLog("org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher"); - v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-fxbrwsr.zip"); - } - - @Test public void bck2BrwsrCompiles() throws Exception { - final File dir = new File("target/tests/b2bcompile/").getAbsoluteFile(); - generateFromArchetype(dir); - - File created = new File(dir, "o-a-test"); - assertTrue(created.isDirectory(), "Project created"); - assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there"); - - Verifier v = new Verifier(created.getAbsolutePath()); - Properties sysProp = v.getSystemProperties(); - if (Boolean.getBoolean("java.awt.headless")) { - sysProp.put("java.awt.headless", "true"); - } - v.addCliOption("-Pbck2brwsr"); - v.executeGoal("verify"); - - v.verifyErrorFreeLog(); - - // does pre-compilation to JavaScript - v.verifyTextInLog("j2js"); - // uses Bck2BrwsrLauncher - v.verifyTextInLog("BaseHTTPLauncher stopServerAndBrwsr"); - // building zip: - v.verifyTextInLog("b2bcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-bck2brwsr.zip"); - - for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) { - if (l.contains("fxbrwsr")) { - fail("No fxbrwsr:\n" + l); - } - } - - File zip = new File(new File(created, "target"), "o-a-test-1.0-SNAPSHOT-bck2brwsr.zip"); - assertTrue(zip.isFile(), "Zip file with website was created"); - - ZipFile zf = new ZipFile(zip); - assertNotNull(zf.getEntry("public_html/index.html"), "index.html found"); - assertNotNull(zf.getEntry("public_html/twitterExample.css"), "css file found"); - - } - - private Verifier generateFromArchetype(final File dir, String... params) throws Exception { - Verifier v = new Verifier(dir.getAbsolutePath()); - v.setAutoclean(false); - v.setLogFileName("generate.log"); - v.deleteDirectory(""); - dir.mkdirs(); - Properties sysProp = v.getSystemProperties(); - sysProp.put("groupId", "org.apidesign.test"); - sysProp.put("artifactId", "o-a-test"); - sysProp.put("package", "org.apidesign.test.oat"); - sysProp.put("archetypeGroupId", "org.apidesign.html"); - sysProp.put("archetypeArtifactId", "knockout4j-archetype"); - sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion()); - - for (String p : params) { - v.addCliOption(p); - } - v.executeGoal("archetype:generate"); - v.verifyErrorFreeLog(); - return v; - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/pom.xml --- a/ko-archetype/pom.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ - - - 4.0.0 - - html - org.apidesign - 0.4-SNAPSHOT - - org.apidesign.html - knockout4j-archetype - 0.4-SNAPSHOT - jar - Knockout 4 Java Maven Archetype - - HTML page with Knockout.js bindings driven by application model - written in Java. Use your favorite language to code. Use - HTML as a lightweight rendering toolkit. Deploy using JavaFX or - bck2brwsr virtual machine. - - - - - src/main/resources - true - - **/pom.xml - - - - src/main/resources - false - - **/pom.xml - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-resources-plugin - 2.6 - - \ - 1.6 - - - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/java/org/apidesign/html/archetype/package-info.java --- a/ko-archetype/src/main/java/org/apidesign/html/archetype/package-info.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.archetype; diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml --- a/ko-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ - - - - - src/main/java - - **/*.java - - - - src/main/resources - - **/*.xhtml - **/*.html - **/*.css - - - - src/test/java - - **/*Test.java - - - - src/main/assembly - - **/*.xml - - - - - - nbactions*.xml - - - - assembly - - fxbrwsr-assembly.xml - bck2brwsr-assembly.xml - - - - \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/nbactions-bck2brwsr.xml --- a/ko-archetype/src/main/resources/archetype-resources/nbactions-bck2brwsr.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - - - - run - - package - bck2brwsr:brwsr - - - true - NONE - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/nbactions-fxbrwsr.xml --- a/ko-archetype/src/main/resources/archetype-resources/nbactions-fxbrwsr.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ - - - - run - - process-classes - bck2brwsr:brwsr - - - - debug - - process-classes - bck2brwsr:brwsr - - - maven - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/nbactions.xml --- a/ko-archetype/src/main/resources/archetype-resources/nbactions.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ - - - - run - - process-classes - bck2brwsr:brwsr - - - - debug - - process-classes - bck2brwsr:brwsr - - - maven - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/pom.xml --- a/ko-archetype/src/main/resources/archetype-resources/pom.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ - - - 4.0.0 - - \${groupId} - \${artifactId} - \${version} - jar - - \${artifactId} - - - - java.net - Java.net - https://maven.java.net/content/repositories/releases/ - - true - - - - netbeans - NetBeans - http://bits.netbeans.org/maven2/ - - - - - java.net - Java.net - https://maven.java.net/content/repositories/releases/ - - true - - - - - - UTF-8 - ${project.version} - ${bck2brwsr.version} - ${bck2brwsr.launcher.version} - MINIMAL - \${package.replace('.','/')}/index.html - - - - - org.apidesign.bck2brwsr - bck2brwsr-maven-plugin - \${bck2brwsr.launcher.version} - - - - brwsr - - - - - \${brwsr.startpage} - \${brwsr} - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.14.1 - - - \${brwsr} - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - true - lib/ - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.7 - - true - - - - - - - - org.testng - testng - 6.5.2 - test - - - org.apidesign.bck2brwsr - vmtest - \${bck2brwsr.version} - test - - - org.apidesign.html - net.java.html.json - \${net.java.html.version} - jar - - - - - fxbrwsr - - true - - - fxbrwsr - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher - true - lib/ - - - \${brwsr.startpage} - - - - - - maven-assembly-plugin - 2.4 - - - distro-assembly - package - - single - - - - src/main/assembly/fxbrwsr.xml - - - - - - - - - - org.apidesign.html - ko-fx - \${net.java.html.version} - - - org.apidesign.bck2brwsr - launcher.fx - \${bck2brwsr.launcher.version} - runtime - - - - - bck2brwsr - - - brwsr - bck2brwsr - - - - - - org.apidesign.bck2brwsr - bck2brwsr-maven-plugin - - - - j2js - - - - - \${project.build.directory}/bck2brwsr.js - \${bck2brwsr.obfuscationlevel} - - - - org.apache.maven.plugins - maven-compiler-plugin - - - netbeans.ignore.jdk.bootclasspath - - - - - maven-assembly-plugin - 2.4 - - - distro-assembly - package - - single - - - - src/main/assembly/bck2brwsr.xml - - - - - - - - - - org.apidesign.bck2brwsr - emul - \${bck2brwsr.version} - rt - - - org.apidesign.html - ko-bck2brwsr - \${net.java.html.version} - runtime - - - org.apidesign.bck2brwsr - launcher.http - \${bck2brwsr.launcher.version} - test - - - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml --- a/ko-archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ - - - - bck2brwsr - - zip - - public_html - - - false - runtime - lib - - *:jar - *:rt - - - - - - ${project.build.directory}/classes/${package.replace('.','/')}/ - - **/* - - - **/*.class - - / - - - - - ${project.build.directory}/${project.build.finalName}.jar - / - - - ${project.build.directory}/bck2brwsr.js - / - - - \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml --- a/ko-archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ - - - - fxbrwsr - - zip - - ${project.build.finalName}-fxbrwsr - - - false - runtime - lib - - - - - ${project.build.directory}/${project.build.finalName}.jar - / - - - \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/main/java/TwitterClient.java --- a/ko-archetype/src/main/resources/archetype-resources/src/main/java/TwitterClient.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -package ${package}; - -import java.util.Arrays; -import java.util.List; -import net.java.html.json.ComputedProperty; -import net.java.html.json.Function; -import net.java.html.json.Model; -import net.java.html.json.OnPropertyChange; -import net.java.html.json.OnReceive; -import net.java.html.json.Property; - -@Model(className="TwitterModel", properties={ - @Property(name="savedLists", type=Tweeters.class, array = true), - @Property(name="activeTweetersName", type=String.class), - @Property(name="activeTweeters", type=String.class, array = true), - @Property(name="userNameToAdd", type=String.class), - @Property(name="loading", type=boolean.class), - @Property(name="currentTweets", type=Tweet.class, array = true) -}) -public class TwitterClient { - @Model(className = "Tweeters", properties = { - @Property(name="name", type = String.class), - @Property(name="userNames", type = String.class, array = true) - }) - static class Twttrs { - } - @Model(className = "Tweet", properties = { - @Property(name = "from_user", type = String.class), - @Property(name = "from_user_id", type = int.class), - @Property(name = "profile_image_url", type = String.class), - @Property(name = "text", type = String.class), - @Property(name = "created_at", type = String.class), - }) - static final class Twt { - @ComputedProperty static String html(String text) { - StringBuilder sb = new StringBuilder(320); - for (int pos = 0;;) { - int http = text.indexOf("http", pos); - if (http == -1) { - sb.append(text.substring(pos)); - return sb.toString(); - } - int spc = text.indexOf(' ', http); - if (spc == -1) { - spc = text.length(); - } - sb.append(text.substring(pos, http)); - String url = text.substring(http, spc); - sb.append("").append(url).append(""); - pos = spc; - } - } - - @ComputedProperty static String userUrl(String from_user) { - return "http://twitter.com/" + from_user; - } - } - @Model(className = "TwitterQuery", properties = { - @Property(array = true, name = "results", type = Twt.class) - }) - public static final class TwttrQr { - } - - @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me") - static void queryTweets(TwitterModel page, TwitterQuery q) { - page.getCurrentTweets().clear(); - page.getCurrentTweets().addAll(q.getResults()); - page.setLoading(false); - } - - @OnPropertyChange("activeTweetersName") - static void changeTweetersList(TwitterModel model) { - Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName()); - model.getActiveTweeters().clear(); - model.getActiveTweeters().addAll(people.getUserNames()); - } - - @OnPropertyChange({ "activeTweeters", "activeTweetersCount" }) - static void refreshTweets(TwitterModel model) { - StringBuilder sb = new StringBuilder(); - sb.append("rpp=25&q="); - String sep = ""; - for (String p : model.getActiveTweeters()) { - sb.append(sep); - sb.append("from:"); - sb.append(p); - sep = " OR "; - } - model.setLoading(true); - model.queryTweets("http://search.twitter.com", sb.toString()); - } - - static { - final TwitterModel model = new TwitterModel(); - final List svdLst = model.getSavedLists(); - svdLst.add(newTweeters("API Design", "JaroslavTulach")); - svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson")); - svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu")); - svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka")); - svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror")); - - model.setActiveTweetersName("NetBeans"); - - model.applyBindings(); - } - - @ComputedProperty - static boolean hasUnsavedChanges(List activeTweeters, List savedLists, String activeTweetersName) { - Tweeters tw = findByName(savedLists, activeTweetersName); - if (activeTweeters == null) { - return false; - } - return !tw.getUserNames().equals(activeTweeters); - } - - @ComputedProperty - static int activeTweetersCount(List activeTweeters) { - return activeTweeters.size(); - } - - @ComputedProperty - static boolean userNameToAddIsValid( - String userNameToAdd, String activeTweetersName, List savedLists, List activeTweeters - ) { - return userNameToAdd != null && - userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") && - !activeTweeters.contains(userNameToAdd); - } - - @Function - static void deleteList(TwitterModel model) { - final List sl = model.getSavedLists(); - sl.remove(findByName(sl, model.getActiveTweetersName())); - if (sl.isEmpty()) { - final Tweeters t = new Tweeters(); - t.setName("New"); - sl.add(t); - } - model.setActiveTweetersName(sl.get(0).getName()); - } - - @Function - static void saveChanges(TwitterModel model) { - Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName()); - int indx = model.getSavedLists().indexOf(t); - if (indx != -1) { - t.setName(model.getActiveTweetersName()); - t.getUserNames().clear(); - t.getUserNames().addAll(model.getActiveTweeters()); - } - } - - @Function - static void addUser(TwitterModel model) { - String n = model.getUserNameToAdd(); - model.getActiveTweeters().add(n); - } - @Function - static void removeUser(String data, TwitterModel model) { - model.getActiveTweeters().remove(data); - } - - private static Tweeters findByName(List list, String name) { - for (Tweeters l : list) { - if (l.getName() != null && l.getName().equals(name)) { - return l; - } - } - return list.isEmpty() ? new Tweeters() : list.get(0); - } - - private static Tweeters newTweeters(String listName, String... userNames) { - Tweeters t = new Tweeters(); - t.setName(listName); - t.getUserNames().addAll(Arrays.asList(userNames)); - return t; - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/main/resources/index.html --- a/ko-archetype/src/main/resources/archetype-resources/src/main/resources/index.html Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ - - - - - - - - Bck2Brwsr's Twitter - - - - - - - -

Bck2Brwsr's Twitter

- -

- This code is based on original - knockout.js - Twitter example and - uses almost unmodified HTML page. It just changes the model. The model - is written in Java language with the help of - - Knockout/Java binding library - . The Java source code has about 180 lines and seems more - dense and shorter than the original JavaScript model. -

-

- The project has two profiles. Either it executes in real Java virtual - machine and renders using JavaFX's WebView (use fxbrwsr profile - - the default). It can also run directly in a browser via - Bck2Brwsr virtual machine - (use bck2brwsr profile). -

- -
-
-
- - - -
- -

Currently viewing user(s):

-
-
    -
  • - -
    -
  • -
-
- -
- - - -
-
-
-
Loading...
- - - - - -
- - -
-
-
-
- - - - - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/main/resources/twitterExample.css --- a/ko-archetype/src/main/resources/archetype-resources/src/main/resources/twitterExample.css Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - Copied from knockout.js Twitter example: - http://knockoutjs.com/examples/twitter.html -*/ - -.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; } -.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; } -.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; } -.tweets table { border-width: 0;} -.tweets tr { vertical-align: top; } -.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; } -.tweets img { width: 4em; } -.tweetInfo { color: Gray; font-size: 0.9em; } -.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; } -input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; } - -.listChooser select, .listChooser button { vertical-align:top; } -.listChooser select { width: 60%; font-size:1.2em; height:1.4em; } -.listChooser button { width: 19%; height:1.68em; float:right; } - -.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; } -.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; } -.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 } -.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; } -.currentUsers li div { padding: 0.6em; } -.currentUsers li:hover { background-color: #EEC; } - -.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; } -.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; } -.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; } - -.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; } diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java --- a/ko-archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -package ${package}; - -import org.apidesign.bck2brwsr.vmtest.BrwsrTest; -import org.apidesign.bck2brwsr.vmtest.HtmlFragment; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** Sometimes it is useful to run tests inside of the real browser. - * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest} - * and that is it. If your code references elements on the HTML page, - * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which - * will be made available on the page before your test starts. - */ -public class IntegrationTest { - - /** Write to testing code here. Use assert (but not TestNG's - * Assert, as TestNG is not compiled with target 1.6 yet). - */ - @HtmlFragment( - "

Put this snippet on the HTML page

\n" - ) - @BrwsrTest - public void runThisTestInABrowser() { - } - - @Factory - public static Object[] create() { - return VMTest.create(IntegrationTest.class); - } - -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/test/java/TwitterClientTest.java --- a/ko-archetype/src/main/resources/archetype-resources/src/test/java/TwitterClientTest.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package ${package}; - -import java.util.List; -import net.java.html.BrwsrCtx; -import net.java.html.json.Models; -import static org.testng.Assert.*; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -/** We can unit test the TwitterModel smoothly. - */ -public class TwitterClientTest { - private TwitterModel model; - - - @BeforeMethod - public void initModel() { - model = Models.bind(new TwitterModel(), BrwsrCtx.EMPTY); - } - - @Test public void testIsValidToAdd() { - model.setUserNameToAdd("Joe"); - Tweeters t = Models.bind(new Tweeters(), BrwsrCtx.EMPTY); - t.setName("test"); - model.getSavedLists().add(t); - model.setActiveTweetersName("test"); - - assertTrue(model.isUserNameToAddIsValid(), "Joe is OK"); - TwitterClient.addUser(model); - assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time"); - assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty"); - - List mod = model.getActiveTweeters(); - assertTrue(model.isHasUnsavedChanges(), "We have modifications"); - assertEquals(mod.size(), 1, "One element in the list"); - assertEquals(mod.get(0), "Joe", "Its name is Joe"); - - assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one"); - - TwitterClient.saveChanges(model); - assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save"); - - assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one"); - } - - @Test public void httpAtTheEnd() { - String res = TwitterClient.Twt.html("Ahoj http://kuk"); - assertEquals(res, "Ahoj http://kuk"); - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-archetype/src/main/resources/archetype-resources/src/test/java/TwitterProtocolTest.java --- a/ko-archetype/src/main/resources/archetype-resources/src/test/java/TwitterProtocolTest.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package ${package}; - -import org.apidesign.bck2brwsr.vmtest.BrwsrTest; -import org.apidesign.bck2brwsr.vmtest.Http; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -public class TwitterProtocolTest { - private TwitterModel page; - @Http(@Http.Resource( - path = "/search.json", - mimeType = "application/json", - parameters = {"callback"}, - content = "$0({\"completed_in\":0.04,\"max_id\":320055706885689344,\"max_id_str\"" - + ":\"320055706885689344\",\"page\":1,\"query\":\"from%3AJaroslavTulach\",\"refresh_url\":" - + "\"?since_id=320055706885689344&q=from%3AJaroslavTulach\"," - + "\"results\":[{\"created_at\":\"Fri, 05 Apr 2013 06:10:01 +0000\"," - + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":" - + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":320055706885689344," - + "\"id_str\":\"320055706885689344\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":" - + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" - + "\"@tom_enebo Amzng! Not that I would like #ruby, but I am really glad you guys stabilized the plugin + " - + "made it work in #netbeans 7.3! Gd wrk.\",\"to_user\":\"tom_enebo\",\"to_user_id\":14498747," - + "\"to_user_id_str\":\"14498747\",\"to_user_name\":\"tom_enebo\",\"in_reply_to_status_id\":319832359509839872," - + "\"in_reply_to_status_id_str\":\"319832359509839872\"},{\"created_at\":\"Thu, 04 Apr 2013 07:33:06 +0000\"," - + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":" - + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":319714227088678913," - + "\"id_str\":\"319714227088678913\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":" - + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" - + "\"RT @drkrab: At #erlangfactory @joerl: Frameworks grow in complexity until nobody can use them.\"}," - + "{\"created_at\":\"Tue, 02 Apr 2013 07:44:34 +0000\",\"from_user\":\"JaroslavTulach\"," - + "\"from_user_id\":420944648,\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\"," - + "\"geo\":null,\"id\":318992336145248256,\"id_str\":\"318992336145248256\",\"iso_language_code\":\"en\"," - + "\"metadata\":{\"result_type\":\"recent\"},\"profile_image_url\":" - + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" - + "\"Twitter renamed to twttr http:\\/\\/t.co\\/tqaN4T1xlZ - good, I don't have to rename #bck2brwsr!\"}," - + "{\"created_at\":\"Sun, 31 Mar 2013 03:52:04 +0000\",\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648," - + "\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null," - + "\"id\":318209051223789568,\"id_str\":\"318209051223789568\",\"iso_language_code\":\"en\",\"metadata\":" - + "{\"result_type\":\"recent\"},\"profile_image_url\":" - + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" - + "\"Math proofs without words. Ingenious: http:\\/\\/t.co\\/sz7yVbfpGw\"}],\"results_per_page\":100," - + "\"since_id\":0,\"since_id_str\":\"0\"})" - )) - @BrwsrTest public void readFromTwttr() throws InterruptedException { - if (page == null) { - page = new TwitterModel(); - page.applyBindings(); - page.queryTweets("", "q=xyz"); - } - - if (page.getCurrentTweets().isEmpty()) { - throw new InterruptedException(); - } - - assert 4 == page.getCurrentTweets().size() : "Four tweets: " + page.getCurrentTweets(); - - String firstDate = page.getCurrentTweets().get(0).getCreated_at(); - assert "Fri, 05 Apr 2013 06:10:01 +0000".equals(firstDate) : "Date is OK: " + firstDate; - } - - @Factory public static Object[] create() { - return VMTest.create(TwitterProtocolTest.class); - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-bck2brwsr/pom.xml --- a/ko-bck2brwsr/pom.xml Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ - - - 4.0.0 - - org.apidesign - html - 0.4-SNAPSHOT - - org.apidesign.html - ko-bck2brwsr - 0.4-SNAPSHOT - Knockout.b2b - http://maven.apache.org - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-javadoc-plugin - - false - - - - - - - org.testng - testng - test - - - junit - junit - - - - - org.netbeans.api - org-openide-util-lookup - provided - - - org.apidesign.bck2brwsr - emul - ${bck2brwsr.version} - rt - jar - compile - - - org.apidesign.bck2brwsr - vm4brwsr - ${bck2brwsr.version} - jar - test - - - org.apidesign.bck2brwsr - vmtest - ${bck2brwsr.version} - test - - - org.apidesign.bck2brwsr - launcher.http - ${bck2brwsr.launcher.version} - test - - - org.apidesign.html - net.java.html.json - 0.4-SNAPSHOT - - - org.apidesign.html - net.java.html.json.tck - 0.4-SNAPSHOT - test - - - org.apidesign.bck2brwsr - core - ${bck2brwsr.version} - jar - - - diff -r 7189e9abb928 -r 73c0973e8e0a ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxImpl.java --- a/ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxImpl.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.ko2brwsr; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import net.java.html.BrwsrCtx; -import org.apidesign.html.context.spi.Contexts; -import org.apidesign.html.json.spi.FunctionBinding; -import org.apidesign.html.json.spi.JSONCall; -import org.apidesign.html.json.spi.PropertyBinding; -import org.apidesign.html.json.spi.Technology; -import org.apidesign.html.json.spi.Transfer; - -/** - * - * @author Jaroslav Tulach - */ -final class BrwsrCtxImpl implements Technology, Transfer { - private BrwsrCtxImpl() {} - - public static final BrwsrCtxImpl DEFAULT = new BrwsrCtxImpl(); - - @Override - public void extract(Object obj, String[] props, Object[] values) { - ConvertTypes.extractJSON(obj, props, values); - } - - @Override - public void loadJSON(final JSONCall call) { - class R implements Runnable { - Object[] arr = { null }; - @Override - public void run() { - call.notifySuccess(arr[0]); - } - } - R r = new R(); - if (call.isJSONP()) { - String me = ConvertTypes.createJSONP(r.arr, r); - ConvertTypes.loadJSONP(call.composeURL(me), me); - } else { - String data = null; - if (call.isDoOutput()) { - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - call.writeData(bos); - data = new String(bos.toByteArray(), "UTF-8"); - } catch (IOException ex) { - call.notifyError(ex); - } - } - ConvertTypes.loadJSON(call.composeURL(null), r.arr, r, call.getMethod(), data); - } - } - - @Override - public Object wrapModel(Object model) { - return model; - } - - @Override - public void bind(PropertyBinding b, Object model, Object data) { - Knockout.bind(data, b, b.getPropertyName(), - "getValue__Ljava_lang_Object_2", - b.isReadOnly() ? null : "setValue__VLjava_lang_Object_2", - false, false - ); - } - - @Override - public void valueHasMutated(Object data, String propertyName) { - Knockout.valueHasMutated(data, propertyName); - } - - @Override - public void expose(FunctionBinding fb, Object model, Object d) { - Knockout.expose(d, fb, fb.getFunctionName(), "call__VLjava_lang_Object_2Ljava_lang_Object_2"); - } - - @Override - public void applyBindings(Object data) { - Knockout.applyBindings(data); - } - - @Override - public Object wrapArray(Object[] arr) { - return arr; - } - - @Override - public M toModel(Class modelClass, Object data) { - return modelClass.cast(data); - } - - @Override - public Object toJSON(InputStream is) throws IOException { - StringBuilder sb = new StringBuilder(); - InputStreamReader r = new InputStreamReader(is); - for (;;) { - int ch = r.read(); - if (ch == -1) { - break; - } - sb.append((char)ch); - } - return ConvertTypes.parse(sb.toString()); - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxPrvdr.java --- a/ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxPrvdr.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.ko2brwsr; - -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.html.context.spi.Contexts; -import org.apidesign.html.json.spi.Technology; -import org.apidesign.html.json.spi.Transfer; -import org.openide.util.lookup.ServiceProvider; - -/** This is an implementation package - just - * include its JAR on classpath and use official {@link Context} API - * to access the functionality. - *

- * Provides binding between models and - * Bck2Brwsr VM. - * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it. - * - * @author Jaroslav Tulach - */ -@ServiceProvider(service = Contexts.Provider.class) -public final class BrwsrCtxPrvdr implements Contexts.Provider { - - @Override - public void fillContext(Contexts.Builder context, Class requestor) { - if (bck2BrwsrVM()) { - context.register(Technology.class, BrwsrCtxImpl.DEFAULT, 50). - register(Transfer.class, BrwsrCtxImpl.DEFAULT, 50); - } - } - - @JavaScriptBody(args = { }, body = "return true;") - private static boolean bck2BrwsrVM() { - return false; - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/ConvertTypes.java --- a/ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/ConvertTypes.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.ko2brwsr; - -import org.apidesign.bck2brwsr.core.JavaScriptBody; - -/** - * - * @author Jaroslav Tulach - */ -final class ConvertTypes { - ConvertTypes() { - } - - public static String toString(Object object, String property) { - Object ret = getProperty(object, property); - return ret == null ? null : ret.toString(); - } - - public static double toDouble(Object object, String property) { - Object ret = getProperty(object, property); - return ret instanceof Number ? ((Number)ret).doubleValue() : Double.NaN; - } - - public static int toInt(Object object, String property) { - Object ret = getProperty(object, property); - return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE; - } - - public static T toModel(Class modelClass, Object object, String property) { - Object ret = getProperty(object, property); - if (ret == null || modelClass.isInstance(ret)) { - return modelClass.cast(ret); - } - throw new IllegalStateException("Value " + ret + " is not of type " + modelClass); - } - - public static String toJSON(Object value) { - if (value == null) { - return "null"; - } - if (value instanceof Enum) { - value = value.toString(); - } - if (value instanceof String) { - return '"' + - ((String)value). - replace("\"", "\\\""). - replace("\n", "\\n"). - replace("\r", "\\r"). - replace("\t", "\\t") - + '"'; - } - return value.toString(); - } - - @JavaScriptBody(args = { "object", "property" }, - body = "if (property === null) return object;\n" - + "var p = object[property]; return p ? p : null;" - ) - private static Object getProperty(Object object, String property) { - return null; - } - - public static String createJSONP(Object[] jsonResult, Runnable whenDone) { - int h = whenDone.hashCode(); - String name; - for (;;) { - name = "jsonp" + Integer.toHexString(h); - if (defineIfUnused(name, jsonResult, whenDone)) { - return name; - } - h++; - } - } - - @JavaScriptBody(args = { "name", "arr", "run" }, body = - "if (window[name]) return false;\n " - + "window[name] = function(data) {\n " - + " delete window[name];\n" - + " var el = window.document.getElementById(name);\n" - + " el.parentNode.removeChild(el);\n" - + " arr[0] = data;\n" - + " run.run__V();\n" - + "};\n" - + "return true;\n" - ) - private static boolean defineIfUnused(String name, Object[] arr, Runnable run) { - return true; - } - - @JavaScriptBody(args = { "s" }, body = "return eval('(' + s + ')');") - static Object parse(String s) { - return s; - } - - @JavaScriptBody(args = { "url", "arr", "callback", "method", "data" }, body = "" - + "var request = new XMLHttpRequest();\n" - + "if (!method) method = 'GET';\n" - + "request.open(method, url, true);\n" - + "request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n" - + "request.onreadystatechange = function() {\n" - + " if (this.readyState!==4) return;\n" - + " try {\n" - + " arr[0] = eval('(' + this.response + ')');\n" - + " } catch (error) {;\n" - + " arr[0] = this.response;\n" - + " }\n" - + " callback.run__V();\n" - + "};" - + "if (data) request.send(data);" - + "else request.send();" - ) - static void loadJSON( - String url, Object[] jsonResult, Runnable whenDone, String method, String data - ) { - } - - @JavaScriptBody(args = { "url", "jsonp" }, body = - "var scrpt = window.document.createElement('script');\n " - + "scrpt.setAttribute('src', url);\n " - + "scrpt.setAttribute('id', jsonp);\n " - + "scrpt.setAttribute('type', 'text/javascript');\n " - + "var body = document.getElementsByTagName('body')[0];\n " - + "body.appendChild(scrpt);\n" - ) - static void loadJSONP(String url, String jsonp) { - - } - - public static void extractJSON(Object jsonObject, String[] props, Object[] values) { - for (int i = 0; i < props.length; i++) { - values[i] = getProperty(jsonObject, props[i]); - } - } - -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/Knockout.java --- a/ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/Knockout.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.ko2brwsr; - -import java.lang.reflect.Method; -import java.util.List; -import org.apidesign.bck2brwsr.core.ExtraJavaScript; -import org.apidesign.bck2brwsr.core.JavaScriptBody; - -/** Provides binding between models and bck2brwsr VM. - * - * @author Jaroslav Tulach - */ -@ExtraJavaScript(resource = "/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js") -final class Knockout { - /** used by tests */ - static Knockout next; - private final Object model; - - Knockout(Object model) { - this.model = model == null ? this : model; - } - - public static Knockout applyBindings( - Object model, String[] propsGettersAndSetters, - String[] methodsAndSignatures - ) { - applyImpl(propsGettersAndSetters, model.getClass(), model, model, methodsAndSignatures); - return new Knockout(model); - } - public static Knockout applyBindings( - Class modelClass, M model, String[] propsGettersAndSetters, - String[] methodsAndSignatures - ) { - Knockout bindings = next; - next = null; - if (bindings == null) { - bindings = new Knockout(null); - } - applyImpl(propsGettersAndSetters, modelClass, bindings, model, methodsAndSignatures); - applyBindings(bindings); - return bindings; - } - - public void valueHasMutated(String prop) { - valueHasMutated(model, prop); - } - @JavaScriptBody(args = { "self", "prop" }, body = - "var p = self[prop]; if (p) p.valueHasMutated();" - ) - public static void valueHasMutated(Object self, String prop) { - } - - - @JavaScriptBody(args = { "id", "ev" }, body = "ko.utils.triggerEvent(window.document.getElementById(id), ev.substring(2));") - public static void triggerEvent(String id, String ev) { - } - - @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive", "array" }, body = - "var bnd = {\n" - + " 'read': function() {\n" - + " var v = model[getter]();\n" - + " if (array) v = v.koArray(); else if (v !== null) v = v.valueOf();\n" - + " return v;\n" - + " },\n" - + " 'owner': bindings\n" - + "};\n" - + "if (setter != null) {\n" - + " bnd['write'] = function(val) {\n" - + " var v = val === null ? null : val.valueOf();" - + " model[setter](v);\n" - + " };\n" - + "}\n" - + "bindings[prop] = ko['computed'](bnd);" - ) - static void bind( - Object bindings, Object model, String prop, String getter, String setter, boolean primitive, boolean array - ) { - } - - @JavaScriptBody(args = { "bindings", "model", "prop", "sig" }, body = - "bindings[prop] = function(data, ev) { model[sig](data, ev); };" - ) - static void expose( - Object bindings, Object model, String prop, String sig - ) { - } - - @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);") - static void applyBindings(Object bindings) {} - - private static void applyImpl( - String[] propsGettersAndSetters, - Class modelClass, - Object bindings, - Object model, - String[] methodsAndSignatures - ) throws IllegalStateException, SecurityException { - for (int i = 0; i < propsGettersAndSetters.length; i += 4) { - try { - Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]); - bind(bindings, model, propsGettersAndSetters[i], - propsGettersAndSetters[i + 1], - propsGettersAndSetters[i + 2], - getter.getReturnType().isPrimitive(), - List.class.isAssignableFrom(getter.getReturnType())); - } catch (NoSuchMethodException ex) { - throw new IllegalStateException(ex.getMessage()); - } - } - for (int i = 0; i < methodsAndSignatures.length; i += 2) { - expose( - bindings, model, methodsAndSignatures[i], methodsAndSignatures[i + 1]); - } - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko-bck2brwsr/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js --- a/ko-bck2brwsr/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3614 +0,0 @@ -/* - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -// Knockout JavaScript library v2.2.1 -// (c) Steven Sanderson - http://knockoutjs.com/ -// License: MIT (http://www.opensource.org/licenses/mit-license.php) - -(function(){ -var DEBUG=true; -(function(window,document,navigator,jQuery,undefined){ -!function(factory) { - // Support three module loading scenarios - if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { - // [1] CommonJS/Node.js - var target = module['exports'] || exports; // module.exports is for Node.js - factory(target); - } else if (typeof define === 'function' && define['amd']) { - // [2] AMD anonymous module - define(['exports'], factory); - } else { - // [3] No module loader (plain "); - }; - - if (jQueryTmplVersion > 0) { - jQuery['tmpl']['tag']['ko_code'] = { - open: "__.push($1 || '');" - }; - jQuery['tmpl']['tag']['ko_with'] = { - open: "with($1) {", - close: "} " - }; - } - }; - - ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine(); - - // Use this one by default *only if jquery.tmpl is referenced* - var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine(); - if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0) - ko.setTemplateEngine(jqueryTmplTemplateEngineInstance); - - ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine); -})(); -}); -})(window,document,navigator,window["jQuery"]); -})(); \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko-bck2brwsr/src/test/java/org/apidesign/html/ko2brwsr/Bck2BrwsrKnockoutTest.java --- a/ko-bck2brwsr/src/test/java/org/apidesign/html/ko2brwsr/Bck2BrwsrKnockoutTest.java Mon Jun 24 17:49:27 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/** - * HTML via Java(tm) Language Bindings - * Copyright (C) 2013 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. apidesign.org - * designates this particular file as subject to the - * "Classpath" exception as provided by apidesign.org - * in the License file that accompanied this code. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException - */ -package org.apidesign.html.ko2brwsr; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLConnection; -import java.util.Map; -import net.java.html.BrwsrCtx; -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.apidesign.html.context.spi.Contexts; -import org.apidesign.html.json.spi.Technology; -import org.apidesign.html.json.spi.Transfer; -import org.apidesign.html.json.tck.KOTest; -import org.apidesign.html.json.tck.KnockoutTCK; -import org.openide.util.lookup.ServiceProvider; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -@ServiceProvider(service = KnockoutTCK.class) -public final class Bck2BrwsrKnockoutTest extends KnockoutTCK { - @Factory public static Object[] create() { - return VMTest.newTests(). - withClasses(testClasses()). - withLaunchers("bck2brwsr"). - withTestAnnotation(KOTest.class). - build(); - } - - @Override - public BrwsrCtx createContext() { - return Contexts.newBuilder(). - register(Transfer.class, BrwsrCtxImpl.DEFAULT, 9). - register(Technology.class, BrwsrCtxImpl.DEFAULT, 9).build(); - } - - - - @Override - public Object createJSON(Map values) { - Object json = createJSON(); - - for (Map.Entry entry : values.entrySet()) { - putValue(json, entry.getKey(), entry.getValue()); - } - return json; - } - - @JavaScriptBody(args = {}, body = "return new Object();") - private static native Object createJSON(); - - @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;") - private static native void putValue(Object json, String key, Object value); - - @Override - public Object executeScript(String script, Object[] arguments) { - return execScript(script, arguments); - } - - @JavaScriptBody(args = { "s", "args" }, body = - "var f = new Function(s); return f.apply(null, args);" - ) - private static native Object execScript(String s, Object[] arguments); - - @JavaScriptBody(args = { }, body = - "var h;" - + "if (!!window && !!window.location && !!window.location.href)\n" - + " h = window.location.href;\n" - + "else " - + " h = null;" - + "return h;\n" - ) - private static native String findBaseURL(); - - @Override - public URI prepareURL(String content, String mimeType, String[] parameters) { - try { - final URL baseURL = new URL(findBaseURL()); - StringBuilder sb = new StringBuilder(); - sb.append("/dynamic?mimeType=").append(mimeType); - for (int i = 0; i < parameters.length; i++) { - sb.append("¶m" + i).append("=").append(parameters[i]); - } - String mangle = content.replace("\n", "%0a") - .replace("\"", "\\\"").replace(" ", "%20"); - sb.append("&content=").append(mangle); - - URL query = new URL(baseURL, sb.toString()); - String uri = (String) query.getContent(new Class[] { String.class }); - URI connectTo = new URI(uri.trim()); - return connectTo; - } catch (IOException ex) { - throw new IllegalStateException(ex); - } catch (URISyntaxException ex) { - throw new IllegalStateException(ex); - } - } -} diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype-test/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype-test/pom.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,48 @@ + + + 4.0.0 + + org.apidesign + html + 0.4-SNAPSHOT + + org.apidesign.html + ko-archetype-test + 0.4-SNAPSHOT + Knockout 4 Java Archetype Test + http://maven.apache.org + Verifies the Knockout & net.java.html.json archetype behaves properly. + + UTF-8 + + + + ${project.groupId} + knockout4j-archetype + 0.4-SNAPSHOT + + + org.testng + testng + test + + + org.apache.maven.shared + maven-verifier + 1.4 + test + + + ${project.groupId} + ko-fx + ${project.version} + provided + + + ${project.groupId} + ko-bck2brwsr + ${project.version} + provided + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,139 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.archetype.test; + +import java.io.IOException; +import java.net.URL; +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFactoryConfigurationException; +import org.testng.annotations.Test; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** + * + * @author Jaroslav Tulach + */ +public class ArchetypeVersionTest { + private String version; + + public ArchetypeVersionTest() { + } + + @BeforeClass public void readCurrentVersion() throws Exception { + version = findCurrentVersion(); + assertFalse(version.isEmpty(), "There should be some version string"); + } + + + @Test public void testComparePomDepsVersions() throws Exception { + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); + URL r = l.getResource("archetype-resources/pom.xml"); + assertNotNull(r, "Archetype pom found"); + + final XPathFactory fact = XPathFactory.newInstance(); + XPathExpression xp2 = fact.newXPath().compile( + "//properties/net.java.html.version/text()" + ); + + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); + String arch = (String) xp2.evaluate(dom, XPathConstants.STRING); + + assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version"); + } + + @Test public void testCheckLauncher() throws Exception { + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); + URL r = l.getResource("archetype-resources/pom.xml"); + assertNotNull(r, "Archetype pom found"); + + final XPathFactory fact = XPathFactory.newInstance(); + XPathExpression xp2 = fact.newXPath().compile( + "//properties/bck2brwsr.launcher.version/text()" + ); + + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); + String arch = (String) xp2.evaluate(dom, XPathConstants.STRING); + + + assertTrue(arch.matches("[0-9\\.]+"), "launcher version seems valid: " + arch); + } + + @Test public void testCheckBck2Brwsr() throws Exception { + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); + URL r = l.getResource("archetype-resources/pom.xml"); + assertNotNull(r, "Archetype pom found"); + + final XPathFactory fact = XPathFactory.newInstance(); + XPathExpression xp2 = fact.newXPath().compile( + "//properties/bck2brwsr.version/text()" + ); + + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); + String arch = (String) xp2.evaluate(dom, XPathConstants.STRING); + + assertTrue(arch.matches("[0-9\\.]+"), "bck2brwsr version seems valid: " + arch); + } + + @Test public void testNbActions() throws Exception { + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); + URL r = l.getResource("archetype-resources/nbactions.xml"); + assertNotNull(r, "Archetype nb file found"); + + final XPathFactory fact = XPathFactory.newInstance(); + XPathExpression xp2 = fact.newXPath().compile( + "//goal/text()" + ); + + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream()); + NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET); + + for (int i = 0; i < goals.getLength(); i++) { + String s = goals.item(i).getTextContent(); + if (s.contains("apidesign")) { + assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s); + } + } + } + + static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException { + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader(); + URL u = l.getResource("META-INF/maven/org.apidesign.html/knockout4j-archetype/pom.xml"); + assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path")); + + final XPathFactory fact = XPathFactory.newInstance(); + fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + XPathExpression xp = fact.newXPath().compile("project/version/text()"); + + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream()); + return xp.evaluate(dom); + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,119 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.archetype.test; + +import java.io.File; +import java.util.Properties; +import java.util.zip.ZipFile; +import org.apache.maven.it.Verifier; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * + * @author Jaroslav Tulach + */ +public class VerifyArchetypeTest { + @Test public void fxBrwsrCompiles() throws Exception { + final File dir = new File("target/tests/fxcompile/").getAbsoluteFile(); + generateFromArchetype(dir); + + File created = new File(dir, "o-a-test"); + assertTrue(created.isDirectory(), "Project created"); + assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there"); + + Verifier v = new Verifier(created.getAbsolutePath()); + v.executeGoal("verify"); + + v.verifyErrorFreeLog(); + + for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) { + if (l.contains("j2js")) { + fail("No pre-compilaton:\n" + l); + } + } + + v.verifyTextInLog("org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher"); + v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-fxbrwsr.zip"); + } + + @Test public void bck2BrwsrCompiles() throws Exception { + final File dir = new File("target/tests/b2bcompile/").getAbsoluteFile(); + generateFromArchetype(dir); + + File created = new File(dir, "o-a-test"); + assertTrue(created.isDirectory(), "Project created"); + assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there"); + + Verifier v = new Verifier(created.getAbsolutePath()); + Properties sysProp = v.getSystemProperties(); + if (Boolean.getBoolean("java.awt.headless")) { + sysProp.put("java.awt.headless", "true"); + } + v.addCliOption("-Pbck2brwsr"); + v.executeGoal("verify"); + + v.verifyErrorFreeLog(); + + // does pre-compilation to JavaScript + v.verifyTextInLog("j2js"); + // uses Bck2BrwsrLauncher + v.verifyTextInLog("BaseHTTPLauncher stopServerAndBrwsr"); + // building zip: + v.verifyTextInLog("b2bcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-bck2brwsr.zip"); + + for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) { + if (l.contains("fxbrwsr")) { + fail("No fxbrwsr:\n" + l); + } + } + + File zip = new File(new File(created, "target"), "o-a-test-1.0-SNAPSHOT-bck2brwsr.zip"); + assertTrue(zip.isFile(), "Zip file with website was created"); + + ZipFile zf = new ZipFile(zip); + assertNotNull(zf.getEntry("public_html/index.html"), "index.html found"); + assertNotNull(zf.getEntry("public_html/twitterExample.css"), "css file found"); + + } + + private Verifier generateFromArchetype(final File dir, String... params) throws Exception { + Verifier v = new Verifier(dir.getAbsolutePath()); + v.setAutoclean(false); + v.setLogFileName("generate.log"); + v.deleteDirectory(""); + dir.mkdirs(); + Properties sysProp = v.getSystemProperties(); + sysProp.put("groupId", "org.apidesign.test"); + sysProp.put("artifactId", "o-a-test"); + sysProp.put("package", "org.apidesign.test.oat"); + sysProp.put("archetypeGroupId", "org.apidesign.html"); + sysProp.put("archetypeArtifactId", "knockout4j-archetype"); + sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion()); + + for (String p : params) { + v.addCliOption(p); + } + v.executeGoal("archetype:generate"); + v.verifyErrorFreeLog(); + return v; + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/pom.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,58 @@ + + + 4.0.0 + + html + org.apidesign + 0.4-SNAPSHOT + + org.apidesign.html + knockout4j-archetype + 0.4-SNAPSHOT + jar + Knockout 4 Java Maven Archetype + + HTML page with Knockout.js bindings driven by application model + written in Java. Use your favorite language to code. Use + HTML as a lightweight rendering toolkit. Deploy using JavaFX or + bck2brwsr virtual machine. + + + + + src/main/resources + true + + **/pom.xml + + + + src/main/resources + false + + **/pom.xml + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + \ + 1.6 + + + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/java/org/apidesign/html/archetype/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/java/org/apidesign/html/archetype/package-info.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,21 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.archetype; diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,44 @@ + + + + + src/main/java + + **/*.java + + + + src/main/resources + + **/*.xhtml + **/*.html + **/*.css + + + + src/test/java + + **/*Test.java + + + + src/main/assembly + + **/*.xml + + + + + + nbactions*.xml + + + + assembly + + fxbrwsr-assembly.xml + bck2brwsr-assembly.xml + + + + \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/nbactions-bck2brwsr.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions-bck2brwsr.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,14 @@ + + + + run + + package + bck2brwsr:brwsr + + + true + NONE + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/nbactions-fxbrwsr.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions-fxbrwsr.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,20 @@ + + + + run + + process-classes + bck2brwsr:brwsr + + + + debug + + process-classes + bck2brwsr:brwsr + + + maven + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/nbactions.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,20 @@ + + + + run + + process-classes + bck2brwsr:brwsr + + + + debug + + process-classes + bck2brwsr:brwsr + + + maven + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/pom.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,266 @@ + + + 4.0.0 + + \${groupId} + \${artifactId} + \${version} + jar + + \${artifactId} + + + + java.net + Java.net + https://maven.java.net/content/repositories/releases/ + + true + + + + netbeans + NetBeans + http://bits.netbeans.org/maven2/ + + + + + java.net + Java.net + https://maven.java.net/content/repositories/releases/ + + true + + + + + + UTF-8 + ${project.version} + ${bck2brwsr.version} + ${bck2brwsr.launcher.version} + MINIMAL + \${package.replace('.','/')}/index.html + + + + + org.apidesign.bck2brwsr + bck2brwsr-maven-plugin + \${bck2brwsr.launcher.version} + + + + brwsr + + + + + \${brwsr.startpage} + \${brwsr} + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.14.1 + + + \${brwsr} + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + true + lib/ + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.7 + + true + + + + + + + + org.testng + testng + 6.5.2 + test + + + org.apidesign.bck2brwsr + vmtest + \${bck2brwsr.version} + test + + + org.apidesign.html + net.java.html.json + \${net.java.html.version} + jar + + + + + fxbrwsr + + true + + + fxbrwsr + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher + true + lib/ + + + \${brwsr.startpage} + + + + + + maven-assembly-plugin + 2.4 + + + distro-assembly + package + + single + + + + src/main/assembly/fxbrwsr.xml + + + + + + + + + + org.apidesign.html + ko-fx + \${net.java.html.version} + + + org.apidesign.bck2brwsr + launcher.fx + \${bck2brwsr.launcher.version} + runtime + + + + + bck2brwsr + + + brwsr + bck2brwsr + + + + + + org.apidesign.bck2brwsr + bck2brwsr-maven-plugin + + + + j2js + + + + + \${project.build.directory}/bck2brwsr.js + \${bck2brwsr.obfuscationlevel} + + + + org.apache.maven.plugins + maven-compiler-plugin + + + netbeans.ignore.jdk.bootclasspath + + + + + maven-assembly-plugin + 2.4 + + + distro-assembly + package + + single + + + + src/main/assembly/bck2brwsr.xml + + + + + + + + + + org.apidesign.bck2brwsr + emul + \${bck2brwsr.version} + rt + + + org.apidesign.html + ko-bck2brwsr + \${net.java.html.version} + runtime + + + org.apidesign.bck2brwsr + launcher.http + \${bck2brwsr.launcher.version} + test + + + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,43 @@ + + + + bck2brwsr + + zip + + public_html + + + false + runtime + lib + + *:jar + *:rt + + + + + + ${project.build.directory}/classes/${package.replace('.','/')}/ + + **/* + + + **/*.class + + / + + + + + ${project.build.directory}/${project.build.finalName}.jar + / + + + ${project.build.directory}/bck2brwsr.js + / + + + \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,23 @@ + + + + fxbrwsr + + zip + + ${project.build.finalName}-fxbrwsr + + + false + runtime + lib + + + + + ${project.build.directory}/${project.build.finalName}.jar + / + + + \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/main/java/TwitterClient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/TwitterClient.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,178 @@ +package ${package}; + +import java.util.Arrays; +import java.util.List; +import net.java.html.json.ComputedProperty; +import net.java.html.json.Function; +import net.java.html.json.Model; +import net.java.html.json.OnPropertyChange; +import net.java.html.json.OnReceive; +import net.java.html.json.Property; + +@Model(className="TwitterModel", properties={ + @Property(name="savedLists", type=Tweeters.class, array = true), + @Property(name="activeTweetersName", type=String.class), + @Property(name="activeTweeters", type=String.class, array = true), + @Property(name="userNameToAdd", type=String.class), + @Property(name="loading", type=boolean.class), + @Property(name="currentTweets", type=Tweet.class, array = true) +}) +public class TwitterClient { + @Model(className = "Tweeters", properties = { + @Property(name="name", type = String.class), + @Property(name="userNames", type = String.class, array = true) + }) + static class Twttrs { + } + @Model(className = "Tweet", properties = { + @Property(name = "from_user", type = String.class), + @Property(name = "from_user_id", type = int.class), + @Property(name = "profile_image_url", type = String.class), + @Property(name = "text", type = String.class), + @Property(name = "created_at", type = String.class), + }) + static final class Twt { + @ComputedProperty static String html(String text) { + StringBuilder sb = new StringBuilder(320); + for (int pos = 0;;) { + int http = text.indexOf("http", pos); + if (http == -1) { + sb.append(text.substring(pos)); + return sb.toString(); + } + int spc = text.indexOf(' ', http); + if (spc == -1) { + spc = text.length(); + } + sb.append(text.substring(pos, http)); + String url = text.substring(http, spc); + sb.append("").append(url).append(""); + pos = spc; + } + } + + @ComputedProperty static String userUrl(String from_user) { + return "http://twitter.com/" + from_user; + } + } + @Model(className = "TwitterQuery", properties = { + @Property(array = true, name = "results", type = Twt.class) + }) + public static final class TwttrQr { + } + + @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me") + static void queryTweets(TwitterModel page, TwitterQuery q) { + page.getCurrentTweets().clear(); + page.getCurrentTweets().addAll(q.getResults()); + page.setLoading(false); + } + + @OnPropertyChange("activeTweetersName") + static void changeTweetersList(TwitterModel model) { + Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName()); + model.getActiveTweeters().clear(); + model.getActiveTweeters().addAll(people.getUserNames()); + } + + @OnPropertyChange({ "activeTweeters", "activeTweetersCount" }) + static void refreshTweets(TwitterModel model) { + StringBuilder sb = new StringBuilder(); + sb.append("rpp=25&q="); + String sep = ""; + for (String p : model.getActiveTweeters()) { + sb.append(sep); + sb.append("from:"); + sb.append(p); + sep = " OR "; + } + model.setLoading(true); + model.queryTweets("http://search.twitter.com", sb.toString()); + } + + static { + final TwitterModel model = new TwitterModel(); + final List svdLst = model.getSavedLists(); + svdLst.add(newTweeters("API Design", "JaroslavTulach")); + svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson")); + svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu")); + svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka")); + svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror")); + + model.setActiveTweetersName("NetBeans"); + + model.applyBindings(); + } + + @ComputedProperty + static boolean hasUnsavedChanges(List activeTweeters, List savedLists, String activeTweetersName) { + Tweeters tw = findByName(savedLists, activeTweetersName); + if (activeTweeters == null) { + return false; + } + return !tw.getUserNames().equals(activeTweeters); + } + + @ComputedProperty + static int activeTweetersCount(List activeTweeters) { + return activeTweeters.size(); + } + + @ComputedProperty + static boolean userNameToAddIsValid( + String userNameToAdd, String activeTweetersName, List savedLists, List activeTweeters + ) { + return userNameToAdd != null && + userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") && + !activeTweeters.contains(userNameToAdd); + } + + @Function + static void deleteList(TwitterModel model) { + final List sl = model.getSavedLists(); + sl.remove(findByName(sl, model.getActiveTweetersName())); + if (sl.isEmpty()) { + final Tweeters t = new Tweeters(); + t.setName("New"); + sl.add(t); + } + model.setActiveTweetersName(sl.get(0).getName()); + } + + @Function + static void saveChanges(TwitterModel model) { + Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName()); + int indx = model.getSavedLists().indexOf(t); + if (indx != -1) { + t.setName(model.getActiveTweetersName()); + t.getUserNames().clear(); + t.getUserNames().addAll(model.getActiveTweeters()); + } + } + + @Function + static void addUser(TwitterModel model) { + String n = model.getUserNameToAdd(); + model.getActiveTweeters().add(n); + } + @Function + static void removeUser(String data, TwitterModel model) { + model.getActiveTweeters().remove(data); + } + + private static Tweeters findByName(List list, String name) { + for (Tweeters l : list) { + if (l.getName() != null && l.getName().equals(name)) { + return l; + } + } + return list.isEmpty() ? new Tweeters() : list.get(0); + } + + private static Tweeters newTweeters(String listName, String... userNames) { + Tweeters t = new Tweeters(); + t.setName(listName); + t.getUserNames().addAll(Arrays.asList(userNames)); + return t; + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/main/resources/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/resources/index.html Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,90 @@ + + + + + + + + Bck2Brwsr's Twitter + + + + + + + +

Bck2Brwsr's Twitter

+ +

+ This code is based on original + knockout.js + Twitter example and + uses almost unmodified HTML page. It just changes the model. The model + is written in Java language with the help of + + Knockout/Java binding library + . The Java source code has about 180 lines and seems more + dense and shorter than the original JavaScript model. +

+

+ The project has two profiles. Either it executes in real Java virtual + machine and renders using JavaFX's WebView (use fxbrwsr profile + - the default). It can also run directly in a browser via + Bck2Brwsr virtual machine + (use bck2brwsr profile). +

+ +
+
+
+ + + +
+ +

Currently viewing user(s):

+
+
    +
  • + +
    +
  • +
+
+ +
+ + + +
+
+
+
Loading...
+ + + + + +
+ + +
+
+
+
+ + + + + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/main/resources/twitterExample.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/resources/twitterExample.css Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,32 @@ +/* + Copied from knockout.js Twitter example: + http://knockoutjs.com/examples/twitter.html +*/ + +.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; } +.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; } +.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; } +.tweets table { border-width: 0;} +.tweets tr { vertical-align: top; } +.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; } +.tweets img { width: 4em; } +.tweetInfo { color: Gray; font-size: 0.9em; } +.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; } +input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; } + +.listChooser select, .listChooser button { vertical-align:top; } +.listChooser select { width: 60%; font-size:1.2em; height:1.4em; } +.listChooser button { width: 19%; height:1.68em; float:right; } + +.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; } +.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; } +.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 } +.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; } +.currentUsers li div { padding: 0.6em; } +.currentUsers li:hover { background-color: #EEC; } + +.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; } +.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; } +.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; } + +.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; } diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,31 @@ +package ${package}; + +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.HtmlFragment; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** Sometimes it is useful to run tests inside of the real browser. + * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest} + * and that is it. If your code references elements on the HTML page, + * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which + * will be made available on the page before your test starts. + */ +public class IntegrationTest { + + /** Write to testing code here. Use assert (but not TestNG's + * Assert, as TestNG is not compiled with target 1.6 yet). + */ + @HtmlFragment( + "

Put this snippet on the HTML page

\n" + ) + @BrwsrTest + public void runThisTestInABrowser() { + } + + @Factory + public static Object[] create() { + return VMTest.create(IntegrationTest.class); + } + +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/test/java/TwitterClientTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/TwitterClientTest.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,50 @@ +package ${package}; + +import java.util.List; +import net.java.html.BrwsrCtx; +import net.java.html.json.Models; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** We can unit test the TwitterModel smoothly. + */ +public class TwitterClientTest { + private TwitterModel model; + + + @BeforeMethod + public void initModel() { + model = Models.bind(new TwitterModel(), BrwsrCtx.EMPTY); + } + + @Test public void testIsValidToAdd() { + model.setUserNameToAdd("Joe"); + Tweeters t = Models.bind(new Tweeters(), BrwsrCtx.EMPTY); + t.setName("test"); + model.getSavedLists().add(t); + model.setActiveTweetersName("test"); + + assertTrue(model.isUserNameToAddIsValid(), "Joe is OK"); + TwitterClient.addUser(model); + assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time"); + assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty"); + + List mod = model.getActiveTweeters(); + assertTrue(model.isHasUnsavedChanges(), "We have modifications"); + assertEquals(mod.size(), 1, "One element in the list"); + assertEquals(mod.get(0), "Joe", "Its name is Joe"); + + assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one"); + + TwitterClient.saveChanges(model); + assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save"); + + assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one"); + } + + @Test public void httpAtTheEnd() { + String res = TwitterClient.Twt.html("Ahoj http://kuk"); + assertEquals(res, "Ahoj http://kuk"); + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/archetype/src/main/resources/archetype-resources/src/test/java/TwitterProtocolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/TwitterProtocolTest.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,73 @@ +package ${package}; + +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.Http; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +public class TwitterProtocolTest { + private TwitterModel page; + @Http(@Http.Resource( + path = "/search.json", + mimeType = "application/json", + parameters = {"callback"}, + content = "$0({\"completed_in\":0.04,\"max_id\":320055706885689344,\"max_id_str\"" + + ":\"320055706885689344\",\"page\":1,\"query\":\"from%3AJaroslavTulach\",\"refresh_url\":" + + "\"?since_id=320055706885689344&q=from%3AJaroslavTulach\"," + + "\"results\":[{\"created_at\":\"Fri, 05 Apr 2013 06:10:01 +0000\"," + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":" + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":320055706885689344," + + "\"id_str\":\"320055706885689344\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":" + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" + + "\"@tom_enebo Amzng! Not that I would like #ruby, but I am really glad you guys stabilized the plugin + " + + "made it work in #netbeans 7.3! Gd wrk.\",\"to_user\":\"tom_enebo\",\"to_user_id\":14498747," + + "\"to_user_id_str\":\"14498747\",\"to_user_name\":\"tom_enebo\",\"in_reply_to_status_id\":319832359509839872," + + "\"in_reply_to_status_id_str\":\"319832359509839872\"},{\"created_at\":\"Thu, 04 Apr 2013 07:33:06 +0000\"," + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":" + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":319714227088678913," + + "\"id_str\":\"319714227088678913\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":" + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" + + "\"RT @drkrab: At #erlangfactory @joerl: Frameworks grow in complexity until nobody can use them.\"}," + + "{\"created_at\":\"Tue, 02 Apr 2013 07:44:34 +0000\",\"from_user\":\"JaroslavTulach\"," + + "\"from_user_id\":420944648,\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\"," + + "\"geo\":null,\"id\":318992336145248256,\"id_str\":\"318992336145248256\",\"iso_language_code\":\"en\"," + + "\"metadata\":{\"result_type\":\"recent\"},\"profile_image_url\":" + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" + + "\"Twitter renamed to twttr http:\\/\\/t.co\\/tqaN4T1xlZ - good, I don't have to rename #bck2brwsr!\"}," + + "{\"created_at\":\"Sun, 31 Mar 2013 03:52:04 +0000\",\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648," + + "\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null," + + "\"id\":318209051223789568,\"id_str\":\"318209051223789568\",\"iso_language_code\":\"en\",\"metadata\":" + + "{\"result_type\":\"recent\"},\"profile_image_url\":" + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\"," + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":" + + "\"Math proofs without words. Ingenious: http:\\/\\/t.co\\/sz7yVbfpGw\"}],\"results_per_page\":100," + + "\"since_id\":0,\"since_id_str\":\"0\"})" + )) + @BrwsrTest public void readFromTwttr() throws InterruptedException { + if (page == null) { + page = new TwitterModel(); + page.applyBindings(); + page.queryTweets("", "q=xyz"); + } + + if (page.getCurrentTweets().isEmpty()) { + throw new InterruptedException(); + } + + assert 4 == page.getCurrentTweets().size() : "Four tweets: " + page.getCurrentTweets(); + + String firstDate = page.getCurrentTweets().get(0).getCreated_at(); + assert "Fri, 05 Apr 2013 06:10:01 +0000".equals(firstDate) : "Date is OK: " + firstDate; + } + + @Factory public static Object[] create() { + return VMTest.create(TwitterProtocolTest.class); + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/bck2brwsr/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/bck2brwsr/pom.xml Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,96 @@ + + + 4.0.0 + + org.apidesign + html + 0.4-SNAPSHOT + + org.apidesign.html + ko-bck2brwsr + 0.4-SNAPSHOT + Knockout.b2b + http://maven.apache.org + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-javadoc-plugin + + false + + + + + + + org.testng + testng + test + + + junit + junit + + + + + org.netbeans.api + org-openide-util-lookup + provided + + + org.apidesign.bck2brwsr + emul + ${bck2brwsr.version} + rt + jar + compile + + + org.apidesign.bck2brwsr + vm4brwsr + ${bck2brwsr.version} + jar + test + + + org.apidesign.bck2brwsr + vmtest + ${bck2brwsr.version} + test + + + org.apidesign.bck2brwsr + launcher.http + ${bck2brwsr.launcher.version} + test + + + org.apidesign.html + net.java.html.json + 0.4-SNAPSHOT + + + org.apidesign.html + net.java.html.json.tck + 0.4-SNAPSHOT + test + + + org.apidesign.bck2brwsr + core + ${bck2brwsr.version} + jar + + + diff -r 7189e9abb928 -r 73c0973e8e0a ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxImpl.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,129 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.ko2brwsr; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import net.java.html.BrwsrCtx; +import org.apidesign.html.context.spi.Contexts; +import org.apidesign.html.json.spi.FunctionBinding; +import org.apidesign.html.json.spi.JSONCall; +import org.apidesign.html.json.spi.PropertyBinding; +import org.apidesign.html.json.spi.Technology; +import org.apidesign.html.json.spi.Transfer; + +/** + * + * @author Jaroslav Tulach + */ +final class BrwsrCtxImpl implements Technology, Transfer { + private BrwsrCtxImpl() {} + + public static final BrwsrCtxImpl DEFAULT = new BrwsrCtxImpl(); + + @Override + public void extract(Object obj, String[] props, Object[] values) { + ConvertTypes.extractJSON(obj, props, values); + } + + @Override + public void loadJSON(final JSONCall call) { + class R implements Runnable { + Object[] arr = { null }; + @Override + public void run() { + call.notifySuccess(arr[0]); + } + } + R r = new R(); + if (call.isJSONP()) { + String me = ConvertTypes.createJSONP(r.arr, r); + ConvertTypes.loadJSONP(call.composeURL(me), me); + } else { + String data = null; + if (call.isDoOutput()) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + call.writeData(bos); + data = new String(bos.toByteArray(), "UTF-8"); + } catch (IOException ex) { + call.notifyError(ex); + } + } + ConvertTypes.loadJSON(call.composeURL(null), r.arr, r, call.getMethod(), data); + } + } + + @Override + public Object wrapModel(Object model) { + return model; + } + + @Override + public void bind(PropertyBinding b, Object model, Object data) { + Knockout.bind(data, b, b.getPropertyName(), + "getValue__Ljava_lang_Object_2", + b.isReadOnly() ? null : "setValue__VLjava_lang_Object_2", + false, false + ); + } + + @Override + public void valueHasMutated(Object data, String propertyName) { + Knockout.valueHasMutated(data, propertyName); + } + + @Override + public void expose(FunctionBinding fb, Object model, Object d) { + Knockout.expose(d, fb, fb.getFunctionName(), "call__VLjava_lang_Object_2Ljava_lang_Object_2"); + } + + @Override + public void applyBindings(Object data) { + Knockout.applyBindings(data); + } + + @Override + public Object wrapArray(Object[] arr) { + return arr; + } + + @Override + public M toModel(Class modelClass, Object data) { + return modelClass.cast(data); + } + + @Override + public Object toJSON(InputStream is) throws IOException { + StringBuilder sb = new StringBuilder(); + InputStreamReader r = new InputStreamReader(is); + for (;;) { + int ch = r.read(); + if (ch == -1) { + break; + } + sb.append((char)ch); + } + return ConvertTypes.parse(sb.toString()); + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxPrvdr.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/BrwsrCtxPrvdr.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,54 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.ko2brwsr; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.html.context.spi.Contexts; +import org.apidesign.html.json.spi.Technology; +import org.apidesign.html.json.spi.Transfer; +import org.openide.util.lookup.ServiceProvider; + +/** This is an implementation package - just + * include its JAR on classpath and use official {@link Context} API + * to access the functionality. + *

+ * Provides binding between models and + * Bck2Brwsr VM. + * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it. + * + * @author Jaroslav Tulach + */ +@ServiceProvider(service = Contexts.Provider.class) +public final class BrwsrCtxPrvdr implements Contexts.Provider { + + @Override + public void fillContext(Contexts.Builder context, Class requestor) { + if (bck2BrwsrVM()) { + context.register(Technology.class, BrwsrCtxImpl.DEFAULT, 50). + register(Transfer.class, BrwsrCtxImpl.DEFAULT, 50); + } + } + + @JavaScriptBody(args = { }, body = "return true;") + private static boolean bck2BrwsrVM() { + return false; + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/ConvertTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/ConvertTypes.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,155 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.ko2brwsr; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +final class ConvertTypes { + ConvertTypes() { + } + + public static String toString(Object object, String property) { + Object ret = getProperty(object, property); + return ret == null ? null : ret.toString(); + } + + public static double toDouble(Object object, String property) { + Object ret = getProperty(object, property); + return ret instanceof Number ? ((Number)ret).doubleValue() : Double.NaN; + } + + public static int toInt(Object object, String property) { + Object ret = getProperty(object, property); + return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE; + } + + public static T toModel(Class modelClass, Object object, String property) { + Object ret = getProperty(object, property); + if (ret == null || modelClass.isInstance(ret)) { + return modelClass.cast(ret); + } + throw new IllegalStateException("Value " + ret + " is not of type " + modelClass); + } + + public static String toJSON(Object value) { + if (value == null) { + return "null"; + } + if (value instanceof Enum) { + value = value.toString(); + } + if (value instanceof String) { + return '"' + + ((String)value). + replace("\"", "\\\""). + replace("\n", "\\n"). + replace("\r", "\\r"). + replace("\t", "\\t") + + '"'; + } + return value.toString(); + } + + @JavaScriptBody(args = { "object", "property" }, + body = "if (property === null) return object;\n" + + "var p = object[property]; return p ? p : null;" + ) + private static Object getProperty(Object object, String property) { + return null; + } + + public static String createJSONP(Object[] jsonResult, Runnable whenDone) { + int h = whenDone.hashCode(); + String name; + for (;;) { + name = "jsonp" + Integer.toHexString(h); + if (defineIfUnused(name, jsonResult, whenDone)) { + return name; + } + h++; + } + } + + @JavaScriptBody(args = { "name", "arr", "run" }, body = + "if (window[name]) return false;\n " + + "window[name] = function(data) {\n " + + " delete window[name];\n" + + " var el = window.document.getElementById(name);\n" + + " el.parentNode.removeChild(el);\n" + + " arr[0] = data;\n" + + " run.run__V();\n" + + "};\n" + + "return true;\n" + ) + private static boolean defineIfUnused(String name, Object[] arr, Runnable run) { + return true; + } + + @JavaScriptBody(args = { "s" }, body = "return eval('(' + s + ')');") + static Object parse(String s) { + return s; + } + + @JavaScriptBody(args = { "url", "arr", "callback", "method", "data" }, body = "" + + "var request = new XMLHttpRequest();\n" + + "if (!method) method = 'GET';\n" + + "request.open(method, url, true);\n" + + "request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n" + + "request.onreadystatechange = function() {\n" + + " if (this.readyState!==4) return;\n" + + " try {\n" + + " arr[0] = eval('(' + this.response + ')');\n" + + " } catch (error) {;\n" + + " arr[0] = this.response;\n" + + " }\n" + + " callback.run__V();\n" + + "};" + + "if (data) request.send(data);" + + "else request.send();" + ) + static void loadJSON( + String url, Object[] jsonResult, Runnable whenDone, String method, String data + ) { + } + + @JavaScriptBody(args = { "url", "jsonp" }, body = + "var scrpt = window.document.createElement('script');\n " + + "scrpt.setAttribute('src', url);\n " + + "scrpt.setAttribute('id', jsonp);\n " + + "scrpt.setAttribute('type', 'text/javascript');\n " + + "var body = document.getElementsByTagName('body')[0];\n " + + "body.appendChild(scrpt);\n" + ) + static void loadJSONP(String url, String jsonp) { + + } + + public static void extractJSON(Object jsonObject, String[] props, Object[] values) { + for (int i = 0; i < props.length; i++) { + values[i] = getProperty(jsonObject, props[i]); + } + } + +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/Knockout.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/Knockout.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,134 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.ko2brwsr; + +import java.lang.reflect.Method; +import java.util.List; +import org.apidesign.bck2brwsr.core.ExtraJavaScript; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** Provides binding between models and bck2brwsr VM. + * + * @author Jaroslav Tulach + */ +@ExtraJavaScript(resource = "/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js") +final class Knockout { + /** used by tests */ + static Knockout next; + private final Object model; + + Knockout(Object model) { + this.model = model == null ? this : model; + } + + public static Knockout applyBindings( + Object model, String[] propsGettersAndSetters, + String[] methodsAndSignatures + ) { + applyImpl(propsGettersAndSetters, model.getClass(), model, model, methodsAndSignatures); + return new Knockout(model); + } + public static Knockout applyBindings( + Class modelClass, M model, String[] propsGettersAndSetters, + String[] methodsAndSignatures + ) { + Knockout bindings = next; + next = null; + if (bindings == null) { + bindings = new Knockout(null); + } + applyImpl(propsGettersAndSetters, modelClass, bindings, model, methodsAndSignatures); + applyBindings(bindings); + return bindings; + } + + public void valueHasMutated(String prop) { + valueHasMutated(model, prop); + } + @JavaScriptBody(args = { "self", "prop" }, body = + "var p = self[prop]; if (p) p.valueHasMutated();" + ) + public static void valueHasMutated(Object self, String prop) { + } + + + @JavaScriptBody(args = { "id", "ev" }, body = "ko.utils.triggerEvent(window.document.getElementById(id), ev.substring(2));") + public static void triggerEvent(String id, String ev) { + } + + @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive", "array" }, body = + "var bnd = {\n" + + " 'read': function() {\n" + + " var v = model[getter]();\n" + + " if (array) v = v.koArray(); else if (v !== null) v = v.valueOf();\n" + + " return v;\n" + + " },\n" + + " 'owner': bindings\n" + + "};\n" + + "if (setter != null) {\n" + + " bnd['write'] = function(val) {\n" + + " var v = val === null ? null : val.valueOf();" + + " model[setter](v);\n" + + " };\n" + + "}\n" + + "bindings[prop] = ko['computed'](bnd);" + ) + static void bind( + Object bindings, Object model, String prop, String getter, String setter, boolean primitive, boolean array + ) { + } + + @JavaScriptBody(args = { "bindings", "model", "prop", "sig" }, body = + "bindings[prop] = function(data, ev) { model[sig](data, ev); };" + ) + static void expose( + Object bindings, Object model, String prop, String sig + ) { + } + + @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);") + static void applyBindings(Object bindings) {} + + private static void applyImpl( + String[] propsGettersAndSetters, + Class modelClass, + Object bindings, + Object model, + String[] methodsAndSignatures + ) throws IllegalStateException, SecurityException { + for (int i = 0; i < propsGettersAndSetters.length; i += 4) { + try { + Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]); + bind(bindings, model, propsGettersAndSetters[i], + propsGettersAndSetters[i + 1], + propsGettersAndSetters[i + 2], + getter.getReturnType().isPrimitive(), + List.class.isAssignableFrom(getter.getReturnType())); + } catch (NoSuchMethodException ex) { + throw new IllegalStateException(ex.getMessage()); + } + } + for (int i = 0; i < methodsAndSignatures.length; i += 2) { + expose( + bindings, model, methodsAndSignatures[i], methodsAndSignatures[i + 1]); + } + } +} diff -r 7189e9abb928 -r 73c0973e8e0a ko/bck2brwsr/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/bck2brwsr/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,3614 @@ +/* + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +// Knockout JavaScript library v2.2.1 +// (c) Steven Sanderson - http://knockoutjs.com/ +// License: MIT (http://www.opensource.org/licenses/mit-license.php) + +(function(){ +var DEBUG=true; +(function(window,document,navigator,jQuery,undefined){ +!function(factory) { + // Support three module loading scenarios + if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { + // [1] CommonJS/Node.js + var target = module['exports'] || exports; // module.exports is for Node.js + factory(target); + } else if (typeof define === 'function' && define['amd']) { + // [2] AMD anonymous module + define(['exports'], factory); + } else { + // [3] No module loader (plain "); + }; + + if (jQueryTmplVersion > 0) { + jQuery['tmpl']['tag']['ko_code'] = { + open: "__.push($1 || '');" + }; + jQuery['tmpl']['tag']['ko_with'] = { + open: "with($1) {", + close: "} " + }; + } + }; + + ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine(); + + // Use this one by default *only if jquery.tmpl is referenced* + var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine(); + if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0) + ko.setTemplateEngine(jqueryTmplTemplateEngineInstance); + + ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine); +})(); +}); +})(window,document,navigator,window["jQuery"]); +})(); \ No newline at end of file diff -r 7189e9abb928 -r 73c0973e8e0a ko/bck2brwsr/src/test/java/org/apidesign/html/ko2brwsr/Bck2BrwsrKnockoutTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/bck2brwsr/src/test/java/org/apidesign/html/ko2brwsr/Bck2BrwsrKnockoutTest.java Mon Jun 24 17:50:44 2013 +0200 @@ -0,0 +1,124 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.ko2brwsr; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Map; +import net.java.html.BrwsrCtx; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.apidesign.html.context.spi.Contexts; +import org.apidesign.html.json.spi.Technology; +import org.apidesign.html.json.spi.Transfer; +import org.apidesign.html.json.tck.KOTest; +import org.apidesign.html.json.tck.KnockoutTCK; +import org.openide.util.lookup.ServiceProvider; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +@ServiceProvider(service = KnockoutTCK.class) +public final class Bck2BrwsrKnockoutTest extends KnockoutTCK { + @Factory public static Object[] create() { + return VMTest.newTests(). + withClasses(testClasses()). + withLaunchers("bck2brwsr"). + withTestAnnotation(KOTest.class). + build(); + } + + @Override + public BrwsrCtx createContext() { + return Contexts.newBuilder(). + register(Transfer.class, BrwsrCtxImpl.DEFAULT, 9). + register(Technology.class, BrwsrCtxImpl.DEFAULT, 9).build(); + } + + + + @Override + public Object createJSON(Map values) { + Object json = createJSON(); + + for (Map.Entry entry : values.entrySet()) { + putValue(json, entry.getKey(), entry.getValue()); + } + return json; + } + + @JavaScriptBody(args = {}, body = "return new Object();") + private static native Object createJSON(); + + @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;") + private static native void putValue(Object json, String key, Object value); + + @Override + public Object executeScript(String script, Object[] arguments) { + return execScript(script, arguments); + } + + @JavaScriptBody(args = { "s", "args" }, body = + "var f = new Function(s); return f.apply(null, args);" + ) + private static native Object execScript(String s, Object[] arguments); + + @JavaScriptBody(args = { }, body = + "var h;" + + "if (!!window && !!window.location && !!window.location.href)\n" + + " h = window.location.href;\n" + + "else " + + " h = null;" + + "return h;\n" + ) + private static native String findBaseURL(); + + @Override + public URI prepareURL(String content, String mimeType, String[] parameters) { + try { + final URL baseURL = new URL(findBaseURL()); + StringBuilder sb = new StringBuilder(); + sb.append("/dynamic?mimeType=").append(mimeType); + for (int i = 0; i < parameters.length; i++) { + sb.append("¶m" + i).append("=").append(parameters[i]); + } + String mangle = content.replace("\n", "%0a") + .replace("\"", "\\\"").replace(" ", "%20"); + sb.append("&content=").append(mangle); + + URL query = new URL(baseURL, sb.toString()); + String uri = (String) query.getContent(new Class[] { String.class }); + URI connectTo = new URI(uri.trim()); + return connectTo; + } catch (IOException ex) { + throw new IllegalStateException(ex); + } catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } +}