Java tutorial
/* * Copyright (C) 2011 Google Inc. * * 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 dk.ilios.spanner.benchmark; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.Primitives; import java.lang.reflect.Field; import java.text.ParseException; import dk.ilios.spanner.Param; import dk.ilios.spanner.internal.InvalidBenchmarkException; import dk.ilios.spanner.util.Parser; import dk.ilios.spanner.util.Parsers; import dk.ilios.spanner.util.Util; /** * Represents an injectable parameter, marked with @Param. Has nothing to do with * particular choices of <i>values</i> for this parameter (except that it knows how to find the * <i>default</i> values). */ public final class Parameter { private final Field field; private final Parser<?> parser; private final ImmutableList<String> defaults; public static Parameter create(Field field) throws InvalidBenchmarkException { return new Parameter(field); } public Parameter(Field field) throws InvalidBenchmarkException { if (Util.isStatic(field)) { throw new InvalidBenchmarkException("Parameter field '%s' must not be static", field.getName()); } if (RESERVED_NAMES.contains(field.getName())) { throw new InvalidBenchmarkException("Class '%s' uses reserved parameter name '%s'", field.getDeclaringClass(), field.getName()); } this.field = field; field.setAccessible(true); Class<?> type = Primitives.wrap(field.getType()); try { this.parser = Parsers.conventionalParser(type); } catch (NoSuchMethodException e) { throw new InvalidBenchmarkException("Type '%s' of parameter field '%s' has no recognized " + "String-converting method; see <TODO> for details", type, field.getName()); } this.defaults = findDefaults(field); validate(defaults); } void validate(ImmutableCollection<String> values) throws InvalidBenchmarkException { for (String valueAsString : values) { try { parser.parse(valueAsString); } catch (ParseException e) { throw new InvalidBenchmarkException("Cannot convert value '%s' to type '%s': %s", valueAsString, field.getType(), e.getMessage()); } } } static final ImmutableSet<String> RESERVED_NAMES = ImmutableSet.of("benchmark", "environment", "instrument", "measurement", // e.g. runtime, allocation, etc. "run", "trial", // currently unused, but we might need it "vm"); String name() { return field.getName(); } ImmutableList<String> defaults() { return defaults; } void inject(Object benchmark, String value) { try { Object o = parser.parse(value); field.set(benchmark, o); } catch (ParseException impossible) { // already validated both defaults and command-line throw new AssertionError(impossible); } catch (IllegalAccessException impossible) { throw new AssertionError(impossible); } } private static ImmutableList<String> findDefaults(Field field) { String[] defaultsAsStrings = field.getAnnotation(Param.class).value(); if (defaultsAsStrings.length > 0) { return ImmutableList.copyOf(defaultsAsStrings); } Class<?> type = field.getType(); if (type == boolean.class) { return ALL_BOOLEANS; } if (type.isEnum()) { ImmutableList.Builder<String> builder = ImmutableList.builder(); for (Object enumConstant : type.getEnumConstants()) { builder.add(enumConstant.toString()); } return builder.build(); } return ImmutableList.of(); } private static final ImmutableList<String> ALL_BOOLEANS = ImmutableList.of("true", "false"); }