1 /* 2 * Copyright (C) 2011 Google Inc. 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 17 package com.google.caliper.runner; 18 19 import com.google.common.collect.ImmutableCollection; 20 import com.google.common.collect.ImmutableMap; 21 import com.google.common.collect.ImmutableSetMultimap; 22 import com.google.common.collect.ImmutableSortedMap; 23 import com.google.common.collect.Ordering; 24 import com.google.common.collect.Sets; 25 26 import java.lang.annotation.Annotation; 27 import java.lang.reflect.Field; 28 import java.util.Map; 29 import java.util.Set; 30 31 /** 32 * Represents all the injectable parameter fields of a single kind (@Param or @VmParam) found in a 33 * benchmark class. Has nothing to do with particular choices of <i>values</i> for these parameters 34 * (except that it knows how to find the <i>default</i> values). 35 */ 36 public final class ParameterSet { create(Class<?> theClass, Class<? extends Annotation> annotationClass)37 public static ParameterSet create(Class<?> theClass, Class<? extends Annotation> annotationClass) 38 throws InvalidBenchmarkException { 39 // deterministic order, not reflection order 40 ImmutableMap.Builder<String, Parameter> parametersBuilder = 41 ImmutableSortedMap.naturalOrder(); 42 43 for (Field field : theClass.getDeclaredFields()) { 44 if (field.isAnnotationPresent(annotationClass)) { 45 Parameter parameter = Parameter.create(field); 46 parametersBuilder.put(field.getName(), parameter); 47 } 48 } 49 return new ParameterSet(parametersBuilder.build()); 50 } 51 52 final ImmutableMap<String, Parameter> map; 53 ParameterSet(ImmutableMap<String, Parameter> map)54 private ParameterSet(ImmutableMap<String, Parameter> map) { 55 this.map = map; 56 } 57 names()58 public Set<String> names() { 59 return map.keySet(); 60 } 61 get(String name)62 public Parameter get(String name) { 63 return map.get(name); 64 } 65 fillInDefaultsFor( ImmutableSetMultimap<String, String> explicitValues)66 public ImmutableSetMultimap<String, String> fillInDefaultsFor( 67 ImmutableSetMultimap<String, String> explicitValues) throws InvalidBenchmarkException { 68 ImmutableSetMultimap.Builder<String, String> combined = ImmutableSetMultimap.builder(); 69 70 // For user parameters, this'll actually be the same as fromClass.keySet(), since any extras 71 // given at the command line are treated as errors; for VM parameters this is not the case. 72 for (String name : Sets.union(map.keySet(), explicitValues.keySet())) { 73 Parameter parameter = map.get(name); 74 ImmutableCollection<String> values = explicitValues.containsKey(name) 75 ? explicitValues.get(name) 76 : parameter.defaults(); 77 78 combined.putAll(name, values); 79 if (values.isEmpty()) { 80 throw new InvalidBenchmarkException("ERROR: No default value provided for " + name); 81 } 82 } 83 return combined.orderKeysBy(Ordering.natural()).build(); 84 } 85 injectAll(Object benchmark, Map<String, String> actualValues)86 public void injectAll(Object benchmark, Map<String, String> actualValues) { 87 for (Parameter parameter : map.values()) { 88 String value = actualValues.get(parameter.name()); 89 parameter.inject(benchmark, value); 90 } 91 } 92 } 93