int lineNumber = 0;
for (String line : lines) {
lineNumber++;
- if (StringUtils.isBlank(line)) {
+ if (StringUtils.isBlank(line) || line.startsWith("#")) {
continue;
}
- if (line.startsWith("#")) {
- continue;
- }
- try {
- String metricKey = StringUtils.substringBefore(line, ":");
- String value = line.substring(metricKey.length() + 1);
- context.addMeasure(createMeasure(context, inputFile, metricKey, value));
- } catch (Exception e) {
- throw new IllegalStateException("Error processing line " + lineNumber + " of file " + measureFile.getAbsolutePath(), e);
- }
+ processMeasure(inputFile, context, measureFile, lineNumber, line);
}
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
}
+ private void processMeasure(InputFile inputFile, SensorContext context, File measureFile, int lineNumber, String line) {
+ try {
+ String metricKey = StringUtils.substringBefore(line, ":");
+ String value = line.substring(metricKey.length() + 1);
+ context.addMeasure(createMeasure(context, inputFile, metricKey, value));
+ } catch (Exception e) {
+ throw new IllegalStateException("Error processing line " + lineNumber + " of file " + measureFile.getAbsolutePath(), e);
+ }
+ }
+
private Measure<?> createMeasure(SensorContext context, InputFile xooFile, String metricKey, String value) {
org.sonar.api.batch.measure.Metric<Serializable> metric = metricFinder.findByKey(metricKey);
+ if (metric == null) {
+ throw new IllegalStateException("Unknow metric with key: " + metricKey);
+ }
MeasureBuilder<Serializable> builder = context.measureBuilder()
.forMetric(metric)
.onFile(xooFile);
*/
package org.sonar.xoo.lang;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
import com.google.common.base.Splitter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
Iterator<String> split = Splitter.on(":").split(line).iterator();
int startOffset = Integer.parseInt(split.next());
int endOffset = Integer.parseInt(split.next());
- HighlightingBuilder.TypeOfText type = HighlightingBuilder.TypeOfText.forCssClass(split.next());
+ TypeOfText type = TypeOfText.forCssClass(split.next());
highlightingBuilder.highlight(startOffset, endOffset, type);
} catch (Exception e) {
throw new IllegalStateException("Error processing line " + lineNumber + " of file " + highlightingFile.getAbsolutePath(), e);
*/
package org.sonar.batch.highlighting;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
import com.google.common.base.Preconditions;
import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import org.sonar.batch.index.ComponentDataCache;
*/
package org.sonar.batch.highlighting;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Ordering;
import org.elasticsearch.common.collect.Sets;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import javax.annotation.Nullable;
return syntaxHighlightingRuleSet;
}
- public SyntaxHighlightingDataBuilder registerHighlightingRule(int startOffset, int endOffset, HighlightingBuilder.TypeOfText typeOfText) {
+ public SyntaxHighlightingDataBuilder registerHighlightingRule(int startOffset, int endOffset, TypeOfText typeOfText) {
SyntaxHighlightingRule syntaxHighlightingRule = SyntaxHighlightingRule.create(startOffset, endOffset,
typeOfText);
this.syntaxHighlightingRuleSet.add(syntaxHighlightingRule);
*/
package org.sonar.batch.highlighting;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import java.io.Serializable;
private final int startPosition;
private final int endPosition;
- private final HighlightingBuilder.TypeOfText textType;
+ private final TypeOfText textType;
- private SyntaxHighlightingRule(int startPosition, int endPosition, HighlightingBuilder.TypeOfText textType) {
+ private SyntaxHighlightingRule(int startPosition, int endPosition, TypeOfText textType) {
this.startPosition = startPosition;
this.endPosition = endPosition;
this.textType = textType;
}
- public static SyntaxHighlightingRule create(int startPosition, int endPosition, HighlightingBuilder.TypeOfText textType) {
+ public static SyntaxHighlightingRule create(int startPosition, int endPosition, TypeOfText textType) {
return new SyntaxHighlightingRule(startPosition, endPosition, textType);
}
return endPosition;
}
- public HighlightingBuilder.TypeOfText getTextType() {
+ public TypeOfText getTextType() {
return textType;
}
}
*/
package org.sonar.batch.highlighting;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
import com.persistit.Value;
import com.persistit.encoding.CoderContext;
import com.persistit.encoding.ValueCoder;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
class SyntaxHighlightingRuleValueCoder implements ValueCoder {
public Object get(Value value, Class clazz, CoderContext context) {
int startPosition = value.getInt();
int endPosition = value.getInt();
- HighlightingBuilder.TypeOfText type = HighlightingBuilder.TypeOfText.values()[value.getInt()];
+ TypeOfText type = TypeOfText.values()[value.getInt()];
return SyntaxHighlightingRule.create(startPosition, endPosition, type);
}
}
*/
package org.sonar.batch.mediumtest;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.symbol.Symbol;
* @param charIndex 0-based offset in file
*/
@CheckForNull
- public List<HighlightingBuilder.TypeOfText> highlightingTypeFor(InputFile file, int charIndex) {
+ public List<TypeOfText> highlightingTypeFor(InputFile file, int charIndex) {
SyntaxHighlightingData syntaxHighlightingData = highlightingPerFile.get(file);
if (syntaxHighlightingData == null) {
return null;
}
- List<HighlightingBuilder.TypeOfText> result = new ArrayList<HighlightingBuilder.TypeOfText>();
+ List<TypeOfText> result = new ArrayList<TypeOfText>();
for (SyntaxHighlightingRule sortedRule : syntaxHighlightingData.syntaxHighlightingRuleSet()) {
if (sortedRule.getStartPosition() <= charIndex && sortedRule.getEndPosition() > charIndex) {
result.add(sortedRule.getTextType());
}
public FakeGlobalReferentialsLoader add(Metric metric) {
+ Boolean optimizedBestValue = metric.isOptimizedBestValue();
ref.metrics().add(new org.sonar.batch.protocol.input.Metric(metricId,
metric.key(),
metric.getType().name(),
metric.getUserManaged(),
metric.getWorstValue(),
metric.getBestValue(),
- metric.isOptimizedBestValue()));
+ optimizedBestValue != null ? optimizedBestValue : false));
metricId++;
return this;
}
Measure currentMeasure = context.getMeasure(CoreMetrics.QUALITY_PROFILES);
Map<String, QProfile> currentProfiles = UsedQProfiles.fromJson(currentMeasure.getData()).profilesByKey();
- // Detect new profiles or updated profiles
+ detectNewOrUpdatedProfiles(context, previousProfiles, currentProfiles);
+
+ detectNoMoreUsedProfiles(context, previousProfiles, currentProfiles);
+ }
+
+ private void detectNoMoreUsedProfiles(DecoratorContext context, Map<String, QProfile> previousProfiles, Map<String, QProfile> currentProfiles) {
+ for (QProfile previousProfile : previousProfiles.values()) {
+ if (!currentProfiles.containsKey(previousProfile.getKey())) {
+ markAsRemoved(context, previousProfile);
+ }
+ }
+ }
+
+ private void detectNewOrUpdatedProfiles(DecoratorContext context, Map<String, QProfile> previousProfiles, Map<String, QProfile> currentProfiles) {
for (QProfile profile : currentProfiles.values()) {
QProfile previousProfile = previousProfiles.get(profile.getKey());
if (previousProfile != null) {
markAsAdded(context, profile);
}
}
-
- // Detect profiles that are not used anymore
- for (QProfile previousProfile : previousProfiles.values()) {
- if (!currentProfiles.containsKey(previousProfile.getKey())) {
- markAsRemoved(context, previousProfile);
- }
- }
}
private void markAsChanged(DecoratorContext context, QProfile previousProfile, QProfile profile) {
@Override
public void addMeasure(Measure<?> measure) {
- if (measure.inputFile() != null) {
- measureCache.put(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), measure.inputFile()), (DefaultMeasure) measure);
+ InputFile inputFile = measure.inputFile();
+ if (inputFile != null) {
+ measureCache.put(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), inputFile), (DefaultMeasure) measure);
} else {
measureCache.put(def.getKey(), def.getKey(), (DefaultMeasure) measure);
}
*/
package org.sonar.batch.source;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
import org.sonar.api.component.Component;
import org.sonar.api.source.Highlightable;
import org.sonar.batch.highlighting.SyntaxHighlightingDataBuilder;
@Override
public HighlightingBuilder highlight(int startOffset, int endOffset, String typeOfText) {
- TypeOfText type = org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText.forCssClass(typeOfText);
+ TypeOfText type = org.sonar.api.batch.sensor.highlighting.TypeOfText.forCssClass(typeOfText);
builder.registerHighlightingRule(startOffset, endOffset, type);
return this;
}
import org.junit.Test;
import org.mockito.ArgumentCaptor;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.core.source.SnapshotDataTypes;
import java.util.Collection;
import static org.fest.assertions.Assertions.assertThat;
-import static org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText.CLASSIC_COMMENT;
-import static org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText.CPP_DOC;
-import static org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText.KEYWORD;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.COMMENT;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.CPP_DOC;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.KEYWORD;
public class SyntaxHighlightingDataBuilderTest {
public void setUpSampleRules() {
SyntaxHighlightingDataBuilder highlightingDataBuilder = new SyntaxHighlightingDataBuilder();
- highlightingDataBuilder.registerHighlightingRule(0, 10, CLASSIC_COMMENT);
+ highlightingDataBuilder.registerHighlightingRule(0, 10, COMMENT);
highlightingDataBuilder.registerHighlightingRule(10, 12, KEYWORD);
highlightingDataBuilder.registerHighlightingRule(24, 38, KEYWORD);
highlightingDataBuilder.registerHighlightingRule(42, 50, KEYWORD);
highlightingDataBuilder.registerHighlightingRule(24, 65, CPP_DOC);
- highlightingDataBuilder.registerHighlightingRule(12, 20, CLASSIC_COMMENT);
+ highlightingDataBuilder.registerHighlightingRule(12, 20, COMMENT);
highlightingRules = highlightingDataBuilder.getSyntaxHighlightingRuleSet();
}
public void should_order_by_start_then_end_offset() throws Exception {
assertThat(highlightingRules).onProperty("startPosition").containsOnly(0, 10, 12, 24, 24, 42);
assertThat(highlightingRules).onProperty("endPosition").containsOnly(10, 12, 20, 38, 65, 50);
- assertThat(highlightingRules).onProperty("textType").containsOnly(CLASSIC_COMMENT, KEYWORD, CLASSIC_COMMENT, KEYWORD, CPP_DOC, KEYWORD);
+ assertThat(highlightingRules).onProperty("textType").containsOnly(COMMENT, KEYWORD, COMMENT, KEYWORD, CPP_DOC, KEYWORD);
}
@Test
import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
-import static org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText.CLASSIC_COMMENT;
-import static org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText.CPP_DOC;
-import static org.sonar.api.batch.sensor.highlighting.HighlightingBuilder.TypeOfText.KEYWORD;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.COMMENT;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.CPP_DOC;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.KEYWORD;
public class SyntaxHighlightingDataTest {
public void should_serialize_rules_to_string() throws Exception {
List<SyntaxHighlightingRule> orderedHighlightingRules = Lists.newArrayList(
- SyntaxHighlightingRule.create(0, 10, CLASSIC_COMMENT),
+ SyntaxHighlightingRule.create(0, 10, COMMENT),
SyntaxHighlightingRule.create(10, 12, KEYWORD),
- SyntaxHighlightingRule.create(12, 20, CLASSIC_COMMENT),
+ SyntaxHighlightingRule.create(12, 20, COMMENT),
SyntaxHighlightingRule.create(24, 38, KEYWORD),
SyntaxHighlightingRule.create(24, 65, CPP_DOC),
SyntaxHighlightingRule.create(42, 50, KEYWORD)
*/
package org.sonar.batch.mediumtest.highlighting;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
import com.google.common.collect.ImmutableMap;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestName;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult;
import org.sonar.xoo.XooPlugin;
.start();
InputFile file = result.inputFiles().get(0);
- assertThat(result.highlightingTypeFor(file, 0)).containsExactly(HighlightingBuilder.TypeOfText.STRING);
- assertThat(result.highlightingTypeFor(file, 9)).containsExactly(HighlightingBuilder.TypeOfText.STRING);
+ assertThat(result.highlightingTypeFor(file, 0)).containsExactly(TypeOfText.STRING);
+ assertThat(result.highlightingTypeFor(file, 9)).containsExactly(TypeOfText.STRING);
assertThat(result.highlightingTypeFor(file, 10)).isEmpty();
- assertThat(result.highlightingTypeFor(file, 11)).containsExactly(HighlightingBuilder.TypeOfText.KEYWORD);
+ assertThat(result.highlightingTypeFor(file, 11)).containsExactly(TypeOfText.KEYWORD);
}
System.out.println("Duration: " + (System.currentTimeMillis() - start));
InputFile file = result.inputFiles().get(0);
- assertThat(result.highlightingTypeFor(file, 0)).containsExactly(HighlightingBuilder.TypeOfText.STRING);
+ assertThat(result.highlightingTypeFor(file, 0)).containsExactly(TypeOfText.STRING);
}
/**
* @since 2.2
+ * @deprecated since 4.5 this is some Java specific stuff that should by handled by SQ Java plugin
*/
+@Deprecated
public class ProjectClasspath implements BatchComponent {
protected MavenProject pom;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.utils.PathUtils;
-import javax.annotation.CheckForNull;
-
import java.io.File;
import java.io.Serializable;
return relativePath;
}
- /**
- * Marked as nullable just for the unit tests that do not call {@link #setFile(java.io.File)}
- * previously.
- */
@Override
- @CheckForNull
public String absolutePath() {
return absolutePath;
}
return new File(absolutePath);
}
- /**
- * Marked as nullable just for the unit tests that do not call {@link #setLanguage(String)}
- * previously.
- */
- @CheckForNull
@Override
public String language() {
return language;
}
/**
- * Marked as nullable just for the unit tests that do not previously call
* {@link #setStatus(org.sonar.api.batch.fs.InputFile.Status)}
*/
- @CheckForNull
@Override
public Status status() {
return status;
}
/**
- * Digest hash of the file. Marked as nullable just for the unit tests
- * that do not previously call {@link #setHash(String)}
+ * Digest hash of the file.
*/
- @CheckForNull
public String hash() {
return hash;
}
* </p>
*
* @since 1.10
+ * @deprecated since 4.5 we don't want any dependency on Maven anymore
*/
+@Deprecated
@SupportedEnvironment("maven")
public interface DependsUponMavenPlugin extends BatchExtension {
* A class to handle maven plugins
*
* @since 1.10
+ * @deprecated since 4.5 we don't want any dependency on Maven anymore
*/
+@Deprecated
public class MavenPlugin {
private static final String CONFIGURATION_ELEMENT = "configuration";
/**
* @since 1.10
+ * @deprecated since 4.5 we don't want any dependency on Maven anymore
*/
+@Deprecated
public interface MavenPluginHandler extends BatchExtension {
/**
/**
* @since 1.10
+ * @deprecated since 4.5 we don't want any dependency on Maven anymore
*/
+@Deprecated
public final class MavenSurefireUtils {
public static final String GROUP_ID = MavenUtils.GROUP_ID_APACHE_MAVEN;
* An utility class to manipulate Maven concepts
*
* @since 1.10
+ * @deprecated since 4.5 we don't want any dependency on Maven anymore
*/
+@Deprecated
public final class MavenUtils {
private static final String MAVEN_COMPILER_PLUGIN = "maven-compiler-plugin";
// ------------ DUPLICATIONS ------------
/**
- * Builder to define tokens in a file. Tokens are used to compute duplication by the core.
+ * Builder to define tokens in a file. Tokens are used to compute duplication using default SonarQube engine.
* @since 4.5
*/
DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile);
/**
* List {@link InputFile.Type} this {@link Sensor} work on. May be used by the platform to skip execution of the {@link Sensor} when
* no file for given type are present in the project.
- * If not type is provided then it will be executed for all types.
+ * If you don't call this method then it means sensor is working on all input file types.
*/
SensorDescriptor workOnFileTypes(InputFile.Type... types);
package org.sonar.api.batch.sensor.duplication;
import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.sonar.api.batch.sensor.SensorContext;
return equalsBuilder.isEquals();
}
+ @Override
+ public int hashCode() {
+ HashCodeBuilder hcBuilder = new HashCodeBuilder(17, 37)
+ .append(originBlock)
+ .append(duplicates.size());
+ for (int i = 0; i < duplicates.size(); i++) {
+ hcBuilder.append(duplicates.get(i));
+ }
+ return hcBuilder.toHashCode();
+ }
+
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).
*/
public interface HighlightingBuilder {
- /**
- * See sonar-colorizer.css
- */
- enum TypeOfText {
- ANNOTATION("a"),
- CONSTANT("c"),
- JAVADOC("j"),
- CLASSIC_COMMENT("cd"),
- CPP_DOC("cppd"),
- KEYWORD("k"),
- STRING("s"),
- KEYWORD_LIGHT("h"),
- PREPROCESS_DIRECTIVE("p");
-
- private final String cssClass;
-
- private TypeOfText(String cssClass) {
- this.cssClass = cssClass;
- }
-
- public static TypeOfText forCssClass(String cssClass) {
- for (TypeOfText typeOfText : TypeOfText.values()) {
- if (typeOfText.cssClass().equals(cssClass)) {
- return typeOfText;
- }
- }
- throw new IllegalArgumentException("No TypeOfText for CSS class " + cssClass);
- }
-
- /**
- * For internal use
- */
- public String cssClass() {
- return cssClass;
- }
- }
-
/**
* Call this method to indicate the type of text in a range.
* @param startOffset Starting position in file for this type of text. Beginning of a file starts with offset '0'.
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.highlighting;
+
+/**
+ * Possible types for highlighting code.
+ * See sonar-colorizer.css
+ * @since 4.5
+ */
+public enum TypeOfText {
+ ANNOTATION("a"),
+ CONSTANT("c"),
+ COMMENT("cd"),
+ /**
+ * @deprecated use {@link #COMMENT}
+ */
+ @Deprecated
+ CPP_DOC("cppd"),
+ /**
+ * For example Javadoc
+ */
+ STRUCTURED_COMMENT("j"),
+ KEYWORD("k"),
+ STRING("s"),
+ KEYWORD_LIGHT("h"),
+ PREPROCESS_DIRECTIVE("p");
+
+ private final String cssClass;
+
+ private TypeOfText(String cssClass) {
+ this.cssClass = cssClass;
+ }
+
+ public static TypeOfText forCssClass(String cssClass) {
+ for (TypeOfText typeOfText : TypeOfText.values()) {
+ if (typeOfText.cssClass().equals(cssClass)) {
+ return typeOfText;
+ }
+ }
+ throw new IllegalArgumentException("No TypeOfText for CSS class " + cssClass);
+ }
+
+ /**
+ * For internal use
+ */
+ public String cssClass() {
+ return cssClass;
+ }
+}
* @since 3.2
*/
public boolean isBestValue() {
+ Double bestValue = metric.getBestValue();
return metric.isOptimizedBestValue() == Boolean.TRUE
- && metric.getBestValue() != null
- && (value == null || NumberUtils.compare(metric.getBestValue(), value) == 0)
+ && bestValue != null
+ && (value == null || NumberUtils.compare(bestValue, value) == 0)
&& allNull(alertStatus, description, tendency, url, data)
&& isZeroVariation(variation1, variation2, variation3, variation4, variation5);
}
/**
* @return this
*/
- public Metric setWorstValue(Double d) {
+ public Metric setWorstValue(@Nullable Double d) {
this.worstValue = d;
return this;
}
* @param bestValue the best value. It can be null.
* @return this
*/
- public Metric setBestValue(Double bestValue) {
+ public Metric setBestValue(@Nullable Double bestValue) {
this.bestValue = bestValue;
return this;
}
return ValueType.PERCENT.equals(type);
}
- public Metric setOptimizedBestValue(Boolean b) {
+ public Metric setOptimizedBestValue(@Nullable Boolean b) {
this.optimizedBestValue = b;
return this;
}