blob: 85dd0be312f3525e245d23e1b1cc0a7f632eb072 [file] [log] [blame]
/**
* HTML via Java(tm) Language Bindings
* Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
*
* 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 net.java.html.json;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import org.apidesign.html.json.impl.WrapperObject;
import org.apidesign.html.json.spi.ContextBuilder;
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;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
/**
*
* @author Jaroslav Tulach <jtulach@netbeans.org>
*/
public class MapModelTest {
private MapTechnology t;
private Context c;
@BeforeMethod public void initTechnology() {
t = new MapTechnology();
c = ContextBuilder.create().withTechnology(t).withTransfer(t).build();
}
@Test public void isThereABinding() throws Exception {
Person p = new Person(c);
p.setFirstName("Jarda");
Map m = (Map)WrapperObject.find(p);
Object v = m.get("firstName");
assertNotNull(v, "Value should be in the map");
assertEquals(v.getClass(), One.class, "It is instance of One");
One o = (One)v;
assertEquals(o.changes, 1, "One change so far");
assertFalse(o.pb.isReadOnly(), "Mutable property");
assertEquals(o.get(), "Jarda", "Value should be in the map");
o.set("Karle");
assertEquals(p.getFirstName(), "Karle", "Model value updated");
assertEquals(o.changes, 2, "Snd change");
}
@Test public void derivedProperty() throws Exception {
Person p = new Person(c);
Map m = (Map)WrapperObject.find(p);
Object v = m.get("fullName");
assertNotNull(v, "Value should be in the map");
assertEquals(v.getClass(), One.class, "It is instance of One");
One o = (One)v;
assertTrue(o.pb.isReadOnly(), "Mutable property");
}
@Test public void changeSex() {
Person p = new Person(c);
p.setFirstName("Trans");
p.setSex(Sex.MALE);
Map m = (Map)WrapperObject.find(p);
Object o = m.get("changeSex");
assertNotNull(o, "Function registered in the model");
assertEquals(o.getClass(), One.class);
One one = (One)o;
assertNotNull(one.fb, "Function binding specified");
one.fb.call(null, null);
assertEquals(p.getSex(), Sex.FEMALE, "Changed");
}
@Test public void setSex() {
Person p = new Person(c);
p.setFirstName("Trans");
Map m = (Map)WrapperObject.find(p);
Object o = m.get("changeSex");
assertNotNull(o, "Function registered in the model");
assertEquals(o.getClass(), One.class);
One one = (One)o;
assertNotNull(one.fb, "Function binding specified");
one.fb.call("FEMALE", new Object());
assertEquals(p.getSex(), Sex.FEMALE, "Changed");
}
static final class One {
int changes;
final PropertyBinding pb;
final FunctionBinding fb;
One(Object m, PropertyBinding pb) throws NoSuchMethodException {
this.pb = pb;
this.fb = null;
}
One(Object m, FunctionBinding fb) throws NoSuchMethodException {
this.pb = null;
this.fb = fb;
}
Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return pb.getValue();
}
void set(Object v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
pb.setValue(v);
}
}
static final class MapTechnology
implements Technology<Map<String,One>>, Transfer {
@Override
public Map<String, One> wrapModel(Object model) {
return new HashMap<String, One>();
}
@Override
public void valueHasMutated(Map<String, One> data, String propertyName) {
One p = data.get(propertyName);
if (p != null) {
p.changes++;
}
}
@Override
public void bind(PropertyBinding b, Object model, Map<String, One> data) {
try {
One o = new One(model, b);
data.put(b.getPropertyName(), o);
} catch (NoSuchMethodException ex) {
throw new IllegalStateException(ex);
}
}
@Override
public void expose(FunctionBinding fb, Object model, Map<String, One> data) {
try {
data.put(fb.getFunctionName(), new One(model, fb));
} catch (NoSuchMethodException ex) {
throw new IllegalStateException(ex);
}
}
@Override
public void applyBindings(Map<String, One> data) {
}
@Override
public Object wrapArray(Object[] arr) {
return arr;
}
@Override
public void extract(Object obj, String[] props, Object[] values) {
Map<?,?> map = obj instanceof Map ? (Map<?,?>)obj : null;
for (int i = 0; i < Math.min(props.length, values.length); i++) {
if (map == null) {
values[i] = null;
} else {
values[i] = map.get(props[i]);
if (values[i] instanceof One) {
values[i] = ((One)values[i]).pb.getValue();
}
}
}
}
@Override
public void loadJSON(JSONCall call) {
call.notifyError(new UnsupportedOperationException());
}
@Override
public <M> M toModel(Class<M> modelClass, Object data) {
return modelClass.cast(data);
}
@Override
public Object toJSON(InputStream is) throws IOException {
throw new IOException();
}
}
}