# HG changeset patch # User Jaroslav Tulach # Date 1365073706 -7200 # Node ID e8916518b38d6ba512a97cc1ac641e48cb52440b # Parent b43aaf398748ed20c0b1266b9c50b024bd854303 clone() on model classes diff -r b43aaf398748 -r e8916518b38d javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java Thu Apr 04 11:45:54 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java Thu Apr 04 13:08:26 2013 +0200 @@ -141,6 +141,10 @@ m.valueHasMutated(dependant); } } - + + @Override + public KOList clone() { + return (KOList)super.clone(); + } } diff -r b43aaf398748 -r e8916518b38d javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu Apr 04 11:45:54 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu Apr 04 13:08:26 2013 +0200 @@ -134,7 +134,7 @@ w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n"); w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n"); w.append("import org.apidesign.bck2brwsr.core.JavaScriptOnly;\n"); - w.append("final class ").append(className).append(" {\n"); + w.append("final class ").append(className).append(" implements Cloneable {\n"); w.append(" private Object json;\n"); w.append(" private boolean locked;\n"); w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n"); @@ -148,6 +148,7 @@ w.append(" );\n"); w.append(" };\n"); writeToString(m.properties(), w); + writeClone(className, m.properties(), w); w.append("}\n"); } finally { w.close(); @@ -540,32 +541,16 @@ private String typeName(Element where, Property p) { String ret; - boolean isModel = false; - boolean isEnum = false; - try { - ret = p.type().getName(); - } catch (MirroredTypeException ex) { - TypeMirror tm = processingEnv.getTypeUtils().erasure(ex.getTypeMirror()); - final Element e = processingEnv.getTypeUtils().asElement(tm); - final Model m = e == null ? null : e.getAnnotation(Model.class); - if (m != null) { - ret = findPkgName(e) + '.' + m.className(); - isModel = true; - models.put(e, m.className()); - } else { - ret = tm.toString(); - } - TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType(); - enm = processingEnv.getTypeUtils().erasure(enm); - isEnum = processingEnv.getTypeUtils().isSubtype(tm, enm); - } + boolean[] isModel = { false }; + boolean[] isEnum = { false }; + ret = checkType(p, isModel, isEnum); if (p.array()) { String bt = findBoxedType(ret); if (bt != null) { return bt; } } - if (!isModel && !"java.lang.String".equals(ret) && !isEnum) { + if (!isModel[0] && !"java.lang.String".equals(ret) && !isEnum[0]) { String bt = findBoxedType(ret); if (bt == null) { processingEnv.getMessager().printMessage( @@ -786,6 +771,25 @@ w.write(" return sb.toString();\n"); w.write(" }\n"); } + private void writeClone(String className, Property[] props, Writer w) throws IOException { + w.write(" public " + className + " clone() {\n"); + w.write(" " + className + " ret = new " + className + "();\n"); + for (Property p : props) { + if (!p.array()) { + boolean isModel[] = { false }; + boolean isEnum[] = { false }; + checkType(p, isModel, isEnum); + if (!isModel[0]) { + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n"); + continue; + } + } + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n"); + } + + w.write(" return ret;\n"); + w.write(" }\n"); + } private String inPckName(Element e) { StringBuilder sb = new StringBuilder(); @@ -809,4 +813,26 @@ } return pt.toString(); } + + private String checkType(Property p, boolean[] isModel, boolean[] isEnum) { + String ret; + try { + ret = p.type().getName(); + } catch (MirroredTypeException ex) { + TypeMirror tm = processingEnv.getTypeUtils().erasure(ex.getTypeMirror()); + final Element e = processingEnv.getTypeUtils().asElement(tm); + final Model m = e == null ? null : e.getAnnotation(Model.class); + if (m != null) { + ret = findPkgName(e) + '.' + m.className(); + isModel[0] = true; + models.put(e, m.className()); + } else { + ret = tm.toString(); + } + TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType(); + enm = processingEnv.getTypeUtils().erasure(enm); + isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm); + } + return ret; + } } diff -r b43aaf398748 -r e8916518b38d javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Thu Apr 04 11:45:54 2013 +0200 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Thu Apr 04 13:08:26 2013 +0200 @@ -27,7 +27,9 @@ import org.apidesign.bck2brwsr.vmtest.BrwsrTest; import org.apidesign.bck2brwsr.vmtest.HtmlFragment; import org.apidesign.bck2brwsr.vmtest.VMTest; +import static org.testng.Assert.assertEquals; import org.testng.annotations.Factory; +import org.testng.annotations.Test; /** * @@ -181,6 +183,28 @@ assert first.getSex() == Sex.FEMALE : "Transverted to female: " + first.getSex(); } + + @Test public void cloneModel() { + Person model = new Person(); + + model.setFirstName("first"); + Person snd = model.clone(); + snd.setFirstName("clone"); + assertEquals("first", model.getFirstName(), "Value has not changed"); + assertEquals("clone", snd.getFirstName(), "Value has changed in clone"); + } + + + @Test public void deepCopyOnClone() { + People model = new People(); + model.getNicknames().add("Jarda"); + assertEquals(model.getNicknames().size(), 1, "One element"); + People snd = model.clone(); + snd.getNicknames().clear(); + assertEquals(snd.getNicknames().size(), 0, "Clone is empty"); + assertEquals(model.getNicknames().size(), 1, "Still one element"); + } + @OnFunction static void call(KnockoutModel m, String data) {