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}