aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Mandrikov <mandrikov@gmail.com>2012-02-09 21:11:53 +0400
committerEvgeny Mandrikov <mandrikov@gmail.com>2012-02-09 22:48:17 +0400
commite476635c3816598feefd88517b6f12421b807a0c (patch)
treef6ab574ee7d62f7a97c27a2c19620af18782422e
parentc3bc6982b7e165304e269d7b7ef309a05148be98 (diff)
downloadsonarqube-e476635c3816598feefd88517b6f12421b807a0c.tar.gz
sonarqube-e476635c3816598feefd88517b6f12421b807a0c.zip
SONAR-3209 Add new batch component - FileLinesContextFactory
* As was discussed with Simon: better to have new beta class than new beta method. * This also provides ability to use this factory from Decorator.
-rw-r--r--plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/visitor/FileLinesVisitor.java5
-rw-r--r--plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SonarAccessor.java21
-rw-r--r--plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java8
-rw-r--r--plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/visitor/FileLinesVisitorTest.java10
-rw-r--r--plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/SquidSensorTest.java14
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContext.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java39
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/DefaultFileLinesContextTest.java31
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java8
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContext.java12
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java36
13 files changed, 157 insertions, 41 deletions
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/visitor/FileLinesVisitor.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/visitor/FileLinesVisitor.java
index 596df2cc277..60ace8723ea 100644
--- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/visitor/FileLinesVisitor.java
+++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/visitor/FileLinesVisitor.java
@@ -20,10 +20,8 @@
package org.sonar.java.ast.visitor;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
-import org.sonar.api.batch.SquidUtils;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.FileLinesContext;
-import org.sonar.api.resources.JavaFile;
import org.sonar.plugins.squid.SonarAccessor;
import org.sonar.squid.api.SourceFile;
import org.sonar.squid.measures.Metric;
@@ -56,8 +54,7 @@ public class FileLinesVisitor extends JavaAstVisitor {
private void processFile() {
SourceFile file = (SourceFile) peekSourceCode();
- JavaFile javaFile = SquidUtils.convertJavaFileKeyFromSquidFormat(file.getKey());
- FileLinesContext measures = sonarAccessor.getSensorContext().createFileLinesContext(javaFile);
+ FileLinesContext measures = sonarAccessor.createFileLinesContext(file);
Source source = getSource();
for (int line = 1; line <= source.getNumberOfLines(); line++) {
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SonarAccessor.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SonarAccessor.java
index 0e6b9b661dd..2b11eba119b 100644
--- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SonarAccessor.java
+++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SonarAccessor.java
@@ -19,8 +19,12 @@
*/
package org.sonar.plugins.squid;
-import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.SquidUtils;
+import org.sonar.api.measures.FileLinesContext;
+import org.sonar.api.measures.FileLinesContextFactory;
+import org.sonar.api.resources.JavaFile;
import org.sonar.squid.api.CodeScanner;
+import org.sonar.squid.api.SourceFile;
import java.util.Collection;
import java.util.Collections;
@@ -30,14 +34,10 @@ import java.util.Collections;
*/
public class SonarAccessor extends CodeScanner {
- private SensorContext sensorContext;
+ private FileLinesContextFactory factory;
- public void setSensorContext(SensorContext sensorContext) {
- this.sensorContext = sensorContext;
- }
-
- public SensorContext getSensorContext() {
- return sensorContext;
+ public void setFileLinesContextFactory(FileLinesContextFactory factory) {
+ this.factory = factory;
}
@Override
@@ -45,4 +45,9 @@ public class SonarAccessor extends CodeScanner {
return Collections.emptyList();
}
+ public FileLinesContext createFileLinesContext(SourceFile file) {
+ JavaFile javaFile = SquidUtils.convertJavaFileKeyFromSquidFormat(file.getKey());
+ return factory.createFor(javaFile);
+ }
+
}
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java
index 5f35c1ee39c..68a332285b3 100644
--- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java
+++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java
@@ -23,6 +23,7 @@ import org.sonar.api.CoreProperties;
import org.sonar.api.batch.*;
import org.sonar.api.checks.AnnotationCheckFactory;
import org.sonar.api.checks.NoSonarFilter;
+import org.sonar.api.measures.FileLinesContextFactory;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.InputFile;
import org.sonar.api.resources.Java;
@@ -45,12 +46,15 @@ public class SquidSensor implements Sensor {
private RulesProfile profile;
private ProjectClasspath projectClasspath;
private ResourceCreationLock lock;
+ private FileLinesContextFactory fileLinesContextFactory;
- public SquidSensor(RulesProfile profile, NoSonarFilter noSonarFilter, ProjectClasspath projectClasspath, ResourceCreationLock lock) {
+ public SquidSensor(RulesProfile profile, NoSonarFilter noSonarFilter, ProjectClasspath projectClasspath, ResourceCreationLock lock,
+ FileLinesContextFactory fileLinesContextFactory) {
this.noSonarFilter = noSonarFilter;
this.profile = profile;
this.projectClasspath = projectClasspath;
this.lock = lock;
+ this.fileLinesContextFactory = fileLinesContextFactory;
}
public boolean shouldExecuteOnProject(Project project) {
@@ -74,7 +78,7 @@ public class SquidSensor implements Sensor {
AnnotationCheckFactory factory = AnnotationCheckFactory.create(profile, SquidConstants.REPOSITORY_KEY, SquidRuleRepository.getCheckClasses());
SquidExecutor squidExecutor = new SquidExecutor(analyzePropertyAccessors, fieldNamesToExcludeFromLcom4Computation, factory, charset);
- squidExecutor.getSquid().register(SonarAccessor.class).setSensorContext(context);
+ squidExecutor.getSquid().register(SonarAccessor.class).setFileLinesContextFactory(fileLinesContextFactory);
squidExecutor.scan(getMainSourceFiles(project), getBytecodeFiles(project));
squidExecutor.save(project, context, noSonarFilter);
squidExecutor.flush();
diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/visitor/FileLinesVisitorTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/visitor/FileLinesVisitorTest.java
index a4be9d8ff2d..b92e56890ef 100644
--- a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/visitor/FileLinesVisitorTest.java
+++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/visitor/FileLinesVisitorTest.java
@@ -22,9 +22,9 @@ package org.sonar.java.ast.visitor;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
-import org.sonar.api.batch.SensorContext;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.FileLinesContext;
+import org.sonar.api.measures.FileLinesContextFactory;
import org.sonar.api.resources.Resource;
import org.sonar.java.ast.JavaAstScanner;
import org.sonar.java.ast.SquidTestUtils;
@@ -39,23 +39,23 @@ import static org.mockito.Mockito.*;
public class FileLinesVisitorTest {
private Squid squid;
- private SensorContext context;
+ private FileLinesContextFactory factory;
private FileLinesContext measures;
@Before
public void setUp() {
squid = new Squid(new JavaSquidConfiguration());
- context = mock(SensorContext.class);
+ factory = mock(FileLinesContextFactory.class);
measures = mock(FileLinesContext.class);
}
@Test
public void analyseTestNcloc() {
ArgumentCaptor<Resource> resourceCaptor = ArgumentCaptor.forClass(Resource.class);
- when(context.createFileLinesContext(resourceCaptor.capture()))
+ when(factory.createFor(resourceCaptor.capture()))
.thenReturn(measures);
- squid.register(SonarAccessor.class).setSensorContext(context);
+ squid.register(SonarAccessor.class).setFileLinesContextFactory(factory);
squid.register(JavaAstScanner.class).scanFile(SquidTestUtils.getInputFile("/metrics/ncloc/TestNcloc.java"));
assertThat(resourceCaptor.getValue().getKey(), is("[default].TestNcloc"));
diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/SquidSensorTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/SquidSensorTest.java
index 70a83928884..3a1cb1bb5c2 100644
--- a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/SquidSensorTest.java
+++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/SquidSensorTest.java
@@ -19,11 +19,6 @@
*/
package org.sonar.plugins.squid;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.*;
-
import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.junit.Test;
@@ -36,12 +31,17 @@ import java.io.File;
import java.util.Arrays;
import java.util.Collection;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.*;
+
public class SquidSensorTest {
@Test
public void testGetBytecodeFiles() {
ProjectClasspath projectClasspath = mock(ProjectClasspath.class);
when(projectClasspath.getElements()).thenReturn(Arrays.asList(new File("classes")));
- SquidSensor sensor = new SquidSensor(null, null, projectClasspath, null);
+ SquidSensor sensor = new SquidSensor(null, null, projectClasspath, null, null);
Configuration configuration = new BaseConfiguration();
Project project = mock(Project.class);
when(project.getConfiguration()).thenReturn(configuration);
@@ -56,7 +56,7 @@ public class SquidSensorTest {
@Test
public void onlyForJava() {
- SquidSensor sensor = new SquidSensor(null, null, null, null);
+ SquidSensor sensor = new SquidSensor(null, null, null, null, null);
Project project = mock(Project.class);
when(project.getLanguageKey()).thenReturn(Java.KEY).thenReturn("groovy");
assertThat(sensor.shouldExecuteOnProject(project), is(true));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContext.java
index c4a8e9a7579..4c998af512c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContext.java
@@ -30,6 +30,7 @@ import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.api.utils.KeyValueFormat.Converter;
@@ -50,6 +51,8 @@ public class DefaultFileLinesContext implements FileLinesContext {
private final Map<String, Map<Integer, Object>> map = Maps.newHashMap();
public DefaultFileLinesContext(SonarIndex index, Resource resource) {
+ Preconditions.checkNotNull(index);
+ Preconditions.checkArgument(Scopes.isFile(resource));
this.index = index;
this.resource = resource;
}
@@ -118,6 +121,7 @@ public class DefaultFileLinesContext implements FileLinesContext {
.setPersistenceMode(PersistenceMode.DATABASE)
.setData(data);
index.addMeasure(resource, measure);
+ entry.setValue(ImmutableMap.copyOf(lines));
}
}
}
@@ -133,9 +137,10 @@ public class DefaultFileLinesContext implements FileLinesContext {
}
/**
- * Checks that measure was not loaded.
+ * Checks that measure was not saved.
*
* @see #loadData(String, Converter)
+ * @see #save()
*/
private boolean shouldSave(Map<Integer, Object> lines) {
return !(lines instanceof ImmutableMap);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java
new file mode 100644
index 00000000000..497cbe1c08e
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch;
+
+import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.measures.FileLinesContext;
+import org.sonar.api.measures.FileLinesContextFactory;
+import org.sonar.api.resources.Resource;
+
+public class DefaultFileLinesContextFactory implements FileLinesContextFactory {
+
+ private final SonarIndex index;
+
+ public DefaultFileLinesContextFactory(SonarIndex index) {
+ this.index = index;
+ }
+
+ public FileLinesContext createFor(Resource resource) {
+ return new DefaultFileLinesContext(index, resource);
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
index 2a75b837b6d..fe42bfca0c0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
@@ -23,7 +23,6 @@ import org.sonar.api.batch.Event;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.SonarIndex;
import org.sonar.api.design.Dependency;
-import org.sonar.api.measures.FileLinesContext;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.Metric;
@@ -123,10 +122,6 @@ public class DefaultSensorContext implements SensorContext {
return index.addMeasure(resourceOrProject(resource), measure);
}
- public FileLinesContext createFileLinesContext(Resource resource) {
- return new DefaultFileLinesContext(index, resource);
- }
-
public void saveViolation(Violation violation, boolean force) {
if (violation.getResource() == null) {
violation.setResource(resourceOrProject(violation.getResource()));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
index 1948b6a686b..bc7516ae550 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
@@ -24,6 +24,7 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.ServerHttpClient;
+import org.sonar.batch.DefaultFileLinesContextFactory;
import org.sonar.batch.DefaultResourceCreationLock;
import org.sonar.batch.ProjectConfigurator;
import org.sonar.batch.ProjectTree;
@@ -53,6 +54,7 @@ public class BatchModule extends Module {
addCoreSingleton(ProjectConfigurator.class);
addCoreSingleton(DefaultResourceCreationLock.class);
addCoreSingleton(DefaultIndex.class);
+ addCoreSingleton(DefaultFileLinesContextFactory.class);
if (dryRun) {
addCoreSingleton(ReadOnlyPersistenceManager.class);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/DefaultFileLinesContextTest.java b/sonar-batch/src/test/java/org/sonar/batch/DefaultFileLinesContextTest.java
index 2cf15e2bd68..d3f73831031 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/DefaultFileLinesContextTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/DefaultFileLinesContextTest.java
@@ -27,7 +27,9 @@ import org.sonar.api.batch.SonarIndex;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.PersistenceMode;
+import org.sonar.api.resources.Directory;
import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
@@ -44,9 +46,15 @@ public class DefaultFileLinesContextTest {
public void setUp() {
index = mock(SonarIndex.class);
resource = mock(Resource.class);
+ when(resource.getScope()).thenReturn(Scopes.FILE);
fileLineMeasures = new DefaultFileLinesContext(index, resource);
}
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldNotAllowCreationForDirectory() {
+ new DefaultFileLinesContext(index, new Directory("key"));
+ }
+
@Test
public void shouldSave() {
fileLineMeasures.setIntValue("hits", 1, 2);
@@ -68,8 +76,20 @@ public class DefaultFileLinesContextTest {
fileLineMeasures.setStringValue("author", 1, "simon");
fileLineMeasures.setStringValue("author", 3, "evgeny");
fileLineMeasures.save();
+ fileLineMeasures.setIntValue("branches", 1, 2);
+ fileLineMeasures.setIntValue("branches", 3, 4);
+ fileLineMeasures.save();
- verify(index, times(2)).addMeasure(Mockito.eq(resource), Mockito.any(Measure.class));
+ verify(index, times(3)).addMeasure(Mockito.eq(resource), Mockito.any(Measure.class));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void shouldNotModifyAfterSave() {
+ fileLineMeasures.setIntValue("hits", 1, 2);
+ fileLineMeasures.save();
+ fileLineMeasures.save();
+ verify(index).addMeasure(Mockito.eq(resource), Mockito.any(Measure.class));
+ fileLineMeasures.setIntValue("hits", 1, 2);
}
@Test
@@ -103,6 +123,15 @@ public class DefaultFileLinesContextTest {
verify(index, never()).addMeasure(Mockito.eq(resource), Mockito.any(Measure.class));
}
+ @Test(expected = UnsupportedOperationException.class)
+ public void shouldNotModifyAfterLoad() {
+ when(index.getMeasure(Mockito.any(Resource.class), Mockito.any(Metric.class)))
+ .thenReturn(new Measure("author").setData("1=simon;3=evgeny"));
+
+ fileLineMeasures.getStringValue("author", 1);
+ fileLineMeasures.setStringValue("author", 1, "evgeny");
+ }
+
@Test
public void shouldNotFailIfNoMeasureInIndex() {
assertThat(fileLineMeasures.getIntValue("hits", 1), nullValue());
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
index 1cc5b291403..fc9189410c2 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
@@ -19,9 +19,7 @@
*/
package org.sonar.api.batch;
-import com.google.common.annotations.Beta;
import org.sonar.api.design.Dependency;
-import org.sonar.api.measures.FileLinesContext;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.Metric;
@@ -152,12 +150,6 @@ public interface SensorContext {
*/
Measure saveMeasure(Resource resource, Measure measure);
- /**
- * @since 2.14
- */
- @Beta
- FileLinesContext createFileLinesContext(Resource resource);
-
// ----------- RULE VIOLATIONS --------------
/**
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContext.java
index f2fe4dcaf18..51a16d337f4 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContext.java
@@ -31,6 +31,9 @@ import com.google.common.annotations.Beta;
* <li>author of line 4 is Simon</li>
* </ul>
* Numbering of lines starts from 1.
+ * Also note that you can't update what already was saved, however it is safe to call {@link #save()} several times.
+ * <p>
+ * Instances of this interface can be obtained using {@link FileLinesContextFactory}.
*
* <p>This interface is not intended to be implemented by clients.</p>
*
@@ -39,6 +42,9 @@ import com.google.common.annotations.Beta;
@Beta
public interface FileLinesContext {
+ /**
+ * @throws UnsupportedOperationException on attempt to update already saved data
+ */
void setIntValue(String metricKey, int line, int value);
/**
@@ -46,6 +52,9 @@ public interface FileLinesContext {
*/
Integer getIntValue(String metricKey, int line);
+ /**
+ * @throws UnsupportedOperationException on attempt to update already saved data
+ */
void setStringValue(String metricKey, int line, String value);
/**
@@ -53,6 +62,9 @@ public interface FileLinesContext {
*/
String getStringValue(String metricKey, int line);
+ /**
+ * Saves unsaved values.
+ */
void save();
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java
new file mode 100644
index 00000000000..5fff3a6380c
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.api.measures;
+
+import com.google.common.annotations.Beta;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.resources.Resource;
+
+/**
+ * <p>This interface is not intended to be implemented by clients.</p>
+ *
+ * @since 2.14
+ */
+@Beta
+public interface FileLinesContextFactory extends BatchComponent {
+
+ FileLinesContext createFor(Resource resource);
+
+}