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 17package com.google.caliper.runner; 18 19import com.google.common.collect.ImmutableCollection; 20import com.google.common.collect.ImmutableMap; 21import com.google.common.collect.ImmutableSetMultimap; 22import com.google.common.collect.ImmutableSortedMap; 23import com.google.common.collect.Ordering; 24import com.google.common.collect.Sets; 25 26import java.lang.annotation.Annotation; 27import java.lang.reflect.Field; 28import java.util.Map; 29import 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 */ 36public final class ParameterSet { 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 54 private ParameterSet(ImmutableMap<String, Parameter> map) { 55 this.map = map; 56 } 57 58 public Set<String> names() { 59 return map.keySet(); 60 } 61 62 public Parameter get(String name) { 63 return map.get(name); 64 } 65 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 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