Skip to content

Commit 95d93b7

Browse files
committed
Revert "JAVA-541 + JAVA-636 + JAVA-984: Polymorphism support to object mapper (apache#686)"
This reverts commit 4a0bc16. The branch was inadvertently merged with the "squash and merge" strategy, the next commit re-merges it with a merge commit to preserve history.
1 parent 4a0bc16 commit 95d93b7

37 files changed

Lines changed: 837 additions & 2047 deletions

changelog/README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
- [new feature] JAVA-1157: Allow asynchronous paging of Mapper Result.
1111
- [improvement] JAVA-1212: Don't retry non-idempotent statements by default.
1212
- [improvement] JAVA-1192: Make EventDebouncer settings updatable at runtime.
13-
- [new feature] JAVA-541: Add polymorphism support to object mapper.
14-
- [new feature] JAVA-636: Allow @Column annotations on getters/setters as well as fields.
15-
- [new feature] JAVA-984: Allow non-void setters in object mapping.
1613

1714
Merged from 3.0.x branch:
1815

clirr-ignores.xml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,6 @@
1313
-->
1414
<differences>
1515

16-
<difference>
17-
<differenceType>8001</differenceType> <!-- class removed -->
18-
<className>com/datastax/driver/mapping/ColumnMapper$Kind</className>
19-
<justification>False positive, the enclosing class is package-private so this was never exposed</justification>
20-
</difference>
21-
22-
2316
<difference>
2417
<differenceType>1001</differenceType> <!-- decreased visibility -->
2518
<className>com/datastax/driver/mapping/ColumnMapper$Kind</className>

driver-core/src/main/java/com/datastax/driver/core/ClusteringOrder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ public enum ClusteringOrder {
2525

2626
ASC, DESC;
2727

28-
}
28+
}

driver-mapping/src/main/java/com/datastax/driver/mapping/AccessorMapper.java

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,22 @@
1919
import com.google.common.util.concurrent.Futures;
2020
import com.google.common.util.concurrent.ListenableFuture;
2121

22-
import java.lang.reflect.Proxy;
2322
import java.util.ArrayList;
2423
import java.util.List;
2524

