diff options
author | Denis Anisimov <denis@vaadin.com> | 2014-11-22 12:27:01 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2016-02-29 13:11:16 +0000 |
commit | 89f76b9dbad93260632ae1e025b607daa64d9f81 (patch) | |
tree | 565b39d3080cf219ada68cfcf6c49f2d8d89f8d6 | |
parent | 4ee39c397a85618e65d2e5dcd3ec556569a73719 (diff) | |
download | vaadin-framework-89f76b9dbad93260632ae1e025b607daa64d9f81.tar.gz vaadin-framework-89f76b9dbad93260632ae1e025b607daa64d9f81.zip |
Use @Inherited for annotations that have inherited semantic (#12351).
Change-Id: I70f0d79095bfd05b83905df6a3eedd1a5e93b48e
-rw-r--r-- | WebContent/release-notes.html | 2 | ||||
-rw-r--r-- | server/src/com/vaadin/annotations/PreserveOnRefresh.java | 2 | ||||
-rw-r--r-- | server/src/com/vaadin/annotations/Push.java | 2 | ||||
-rw-r--r-- | server/src/com/vaadin/annotations/Theme.java | 2 | ||||
-rw-r--r-- | server/src/com/vaadin/annotations/Title.java | 2 | ||||
-rw-r--r-- | server/src/com/vaadin/annotations/VaadinServletConfiguration.java | 2 | ||||
-rw-r--r-- | server/src/com/vaadin/annotations/Widgetset.java | 2 | ||||
-rw-r--r-- | server/src/com/vaadin/server/UIProvider.java | 34 | ||||
-rw-r--r-- | server/tests/src/com/vaadin/server/UIProviderTest.java | 113 |
9 files changed, 152 insertions, 9 deletions
diff --git a/WebContent/release-notes.html b/WebContent/release-notes.html index 4286b3ace0..f7b5611be5 100644 --- a/WebContent/release-notes.html +++ b/WebContent/release-notes.html @@ -140,6 +140,8 @@ cause problems with external libraries compiled against said versions.</li> <li>Declarative format is now using "vaadin-" as a default prefix instead of the "v-" prefix used in 7.5. This default can be changed in deployment configuration.</li> + <li>The annotations @PreserveOnRefresh, @Push, @Theme, @Title, @VaadinServletConfiguration and @Widgetset now use + @Inherited. The annotation is also looked up in extended interfaces for backwards compatibility.</li> </ul> <h3 id="knownissues">Known Issues and Limitations</h3> <ul> diff --git a/server/src/com/vaadin/annotations/PreserveOnRefresh.java b/server/src/com/vaadin/annotations/PreserveOnRefresh.java index 7f4ef3ffe5..86723b97fc 100644 --- a/server/src/com/vaadin/annotations/PreserveOnRefresh.java +++ b/server/src/com/vaadin/annotations/PreserveOnRefresh.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -45,6 +46,7 @@ import com.vaadin.ui.UI; */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) +@Inherited public @interface PreserveOnRefresh { // Empty marker annotation } diff --git a/server/src/com/vaadin/annotations/Push.java b/server/src/com/vaadin/annotations/Push.java index b6a28c1560..736bc4488b 100644 --- a/server/src/com/vaadin/annotations/Push.java +++ b/server/src/com/vaadin/annotations/Push.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -38,6 +39,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Push { /** * Returns the {@link PushMode} to use for the annotated UI. The default diff --git a/server/src/com/vaadin/annotations/Theme.java b/server/src/com/vaadin/annotations/Theme.java index 61c47389ad..03fa1179bc 100644 --- a/server/src/com/vaadin/annotations/Theme.java +++ b/server/src/com/vaadin/annotations/Theme.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -28,6 +29,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Theme { /** * @return simple name of the theme diff --git a/server/src/com/vaadin/annotations/Title.java b/server/src/com/vaadin/annotations/Title.java index 38a3d75f17..07eaf17e33 100644 --- a/server/src/com/vaadin/annotations/Title.java +++ b/server/src/com/vaadin/annotations/Title.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -28,6 +29,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Title { /** * Gets the HTML title that should be used if the UI is used on it's own. diff --git a/server/src/com/vaadin/annotations/VaadinServletConfiguration.java b/server/src/com/vaadin/annotations/VaadinServletConfiguration.java index 00af38ecc1..907f2c3a0c 100644 --- a/server/src/com/vaadin/annotations/VaadinServletConfiguration.java +++ b/server/src/com/vaadin/annotations/VaadinServletConfiguration.java @@ -18,6 +18,7 @@ package com.vaadin.annotations; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -44,6 +45,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface VaadinServletConfiguration { /** * Defines the init parameter name for methods in diff --git a/server/src/com/vaadin/annotations/Widgetset.java b/server/src/com/vaadin/annotations/Widgetset.java index c6ef6a7194..2dcf93af13 100644 --- a/server/src/com/vaadin/annotations/Widgetset.java +++ b/server/src/com/vaadin/annotations/Widgetset.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -28,6 +29,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Widgetset { /** * @return name of the widgetset diff --git a/server/src/com/vaadin/server/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java index d3d834cad7..4ed86b9c31 100644 --- a/server/src/com/vaadin/server/UIProvider.java +++ b/server/src/com/vaadin/server/UIProvider.java @@ -18,6 +18,7 @@ package com.vaadin.server; import java.io.Serializable; import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; import com.vaadin.annotations.PreserveOnRefresh; import com.vaadin.annotations.Push; @@ -43,8 +44,15 @@ public abstract class UIProvider implements Serializable { /** * Helper to get an annotation for a class. If the annotation is not present - * on the target class, its super classes and implemented interfaces are - * also searched for the annotation. + * on the target class, its super classes and directly implemented + * interfaces are also searched for the annotation. Interfaces implemented + * by superclasses are not taken into account. + * <p> + * Note that searching implemented interfaces for {@code @Inherited} + * annotations and searching for superclasses for non-inherited annotations + * do not follow the standard semantics and are supported for backwards + * compatibility. Future versions of the framework might only support the + * standard semantics of {@code @Inherited}. * * @param clazz * the class from which the annotation should be found @@ -55,18 +63,26 @@ public abstract class UIProvider implements Serializable { */ protected static <T extends Annotation> T getAnnotationFor(Class<?> clazz, Class<T> annotationType) { - // Find from the class hierarchy - Class<?> currentType = clazz; - while (currentType != Object.class) { - T annotation = currentType.getAnnotation(annotationType); + // Don't discover hierarchy if annotation is inherited + if (annotationType.getAnnotation(Inherited.class) != null) { + T annotation = clazz.getAnnotation(annotationType); if (annotation != null) { return annotation; - } else { - currentType = currentType.getSuperclass(); + } + } else { + // Find from the class hierarchy + Class<?> currentType = clazz; + while (currentType != Object.class) { + T annotation = currentType.getAnnotation(annotationType); + if (annotation != null) { + return annotation; + } else { + currentType = currentType.getSuperclass(); + } } } - // Find from an implemented interface + // Find from a directly implemented interface for (Class<?> iface : clazz.getInterfaces()) { T annotation = iface.getAnnotation(annotationType); if (annotation != null) { diff --git a/server/tests/src/com/vaadin/server/UIProviderTest.java b/server/tests/src/com/vaadin/server/UIProviderTest.java new file mode 100644 index 0000000000..579a3f1858 --- /dev/null +++ b/server/tests/src/com/vaadin/server/UIProviderTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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.vaadin.server; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.annotations.Theme; +import com.vaadin.annotations.Widgetset; + +/** + * Tests for {@link UIProvider} class. + * + * @author Vaadin Ltd + */ +public class UIProviderTest { + + @Test + public void getAnnotationFor_widgetsetAnnotationForSubclass_annotationFound() { + Assert.assertNotNull("Widgetset annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, Widgetset.class)); + } + + @Test + public void getAnnotationFor_themeAnnotationForSubclass_annotationFound() { + Assert.assertNotNull("Theme annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, Theme.class)); + } + + @Test + public void getAnnotationFor_themeAnnotationForSubclass_annotationOverridden() { + Assert.assertEquals( + "Theme annotation is not overridden correctly in subclass", + "c", UIProvider.getAnnotationFor(TestClass.class, Theme.class) + .value()); + } + + @Test + public void getAnnotationFor_notInheritedAnnotationForSubclass_annotationFound() { + Assert.assertNotNull( + "TestAnnotation annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, + TestAnnotation.class)); + } + + @Test + public void getAnnotationFor_directAnnotationForSubclass_annotationFound() { + Assert.assertNotNull( + "TestAnnotation1 annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, + TestAnnotation1.class)); + } + + @Test + public void getAnnotationFor_annotationInheritedFromInterface_annotationFound() { + Assert.assertNotNull( + "Theme annotation is not inherited from interface", UIProvider + .getAnnotationFor(ClassImplementingInterface.class, + Theme.class)); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface TestAnnotation { + + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface TestAnnotation1 { + + } + + @Widgetset("a") + @Theme("b") + @TestAnnotation + public static class TestSuperClass { + + } + + @TestAnnotation1 + @Theme("c") + public static class TestClass extends TestSuperClass { + + } + + @Theme("d") + public interface InterfaceWithAnnotation { + } + + public static class ClassImplementingInterface implements + InterfaceWithAnnotation { + } + +} |