/*
* Copyright 2008-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.nominanuda.web.mvc;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.LinkedList;
import java.util.List;
import com.nominanuda.urispec.StringModelAdapter;
import com.nominanuda.urispec.URISpec;
import com.nominanuda.zen.common.Check;
import com.nominanuda.zen.common.Ex.NoException;
import com.nominanuda.zen.obj.Arr;
import com.nominanuda.zen.obj.JsonPath;
import com.nominanuda.zen.obj.JsonSerializer;
import com.nominanuda.zen.obj.JsonType;
import com.nominanuda.zen.obj.Obj;
import com.nominanuda.zen.obj.Stru;
import com.nominanuda.zen.obj.JsonPath.SafeConvertor;
public class ObjURISpec extends URISpec<Obj> {
private static final JsonSerializer jsonSerializer = new JsonSerializer();
private static final ObjStringModelAdapter defaultModelAdapter = new ObjStringModelAdapter();
public ObjURISpec(String spec) {
super(spec, defaultModelAdapter);
}
static class ObjStringModelAdapter implements StringModelAdapter<Obj> {
private JsonPath M = new JsonPath();
private final static XURLDecoder urlDecoder = new XURLDecoder();
public List<String> getAsList(Obj model, String path) {
LinkedList<String> res = new LinkedList<String>();
Object val = M.getPathSafe(model, path);
if(val == null) {
return null;
}
if(JsonType.isArr(val)) {
Arr a = (Arr)val;
int len = a.len();
for(int i = 0; i < len; i++) {
while(res.size() < i+1) {
res.add(null);
}
Object v = a.fetch(i);
res.set(i, v == null ? null : v.toString());
}
} else {
res.add(val.toString());
}
return res;
}
public Obj createStringModel() {
return Obj.make();
}
public void setAll(Obj from, Obj to) {
M.copy(from, to, JsonPath.MERGE_POLICY_OVERRIDE);
}
public void pushAll(Obj from, Obj to) {
M.copy(M.convertLeaves(from, urlDecoder), to,
JsonPath.MERGE_POLICY_PUSH);
}
public void push(Obj model, String path, String val) {
M.setOrPushPathProperty(model, path, urlDecoder.apply(val));
}
@Override
public void set(Obj model, String path, String val) {
M.setPathProperty(model, path, urlDecoder.apply(val));
}
public boolean validateModel(Object m) {
return m != null && m instanceof Obj;
}
public void set(Obj model, String key, List<String> val) {
Arr arr = Arr.make();
for(String s : val) {
arr.push(urlDecoder.apply(s));
}
M.setPathProperty(model, key, arr);
}
public String getFirst(Obj model, String key) {
Object o = M.getPathSafe(model, key);
if(o == null) {
return null;
} else if(JsonType.isNullablePrimitive(o)) {
return jsonSerializer.toString(o);
} else if(JsonType.isArr(o)) {
Arr a = (Arr)o;
if(a.len() == 0) {
return null;
} else {
Object v = a.fetch(0);
Check.illegalargument.assertTrue(JsonType.isNullablePrimitive(v));
return v == null
? null : jsonSerializer.toString(v);
}
} else {
return Check.illegalargument.fail();
}
}
private static class XURLDecoder implements SafeConvertor<Object,Object> {
public Object apply(Object x) throws NoException {
try {
return x == null ? null : URLDecoder.decode(((String)x), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e);
}
}
public boolean canConvert(Object o) {
return true;
}
}
}
}