com.datastax.driver.mapping.AnnotationChecks Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scylla-driver-mapping Show documentation
Show all versions of scylla-driver-mapping Show documentation
Object mapper for the CQL Java Driver.
/*
* Copyright DataStax, 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 com.datastax.driver.mapping;
import com.datastax.driver.mapping.annotations.ClusteringColumn;
import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.Computed;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/** Various checks on mapping annotations. */
class AnnotationChecks {
// The package containing the mapping annotations
private static final Package MAPPING_PACKAGE = Table.class.getPackage();
/**
* Checks that a class is decorated with the given annotation, and return the annotation instance.
* Also validates that no other mapping annotation is present.
*/
static T getTypeAnnotation(Class annotation, Class> annotatedClass) {
T instance = annotatedClass.getAnnotation(annotation);
if (instance == null)
throw new IllegalArgumentException(
String.format(
"@%s annotation was not found on %s", annotation.getSimpleName(), annotatedClass));
// Check that no other mapping annotations are present
validateAnnotations(annotatedClass, annotation);
return instance;
}
private static void validateAnnotations(Class> clazz, Class extends Annotation> allowed) {
Collection classAnnotations = new HashSet();
Collections.addAll(classAnnotations, clazz.getAnnotations());
Class extends Annotation> invalid =
validateAnnotations(classAnnotations, Collections.singleton(allowed));
if (invalid != null)
throw new IllegalArgumentException(
String.format(
"Cannot have both @%s and @%s on %s",
allowed.getSimpleName(), invalid.getSimpleName(), clazz));
}
/**
* Checks that a field is only annotated with the given mapping annotations, and that its "frozen"
* annotations are valid.
*/
static void validateAnnotations(
String propertyName,
Map, Annotation> annotations,
Collection extends Class extends Annotation>> allowed) {
Class extends Annotation> invalid = validateAnnotations(annotations.values(), allowed);
if (invalid != null) {
throw new IllegalArgumentException(
String.format(
"Annotation @%s is not allowed on property '%s'",
invalid.getSimpleName(), propertyName));
}
checkValidPrimaryKey(propertyName, annotations);
checkValidComputed(propertyName, annotations);
}
// Returns the offending annotation if there is one
private static Class extends Annotation> validateAnnotations(
Collection annotations,
Collection extends Class extends Annotation>> allowed) {
for (Annotation annotation : annotations) {
Class extends Annotation> actual = annotation.annotationType();
if (actual.getPackage().equals(MAPPING_PACKAGE) && !allowed.contains(actual)) return actual;
}
return null;
}
private static void checkValidPrimaryKey(
String propertyName, Map, Annotation> annotations) {
if (annotations.containsKey(PartitionKey.class)
&& annotations.containsKey(ClusteringColumn.class))
throw new IllegalArgumentException(
String.format(
"Property '%s' cannot be annotated with both @PartitionKey and @ClusteringColumn",
propertyName));
}
private static void checkValidComputed(
String propertyName, Map, Annotation> annotations) {
if (annotations.containsKey(Computed.class)) {
Computed computed = (Computed) annotations.get(Computed.class);
if (computed.value().isEmpty()) {
throw new IllegalArgumentException(
String.format(
"Property '%s': attribute 'value' of annotation @Computed is mandatory for computed properties",
propertyName));
}
if (annotations.containsKey(Column.class)) {
throw new IllegalArgumentException(
String.format(
"Property '%s' cannot be annotated with both @Column and @Computed", propertyName));
}
}
}
static void validateOrder(List properties, String annotation) {
for (int i = 0; i < properties.size(); i++) {
AliasedMappedProperty property = properties.get(i);
int pos = property.mappedProperty.getPosition();
if (pos != i)
throw new IllegalArgumentException(
String.format(
"Invalid ordering value %d for annotation %s of property '%s', was expecting %d",
pos, annotation, property.mappedProperty.getPropertyName(), i));
}
}
}