implement wrapper to replace Casser.pojo
This commit is contained in:
parent
64d2d6fdd9
commit
5c88f2d4e4
11 changed files with 220 additions and 30 deletions
|
@ -19,6 +19,7 @@ import java.lang.reflect.Method;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import casser.core.Instantiator;
|
import casser.core.Instantiator;
|
||||||
|
import casser.core.WrapperInstantiator;
|
||||||
|
|
||||||
public interface CasserSettings {
|
public interface CasserSettings {
|
||||||
|
|
||||||
|
@ -33,5 +34,7 @@ public interface CasserSettings {
|
||||||
Instantiator getDslInstantiator();
|
Instantiator getDslInstantiator();
|
||||||
|
|
||||||
Instantiator getPojoInstantiator();
|
Instantiator getPojoInstantiator();
|
||||||
|
|
||||||
|
WrapperInstantiator getWrapperInstantiator();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,10 @@ import java.lang.reflect.Method;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import casser.core.Instantiator;
|
import casser.core.Instantiator;
|
||||||
|
import casser.core.WrapperInstantiator;
|
||||||
import casser.core.reflect.ReflectionDslInstantiator;
|
import casser.core.reflect.ReflectionDslInstantiator;
|
||||||
import casser.core.reflect.ReflectionPojoInstantiator;
|
import casser.core.reflect.ReflectionPojoInstantiator;
|
||||||
|
import casser.core.reflect.ReflectionWrapperInstantiator;
|
||||||
import casser.mapping.convert.CamelCaseToUnderscoreConverter;
|
import casser.mapping.convert.CamelCaseToUnderscoreConverter;
|
||||||
import casser.mapping.convert.MethodNameToPropertyConverter;
|
import casser.mapping.convert.MethodNameToPropertyConverter;
|
||||||
|
|
||||||
|
@ -56,6 +58,9 @@ public class DefaultCasserSettings implements CasserSettings {
|
||||||
return ReflectionPojoInstantiator.INSTANCE;
|
return ReflectionPojoInstantiator.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WrapperInstantiator getWrapperInstantiator() {
|
||||||
|
return ReflectionWrapperInstantiator.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package casser.core;
|
package casser.core;
|
||||||
|
|
||||||
import java.lang.reflect.Proxy;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import casser.config.CasserSettings;
|
import casser.config.CasserSettings;
|
||||||
import casser.config.DefaultCasserSettings;
|
import casser.config.DefaultCasserSettings;
|
||||||
import casser.core.reflect.DslInvocationHandler;
|
|
||||||
import casser.core.reflect.PojoInvocationHandler;
|
|
||||||
import casser.mapping.convert.UDTValueWritable;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.Cluster;
|
import com.datastax.driver.core.Cluster;
|
||||||
import com.datastax.driver.core.Session;
|
import com.datastax.driver.core.Session;
|
||||||
|
@ -97,5 +94,13 @@ public final class Casser {
|
||||||
public static <E> E pojo(Class<E> iface, ClassLoader classLoader) {
|
public static <E> E pojo(Class<E> iface, ClassLoader classLoader) {
|
||||||
return settings.getPojoInstantiator().instantiate(iface, classLoader);
|
return settings.getPojoInstantiator().instantiate(iface, classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <E> E wrap(Map<String, Object> map, Class<E> iface) {
|
||||||
|
return wrap(map, iface, iface.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> E wrap(Map<String, Object> map, Class<E> iface, ClassLoader classLoader) {
|
||||||
|
return settings.getWrapperInstantiator().instantiate(map, iface, classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
24
src/main/java/casser/core/WrapperInstantiator.java
Normal file
24
src/main/java/casser/core/WrapperInstantiator.java
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Noorq, Inc.
|
||||||
|
*
|
||||||
|
* 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 casser.core;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface WrapperInstantiator {
|
||||||
|
|
||||||
|
<E> E instantiate(Map<String, Object> map, Class<E> iface, ClassLoader classLoader);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Noorq, Inc.
|
||||||
|
*
|
||||||
|
* 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 casser.core.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import casser.core.WrapperInstantiator;
|
||||||
|
import casser.mapping.MapExportable;
|
||||||
|
|
||||||
|
public enum ReflectionWrapperInstantiator implements WrapperInstantiator {
|
||||||
|
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <E> E instantiate(Map<String, Object> map, Class<E> iface,
|
||||||
|
ClassLoader classLoader) {
|
||||||
|
|
||||||
|
WrapperInvocationHandler<E> handler = new WrapperInvocationHandler<E>(map, iface);
|
||||||
|
E proxy = (E) Proxy.newProxyInstance(
|
||||||
|
classLoader,
|
||||||
|
new Class[] { iface, MapExportable.class },
|
||||||
|
handler);
|
||||||
|
return proxy;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Noorq, Inc.
|
||||||
|
*
|
||||||
|
* 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 casser.core.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import casser.mapping.MapExportable;
|
||||||
|
import casser.support.CasserException;
|
||||||
|
|
||||||
|
public class WrapperInvocationHandler<E> implements InvocationHandler {
|
||||||
|
|
||||||
|
private final Map<String, Object> map;
|
||||||
|
private final Class<E> iface;
|
||||||
|
|
||||||
|
public WrapperInvocationHandler(Map<String, Object> map, Class<E> iface) {
|
||||||
|
this.map = map;
|
||||||
|
this.iface = iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args)
|
||||||
|
throws Throwable {
|
||||||
|
|
||||||
|
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
|
||||||
|
throw new CasserException("invalid getter method " + method);
|
||||||
|
}
|
||||||
|
|
||||||
|
String methodName = method.getName();
|
||||||
|
|
||||||
|
if ("toString".equals(methodName)) {
|
||||||
|
return "Wrapper:" + iface + ":" + map.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
|
||||||
|
return Collections.unmodifiableMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object value = map.get(methodName);
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
|
||||||
|
Class<?> returnType = method.getReturnType();
|
||||||
|
|
||||||
|
if (returnType.isPrimitive()) {
|
||||||
|
|
||||||
|
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType);
|
||||||
|
if (type == null) {
|
||||||
|
throw new CasserException("unknown primitive type " + returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type.getDefaultValue();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/main/java/casser/mapping/MapExportable.java
Normal file
26
src/main/java/casser/mapping/MapExportable.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Noorq, Inc.
|
||||||
|
*
|
||||||
|
* 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 casser.mapping;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface MapExportable {
|
||||||
|
|
||||||
|
public static final String TO_MAP_METHOD = "toMap";
|
||||||
|
|
||||||
|
Map<String, Object> toMap();
|
||||||
|
|
||||||
|
}
|
|
@ -15,17 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package casser.test.unit.core.dsl;
|
package casser.test.unit.core.dsl;
|
||||||
|
|
||||||
|
import casser.mapping.MapExportable;
|
||||||
import casser.mapping.Table;
|
import casser.mapping.Table;
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
public interface Account {
|
public interface Account extends MapExportable {
|
||||||
|
|
||||||
String getId();
|
Long id();
|
||||||
|
|
||||||
void setId(String acc);
|
boolean active();
|
||||||
|
|
||||||
boolean isActive();
|
|
||||||
|
|
||||||
void setActive(boolean a);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,14 @@ public class DslTest {
|
||||||
|
|
||||||
System.out.println("account = " + account);
|
System.out.println("account = " + account);
|
||||||
|
|
||||||
|
/*
|
||||||
try {
|
try {
|
||||||
account.getId();
|
account.id();
|
||||||
}
|
}
|
||||||
catch(DslPropertyException e) {
|
catch(DslPropertyException e) {
|
||||||
System.out.println(e.getProperty());
|
System.out.println(e.getProperty());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,44 +15,52 @@
|
||||||
*/
|
*/
|
||||||
package casser.test.unit.core.dsl;
|
package casser.test.unit.core.dsl;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import casser.core.Casser;
|
import casser.core.Casser;
|
||||||
import casser.support.CasserException;
|
import casser.support.CasserException;
|
||||||
|
|
||||||
public class PojoTest {
|
public class WrapperTest {
|
||||||
|
|
||||||
Account account = Casser.pojo(Account.class);
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObject() throws Exception {
|
public void testWrap() throws Exception {
|
||||||
|
|
||||||
Assert.assertNull(account.getId());
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
map.put("id", 123L);
|
||||||
|
map.put("active", Boolean.TRUE);
|
||||||
|
map.put("unknownField", "he-he");
|
||||||
|
|
||||||
account.setId("testAcc");
|
Account account = Casser.wrap(map, Account.class);
|
||||||
|
|
||||||
Assert.assertEquals("testAcc", account.getId());
|
Assert.assertEquals(Long.valueOf(123L), account.id());
|
||||||
|
Assert.assertTrue(account.active());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrimitive() throws Exception {
|
public void testPrimitive() throws Exception {
|
||||||
|
|
||||||
Assert.assertFalse(account.isActive());
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
|
|
||||||
account.setActive(true);
|
map.put("id", 123L);
|
||||||
|
|
||||||
Assert.assertEquals(true, account.isActive());
|
|
||||||
|
|
||||||
|
|
||||||
|
Account account = Casser.wrap(map, Account.class);
|
||||||
|
|
||||||
|
Assert.assertFalse(account.active());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected=CasserException.class)
|
@Test(expected=CasserException.class)
|
||||||
public void testWrongMethods() throws Exception {
|
public void testWrongMethods() throws Exception {
|
||||||
|
|
||||||
Casser.pojo(WrongAccount.class);
|
WrongAccount wrongAccount = Casser.wrap(new HashMap<String, Object>(), WrongAccount.class);
|
||||||
|
|
||||||
|
wrongAccount.id();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,6 @@ package casser.test.unit.core.dsl;
|
||||||
|
|
||||||
public interface WrongAccount {
|
public interface WrongAccount {
|
||||||
|
|
||||||
void getId();
|
void id();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue