From 7b199738361b620bdd642a2ceeee440b31044789 Mon Sep 17 00:00:00 2001
From: Roland Praml NOT NULL generation on DDL.
+ * Normally if you put the {@link NotNull} annotation on a property, Ebean will only generate a
+ * NOT NULL in DDL if you do not change the validation-groups!
+ */
+public interface EbeanDDL {
+
+}
diff --git a/src/main/java/com/avaje/ebean/annotation/Formula.java b/src/main/java/com/avaje/ebean/annotation/Formula.java
index 647edcfd1..e0b9cb682 100644
--- a/src/main/java/com/avaje/ebean/annotation/Formula.java
+++ b/src/main/java/com/avaje/ebean/annotation/Formula.java
@@ -1,11 +1,13 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.avaje.ebean.Query;
+import com.avaje.ebean.config.dbplatform.DatabasePlatform;
/**
* Assign to a property to be based on a SQL formula.
@@ -67,6 +69,7 @@ import com.avaje.ebean.Query;
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(Formula.List.class)
public @interface Formula {
/**
@@ -102,5 +105,17 @@ public @interface Formula {
* }
*/
String join() default "";
+
+ Class extends DatabasePlatform>[] platforms() default {};
+
+ /**
+ * Repeatable support for {@link Formula}.
+ */
+ @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface List {
+
+ Formula[] value() default {};
+ }
}
diff --git a/src/main/java/com/avaje/ebean/annotation/Where.java b/src/main/java/com/avaje/ebean/annotation/Where.java
index 5fc586593..2c9ccf03a 100644
--- a/src/main/java/com/avaje/ebean/annotation/Where.java
+++ b/src/main/java/com/avaje/ebean/annotation/Where.java
@@ -1,10 +1,13 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import com.avaje.ebean.config.dbplatform.DatabasePlatform;
+
/**
* Add an Literal to add to the where clause when a many property (List, Set or
* Map) is loaded or refreshed.
@@ -40,6 +43,7 @@ import java.lang.annotation.Target;
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(Where.List.class)
public @interface Where {
/**
@@ -50,5 +54,19 @@ public @interface Where {
*
* Looks first at the field and then at the getter method. *
+ *
+ * If a repeatable annotation class is specified and the annotation is platform
+ * specific(see {@link #getPlatformMatchingAnnotation(Set, Class)}), then the platform specific
+ * annotation is returned. Otherwise the first annotation is retured. Note that you must no longer
+ * handle "java 1.6 repeatable containers" like {@link JoinColumn} / {@link JoinColumns} yourself.
+ *
*/
protected
@@ -69,7 +108,7 @@ public abstract class AnnotationBase {
protected
* Warning: this method operates generically on annotated elements. In other words, this method
* does not execute specialized search algorithms for classes or methods. It only traverses through Annotations!
+ * It also does not filter out platform dependent annotations!
*/
public static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType) {
if (annotationType == null) {
@@ -132,6 +172,19 @@ public abstract class AnnotationBase {
}
}
+ /**
+ * Finds the first annotation of a type for this platform. (if annotation is platform specific, otherwise first
+ * found annotation is returned)
+ */
+ public static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType,
+ Class extends DatabasePlatform> databasePlatform) {
+ if (annotationType == null) {
+ return null;
+ }
+ Set anns = findAnnotations(annotatedElement, annotationType);
+ return getPlatformMatchingAnnotation(anns, databasePlatform);
+ }
+
/**
* Perform the search algorithm avoiding endless recursion by tracking which
* annotations have already been visited.
@@ -139,7 +192,7 @@ public abstract class AnnotationBase {
@SuppressWarnings("unchecked")
private static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType, Set
+ * Meta-annotations will be searched if the annotation is not directly present on the supplied element.
+ *
+ * Warning: this method operates generically on annotated elements. In other words, this method
+ * does not execute specialized search algorithms for classes or methods. It only traverses through Annotations!
+ */
+ public static Set findAnnotations(AnnotatedElement annotatedElement, Class annotationType) {
+ if (annotationType == null) {
+ return null;
+ }
+ Set ret = new LinkedHashSet();
+ findMetaAnnotations(annotatedElement, annotationType, ret, new HashSet
+ * value() method for a possible containerAnnotation.
+ * Method is retuned only, if its signature is array of containingType.
+ */
+ private static Method getRepeatableValueMethod(
+ Annotation containerAnnotation, Class containingType) {
+
+ Method method = valueMethods.get(containerAnnotation);
+ if (method == null) {
+ try {
+ method = containerAnnotation.annotationType().getMethod("value");
+ } catch (NoSuchMethodException e) {
+ method = nullMethod;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ Method prev = valueMethods.putIfAbsent(containerAnnotation, method);
+ method = prev == null ? method : prev;
+ }
+ if (method != nullMethod) {
+ Class> retType = method.getReturnType();
+ if (retType.isArray() && retType.getComponentType() == containingType) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds a suitable annotation from Set for this platform.
+ * To distinguish between platforms, annotation type T must define
+ * a method withthis signature:
+ * Class extends DatabasePlatform>[] platforms() default {};
+ *
+ *
+ * (This mechanism is currently used by {@link Where} and {@link Formula})
+ */
+ public static ann[0]
+ * databasePlatform