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
034public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
035
036  private InputComponent component;
037  private Metric<G> metric;
038  private G value;
039  private boolean fromCore = false;
040
041  public DefaultMeasure() {
042    super();
043  }
044
045  public DefaultMeasure(@Nullable SensorStorage storage) {
046    super(storage);
047  }
048
049  @Override
050  public DefaultMeasure<G> on(InputComponent component) {
051    Preconditions.checkArgument(component != null, "Component can't be null");
052    Preconditions.checkState(this.component == null, "on() already called");
053    this.component = component;
054    return this;
055  }
056
057  @Override
058  public DefaultMeasure<G> forMetric(Metric<G> metric) {
059    Preconditions.checkState(this.metric == null, "Metric already defined");
060    Preconditions.checkNotNull(metric, "metric should be non null");
061    this.metric = metric;
062    return this;
063  }
064
065  @Override
066  public DefaultMeasure<G> withValue(G value) {
067    Preconditions.checkState(this.value == null, "Measure value already defined");
068    Preconditions.checkNotNull(value, "Measure value can't be null");
069    this.value = value;
070    return this;
071  }
072
073  /**
074   * For internal use.
075   */
076  public boolean isFromCore() {
077    return fromCore;
078  }
079
080  /**
081   * For internal use. Used by core components to bypass check that prevent a plugin to store core measures.
082   */
083  public DefaultMeasure<G> setFromCore() {
084    this.fromCore = true;
085    return this;
086  }
087
088  @Override
089  public void doSave() {
090    Preconditions.checkNotNull(this.value, "Measure value can't be null");
091    Preconditions.checkNotNull(this.metric, "Measure metric can't be null");
092    Preconditions.checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type %s", this.metric.valueType());
093    storage.store(this);
094  }
095
096  @Override
097  public Metric<G> metric() {
098    return metric;
099  }
100
101  @Override
102  public InputComponent inputComponent() {
103    return component;
104  }
105
106  @Override
107  public G value() {
108    return value;
109  }
110
111  // For testing purpose
112
113  @Override
114  public boolean equals(Object obj) {
115    if (obj == null) {
116      return false;
117    }
118    if (obj == this) {
119      return true;
120    }
121    if (obj.getClass() != getClass()) {
122      return false;
123    }
124    DefaultMeasure<?> rhs = (DefaultMeasure<?>) obj;
125    return new EqualsBuilder()
126      .append(component, rhs.component)
127      .append(metric, rhs.metric)
128      .append(value, rhs.value)
129      .isEquals();
130  }
131
132  @Override
133  public int hashCode() {
134    return new HashCodeBuilder(27, 45).append(component).append(metric).append(value).toHashCode();
135  }
136
137}