Home | History | Annotate | Download | only in model
      1 /*
      2  * Copyright (C) 2012 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.model;
     18 
     19 import static com.google.caliper.model.PersistentHashing.getPersistentHashFunction;
     20 import static com.google.common.base.Preconditions.checkNotNull;
     21 import static com.google.common.base.Preconditions.checkState;
     22 
     23 import com.google.common.base.MoreObjects;
     24 import com.google.common.collect.ImmutableSortedMap;
     25 import com.google.common.collect.Maps;
     26 
     27 import java.util.Map;
     28 import java.util.SortedMap;
     29 
     30 /**
     31  * A specification by which the application of an instrument can be uniquely identified.
     32  *
     33  * @author gak (at) google.com (Gregory Kick)
     34  */
     35 public final class InstrumentSpec {
     36   static final InstrumentSpec DEFAULT = new InstrumentSpec();
     37 
     38   @ExcludeFromJson
     39   private int id;
     40   private String className;
     41   private SortedMap<String, String> options;
     42   @ExcludeFromJson
     43   private int hash;
     44 
     45   private InstrumentSpec() {
     46     this.className = "";
     47     this.options = Maps.newTreeMap();
     48   }
     49 
     50   private InstrumentSpec(Builder builder) {
     51     this.className = builder.className;
     52     this.options = Maps.newTreeMap(builder.options);
     53   }
     54 
     55   public String className() {
     56     return className;
     57   }
     58 
     59   public ImmutableSortedMap<String, String> options() {
     60     return ImmutableSortedMap.copyOf(options);
     61   }
     62 
     63   @Override public boolean equals(Object obj) {
     64     if (obj == this) {
     65       return true;
     66     } else if (obj instanceof InstrumentSpec) {
     67       InstrumentSpec that = (InstrumentSpec) obj;
     68       return this.className.equals(that.className)
     69           && this.options.equals(that.options);
     70     } else {
     71       return false;
     72     }
     73   }
     74 
     75   private void initHash() {
     76     if (hash == 0) {
     77       this.hash = getPersistentHashFunction()
     78           .newHasher()
     79           .putUnencodedChars(className)
     80           .putObject(options, StringMapFunnel.INSTANCE)
     81           .hash().asInt();
     82     }
     83   }
     84 
     85   @Override public int hashCode() {
     86     initHash();
     87     return hash;
     88   }
     89 
     90   @Override public String toString() {
     91     return MoreObjects.toStringHelper(this)
     92         .add("className", className)
     93         .add("options", options)
     94         .toString();
     95   }
     96 
     97   public static final class Builder {
     98     private String className;
     99     private final SortedMap<String, String> options = Maps.newTreeMap();
    100 
    101     public Builder className(String className) {
    102       this.className = checkNotNull(className);
    103       return this;
    104     }
    105 
    106     public Builder instrumentClass(Class<?> insturmentClass) {
    107       return className(insturmentClass.getName());
    108     }
    109 
    110     public Builder addOption(String option, String value) {
    111       this.options.put(option, value);
    112       return this;
    113     }
    114 
    115     public Builder addAllOptions(Map<String, String> options) {
    116       this.options.putAll(options);
    117       return this;
    118     }
    119 
    120     public InstrumentSpec build() {
    121       checkState(className != null);
    122       return new InstrumentSpec(this);
    123     }
    124   }
    125 }
    126