1.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java Thu Apr 04 11:45:54 2013 +0200
1.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java Thu Apr 04 13:08:26 2013 +0200
1.3 @@ -141,6 +141,10 @@
1.4 m.valueHasMutated(dependant);
1.5 }
1.6 }
1.7 -
1.8 +
1.9 + @Override
1.10 + public KOList clone() {
1.11 + return (KOList)super.clone();
1.12 + }
1.13
1.14 }
2.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu Apr 04 11:45:54 2013 +0200
2.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu Apr 04 13:08:26 2013 +0200
2.3 @@ -134,7 +134,7 @@
2.4 w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
2.5 w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
2.6 w.append("import org.apidesign.bck2brwsr.core.JavaScriptOnly;\n");
2.7 - w.append("final class ").append(className).append(" {\n");
2.8 + w.append("final class ").append(className).append(" implements Cloneable {\n");
2.9 w.append(" private Object json;\n");
2.10 w.append(" private boolean locked;\n");
2.11 w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
2.12 @@ -148,6 +148,7 @@
2.13 w.append(" );\n");
2.14 w.append(" };\n");
2.15 writeToString(m.properties(), w);
2.16 + writeClone(className, m.properties(), w);
2.17 w.append("}\n");
2.18 } finally {
2.19 w.close();
2.20 @@ -540,32 +541,16 @@
2.21
2.22 private String typeName(Element where, Property p) {
2.23 String ret;
2.24 - boolean isModel = false;
2.25 - boolean isEnum = false;
2.26 - try {
2.27 - ret = p.type().getName();
2.28 - } catch (MirroredTypeException ex) {
2.29 - TypeMirror tm = processingEnv.getTypeUtils().erasure(ex.getTypeMirror());
2.30 - final Element e = processingEnv.getTypeUtils().asElement(tm);
2.31 - final Model m = e == null ? null : e.getAnnotation(Model.class);
2.32 - if (m != null) {
2.33 - ret = findPkgName(e) + '.' + m.className();
2.34 - isModel = true;
2.35 - models.put(e, m.className());
2.36 - } else {
2.37 - ret = tm.toString();
2.38 - }
2.39 - TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
2.40 - enm = processingEnv.getTypeUtils().erasure(enm);
2.41 - isEnum = processingEnv.getTypeUtils().isSubtype(tm, enm);
2.42 - }
2.43 + boolean[] isModel = { false };
2.44 + boolean[] isEnum = { false };
2.45 + ret = checkType(p, isModel, isEnum);
2.46 if (p.array()) {
2.47 String bt = findBoxedType(ret);
2.48 if (bt != null) {
2.49 return bt;
2.50 }
2.51 }
2.52 - if (!isModel && !"java.lang.String".equals(ret) && !isEnum) {
2.53 + if (!isModel[0] && !"java.lang.String".equals(ret) && !isEnum[0]) {
2.54 String bt = findBoxedType(ret);
2.55 if (bt == null) {
2.56 processingEnv.getMessager().printMessage(
2.57 @@ -786,6 +771,25 @@
2.58 w.write(" return sb.toString();\n");
2.59 w.write(" }\n");
2.60 }
2.61 + private void writeClone(String className, Property[] props, Writer w) throws IOException {
2.62 + w.write(" public " + className + " clone() {\n");
2.63 + w.write(" " + className + " ret = new " + className + "();\n");
2.64 + for (Property p : props) {
2.65 + if (!p.array()) {
2.66 + boolean isModel[] = { false };
2.67 + boolean isEnum[] = { false };
2.68 + checkType(p, isModel, isEnum);
2.69 + if (!isModel[0]) {
2.70 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
2.71 + continue;
2.72 + }
2.73 + }
2.74 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n");
2.75 + }
2.76 +
2.77 + w.write(" return ret;\n");
2.78 + w.write(" }\n");
2.79 + }
2.80
2.81 private String inPckName(Element e) {
2.82 StringBuilder sb = new StringBuilder();
2.83 @@ -809,4 +813,26 @@
2.84 }
2.85 return pt.toString();
2.86 }
2.87 +
2.88 + private String checkType(Property p, boolean[] isModel, boolean[] isEnum) {
2.89 + String ret;
2.90 + try {
2.91 + ret = p.type().getName();
2.92 + } catch (MirroredTypeException ex) {
2.93 + TypeMirror tm = processingEnv.getTypeUtils().erasure(ex.getTypeMirror());
2.94 + final Element e = processingEnv.getTypeUtils().asElement(tm);
2.95 + final Model m = e == null ? null : e.getAnnotation(Model.class);
2.96 + if (m != null) {
2.97 + ret = findPkgName(e) + '.' + m.className();
2.98 + isModel[0] = true;
2.99 + models.put(e, m.className());
2.100 + } else {
2.101 + ret = tm.toString();
2.102 + }
2.103 + TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
2.104 + enm = processingEnv.getTypeUtils().erasure(enm);
2.105 + isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
2.106 + }
2.107 + return ret;
2.108 + }
2.109 }
3.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Thu Apr 04 11:45:54 2013 +0200
3.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Thu Apr 04 13:08:26 2013 +0200
3.3 @@ -27,7 +27,9 @@
3.4 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
3.5 import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
3.6 import org.apidesign.bck2brwsr.vmtest.VMTest;
3.7 +import static org.testng.Assert.assertEquals;
3.8 import org.testng.annotations.Factory;
3.9 +import org.testng.annotations.Test;
3.10
3.11 /**
3.12 *
3.13 @@ -181,6 +183,28 @@
3.14
3.15 assert first.getSex() == Sex.FEMALE : "Transverted to female: " + first.getSex();
3.16 }
3.17 +
3.18 + @Test public void cloneModel() {
3.19 + Person model = new Person();
3.20 +
3.21 + model.setFirstName("first");
3.22 + Person snd = model.clone();
3.23 + snd.setFirstName("clone");
3.24 + assertEquals("first", model.getFirstName(), "Value has not changed");
3.25 + assertEquals("clone", snd.getFirstName(), "Value has changed in clone");
3.26 + }
3.27 +
3.28 +
3.29 + @Test public void deepCopyOnClone() {
3.30 + People model = new People();
3.31 + model.getNicknames().add("Jarda");
3.32 + assertEquals(model.getNicknames().size(), 1, "One element");
3.33 + People snd = model.clone();
3.34 + snd.getNicknames().clear();
3.35 + assertEquals(snd.getNicknames().size(), 0, "Clone is empty");
3.36 + assertEquals(model.getNicknames().size(), 1, "Still one element");
3.37 + }
3.38 +
3.39
3.40 @OnFunction
3.41 static void call(KnockoutModel m, String data) {