001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info AT sonarsource DOT com
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.batch.sensor.measure.internal;
021
022import com.google.common.base.Preconditions;
023import java.io.Serializable;
024import javax.annotation.Nullable;
025import org.apache.commons.lang.builder.EqualsBuilder;
026import org.apache.commons.lang.builder.HashCodeBuilder;
027import org.sonar.api.batch.fs.InputComponent;
028import org.sonar.api.batch.measure.Metric;
029import org.sonar.api.batch.sensor.internal.DefaultStorable;
030import org.sonar.api.batch.sensor.internal.SensorStorage;
031import org.sonar.api.batch.sensor.measure.Measure;
032import org.sonar.api.batch.sensor.measure.NewMeasure;
033
034import static java.util.Objects.requireNonNull;
035
036public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
037
038  private InputComponent component;
039  private Metric<G> metric;
040  private G value;
041  private boolean fromCore = false;
042
043  public DefaultMeasure() {
044    super();
045  }
046
047  public DefaultMeasure(@Nullable SensorStorage storage) {
048    super(storage);
049  }
050
051  @Override
052  public DefaultMeasure<G> on(InputComponent component) {
053    Preconditions.checkArgument(component != null, "Component can't be null");
054    Preconditions.checkState(this.component == null, "on() already called");
055    this.component = component;
056    return this;
057  }
058
059  @Override
060  public DefaultMeasure<G> forMetric(Metric<G> metric) {
061    Preconditions.checkState(this.metric == null, "Metric already defined");
062    requireNonNull(metric, "metric should be non null");
063    this.metric = metric;
064    return this;
065  }
066
067  @Override
068  public DefaultMeasure<G> withValue(G value) {
069    Preconditions.checkState(this.value == null, "Measure value already defined");
070    requireNonNull(value, "Measure value can't be null");
071    this.value = value;
072    return this;
073  }
074
075  /**
076   * For internal use.
077   */
078  public boolean isFromCore() {
079    return fromCore;
080  }
081
082  /**
083   * For internal use. Used by core components to bypass check that prevent a plugin to store core measures.
084   */
085  public DefaultMeasure<G> setFromCore() {
086    this.fromCore = true;
087    return this;
088  }
089
090  @Override
091  public void doSave() {
092    requireNonNull(this.value, "Measure value can't be null");
093    requireNonNull(this.metric, "Measure metric can't be null");
094    Preconditions.checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type %s", this.metric.valueType());
095    storage.store(this);
096  }
097
098  @Override
099  public Metric<G> metric() {
100    return metric;
101  }
102
103  @Override
104  public InputComponent inputComponent() {
105    return component;
106  }
107
108  @Override
109  public G value() {
110    return value;
111  }
112
113  // For testing purpose
114
115  @Override
116  public boolean equals(Object obj) {
117    if (obj == null) {
118      return false;
119    }
120    if (obj == this) {
121      return true;
122    }
123    if (obj.getClass() != getClass()) {
124      return false;
125    }
126    DefaultMeasure<?> rhs = (DefaultMeasure<?>) obj;
127    return new EqualsBuilder()
128      .append(component, rhs.component)
129      .append(metric, rhs.metric)
130      .append(value, rhs.value)
131      .isEquals();
132  }
133
134  @Override
135  public int hashCode() {
136    return new HashCodeBuilder(27, 45).append(component).append(metric).append(value).toHashCode();
137  }
138
139}