View Javadoc

1   /*******************************************************************************
2    * Copyright 2013 André Rouél and Dominik Seichter
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 net.sf.qualitytest.blueprint.strategy.creation;
17  
18  import java.text.MessageFormat;
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import javax.annotation.Nonnull;
23  
24  import net.sf.qualitycheck.ArgumentsChecked;
25  import net.sf.qualitycheck.Check;
26  import net.sf.qualitycheck.Throws;
27  import net.sf.qualitycheck.exception.IllegalNotNullArgumentException;
28  import net.sf.qualitytest.blueprint.BlueprintConfiguration;
29  import net.sf.qualitytest.blueprint.BlueprintExceptionRunnable;
30  import net.sf.qualitytest.blueprint.BlueprintSession;
31  import net.sf.qualitytest.blueprint.CreationStrategy;
32  import net.sf.qualitytest.blueprint.SafeInvoke;
33  import net.sf.qualitytest.blueprint.SafeInvoke.ExceptionRunnable;
34  import net.sf.qualitytest.exception.BlueprintException;
35  
36  /**
37   * Strategy to create values and increment each new value by 1. This is useful to create tests which are not random but
38   * use not the same value for each type every time.
39   * 
40   * @author Dominik Seichter
41   */
42  public class IncrementValueCreationStrategy<T extends Number> implements CreationStrategy<T> {
43  
44  	private static final Map<Class<?>, Class<? extends Number>> PRIMITIVE_MAPPING = new HashMap<Class<?>, Class<? extends Number>>();
45  
46  	static {
47  		PRIMITIVE_MAPPING.put(Integer.TYPE, Integer.class);
48  		PRIMITIVE_MAPPING.put(Long.TYPE, Long.class);
49  		PRIMITIVE_MAPPING.put(Double.TYPE, Double.class);
50  		PRIMITIVE_MAPPING.put(Float.TYPE, Float.class);
51  		PRIMITIVE_MAPPING.put(Byte.TYPE, Byte.class);
52  		PRIMITIVE_MAPPING.put(Short.TYPE, Short.class);
53  	};
54  
55  	private static final long DEFAULT_OFFSET = 1L;
56  	private T currentValue;
57  	private final long offset;
58  	private final long maxValueOfType;
59  
60  	@ArgumentsChecked
61  	public IncrementValueCreationStrategy(@Nonnull final T initialValue) {
62  		this.currentValue = Check.notNull(initialValue, "initialValue");
63  		this.offset = DEFAULT_OFFSET;
64  		this.maxValueOfType = readMaxValueOfType();
65  	}
66  
67  	@ArgumentsChecked
68  	public IncrementValueCreationStrategy(@Nonnull final T initialValue, final long offset) {
69  		this.currentValue = Check.notNull(initialValue, "initialValue");
70  		this.offset = offset;
71  		this.maxValueOfType = readMaxValueOfType();
72  	}
73  
74  	@ArgumentsChecked
75  	@Throws(IllegalNotNullArgumentException.class)
76  	public T createValue(final Class<?> expectedClazz, final BlueprintConfiguration config, final BlueprintSession session) {
77  		Check.notNull(expectedClazz, "expectedClazz");
78  
79  		final long value = (currentValue.longValue() % maxValueOfType) + offset;
80  		final String action = MessageFormat.format("Creating value {0} for type {1}.", value, expectedClazz);
81  		currentValue = SafeInvoke.invoke(new BlueprintExceptionRunnable<T>(session, action) {
82  			@SuppressWarnings("unchecked")
83  			@Override
84  			public T runInternal() throws Exception {
85  				if (expectedClazz.isPrimitive()) {
86  					final Class<?> clazz = PRIMITIVE_MAPPING.get(expectedClazz);
87  					return (T) clazz.getConstructor(String.class).newInstance(String.valueOf(value));
88  				} else {
89  					return (T) expectedClazz.getConstructor(String.class).newInstance(String.valueOf(value));
90  				}
91  			}
92  
93  		}, BlueprintException.class);
94  
95  		return currentValue;
96  	}
97  
98  	private long readMaxValueOfType() {
99  		final Number n = SafeInvoke.invoke(new ExceptionRunnable<Number>() {
100 			@Override
101 			public Number run() throws Exception {
102 				return (Number) currentValue.getClass().getField("MAX_VALUE").get(null);
103 			}
104 
105 		}, BlueprintException.class);
106 		return n.longValue();
107 	}
108 }