This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 251076
Collapse All | Expand All

(-)a/api.knockout/nbproject/project.xml (+8 lines)
Lines 41-46 Link Here
41
                    </run-dependency>
41
                    </run-dependency>
42
                </dependency>
42
                </dependency>
43
                <dependency>
43
                <dependency>
44
                    <code-name-base>org.openide.util</code-name-base>
45
                    <build-prerequisite/>
46
                    <compile-dependency/>
47
                    <run-dependency>
48
                        <specification-version>9.3</specification-version>
49
                    </run-dependency>
50
                </dependency>
51
                <dependency>
44
                    <code-name-base>org.openide.util.lookup</code-name-base>
52
                    <code-name-base>org.openide.util.lookup</code-name-base>
45
                    <build-prerequisite/>
53
                    <build-prerequisite/>
46
                    <compile-dependency/>
54
                    <compile-dependency/>
(-)a/api.knockout/src/org/netbeans/spi/knockout/Bindings.java (-17 / +57 lines)
Lines 42-54 Link Here
42
package org.netbeans.spi.knockout;
42
package org.netbeans.spi.knockout;
43
43
44
import java.util.ArrayList;
44
import java.util.ArrayList;
45
import java.util.Collection;
46
import java.util.Collections;
47
import java.util.HashMap;
45
import java.util.HashSet;
48
import java.util.HashSet;
46
import java.util.LinkedHashSet;
49
import java.util.LinkedHashSet;
47
import java.util.List;
50
import java.util.List;
51
import java.util.Map;
48
import java.util.Set;
52
import java.util.Set;
49
import org.netbeans.spi.knockout.BindingsProvider.Response;
53
import org.netbeans.spi.knockout.BindingsProvider.Response;
50
import org.openide.filesystems.FileObject;
54
import org.openide.filesystems.FileObject;
55
import org.openide.util.BaseUtilities;
51
import org.openide.util.Lookup;
56
import org.openide.util.Lookup;
57
import org.openide.util.TopologicalSortException;
52
58
53
/**
59
/**
54
 * Allows structural description of a <code>ko.applyBindings</code> parameter.
60
 * Allows structural description of a <code>ko.applyBindings</code> parameter.
Lines 63-69 Link Here
63
69
64
    private final String name;
70
    private final String name;
65
    private final List<Bindings> subBindings = new ArrayList<>();
71
    private final List<Bindings> subBindings = new ArrayList<>();
66
    private final List<String> props = new ArrayList<>();
72
    private final List<Object> props = new ArrayList<>();
67
73
68
    private Bindings(String name) {
74
    private Bindings(String name) {
69
        this.name = name;
75
        this.name = name;
Lines 144-150 Link Here
144
     */
150
     */
145
    public final Bindings modelProperty(String name, Bindings binding, boolean array) {
151
    public final Bindings modelProperty(String name, Bindings binding, boolean array) {
146
        subBindings.add(binding);
152
        subBindings.add(binding);
147
        addProp(name, array, binding.name);
153
        addProp(name, array, binding);
148
        return this;
154
        return this;
149
    }
155
    }
150
156
Lines 152-195 Link Here
152
        StringBuilder sb = new StringBuilder();
158
        StringBuilder sb = new StringBuilder();
153
        //sb.append("(function() {\n");
159
        //sb.append("(function() {\n");
154
        HashSet<Bindings> visited = new HashSet<>();
160
        HashSet<Bindings> visited = new HashSet<>();
155
        LinkedHashSet<Bindings> lhs = new LinkedHashSet<>();
161
        Collection<Bindings> lhs = new LinkedHashSet<>();
156
        walkBindings(visited, lhs);
162
        StringBuilder delayedInit = new StringBuilder();
163
        if (!walkBindings(visited, lhs)) {
164
            Map<Bindings, List<Bindings>> edges = new HashMap<>();
165
            for (Bindings b : lhs) {
166
                edges.put(b, b.subBindings);
167
            }
168
            try {
169
                BaseUtilities.topologicalSort(lhs, edges);
170
                // There is a cycle, so the resolution should fail
171
                throw new IllegalStateException();
172
            } catch (TopologicalSortException ex) {
173
                lhs = Collections.checkedList(ex.partialSort(), Bindings.class);
174
            }
175
        }
157
        for (Bindings b : lhs) {
176
        for (Bindings b : lhs) {
158
            b.generate(sb);
177
            b.generate(sb, delayedInit, visited);
178
            visited.remove(b);
159
        }
179
        }
160
        sb.append("  ko.applyBindings(").append(name).append(");\n");
180
        sb.append(delayedInit);
181
        sb.append("\nko.applyBindings(").append(name).append(");\n");
161
        //sb.append("}());");
182
        //sb.append("}());");
162
        return sb.toString();
183
        return sb.toString();