26-
class AccessorMapper<T> {
25+
abstract class AccessorMapper<T> {
2726

28-
final Class<T> daoClass;
29-
final List<MethodMapper> methods;
30-
private final Class<T>[] proxyClasses;
31-
private final AccessorInvocationHandler<T> handler;
27+
public final Class<T> daoClass;
28+
protected final List<MethodMapper> methods;
3229

33-
@SuppressWarnings({"unchecked", "rawtypes"})
34-
AccessorMapper(Class<T> daoClass, List<MethodMapper> methods) {
30+
protected AccessorMapper(Class<T> daoClass, List<MethodMapper> methods) {
3531
this.daoClass = daoClass;
3632
this.methods = methods;
37-
this.proxyClasses = (Class<T>[]) new Class[]{daoClass};
38-
this.handler = new AccessorInvocationHandler<T>(this);
3933
}
4034

41-
@SuppressWarnings("unchecked")
42-
T createProxy() {
43-
try {
44-
return (T) Proxy.newProxyInstance(daoClass.getClassLoader(), proxyClasses, handler);
45-
} catch (Exception e) {
46-
throw new RuntimeException("Cannot create instance for Accessor interface " + daoClass.getName());
47-
}
48-
}
35+
abstract T createProxy();
4936

50-
void prepare(MappingManager manager) {
37+
public void prepare(MappingManager manager) {
5138
List<ListenableFuture<PreparedStatement>> statements = new ArrayList<ListenableFuture<PreparedStatement>>(methods.size());
5239

5340
for (MethodMapper method : methods)
@@ -62,4 +49,7 @@ void prepare(MappingManager manager) {
6249
}
6350
}
6451

52+
interface Factory {
53+
public <T> AccessorMapper<T> create(Class<T> daoClass, List<MethodMapper> methods);
54+
}
6555
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (C) 2012-2015 DataStax Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.datastax.driver.mapping;
17+
18+
import java.lang.reflect.Proxy;
19+
import java.util.List;
20+
21+
class AccessorReflectionMapper<T> extends AccessorMapper<T> {
22+
23+
private static AccessorReflectionFactory factory = new AccessorReflectionFactory();
24+
25+
private final Class<T>[] proxyClasses;
26+
private final AccessorInvocationHandler<T> handler;
27+
28+
@SuppressWarnings({"unchecked", "rawtypes"})
29+
private AccessorReflectionMapper(Class<T> daoClass, List<MethodMapper> methods) {
30+
super(daoClass, methods);
31+
this.proxyClasses = (Class<T>[]) new Class[]{daoClass};
32+
this.handler = new AccessorInvocationHandler<T>(this);
33+
}
34+
35+
public static Factory factory() {
36+
return factory;
37+
}
38+
39+
@SuppressWarnings("unchecked")
40+
@Override
41+
public T createProxy() {
42+
try {
43+
return (T) Proxy.newProxyInstance(daoClass.getClassLoader(), proxyClasses, handler);
44+
} catch (Exception e) {
45+
throw new RuntimeException("Cannot create instance for Accessor interface " + daoClass.getName());
46+
}
47+
}
48+
49+
private static class AccessorReflectionFactory implements Factory {
50+
@Override
51+
public <T> AccessorMapper<T> create(Class<T> daoClass, List<MethodMapper> methods) {
52+
return new AccessorReflectionMapper<T>(daoClass, methods);
53+
}
54+
}
55+
}

driver-mapping/src/main/java/com/datastax/driver/mapping/AnnotationChecks.java

Lines changed: 25 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,11 @@
1515
*/
1616
package com.datastax.driver.mapping;
1717

18-
import com.datastax.driver.mapping.annotations.Column;
1918
import com.datastax.driver.mapping.annotations.Computed;
2019
import com.datastax.driver.mapping.annotations.Table;
2120

2221
import java.lang.annotation.Annotation;
23-
import java.util.Collection;
24-
import java.util.Collections;
25-
import java.util.HashSet;
26-
import java.util.List;
22+
import java.lang.reflect.Field;
2723

2824
/**
2925
* Various checks on mapping annotations.
@@ -40,75 +36,59 @@ class AnnotationChecks {
4036
static <T extends Annotation> T getTypeAnnotation(Class<T> annotation, Class<?> annotatedClass) {
4137
T instance = annotatedClass.getAnnotation(annotation);
4238
if (instance == null)
43-
throw new IllegalArgumentException(String.format("@%s annotation was not found on %s",
44-
annotation.getSimpleName(), annotatedClass));
39+
throw new IllegalArgumentException(String.format("@%s annotation was not found on type %s",
40+
annotation.getSimpleName(), annotatedClass.getName()));
4541

4642
// Check that no other mapping annotations are present
4743
validateAnnotations(annotatedClass, annotation);
4844

4945
return instance;
5046
}
5147

52-
@SuppressWarnings("unchecked")
5348
private static void validateAnnotations(Class<?> clazz, Class<? extends Annotation> allowed) {
5449
@SuppressWarnings("unchecked")
55-
Collection<Annotation> classAnnotations = new HashSet<Annotation>();
56-
Collections.addAll(classAnnotations, clazz.getAnnotations());
57-
Class<? extends Annotation> invalid = validateAnnotations(classAnnotations, Collections.singleton(allowed));
50+
Class<? extends Annotation> invalid = validateAnnotations(clazz.getAnnotations(), allowed);
5851
if (invalid != null)
59-
throw new IllegalArgumentException(String.format("Cannot have both @%s and @%s on %s",
52+
throw new IllegalArgumentException(String.format("Cannot have both @%s and @%s on type %s",
6053
allowed.getSimpleName(), invalid.getSimpleName(),
61-
clazz));
54+
clazz.getName()));
6255
}
6356

6457
/**
6558
* Checks that a field is only annotated with the given mapping annotations, and that its "frozen" annotations are valid.
6659
*/
67-
static void validateAnnotations(PropertyMapper property, Collection<? extends Class<? extends Annotation>> allowed) {
68-
Class<? extends Annotation> invalid = validateAnnotations(property.getAnnotations(), allowed);
69-
if (invalid != null) {
70-
throw new IllegalArgumentException(String.format("Annotation @%s is not allowed on property '%s'",
60+
static void validateAnnotations(Field field, String classDescription, Class<? extends Annotation>... allowed) {
61+
Class<? extends Annotation> invalid = validateAnnotations(field.getAnnotations(), allowed);
62+
if (invalid != null)
63+
throw new IllegalArgumentException(String.format("Annotation @%s is not allowed on field %s of %s %s",
7164
invalid.getSimpleName(),
72-
property));
73-
}
74-
checkValidPrimaryKey(property);
75-
checkValidComputed(property);
65+
field.getName(), classDescription,
66+
field.getDeclaringClass().getName()));
67+
68+
checkValidComputed(field);
7669
}
7770

7871
// Returns the offending annotation if there is one
79-
private static Class<? extends Annotation> validateAnnotations(Collection<Annotation> annotations, Collection<? extends Class<? extends Annotation>> allowed) {
72+
private static Class<? extends Annotation> validateAnnotations(Annotation[] annotations, Class<? extends Annotation>... allowed) {
8073
for (Annotation annotation : annotations) {
8174
Class<? extends Annotation> actual = annotation.annotationType();
82-
if (actual.getPackage().equals(MAPPING_PACKAGE) && !allowed.contains(actual))
75+
if (actual.getPackage().equals(MAPPING_PACKAGE) && !contains(allowed, actual))
8376
return actual;
8477
}
8578
return null;
8679
}
8780

88-
private static void checkValidPrimaryKey(PropertyMapper property) {
89-
if (property.isPartitionKey() && property.isClusteringColumn())
90-
throw new IllegalArgumentException(String.format("Property '%s' cannot be annotated with both @PartitionKey and @ClusteringColumn", property));
91-
}
92-
93-
private static void checkValidComputed(PropertyMapper property) {
94-
if (property.isComputed()) {
95-
Computed computed = property.annotation(Computed.class);
96-
if (computed.value().isEmpty()) {
97-
throw new IllegalArgumentException(String.format("Property '%s': attribute 'value' of annotation @Computed is mandatory for computed properties", property));
98-
}
99-
if (property.hasAnnotation(Column.class)) {
100-
throw new IllegalArgumentException(String.format("Property '%s' cannot be annotated with both @Column and @Computed", property));
101-
}
102-
}
81+
private static boolean contains(Object[] array, Object target) {
82+
for (Object element : array)
83+
if (element.equals(target))
84+
return true;
85+
return false;
10386
}
10487

105-
static void validateOrder(List<PropertyMapper> properties, String annotation) {
106-
for (int i = 0; i < properties.size(); i++) {
107-
PropertyMapper property = properties.get(i);
108-
int pos = property.position;
109-
if (pos != i)
110-
throw new IllegalArgumentException(String.format("Invalid ordering value %d for annotation %s of property '%s', was expecting %d",
111-
pos, annotation, property, i));
88+
static void checkValidComputed(Field field) {
89+
Computed computed = field.getAnnotation(Computed.class);
90+
if (computed != null && computed.value().isEmpty()) {
91+
throw new IllegalArgumentException(String.format("Field %s: attribute 'value' of annotation @Computed is mandatory for computed fields", field.getName()));
11292
}
11393
}
11494
}

0 commit comments

Comments
 (0)