001/* 002 * Copyright 2015 SirWellington Tech. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANYTIME KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package tech.sirwellington.alchemy.test.junit.runners; 018 019import java.lang.annotation.Retention; 020import java.lang.annotation.Target; 021import java.nio.ByteBuffer; 022import java.time.Instant; 023import java.util.Date; 024import java.util.List; 025 026import tech.sirwellington.alchemy.annotations.access.Internal; 027import tech.sirwellington.alchemy.annotations.access.NonInstantiable; 028import tech.sirwellington.alchemy.generator.*; 029 030import static java.lang.annotation.ElementType.FIELD; 031import static java.lang.annotation.RetentionPolicy.RUNTIME; 032import static tech.sirwellington.alchemy.generator.CollectionGenerators.listOf; 033import static tech.sirwellington.alchemy.generator.NumberGenerators.positiveIntegers; 034import static tech.sirwellington.alchemy.generator.NumberGenerators.positiveLongs; 035import static tech.sirwellington.alchemy.generator.ObjectGenerators.pojos; 036import static tech.sirwellington.alchemy.generator.StringGenerators.alphanumericStrings; 037import static tech.sirwellington.alchemy.test.Checks.Internal.checkNotNull; 038import static tech.sirwellington.alchemy.test.Checks.Internal.checkThat; 039 040/** 041 * Used in with the {@link AlchemyTestRunner}, this Annotations allows the Runtime Injection of {@link List} values, using 042 * {@link CollectionGenerators} from the {@link AlchemyGenerator} library. 043 * <p> 044 * Example: 045 * <pre> 046 * {@code 047 * `@RunWith(AlchemyTestRunner.class) 048 * public class ExampleTest 049 * { 050 * 051 * `@GenerateList(String.class) 052 * private List<String> ids; 053 * 054 * ... 055 * } 056 * } 057 * </pre> Note, ticks (`) used to escape Javadocs. 058 * 059 * @author SirWellington 060 * @see GenerateEnum 061 * @see GeneratePojo 062 */ 063@Target(FIELD) 064@Retention(RUNTIME) 065public @interface GenerateList 066{ 067 068 /** 069 * Specify the Generic Type of the List. This is necessary since the type information is erased at Runtime. 070 * 071 * @return 072 */ 073 Class<?> value(); 074 075 /** 076 * The number of elements to include in the list. Defaults to 10. This number must be {@code > 0}. 077 * 078 * @return 079 */ 080 int size() default 10; 081 082 @Internal 083 @NonInstantiable 084 static class Values 085 { 086 087 private Values() throws IllegalAccessException 088 { 089 throw new IllegalAccessException("cannot instantiate"); 090 } 091 092 static AlchemyGenerator<List<?>> createGeneratorFor(GenerateList annotation) throws IllegalArgumentException 093 { 094 checkNotNull(annotation, "missing annotation"); 095 final int size = annotation.size(); 096 checkThat(size > 0, "size must be > 0"); 097 098 Class<?> genericType = annotation.value(); 099 checkNotNull(genericType, "annotation is missing generic type information"); 100 101 final AlchemyGenerator<?> generator = determineGeneratorFor(genericType); 102 103 return new AlchemyGenerator<List<?>>() 104 { 105 @Override 106 public List<?> get() 107 { 108 return listOf(generator, size); 109 } 110 }; 111 } 112 113 private static AlchemyGenerator<?> determineGeneratorFor(Class<?> genericType) 114 { 115 if (genericType == String.class) 116 { 117 return alphanumericStrings(); 118 } 119 120 if (genericType == Integer.class) 121 { 122 return positiveIntegers(); 123 } 124 125 if (genericType == Long.class) 126 { 127 return positiveLongs(); 128 } 129 130 if (genericType == Double.class) 131 { 132 return NumberGenerators.doubles(0, 10000); 133 } 134 135 if (Date.class.isAssignableFrom(genericType)) 136 { 137 return DateGenerators.anyTime(); 138 } 139 140 if (genericType == Instant.class) 141 { 142 return TimeGenerators.anytime(); 143 } 144 145 if (genericType == Boolean.class) 146 { 147 return BooleanGenerators.booleans(); 148 } 149 150 if (ByteBuffer.class.isAssignableFrom(genericType)) 151 { 152 return BinaryGenerators.byteBuffers(1024); 153 } 154 155 return pojos(genericType); 156 } 157 } 158 159}