163
    }
184
    }
164
185
165
    private void generate(StringBuilder sb) {
186
    private void generate(StringBuilder sb, StringBuilder delayedInit, Set<Bindings> notYetProcessed) {
166
        sb.append("var ").append(name).append(" = {");
187
        sb.append("var ").append(name).append(" = {");
167
        String sep = "\n";
188
        String sep = "\n";
168
        for (String s : props) {
189
        for (int i = 0; i < props.size(); i += 3) {
169
            sb.append(sep).append("  ").append(s);
190
            String propName = (String)props.get(i);
191
            Boolean array = (Boolean)props.get(i + 1);
192
            Object value = props.get(i + 2);
193
            
194
            if (value instanceof Bindings) {
195
                Bindings b = (Bindings) value;
196
                if (notYetProcessed.contains(b)) {
197
                    delayedInit.append("\n").append(this.name).append("[\"").
198
                        append(propName).append("\"] = ").append(b.name).
199
                        append(";");
200
                    continue;
201
                }
202
                value = b.name;
203
            }
204
            
205
            if (array) {
206
                value = "[ " + value + " ]";
207
            }
208
            sb.append(sep).append("  ").append('\"').append(propName).append("\" : ").append(value);
170
            sep = ",\n";
209
            sep = ",\n";
171
        }
210
        }
172
        sb.append("\n};\n");
211
        sb.append("\n};\n");
173
    }
212
    }
174
213
175
    private void addProp(String name, boolean array, String value) {
214
    private void addProp(String name, boolean array, Object value) {
176
        if (array) {
177
            value = "[ " + value + " ]";
178
        }
179
        if (name.contains("\"")) {
215
        if (name.contains("\"")) {
180
            throw new IllegalStateException("Wrong name " + name);
216
            throw new IllegalStateException("Wrong name " + name);
181
        }
217
        }
182
        props.add('\"' + name + "\" : " + value);
218
        props.add(name);
219
        props.add(array);
220
        props.add(value);
183
    }
221
    }
184
222
185
    private void walkBindings(Set<Bindings> visited, Set<Bindings> collect) {
223
    private boolean walkBindings(Set<Bindings> visited, Collection<Bindings> collect) {
186
        if (!visited.add(this)) {
224
        if (!visited.add(this)) {
187
            return;
225
            return false;
188
        }
226
        }
227
        boolean ok = true;
189
        for (Bindings b : subBindings) {
228
        for (Bindings b : subBindings) {
190
            b.walkBindings(visited, collect);
229
            ok &= b.walkBindings(visited, collect);
191
        }
230
        }
192
        collect.add(this);
231
        collect.add(this);
232
        return ok;
193
    }
233
    }
194
234
195
    /**
235
    /**
(-)a/api.knockout/test/unit/src/org/netbeans/spi/knockout/BindingsNGTest.java (+30 lines)
Lines 91-96 Link Here
91
        assertEquals(eng.eval("ko.value.currentTweets[0].from_user_id"), 0d, "Boolean values are set to true");
91
        assertEquals(eng.eval("ko.value.currentTweets[0].from_user_id"), 0d, "Boolean values are set to true");
92
    }
92
    }
93
93
94
    @Test
95
    public void generateRecursiveModel() throws Exception {
96
        Bindings m1 = Bindings.create("Hello");
97
        Bindings m2 = Bindings.create("Multi");
98
        m1.modelProperty("multi", m2, false);
99
        m2.modelProperty("hello", m1, false);
100
        m2.intProperty("int", false);
101
        String txt = m2.generate();
102
        assertValidJS(txt);
103
        assertNotNull(eng.eval("ko"), txt);
104
        assertNotNull(eng.eval("Hello.multi"), txt);
105
        assertEquals(eng.eval("Hello.multi.hello === Hello"), Boolean.TRUE, txt);
106
    }
107
108
    @Test
109
    public void generateRecursiveModel2() throws Exception {
110
        Bindings one = Bindings.create("One");
111
        Bindings two = Bindings.create("Two");
112
        Bindings three = Bindings.create("Three");
113
        one.modelProperty("three", three, false);
114
        two.modelProperty("one", one, false);
115
        three.modelProperty("two",two , false);
116
        String txt = two.generate();
117
        assertValidJS(txt);
118
        assertNotNull(eng.eval("ko"), txt);
119
        assertNotNull(eng.eval("One.three"), txt);
120
        assertNotNull(eng.eval("One.three.two"), txt);
121
        assertEquals(eng.eval("One.three.two.one === One"), Boolean.TRUE, txt);
122
    }
123
94
    private void assertValidJS(String txt) {
124
    private void assertValidJS(String txt) {
95
        assertNotNull(txt, "We have some script");
125
        assertNotNull(txt, "We have some script");
96
        try {
126
        try {

Return to bug 251076