diff options
43 files changed, 903 insertions, 500 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java index 243aac29ca5..2cbc2ce8285 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java @@ -37,10 +37,10 @@ import org.sonar.api.measures.*; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.core.technicaldebt.TechnicalDebtConverter; -import org.sonar.core.technicaldebt.TechnicalDebtModel; import java.util.Arrays; import java.util.Collection; @@ -59,12 +59,12 @@ public final class TechnicalDebtDecorator implements Decorator { private static final int DECIMALS_PRECISION = 5; private final ResourcePerspectives perspectives; - private final TechnicalDebtModel technicalDebtModel; + private final TechnicalDebtModel model; private final TechnicalDebtConverter converter; - public TechnicalDebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel technicalDebtModel, TechnicalDebtConverter converter) { + public TechnicalDebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, TechnicalDebtConverter converter) { this.perspectives = perspectives; - this.technicalDebtModel = technicalDebtModel; + this.model = model; this.converter = converter; } @@ -93,7 +93,7 @@ public final class TechnicalDebtDecorator implements Decorator { Map<Characteristic, Double> characteristicCosts = newHashMap(); Map<Requirement, Double> requirementCosts = newHashMap(); - for (Requirement requirement : technicalDebtModel.requirements()) { + for (Requirement requirement : model.requirements()) { List<Issue> requirementIssues = issuesByRequirement.get(requirement); double value = computeTechnicalDebt(CoreMetrics.TECHNICAL_DEBT, context, requirement, requirementIssues); @@ -155,7 +155,7 @@ public final class TechnicalDebtDecorator implements Decorator { for (Issue issue : issues) { String repositoryKey = issue.ruleKey().repository(); String key = issue.ruleKey().rule(); - Requirement requirement = technicalDebtModel.requirementsByRule(issue.ruleKey()); + Requirement requirement = model.requirementsByRule(issue.ruleKey()); if (requirement == null) { LoggerFactory.getLogger(getClass()).debug("No technical debt requirement for: " + repositoryKey + "/" + key); } else { @@ -174,7 +174,8 @@ public final class TechnicalDebtDecorator implements Decorator { } for (Measure measure : context.getChildrenMeasures(MeasuresFilters.requirement(metric, requirement))) { - if (measure.getRequirement() != null && measure.getRequirement().equals(requirement) && measure.getValue() != null) { + Requirement measureRequirement = measure.getRequirement(); + if (measureRequirement != null && measureRequirement.equals(requirement) && measure.getValue() != null) { value += measure.getValue(); } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java index 83ce44f3cef..8b8b992365b 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java @@ -27,8 +27,8 @@ import org.sonar.api.resources.Project; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Resource; import org.sonar.api.resources.Scopes; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; import org.sonar.batch.components.PastMeasuresLoader; import org.sonar.batch.components.PastSnapshot; import org.sonar.batch.components.TimeMachineConfiguration; diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/technical_debt_pyramid.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/technical_debt_pyramid.html.erb index ce4b00c2d5a..4096ad3e416 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/technical_debt_pyramid.html.erb +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/technical_debt_pyramid.html.erb @@ -1,8 +1,7 @@ <% technical_debt = measure('sqale_index') - model_with_root_characteristics = Internal.technical_debt.findRootCharacteristics() - root_characteristics = model_with_root_characteristics.rootCharacteristics().to_a + root_characteristics = Internal.technical_debt.findRootCharacteristics().to_a should_display_diff_measures = dashboard_configuration.selected_period? && technical_debt.variation(dashboard_configuration.period_index)!=nil if technical_debt.nil? || root_characteristics.empty? diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java index dd114e59d23..dbc9352eac0 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java @@ -42,11 +42,13 @@ import org.sonar.api.resources.File; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import org.sonar.api.test.IsMeasure; import org.sonar.core.technicaldebt.TechnicalDebtConverter; -import org.sonar.core.technicaldebt.TechnicalDebtModel; import java.util.List; @@ -68,7 +70,7 @@ public class TechnicalDebtDecoratorTest { TechnicalDebtConverter converter; @Mock - TechnicalDebtModel technicalDebtModel; + TechnicalDebtModel defaultTechnicalDebtModel; @Mock Issuable issuable; @@ -80,7 +82,7 @@ public class TechnicalDebtDecoratorTest { ResourcePerspectives perspectives = mock(ResourcePerspectives.class); when(perspectives.as(Issuable.class, resource)).thenReturn(issuable); - decorator = new TechnicalDebtDecorator(perspectives, technicalDebtModel, converter); + decorator = new TechnicalDebtDecorator(perspectives, defaultTechnicalDebtModel, converter); } @Test @@ -114,8 +116,8 @@ public class TechnicalDebtDecoratorTest { List<Issue> issues = newArrayList(issue1, issue2, issue3, issue4); - when(technicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement1); - when(technicalDebtModel.requirementsByRule(RuleKey.of("repo2", "rule2"))).thenReturn(requirement2); + when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement1); + when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo2", "rule2"))).thenReturn(requirement2); ListMultimap<Requirement, Issue> result = decorator.issuesByRequirement(issues); @@ -133,8 +135,8 @@ public class TechnicalDebtDecoratorTest { when(issuable.issues()).thenReturn(newArrayList(issue)); Requirement requirement = mock(Requirement.class); - when(technicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement); - when(technicalDebtModel.requirements()).thenReturn(newArrayList(requirement)); + when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement); + doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements(); decorator.decorate(resource, context); @@ -150,13 +152,13 @@ public class TechnicalDebtDecoratorTest { Issue issue = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt); when(issuable.issues()).thenReturn(newArrayList(issue)); - Characteristic parentCharacteristic = new Characteristic().setKey("parentCharacteristic"); - Characteristic characteristic = new Characteristic().setKey("characteristic").setParent(parentCharacteristic); + DefaultCharacteristic parentCharacteristic = new DefaultCharacteristic().setKey("parentCharacteristic"); + DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(parentCharacteristic); RuleKey ruleKey = RuleKey.of("repo1", "rule1"); - Requirement requirement = new Requirement().setCharacteristic(characteristic).setRuleKey(ruleKey); + DefaultRequirement requirement = new DefaultRequirement().setCharacteristic(characteristic).setRuleKey(ruleKey); - when(technicalDebtModel.requirementsByRule(ruleKey)).thenReturn(requirement); - when(technicalDebtModel.requirements()).thenReturn(newArrayList(requirement)); + when(defaultTechnicalDebtModel.requirementsByRule(ruleKey)).thenReturn(requirement); + doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements(); decorator.decorate(resource, context); @@ -180,16 +182,16 @@ public class TechnicalDebtDecoratorTest { Issue issue4 = createIssue("rule2", "repo2").setTechnicalDebt(technicalDebt2); when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4)); - Characteristic rootCharacteristic = new Characteristic().setKey("rootCharacteristic"); - Characteristic characteristic = new Characteristic().setKey("characteristic").setParent(rootCharacteristic); + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("rootCharacteristic"); + DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(rootCharacteristic); RuleKey ruleKey1 = RuleKey.of("repo1", "rule1"); - Requirement requirement1 = new Requirement().setRuleKey(ruleKey1).setCharacteristic(characteristic); + DefaultRequirement requirement1 = new DefaultRequirement().setRuleKey(ruleKey1).setCharacteristic(characteristic); RuleKey ruleKey2 = RuleKey.of("repo2", "rule2"); - Requirement requirement2 = new Requirement().setRuleKey(ruleKey2).setCharacteristic(characteristic); + DefaultRequirement requirement2 = new DefaultRequirement().setRuleKey(ruleKey2).setCharacteristic(characteristic); - when(technicalDebtModel.requirementsByRule(ruleKey1)).thenReturn(requirement1); - when(technicalDebtModel.requirementsByRule(ruleKey2)).thenReturn(requirement2); - when(technicalDebtModel.requirements()).thenReturn(newArrayList(requirement1, requirement2)); + when(defaultTechnicalDebtModel.requirementsByRule(ruleKey1)).thenReturn(requirement1); + when(defaultTechnicalDebtModel.requirementsByRule(ruleKey2)).thenReturn(requirement2); + doReturn(newArrayList(requirement1, requirement2)).when(defaultTechnicalDebtModel).requirements(); decorator.decorate(resource, context); @@ -207,13 +209,13 @@ public class TechnicalDebtDecoratorTest { Issue issue2 = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt1); when(issuable.issues()).thenReturn(newArrayList(issue1, issue2)); - Characteristic rootCharacteristic = new Characteristic().setKey("rootCharacteristic"); - Characteristic characteristic = new Characteristic().setKey("characteristic").setParent(rootCharacteristic); + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("rootCharacteristic"); + DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(rootCharacteristic); RuleKey ruleKey1 = RuleKey.of("repo1", "rule1"); - Requirement requirement = new Requirement().setRuleKey(ruleKey1).setCharacteristic(characteristic); + DefaultRequirement requirement = new DefaultRequirement().setRuleKey(ruleKey1).setCharacteristic(characteristic); - when(technicalDebtModel.requirementsByRule(ruleKey1)).thenReturn(requirement); - when(technicalDebtModel.requirements()).thenReturn(newArrayList(requirement)); + when(defaultTechnicalDebtModel.requirementsByRule(ruleKey1)).thenReturn(requirement); + doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements(); Measure measure = new Measure().setRequirement(requirement).setValue(5.0); when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(newArrayList(measure)); @@ -244,7 +246,7 @@ public class TechnicalDebtDecoratorTest { DecoratorContext context = mock(DecoratorContext.class); when(context.getResource()).thenReturn(new Project("foo")); // this is a top characteristic - Characteristic rootCharacteristic = new Characteristic().setKey("root"); + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("root"); decorator.saveTechnicalDebt(context, rootCharacteristic, 0.0, true); verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT).setCharacteristic(rootCharacteristic)); @@ -258,8 +260,8 @@ public class TechnicalDebtDecoratorTest { DecoratorContext context = mock(DecoratorContext.class); when(context.getResource()).thenReturn(new Project("foo")); - Characteristic rootCharacteristic = new Characteristic().setKey("rootCharacteristic"); - Characteristic characteristic = new Characteristic().setKey("characteristic").setParent(rootCharacteristic); + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("rootCharacteristic"); + DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(rootCharacteristic); decorator.saveTechnicalDebt(context, characteristic, 0.0, true); verify(context, never()).saveMeasure(any(Measure.class)); diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java index f7b821493ad..88ce12563d1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java @@ -31,10 +31,10 @@ import org.sonar.api.measures.Metric; import org.sonar.api.measures.MetricFinder; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Resource; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.batch.index.DefaultIndex; -import org.sonar.core.technicaldebt.TechnicalDebtModel; import javax.annotation.Nullable; import javax.persistence.Query; @@ -100,10 +100,10 @@ public class DefaultTimeMachine implements TimeMachine { sb.append("SELECT s.createdAt, m.metricId, m.value "); } sb.append(" FROM ") - .append(MeasureModel.class.getSimpleName()) - .append(" m, ") - .append(Snapshot.class.getSimpleName()) - .append(" s WHERE m.snapshotId=s.id AND s.resourceId=:resourceId AND s.status=:status AND s.qualifier<>:lib"); + .append(MeasureModel.class.getSimpleName()) + .append(" m, ") + .append(Snapshot.class.getSimpleName()) + .append(" s WHERE m.snapshotId=s.id AND s.resourceId=:resourceId AND s.status=:status AND s.qualifier<>:lib"); params.put("resourceId", resource.getId()); params.put("status", Snapshot.STATUS_PROCESSED); params.put("lib", Qualifiers.LIBRARY); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 3e27654af56..2c18795727d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -45,6 +45,7 @@ import org.sonar.batch.scan.maven.FakeMavenPluginExecutor; import org.sonar.batch.scan.maven.MavenPluginExecutor; import org.sonar.batch.source.HighlightableBuilder; import org.sonar.batch.source.SymbolizableBuilder; +import org.sonar.batch.technicaldebt.TechnicalDebtModelLoader; import org.sonar.batch.technicaldebt.TechnicalDebtModelProvider; import org.sonar.core.component.ScanGraph; import org.sonar.core.issue.IssueNotifications; @@ -53,7 +54,6 @@ import org.sonar.core.issue.workflow.FunctionExecutor; import org.sonar.core.issue.workflow.IssueWorkflow; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.technicaldebt.TechnicalDebtConverter; -import org.sonar.core.technicaldebt.TechnicalDebtFinder; import org.sonar.core.test.TestPlanBuilder; import org.sonar.core.test.TestPlanPerspectiveLoader; import org.sonar.core.test.TestableBuilder; @@ -148,7 +148,7 @@ public class ProjectScanContainer extends ComponentContainer { SymbolizableBuilder.class, // technical debt - TechnicalDebtFinder.class, + TechnicalDebtModelLoader.class, TechnicalDebtConverter.class, new TechnicalDebtModelProvider(), diff --git a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java index cbb83221a26..2e71d86e640 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java @@ -23,10 +23,10 @@ import com.google.common.base.Objects; import org.sonar.api.BatchExtension; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.WorkDayDuration; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.batch.Requirement; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.core.technicaldebt.TechnicalDebtConverter; -import org.sonar.core.technicaldebt.TechnicalDebtModel; /** * Computes the remediation cost based on the quality and analysis models. @@ -34,15 +34,15 @@ import org.sonar.core.technicaldebt.TechnicalDebtModel; public class TechnicalDebtCalculator implements BatchExtension { private final TechnicalDebtConverter converter; - private TechnicalDebtModel technicalDebtModel; + private TechnicalDebtModel model; - public TechnicalDebtCalculator(TechnicalDebtModel technicalDebtModel, TechnicalDebtConverter converter) { - this.technicalDebtModel = technicalDebtModel; + public TechnicalDebtCalculator(TechnicalDebtModel model, TechnicalDebtConverter converter) { + this.model = model; this.converter = converter; } public WorkDayDuration calculTechnicalDebt(Issue issue) { - Requirement requirement = technicalDebtModel.requirementsByRule(issue.ruleKey()); + Requirement requirement = model.requirementsByRule(issue.ruleKey()); if (requirement != null) { return converter.fromMinutes(calculTechnicalDebt(requirement, issue)); } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtFinder.java b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoader.java index aebbe56c4e9..1c8fac76f42 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtFinder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoader.java @@ -18,17 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.core.technicaldebt; +package org.sonar.batch.technicaldebt; -import com.google.common.collect.Maps; import org.sonar.api.BatchComponent; -import org.sonar.api.ServerComponent; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.core.technicaldebt.DefaultTechnicalDebtModel; import org.sonar.core.technicaldebt.db.CharacteristicDao; import org.sonar.core.technicaldebt.db.CharacteristicDto; @@ -38,20 +37,20 @@ import java.util.Map; import static com.google.common.collect.Maps.newHashMap; -public class TechnicalDebtFinder implements ServerComponent, BatchComponent { +public class TechnicalDebtModelLoader implements BatchComponent { private final CharacteristicDao dao; private final RuleFinder ruleFinder; - public TechnicalDebtFinder(CharacteristicDao dao, RuleFinder ruleFinder) { + public TechnicalDebtModelLoader(CharacteristicDao dao, RuleFinder ruleFinder) { this.dao = dao; this.ruleFinder = ruleFinder; } - public TechnicalDebtModel findAll() { - TechnicalDebtModel model = new TechnicalDebtModel(); + public TechnicalDebtModel load() { + DefaultTechnicalDebtModel model = new DefaultTechnicalDebtModel(); List<CharacteristicDto> dtos = dao.selectEnabledCharacteristics(); - Map<Integer, Characteristic> characteristicsById = newHashMap(); + Map<Integer, DefaultCharacteristic> characteristicsById = newHashMap(); addRootCharacteristics(model, dtos, characteristicsById); addCharacteristics(model, dtos, characteristicsById); @@ -59,50 +58,33 @@ public class TechnicalDebtFinder implements ServerComponent, BatchComponent { return model; } - public TechnicalDebtModel findRootCharacteristics() { - TechnicalDebtModel model = new TechnicalDebtModel(); - List<CharacteristicDto> dtos = dao.selectEnabledRootCharacteristics(); - addRootCharacteristics(model, dtos, Maps.<Integer, Characteristic>newHashMap()); - return model; - } - - public Requirement findRequirement(Rule rule) { - CharacteristicDto requirementDto = dao.selectRequirement(rule.getId()); - CharacteristicDto characteristicDto = dao.selectCharacteristic(requirementDto.getParentId()); - CharacteristicDto rootCharacteristicDto = dao.selectCharacteristic(characteristicDto.getParentId()); - - Characteristic rootCharacteristic = rootCharacteristicDto.toCharacteristic(null); - Characteristic characteristic = characteristicDto.toCharacteristic(rootCharacteristic); - return requirementDto.toRequirement(RuleKey.of(rule.getRepositoryKey(), rule.getKey()), characteristic, rootCharacteristic); - } - - private void addRootCharacteristics(TechnicalDebtModel model, List<CharacteristicDto> dtos, Map<Integer, Characteristic> characteristicsById){ + private void addRootCharacteristics(DefaultTechnicalDebtModel model, List<CharacteristicDto> dtos, Map<Integer, DefaultCharacteristic> characteristicsById) { for (CharacteristicDto dto : dtos) { if (dto.getParentId() == null) { - Characteristic rootCharacteristic = dto.toCharacteristic(null); + DefaultCharacteristic rootCharacteristic = dto.toCharacteristic(null); model.addRootCharacteristic(rootCharacteristic); characteristicsById.put(dto.getId(), rootCharacteristic); } } } - private void addCharacteristics(TechnicalDebtModel model, List<CharacteristicDto> dtos, Map<Integer, Characteristic> characteristicsById){ + private void addCharacteristics(DefaultTechnicalDebtModel model, List<CharacteristicDto> dtos, Map<Integer, DefaultCharacteristic> characteristicsById) { for (CharacteristicDto dto : dtos) { if (dto.getParentId() != null && dto.getRuleId() == null) { - Characteristic parent = characteristicsById.get(dto.getParentId()); - Characteristic characteristic = dto.toCharacteristic(parent); + DefaultCharacteristic parent = characteristicsById.get(dto.getParentId()); + DefaultCharacteristic characteristic = dto.toCharacteristic(parent); characteristicsById.put(dto.getId(), characteristic); } } } - private void addRequirements(TechnicalDebtModel model, List<CharacteristicDto> dtos, Map<Integer, Characteristic> characteristicsById){ + private void addRequirements(DefaultTechnicalDebtModel model, List<CharacteristicDto> dtos, Map<Integer, DefaultCharacteristic> characteristicsById) { Map<Integer, Rule> rulesById = rulesById(ruleFinder.findAll(RuleQuery.create())); for (CharacteristicDto dto : dtos) { Integer ruleId = dto.getRuleId(); if (ruleId != null) { - Characteristic characteristic = characteristicsById.get(dto.getParentId()); - Characteristic rootCharacteristic = characteristicsById.get(dto.getRootId()); + DefaultCharacteristic characteristic = characteristicsById.get(dto.getParentId()); + DefaultCharacteristic rootCharacteristic = characteristicsById.get(dto.getRootId()); Rule rule = rulesById.get(ruleId); RuleKey ruleKey = RuleKey.of(rule.getRepositoryKey(), rule.getKey()); dto.toRequirement(ruleKey, characteristic, rootCharacteristic); diff --git a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProvider.java b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProvider.java index 1bb8e0642e2..24ea9b6543f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProvider.java @@ -23,9 +23,8 @@ package org.sonar.batch.technicaldebt; import org.picocontainer.injectors.ProviderAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.api.utils.TimeProfiler; -import org.sonar.core.technicaldebt.TechnicalDebtFinder; -import org.sonar.core.technicaldebt.TechnicalDebtModel; public class TechnicalDebtModelProvider extends ProviderAdapter { @@ -33,10 +32,10 @@ public class TechnicalDebtModelProvider extends ProviderAdapter { private TechnicalDebtModel model; - public TechnicalDebtModel provide(TechnicalDebtFinder modelFinder) { + public TechnicalDebtModel provide(TechnicalDebtModelLoader loader) { if (model == null) { TimeProfiler profiler = new TimeProfiler(LOG).start("Loading technical debt model"); - model = modelFinder.findAll(); + model = loader.load(); profiler.stop(); } return model; diff --git a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java index ae829e70e55..acf0d993d0c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java @@ -27,10 +27,10 @@ import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import org.sonar.core.technicaldebt.TechnicalDebtConverter; -import org.sonar.core.technicaldebt.TechnicalDebtModel; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.*; @@ -39,7 +39,7 @@ import static org.mockito.Mockito.*; public class TechnicalDebtCalculatorTest { @Mock - TechnicalDebtModel technicalDebtModel; + TechnicalDebtModel model; @Mock TechnicalDebtConverter converter; @@ -54,7 +54,7 @@ public class TechnicalDebtCalculatorTest { when(converter.toMinutes(tenMinutes)).thenReturn(10l); when(converter.toMinutes(fiveMinutes)).thenReturn(5l); - remediationCostCalculator = new TechnicalDebtCalculator(technicalDebtModel, converter); + remediationCostCalculator = new TechnicalDebtCalculator(model, converter); } @Test @@ -62,10 +62,10 @@ public class TechnicalDebtCalculatorTest { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey); - Requirement requirement = mock(Requirement.class); + DefaultRequirement requirement = mock(DefaultRequirement.class); Mockito.when(requirement.factor()).thenReturn(tenMinutes); Mockito.when(requirement.offset()).thenReturn(fiveMinutes); - when(technicalDebtModel.requirementsByRule(ruleKey)).thenReturn(requirement); + when(model.requirementsByRule(ruleKey)).thenReturn(requirement); remediationCostCalculator.calculTechnicalDebt(issue); @@ -77,10 +77,10 @@ public class TechnicalDebtCalculatorTest { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey).setEffortToFix(2d); - Requirement requirement = mock(Requirement.class); + DefaultRequirement requirement = mock(DefaultRequirement.class); Mockito.when(requirement.factor()).thenReturn(tenMinutes); Mockito.when(requirement.offset()).thenReturn(fiveMinutes); - when(technicalDebtModel.requirementsByRule(ruleKey)).thenReturn(requirement); + when(model.requirementsByRule(ruleKey)).thenReturn(requirement); remediationCostCalculator.calculTechnicalDebt(issue); @@ -92,10 +92,10 @@ public class TechnicalDebtCalculatorTest { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey).setEffortToFix(2d); - Requirement requirement = mock(Requirement.class); + DefaultRequirement requirement = mock(DefaultRequirement.class); Mockito.when(requirement.factor()).thenReturn(tenMinutes); Mockito.when(requirement.offset()).thenReturn(null); - when(technicalDebtModel.requirementsByRule(ruleKey)).thenReturn(requirement); + when(model.requirementsByRule(ruleKey)).thenReturn(requirement); remediationCostCalculator.calculTechnicalDebt(issue); @@ -107,10 +107,10 @@ public class TechnicalDebtCalculatorTest { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey).setEffortToFix(2d); - Requirement requirement = mock(Requirement.class); + DefaultRequirement requirement = mock(DefaultRequirement.class); Mockito.when(requirement.factor()).thenReturn(null); Mockito.when(requirement.offset()).thenReturn(fiveMinutes); - when(technicalDebtModel.requirementsByRule(ruleKey)).thenReturn(requirement); + when(model.requirementsByRule(ruleKey)).thenReturn(requirement); remediationCostCalculator.calculTechnicalDebt(issue); @@ -121,7 +121,7 @@ public class TechnicalDebtCalculatorTest { public void no_technical_debt_if_requirement_not_found() throws Exception { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey); - when(technicalDebtModel.requirementsByRule(ruleKey)).thenReturn(null); + when(model.requirementsByRule(ruleKey)).thenReturn(null); assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isNull(); verify(converter, never()).fromMinutes(anyLong()); diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtFinderTest.java b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoaderTest.java index 46608377b31..6d6cea6d4db 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtFinderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoaderTest.java @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.core.technicaldebt; +package org.sonar.batch.technicaldebt; import org.junit.Before; import org.junit.Test; @@ -29,9 +29,10 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; +import org.sonar.core.technicaldebt.DefaultTechnicalDebtModel; import org.sonar.core.technicaldebt.db.CharacteristicDao; import org.sonar.core.technicaldebt.db.CharacteristicDto; @@ -41,7 +42,7 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) -public class TechnicalDebtFinderTest { +public class TechnicalDebtModelLoaderTest { @Mock CharacteristicDao dao; @@ -49,11 +50,11 @@ public class TechnicalDebtFinderTest { @Mock RuleFinder ruleFinder; - TechnicalDebtFinder finder; + TechnicalDebtModelLoader loader; @Before - public void setUp() throws Exception { - finder = new TechnicalDebtFinder(dao, ruleFinder); + public void before() { + loader = new TechnicalDebtModelLoader(dao, ruleFinder); } @Test @@ -85,10 +86,10 @@ public class TechnicalDebtFinderTest { when(ruleFinder.findAll(any(RuleQuery.class))).thenReturn(newArrayList(rule)); when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(rootCharacteristicDto, characteristicDto, requirementDto)); - TechnicalDebtModel result = finder.findAll(); + DefaultTechnicalDebtModel result = (DefaultTechnicalDebtModel) loader.load(); assertThat(result.rootCharacteristics()).hasSize(1); - Characteristic rootCharacteristic = result.characteristicByKey("MEMORY_EFFICIENCY"); + DefaultCharacteristic rootCharacteristic = result.characteristicByKey("MEMORY_EFFICIENCY"); assertThat(rootCharacteristic.key()).isEqualTo("MEMORY_EFFICIENCY"); assertThat(rootCharacteristic.name()).isEqualTo("Memory use"); assertThat(rootCharacteristic.parent()).isNull(); @@ -96,7 +97,7 @@ public class TechnicalDebtFinderTest { assertThat(rootCharacteristic.children()).hasSize(1); assertThat(rootCharacteristic.children().get(0).key()).isEqualTo("EFFICIENCY"); - Characteristic characteristic = result.characteristicByKey("EFFICIENCY"); + DefaultCharacteristic characteristic = result.characteristicByKey("EFFICIENCY"); assertThat(characteristic.key()).isEqualTo("EFFICIENCY"); assertThat(characteristic.name()).isEqualTo("Efficiency"); assertThat(characteristic.parent().key()).isEqualTo("MEMORY_EFFICIENCY"); @@ -104,48 +105,11 @@ public class TechnicalDebtFinderTest { assertThat(characteristic.requirements()).hasSize(1); assertThat(characteristic.requirements().get(0).ruleKey()).isEqualTo(ruleKey); - Requirement requirement = result.requirementsByRule(ruleKey); + DefaultRequirement requirement = result.requirementsByRule(ruleKey); assertThat(requirement.ruleKey()).isEqualTo(ruleKey); assertThat(requirement.function()).isEqualTo("linear"); assertThat(requirement.factor()).isEqualTo(WorkUnit.create(2d, WorkUnit.DAYS)); assertThat(requirement.offset()).isEqualTo(WorkUnit.create(0d, WorkUnit.DEFAULT_UNIT)); } - @Test - public void find_root_characteristics() throws Exception { - CharacteristicDto rootCharacteristicDto = new CharacteristicDto() - .setId(1) - .setKey("MEMORY_EFFICIENCY") - .setName("Memory use"); - when(dao.selectEnabledRootCharacteristics()).thenReturn(newArrayList(rootCharacteristicDto)); - - TechnicalDebtModel result = finder.findRootCharacteristics(); - assertThat(result.rootCharacteristics()).hasSize(1); - - Characteristic rootCharacteristic = result.characteristicByKey("MEMORY_EFFICIENCY"); - assertThat(rootCharacteristic.key()).isEqualTo("MEMORY_EFFICIENCY"); - assertThat(rootCharacteristic.name()).isEqualTo("Memory use"); - assertThat(rootCharacteristic.parent()).isNull(); - assertThat(rootCharacteristic.requirements()).isEmpty(); - assertThat(rootCharacteristic.children()).isEmpty(); - } - - @Test - public void find_requirement() throws Exception { - Rule rule = Rule.create("repo", "key"); - rule.setId(1); - - when(dao.selectRequirement(rule.getId())).thenReturn( - new CharacteristicDto().setId(3).setRuleId(10).setParentId(2).setFunction("linear").setFactorValue(30.0).setFactorUnit("mn")); - when(dao.selectCharacteristic(2)).thenReturn( - new CharacteristicDto().setId(2).setKey("COMPILER_RELATED_PORTABILITY").setParentId(1)); - when(dao.selectCharacteristic(1)).thenReturn( - new CharacteristicDto().setId(1).setKey("PORTABILITY")); - - Requirement result = finder.findRequirement(rule); - - assertThat(result.ruleKey()).isEqualTo(RuleKey.of("repo", "key")); - assertThat(result.characteristic().key()).isEqualTo("COMPILER_RELATED_PORTABILITY"); - assertThat(result.characteristic().parent().key()).isEqualTo("PORTABILITY"); - } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProviderTest.java index b632b32fb4d..e4bee8d0ea2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProviderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelProviderTest.java @@ -24,8 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.sonar.core.technicaldebt.TechnicalDebtFinder; -import org.sonar.core.technicaldebt.TechnicalDebtModel; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.*; @@ -34,28 +33,28 @@ import static org.mockito.Mockito.*; public class TechnicalDebtModelProviderTest { @Mock - TechnicalDebtFinder modelFinder; + TechnicalDebtModelLoader loader; @Test - public void load_model(){ - TechnicalDebtModel model = new TechnicalDebtModel(); - when(modelFinder.findAll()).thenReturn(model); + public void load_model() { + TechnicalDebtModel model = mock(TechnicalDebtModel.class); + when(loader.load()).thenReturn(model); TechnicalDebtModelProvider provider = new TechnicalDebtModelProvider(); - TechnicalDebtModel result = provider.provide(modelFinder); + TechnicalDebtModel result = provider.provide(loader); assertThat(result).isNotNull(); } @Test - public void load_model_only_once(){ - TechnicalDebtModel model = new TechnicalDebtModel(); - when(modelFinder.findAll()).thenReturn(model); + public void load_model_only_once() { + TechnicalDebtModel model = mock(TechnicalDebtModel.class); + when(loader.load()).thenReturn(model); TechnicalDebtModelProvider provider = new TechnicalDebtModelProvider(); - provider.provide(modelFinder); - verify(modelFinder).findAll(); + provider.provide(loader); + verify(loader).load(); - provider.provide(modelFinder); - verifyZeroInteractions(modelFinder); + provider.provide(loader); + verifyZeroInteractions(loader); } } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManager.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManager.java new file mode 100644 index 00000000000..efea9e3f4f5 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManager.java @@ -0,0 +1,77 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.core.technicaldebt; + +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.Rule; +import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.server.Characteristic; +import org.sonar.api.technicaldebt.server.TechnicalDebtManager; +import org.sonar.core.technicaldebt.db.CharacteristicDao; +import org.sonar.core.technicaldebt.db.CharacteristicDto; + +import javax.annotation.Nullable; + +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; + +public class DefaultTechnicalDebtManager implements TechnicalDebtManager { + + private final CharacteristicDao dao; + + public DefaultTechnicalDebtManager(CharacteristicDao dao) { + this.dao = dao; + } + + public List<Characteristic> findRootCharacteristics() { + List<CharacteristicDto> dtos = dao.selectEnabledRootCharacteristics(); + List<Characteristic> characteristics = newArrayList(); + for (CharacteristicDto dto : dtos) { + characteristics.add(toCharacteristic(dto, null)); + } + return characteristics; + } + + public Characteristic findCharacteristicById(Integer id) { + return toCharacteristic(dao.selectById(id), null); + } + + public Characteristic findRequirementByRule(Rule rule) { + CharacteristicDto requirementDto = dao.selectByRuleId(rule.getId()); + return toCharacteristic(requirementDto, RuleKey.of(rule.getRepositoryKey(), rule.getKey())); + } + + private static Characteristic toCharacteristic(CharacteristicDto dto, @Nullable RuleKey ruleKey) { + return new Characteristic() + .setId(dto.getId()) + .setKey(dto.getKey()) + .setName(dto.getName()) + .setOrder(dto.getOrder()) + .setParentId(dto.getParentId()) + .setRootId(dto.getRootId()) + .setRuleKey(ruleKey) + .setFunction(dto.getFunction()) + .setFactor(WorkUnit.create(dto.getFactorValue(), dto.getFactorUnit())) + .setOffset(WorkUnit.create(dto.getOffsetValue(), dto.getOffsetUnit())); + } + +} diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModel.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModel.java index 1cbaddfe64c..f08da844aa4 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModel.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModel.java @@ -23,8 +23,9 @@ package org.sonar.core.technicaldebt; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import javax.annotation.CheckForNull; @@ -33,83 +34,83 @@ import java.util.List; import static com.google.common.collect.Lists.newArrayList; -public class TechnicalDebtModel { +public class DefaultTechnicalDebtModel implements TechnicalDebtModel { - private Collection<Characteristic> rootCharacteristics; + private Collection<DefaultCharacteristic> rootCharacteristics; - public TechnicalDebtModel() { + public DefaultTechnicalDebtModel() { rootCharacteristics = newArrayList(); } - public TechnicalDebtModel addRootCharacteristic(Characteristic characteristic) { + public DefaultTechnicalDebtModel addRootCharacteristic(DefaultCharacteristic characteristic) { rootCharacteristics.add(characteristic); return this; } - public List<Characteristic> rootCharacteristics() { - return newArrayList(Iterables.filter(rootCharacteristics, new Predicate<Characteristic>() { + public List<DefaultCharacteristic> rootCharacteristics() { + return newArrayList(Iterables.filter(rootCharacteristics, new Predicate<DefaultCharacteristic>() { @Override - public boolean apply(Characteristic input) { + public boolean apply(DefaultCharacteristic input) { return input.isRoot(); } })); } @CheckForNull - public Characteristic characteristicByKey(final String key) { - return Iterables.find(characteristics(), new Predicate<Characteristic>() { + public DefaultCharacteristic characteristicByKey(final String key) { + return Iterables.find(characteristics(), new Predicate<DefaultCharacteristic>() { @Override - public boolean apply(Characteristic input) { + public boolean apply(DefaultCharacteristic input) { return input.key().equals(key); } }, null); } @CheckForNull - public Characteristic characteristicById(final Integer id){ - return Iterables.find(characteristics(), new Predicate<Characteristic>() { + public DefaultCharacteristic characteristicById(final Integer id){ + return Iterables.find(characteristics(), new Predicate<DefaultCharacteristic>() { @Override - public boolean apply(Characteristic input) { + public boolean apply(DefaultCharacteristic input) { return input.id().equals(id); } }, null); } @CheckForNull - public Requirement requirementsByRule(final RuleKey ruleKey) { - return Iterables.find(requirements(), new Predicate<Requirement>() { + public DefaultRequirement requirementsByRule(final RuleKey ruleKey) { + return Iterables.find(requirements(), new Predicate<DefaultRequirement>() { @Override - public boolean apply(Requirement input) { + public boolean apply(DefaultRequirement input) { return input.ruleKey().equals(ruleKey); } }, null); } @CheckForNull - public Requirement requirementsById(final Integer id){ - return Iterables.find(requirements(), new Predicate<Requirement>() { + public DefaultRequirement requirementsById(final Integer id){ + return Iterables.find(requirements(), new Predicate<DefaultRequirement>() { @Override - public boolean apply(Requirement input) { + public boolean apply(DefaultRequirement input) { return input.id().equals(id); } }, null); } - public List<Characteristic> characteristics() { - List<Characteristic> flatCharacteristics = newArrayList(); - for (Characteristic rootCharacteristic : rootCharacteristics) { + public List<DefaultCharacteristic> characteristics() { + List<DefaultCharacteristic> flatCharacteristics = newArrayList(); + for (DefaultCharacteristic rootCharacteristic : rootCharacteristics) { flatCharacteristics.add(rootCharacteristic); - for (Characteristic characteristic : rootCharacteristic.children()) { + for (DefaultCharacteristic characteristic : rootCharacteristic.children()) { flatCharacteristics.add(characteristic); } } return flatCharacteristics; } - public List<Requirement> requirements() { - List<Requirement> allRequirements = newArrayList(); - for (Characteristic characteristic : characteristics()) { - for (Requirement requirement : characteristic.requirements()) { + public List<DefaultRequirement> requirements() { + List<DefaultRequirement> allRequirements = newArrayList(); + for (DefaultCharacteristic characteristic : characteristics()) { + for (DefaultRequirement requirement : characteristic.requirements()) { allRequirements.add(requirement); } } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelService.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelService.java deleted file mode 100644 index caa856103c3..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelService.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.core.technicaldebt; - -import org.apache.ibatis.session.SqlSession; -import org.sonar.api.ServerExtension; -import org.sonar.api.rules.Rule; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; -import org.sonar.core.persistence.MyBatis; -import org.sonar.core.technicaldebt.db.CharacteristicDao; -import org.sonar.core.technicaldebt.db.CharacteristicDto; - -import javax.annotation.Nullable; - -public class TechnicalDebtModelService implements ServerExtension { - - private final MyBatis mybatis; - private final CharacteristicDao dao; - - public TechnicalDebtModelService(MyBatis mybatis, CharacteristicDao dao) { - this.mybatis = mybatis; - this.dao = dao; - } - - public void create(Characteristic characteristic, @Nullable Integer parentId, SqlSession session) { - CharacteristicDto characteristicDto = CharacteristicDto.toDto(characteristic, parentId); - dao.insert(characteristicDto, session); - characteristic.setId(characteristicDto.getId()); - } - - public void create(Characteristic characteristic, @Nullable Integer parentId) { - SqlSession session = mybatis.openSession(); - try { - create(characteristic, parentId, session); - session.commit(); - } finally { - MyBatis.closeQuietly(session); - } - } - - public void create(Requirement requirement, Integer characteristicId, Integer rootCharacteristicId, TechnicalDebtRuleCache ruleCache, SqlSession session) { - Rule rule = ruleCache.getByRuleKey(requirement.ruleKey()); - CharacteristicDto requirementDto = CharacteristicDto.toDto(requirement, characteristicId, rootCharacteristicId, rule.getId()); - dao.insert(requirementDto, session); - requirement.setId(requirementDto.getId()); - } - - public void create(Requirement requirement, Integer characteristicId, Integer rootCharacteristicId, TechnicalDebtRuleCache ruleCache) { - SqlSession session = mybatis.openSession(); - try { - create(requirement, characteristicId, rootCharacteristicId, ruleCache, session); - session.commit(); - } finally { - MyBatis.closeQuietly(session); - } - } - - public void disable(Requirement requirement, SqlSession session) { - dao.disable(requirement.id(), session); - } - - public void disable(Requirement requirement) { - SqlSession session = mybatis.openSession(); - try { - disable(requirement, session); - session.commit(); - } finally { - MyBatis.closeQuietly(session); - } - } - -} diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizer.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizer.java index 0c885d13c94..2dd4f95a695 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizer.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizer.java @@ -28,8 +28,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.ServerExtension; import org.sonar.api.rules.Rule; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import org.sonar.api.utils.ValidationMessages; import org.sonar.core.persistence.MyBatis; import org.sonar.core.technicaldebt.db.CharacteristicDao; @@ -58,12 +58,12 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { this.importer = importer; } - public List<CharacteristicDto> initAndMergePlugins(ValidationMessages messages, TechnicalDebtRuleCache rulesCache) { + public List<CharacteristicDto> synchronize(ValidationMessages messages, TechnicalDebtRuleCache rulesCache) { SqlSession session = mybatis.openSession(); List<CharacteristicDto> model = newArrayList(); try { - model = initAndMergePlugins(messages, rulesCache, session); + model = synchronize(messages, rulesCache, session); session.commit(); } finally { MyBatis.closeQuietly(session); @@ -71,8 +71,8 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { return model; } - public List<CharacteristicDto> initAndMergePlugins(ValidationMessages messages, TechnicalDebtRuleCache rulesCache, SqlSession session) { - TechnicalDebtModel defaultModel = loadModelFromXml(TechnicalDebtModelRepository.DEFAULT_MODEL, messages, rulesCache); + public List<CharacteristicDto> synchronize(ValidationMessages messages, TechnicalDebtRuleCache rulesCache, SqlSession session) { + DefaultTechnicalDebtModel defaultModel = loadModelFromXml(TechnicalDebtModelRepository.DEFAULT_MODEL, messages, rulesCache); List<CharacteristicDto> model = loadOrCreateModelFromDb(defaultModel, messages, session); disableRequirementsOnRemovedRules(model, rulesCache, session); mergePlugins(model, defaultModel, messages, rulesCache, session); @@ -81,7 +81,7 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { return model; } - private List<CharacteristicDto> loadOrCreateModelFromDb(TechnicalDebtModel defaultModel, ValidationMessages messages, SqlSession session) { + private List<CharacteristicDto> loadOrCreateModelFromDb(DefaultTechnicalDebtModel defaultModel, ValidationMessages messages, SqlSession session) { List<CharacteristicDto> characteristicDtos = loadModel(); if (characteristicDtos.isEmpty()) { return createTechnicalDebtModel(defaultModel, session); @@ -93,13 +93,13 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { return dao.selectEnabledCharacteristics(); } - private List<CharacteristicDto> createTechnicalDebtModel(TechnicalDebtModel defaultModel, SqlSession session) { + private List<CharacteristicDto> createTechnicalDebtModel(DefaultTechnicalDebtModel defaultModel, SqlSession session) { List<CharacteristicDto> characteristics = newArrayList(); - for (Characteristic rootCharacteristic : defaultModel.rootCharacteristics()) { + for (DefaultCharacteristic rootCharacteristic : defaultModel.rootCharacteristics()) { CharacteristicDto rootCharacteristicDto = CharacteristicDto.toDto(rootCharacteristic, null); dao.insert(rootCharacteristicDto, session); characteristics.add(rootCharacteristicDto); - for (Characteristic characteristic : rootCharacteristic.children()) { + for (DefaultCharacteristic characteristic : rootCharacteristic.children()) { CharacteristicDto characteristicDto = CharacteristicDto.toDto(characteristic, rootCharacteristicDto.getId()); dao.insert(characteristicDto, session); characteristics.add(characteristicDto); @@ -108,28 +108,28 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { return characteristics; } - private void mergePlugins(List<CharacteristicDto> existingModel, TechnicalDebtModel defaultModel, ValidationMessages messages, TechnicalDebtRuleCache rulesCache, SqlSession session) { + private void mergePlugins(List<CharacteristicDto> existingModel, DefaultTechnicalDebtModel defaultModel, ValidationMessages messages, TechnicalDebtRuleCache rulesCache, SqlSession session) { for (String pluginKey : getContributingPluginListWithoutSqale()) { - TechnicalDebtModel pluginModel = loadModelFromXml(pluginKey, messages, rulesCache); + DefaultTechnicalDebtModel pluginModel = loadModelFromXml(pluginKey, messages, rulesCache); checkPluginDoNotAddNewCharacteristic(pluginModel, defaultModel); mergePlugin(pluginModel, existingModel, messages, rulesCache, session); } } - private void mergePlugin(TechnicalDebtModel pluginModel, List<CharacteristicDto> existingModel, ValidationMessages messages, TechnicalDebtRuleCache rulesCache, SqlSession session) { + private void mergePlugin(DefaultTechnicalDebtModel pluginModel, List<CharacteristicDto> existingModel, ValidationMessages messages, TechnicalDebtRuleCache rulesCache, SqlSession session) { if (!messages.hasErrors()) { - for (Requirement pluginRequirement : pluginModel.requirements()) { + for (DefaultRequirement pluginRequirement : pluginModel.requirements()) { Rule rule = rulesCache.getByRuleKey(pluginRequirement.ruleKey()); - if (!find(existingModel, rule)) { + if (!isRequirementExists(existingModel, rule)) { CharacteristicDto characteristicDto = findCharacteristic(existingModel, pluginRequirement.characteristic().key()); - CharacteristicDto requirementDto = CharacteristicDto.toDto(pluginRequirement, characteristicDto.getId(), characteristicDto.getRootId(), rule.getId()); + CharacteristicDto requirementDto = CharacteristicDto.toDto(pluginRequirement, characteristicDto.getId(), characteristicDto.getRootId(), rule.getId()); dao.insert(requirementDto, session); } } } } - private TechnicalDebtModel loadModelFromXml(String pluginKey, ValidationMessages messages, TechnicalDebtRuleCache rulesCache) { + public DefaultTechnicalDebtModel loadModelFromXml(String pluginKey, ValidationMessages messages, TechnicalDebtRuleCache rulesCache) { Reader xmlFileReader = null; try { xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey); @@ -139,9 +139,9 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { } } - private void checkPluginDoNotAddNewCharacteristic(TechnicalDebtModel pluginModel, TechnicalDebtModel defaultModel) { - List<Characteristic> characteristics = defaultModel.characteristics(); - for (Characteristic characteristic : pluginModel.characteristics()) { + private void checkPluginDoNotAddNewCharacteristic(DefaultTechnicalDebtModel pluginModel, DefaultTechnicalDebtModel defaultModel) { + List<DefaultCharacteristic> characteristics = defaultModel.characteristics(); + for (DefaultCharacteristic characteristic : pluginModel.characteristics()) { if (!characteristics.contains(characteristic)) { throw new IllegalArgumentException("The characteristic : " + characteristic.key() + " cannot be used as it's not available in default characteristics."); } @@ -172,7 +172,7 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { }); } - private boolean find(List<CharacteristicDto> existingModel, final Rule rule) { + private boolean isRequirementExists(List<CharacteristicDto> existingModel, final Rule rule) { return Iterables.any(existingModel, new Predicate<CharacteristicDto>() { @Override public boolean apply(CharacteristicDto input) { @@ -181,4 +181,5 @@ public class TechnicalDebtModelSynchronizer implements ServerExtension { } }); } + } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRuleCache.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRuleCache.java index f5b9c06573e..e435fe6a022 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRuleCache.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRuleCache.java @@ -54,13 +54,19 @@ public class TechnicalDebtRuleCache { return lookUpRuleInCache(ruleKey.repository(), ruleKey.rule()); } + @CheckForNull + public Rule getByRuleId(Integer ruleId) { + initRules(); + return cachedRulesId.get(ruleId); + } + public boolean exists(Rule rule) { return getRule(rule.getRepositoryKey(), rule.getKey()) != null; } public boolean exists(Integer ruleId) { initRules(); - return cachedRulesId.get(ruleId) != null; + return getByRuleId(ruleId) != null; } public boolean exists(RuleKey ruleKey) { diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java index d5eef27622a..7482db5dd5e 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java @@ -33,9 +33,9 @@ import org.slf4j.LoggerFactory; import org.sonar.api.ServerExtension; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import org.sonar.api.utils.ValidationMessages; import javax.xml.stream.XMLInputFactory; @@ -67,12 +67,12 @@ public class TechnicalDebtXMLImporter implements ServerExtension { public static final String PROPERTY_FACTOR = "remediationFactor"; public static final String PROPERTY_OFFSET = "offset"; - public TechnicalDebtModel importXML(String xml, ValidationMessages messages, TechnicalDebtRuleCache technicalDebtRuleCache) { + public DefaultTechnicalDebtModel importXML(String xml, ValidationMessages messages, TechnicalDebtRuleCache technicalDebtRuleCache) { return importXML(new StringReader(xml), messages, technicalDebtRuleCache); } - public TechnicalDebtModel importXML(Reader xml, ValidationMessages messages, TechnicalDebtRuleCache repositoryCache) { - TechnicalDebtModel model = new TechnicalDebtModel(); + public DefaultTechnicalDebtModel importXML(Reader xml, ValidationMessages messages, TechnicalDebtRuleCache repositoryCache) { + DefaultTechnicalDebtModel model = new DefaultTechnicalDebtModel(); try { SMInputFactory inputFactory = initStax(); SMHierarchicCursor cursor = inputFactory.rootElementCursor(xml); @@ -103,9 +103,9 @@ public class TechnicalDebtXMLImporter implements ServerExtension { return new SMInputFactory(xmlFactory); } - private Characteristic processCharacteristic(TechnicalDebtModel model, Characteristic parent, SMInputCursor chcCursor, ValidationMessages messages, + private DefaultCharacteristic processCharacteristic(DefaultTechnicalDebtModel model, DefaultCharacteristic parent, SMInputCursor chcCursor, ValidationMessages messages, TechnicalDebtRuleCache technicalDebtRuleCache) throws XMLStreamException { - Characteristic characteristic = new Characteristic(); + DefaultCharacteristic characteristic = new DefaultCharacteristic(); characteristic.setParent(parent); SMInputCursor cursor = chcCursor.childElementCursor(); @@ -122,7 +122,7 @@ public class TechnicalDebtXMLImporter implements ServerExtension { processCharacteristic(model, characteristic, cursor, messages, technicalDebtRuleCache); } else if (StringUtils.equals(node, REPOSITORY_KEY)) { - Requirement requirement = processRequirement(model, cursor, messages, technicalDebtRuleCache); + DefaultRequirement requirement = processRequirement(model, cursor, messages, technicalDebtRuleCache); if (requirement != null) { requirement.setCharacteristic(parent); } @@ -137,10 +137,10 @@ public class TechnicalDebtXMLImporter implements ServerExtension { return null; } - private Requirement processRequirement(TechnicalDebtModel model, SMInputCursor cursor, ValidationMessages messages, TechnicalDebtRuleCache technicalDebtRuleCache) + private DefaultRequirement processRequirement(DefaultTechnicalDebtModel model, SMInputCursor cursor, ValidationMessages messages, TechnicalDebtRuleCache technicalDebtRuleCache) throws XMLStreamException { - Requirement requirement = new Requirement(); + DefaultRequirement requirement = new DefaultRequirement(); String ruleRepositoryKey = cursor.collectDescendantText().trim(); String ruleKey = null; Properties properties = new Properties(); @@ -159,7 +159,7 @@ public class TechnicalDebtXMLImporter implements ServerExtension { return processFunctionsOnRequirement(requirement, properties, messages); } - private void fillRule(Requirement requirement, String ruleRepositoryKey, String ruleKey, ValidationMessages messages, + private void fillRule(DefaultRequirement requirement, String ruleRepositoryKey, String ruleKey, ValidationMessages messages, TechnicalDebtRuleCache technicalDebtRuleCache) { if (StringUtils.isNotBlank(ruleRepositoryKey) && StringUtils.isNotBlank(ruleKey)) { Rule rule = technicalDebtRuleCache.getByRuleKey(RuleKey.of(ruleRepositoryKey, ruleKey)); @@ -171,7 +171,7 @@ public class TechnicalDebtXMLImporter implements ServerExtension { } } - private Property processProperty(Requirement requirement, SMInputCursor cursor, ValidationMessages messages) throws XMLStreamException { + private Property processProperty(DefaultRequirement requirement, SMInputCursor cursor, ValidationMessages messages) throws XMLStreamException { SMInputCursor c = cursor.childElementCursor(); String key = null; Double value = null; @@ -195,7 +195,7 @@ public class TechnicalDebtXMLImporter implements ServerExtension { return new Property(key, value, textValue); } - private Requirement processFunctionsOnRequirement(Requirement requirement, Properties properties, ValidationMessages messages) { + private DefaultRequirement processFunctionsOnRequirement(DefaultRequirement requirement, Properties properties, ValidationMessages messages) { Property function = properties.function(); Property factor = properties.factor(); Property offset = properties.offset(); @@ -203,7 +203,7 @@ public class TechnicalDebtXMLImporter implements ServerExtension { if (function != null) { String functionKey = function.getTextValue(); if ("linear_threshold".equals(functionKey)) { - function.setTextValue(Requirement.FUNCTION_LINEAR); + function.setTextValue(DefaultRequirement.FUNCTION_LINEAR); offset.setValue(0d); messages.addWarningText(String.format("Linear with threshold function is no more used, function of the requirement '%s' is replaced by linear.", requirement.ruleKey())); } else if ("constant_resource".equals(functionKey)) { diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java index f20efc59ef5..03e58946de8 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java @@ -61,31 +61,31 @@ public class CharacteristicDao implements BatchComponent, ServerComponent { } } - public CharacteristicDto selectCharacteristic(String key) { + public CharacteristicDto selectByKey(String key) { SqlSession session = mybatis.openSession(); CharacteristicMapper mapper = session.getMapper(CharacteristicMapper.class); try { - return mapper.selectCharacteristicByKey(key); + return mapper.selectByKey(key); } finally { MyBatis.closeQuietly(session); } } - public CharacteristicDto selectCharacteristic(Integer id) { + public CharacteristicDto selectById(Integer id) { SqlSession session = mybatis.openSession(); CharacteristicMapper mapper = session.getMapper(CharacteristicMapper.class); try { - return mapper.selectCharacteristicById(id); + return mapper.selectById(id); } finally { MyBatis.closeQuietly(session); } } - public CharacteristicDto selectRequirement(Integer ruleId) { + public CharacteristicDto selectByRuleId(Integer ruleId) { SqlSession session = mybatis.openSession(); CharacteristicMapper mapper = session.getMapper(CharacteristicMapper.class); try { - return mapper.selectRequirementByRuleId(ruleId); + return mapper.selectByRuleId(ruleId); } finally { MyBatis.closeQuietly(session); } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDto.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDto.java index 5bbad0f6e58..1c891d53c60 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDto.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDto.java @@ -21,9 +21,9 @@ package org.sonar.core.technicaldebt.db; import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import javax.annotation.CheckForNull; import javax.annotation.Nullable; @@ -196,8 +196,8 @@ public class CharacteristicDto implements Serializable { return this; } - public Characteristic toCharacteristic(Characteristic parent) { - return new Characteristic() + public DefaultCharacteristic toCharacteristic(DefaultCharacteristic parent) { + return new DefaultCharacteristic() .setId(id) .setKey(kee) .setName(name) @@ -208,7 +208,7 @@ public class CharacteristicDto implements Serializable { .setUpdatedAt(updatedAt); } - public static CharacteristicDto toDto(Characteristic characteristic, @Nullable Integer parentId) { + public static CharacteristicDto toDto(DefaultCharacteristic characteristic, @Nullable Integer parentId) { return new CharacteristicDto() .setKey(characteristic.key()) .setName(characteristic.name()) @@ -220,8 +220,8 @@ public class CharacteristicDto implements Serializable { .setUpdatedAt(characteristic.updatedAt()); } - public Requirement toRequirement(RuleKey ruleKey, Characteristic characteristic, Characteristic rootCharacteristic) { - return new Requirement() + public DefaultRequirement toRequirement(RuleKey ruleKey, DefaultCharacteristic characteristic, DefaultCharacteristic rootCharacteristic) { + return new DefaultRequirement() .setId(id) .setRuleKey(ruleKey) .setCharacteristic(characteristic) @@ -233,7 +233,7 @@ public class CharacteristicDto implements Serializable { .setUpdatedAt(updatedAt); } - public static CharacteristicDto toDto(Requirement requirement, Integer characteristicId, Integer rootCharacteristicId, Integer ruleId) { + public static CharacteristicDto toDto(DefaultRequirement requirement, Integer characteristicId, Integer rootCharacteristicId, Integer ruleId) { return new CharacteristicDto() .setRuleId(ruleId) .setParentId(characteristicId) diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java index afa98c47a0d..be972668908 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java @@ -28,11 +28,11 @@ public interface CharacteristicMapper { List<CharacteristicDto> selectEnabledRootCharacteristics(); - CharacteristicDto selectCharacteristicByKey(String key); + CharacteristicDto selectByKey(String key); - CharacteristicDto selectCharacteristicById(Integer id); + CharacteristicDto selectById(Integer id); - CharacteristicDto selectRequirementByRuleId(Integer ruleId); + CharacteristicDto selectByRuleId(Integer ruleId); void insert(CharacteristicDto characteristic); diff --git a/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml b/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml index 9d7de18876d..b6b3fe2be4c 100644 --- a/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml @@ -41,7 +41,7 @@ order by characteristic_order asc </select> - <select id="selectCharacteristicByKey" parameterType="String" resultType="Characteristic"> + <select id="selectByKey" parameterType="String" resultType="Characteristic"> select <include refid="characteristicColumns"/> from characteristics c <where> @@ -50,7 +50,7 @@ </where> </select> - <select id="selectCharacteristicById" parameterType="Integer" resultType="Characteristic"> + <select id="selectById" parameterType="Integer" resultType="Characteristic"> select <include refid="characteristicColumns"/> from characteristics c <where> @@ -59,7 +59,7 @@ </where> </select> - <select id="selectRequirementByRuleId" parameterType="Integer" resultType="Characteristic"> + <select id="selectByRuleId" parameterType="Integer" resultType="Characteristic"> select <include refid="characteristicColumns"/> from characteristics c <where> diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java new file mode 100644 index 00000000000..085cb82d638 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.core.technicaldebt; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.Rule; +import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.server.Characteristic; +import org.sonar.core.technicaldebt.db.CharacteristicDao; +import org.sonar.core.technicaldebt.db.CharacteristicDto; + +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class DefaultTechnicalDebtManagerTest { + + @Mock + CharacteristicDao dao; + + DefaultTechnicalDebtManager finder; + + @Before + public void setUp() throws Exception { + finder = new DefaultTechnicalDebtManager(dao); + } + + @Test + public void find_root_characteristics() throws Exception { + CharacteristicDto rootCharacteristicDto = new CharacteristicDto() + .setId(1) + .setKey("MEMORY_EFFICIENCY") + .setName("Memory use"); + when(dao.selectEnabledRootCharacteristics()).thenReturn(newArrayList(rootCharacteristicDto)); + + List<Characteristic> result = finder.findRootCharacteristics(); + assertThat(result).hasSize(1); + + Characteristic rootCharacteristic = result.get(0); + assertThat(rootCharacteristic.key()).isEqualTo("MEMORY_EFFICIENCY"); + assertThat(rootCharacteristic.name()).isEqualTo("Memory use"); + assertThat(rootCharacteristic.parentId()).isNull(); + assertThat(rootCharacteristic.rootId()).isNull(); + } + + @Test + public void find_requirement() throws Exception { + Rule rule = Rule.create("repo", "key"); + rule.setId(1); + + when(dao.selectByRuleId(rule.getId())).thenReturn( + new CharacteristicDto().setId(3).setRuleId(10).setParentId(2).setRootId(1).setFunction("linear").setFactorValue(30.0).setFactorUnit("mn")); + + Characteristic result = finder.findRequirementByRule(rule); + + assertThat(result.id()).isEqualTo(3); + assertThat(result.parentId()).isEqualTo(2); + assertThat(result.rootId()).isEqualTo(1); + assertThat(result.ruleKey()).isEqualTo(RuleKey.of("repo", "key")); + assertThat(result.function()).isEqualTo("linear"); + assertThat(result.factor()).isEqualTo(WorkUnit.create(30.0, WorkUnit.MINUTES)); + assertThat(result.offset()).isEqualTo(WorkUnit.create()); + } + + @Test + public void find_characteristic() throws Exception { + Rule rule = Rule.create("repo", "key"); + rule.setId(1); + + when(dao.selectById(2)).thenReturn( + new CharacteristicDto().setId(2).setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler").setParentId(1).setRootId(1)); + + Characteristic result = finder.findCharacteristicById(2); + + assertThat(result.id()).isEqualTo(2); + assertThat(result.parentId()).isEqualTo(1); + assertThat(result.rootId()).isEqualTo(1); + assertThat(result.key()).isEqualTo("COMPILER_RELATED_PORTABILITY"); + assertThat(result.name()).isEqualTo("Compiler"); + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java index ff161409b57..12d927b5f62 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java @@ -23,28 +23,28 @@ package org.sonar.core.technicaldebt; import org.junit.Before; import org.junit.Test; import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import static org.fest.assertions.Assertions.assertThat; -public class TechnicalDebtModelTest { +public class DefaultTechnicalDebtModelTest { - private TechnicalDebtModel sqaleModel; + private DefaultTechnicalDebtModel sqaleModel; @Before public void setUp() throws Exception { - sqaleModel = new TechnicalDebtModel(); + sqaleModel = new DefaultTechnicalDebtModel(); } @Test public void get_root_characteristics() throws Exception { - Characteristic rootCharacteristic = new Characteristic() + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic() .setKey("MEMORY_EFFICIENCY") .setName("Memory use"); - new Characteristic() + new DefaultCharacteristic() .setKey("EFFICIENCY") .setName("Efficiency") .setParent(rootCharacteristic); @@ -52,17 +52,17 @@ public class TechnicalDebtModelTest { sqaleModel.addRootCharacteristic(rootCharacteristic); assertThat(sqaleModel.rootCharacteristics()).hasSize(1); - Characteristic resultRootCharacteristic = sqaleModel.rootCharacteristics().get(0); + DefaultCharacteristic resultRootCharacteristic = sqaleModel.rootCharacteristics().get(0); assertThat(resultRootCharacteristic).isEqualTo(rootCharacteristic); } @Test public void get_characteristic_by_key() throws Exception { - Characteristic rootCharacteristic = new Characteristic() + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic() .setKey("MEMORY_EFFICIENCY") .setName("Memory use"); - Characteristic characteristic = new Characteristic() + DefaultCharacteristic characteristic = new DefaultCharacteristic() .setKey("EFFICIENCY") .setName("Efficiency") .setParent(rootCharacteristic); @@ -78,17 +78,17 @@ public class TechnicalDebtModelTest { @Test public void get_requirement_by_rule_key() throws Exception { - Characteristic rootCharacteristic = new Characteristic() + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic() .setKey("MEMORY_EFFICIENCY") .setName("Memory use"); - Characteristic characteristic = new Characteristic() + DefaultCharacteristic characteristic = new DefaultCharacteristic() .setKey("EFFICIENCY") .setName("Efficiency") .setParent(rootCharacteristic); RuleKey ruleKey = RuleKey.of("checkstyle", "Regexp"); - Requirement requirement = new Requirement() + DefaultRequirement requirement = new DefaultRequirement() .setCharacteristic(characteristic) .setRuleKey(ruleKey) .setFunction("linear") diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java index 7b94b394b4e..c1b83e5c119 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java @@ -30,9 +30,9 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import org.sonar.api.utils.ValidationMessages; import org.sonar.core.persistence.MyBatis; import org.sonar.core.technicaldebt.db.CharacteristicDao; @@ -70,7 +70,7 @@ public class TechnicalDebtModelSynchronizerTest { @Mock TechnicalDebtXMLImporter xmlImporter; - private TechnicalDebtModel defaultModel; + private DefaultTechnicalDebtModel defaultModel; private TechnicalDebtModelSynchronizer manager; @@ -78,7 +78,7 @@ public class TechnicalDebtModelSynchronizerTest { public void initAndMerge() throws Exception { when(myBatis.openSession()).thenReturn(session); - defaultModel = new TechnicalDebtModel(); + defaultModel = new DefaultTechnicalDebtModel(); Reader defaultModelReader = mock(Reader.class); when(technicalDebtModelRepository.createReaderForXMLFile("technical-debt")).thenReturn(defaultModelReader); when(xmlImporter.importXML(eq(defaultModelReader), any(ValidationMessages.class), eq(ruleCache))).thenReturn(defaultModel); @@ -88,14 +88,14 @@ public class TechnicalDebtModelSynchronizerTest { @Test public void create_default_model_on_first_execution_when_no_plugin() throws Exception { - Characteristic rootCharacteristic = new Characteristic().setKey("PORTABILITY"); - new Characteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(rootCharacteristic); + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + new DefaultCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(rootCharacteristic); defaultModel.addRootCharacteristic(rootCharacteristic); when(technicalDebtModelRepository.getContributingPluginList()).thenReturn(Collections.<String>emptyList()); when(dao.selectEnabledCharacteristics()).thenReturn(Lists.<CharacteristicDto>newArrayList()); - manager.initAndMergePlugins(ValidationMessages.create(), ruleCache); + manager.synchronize(ValidationMessages.create(), ruleCache); verify(dao).selectEnabledCharacteristics(); ArgumentCaptor<CharacteristicDto> characteristicCaptor = ArgumentCaptor.forClass(CharacteristicDto.class); @@ -110,24 +110,24 @@ public class TechnicalDebtModelSynchronizerTest { @Test public void create_model_with_requirements_from_plugin_on_first_execution() throws Exception { // Default model - Characteristic defaultRootCharacteristic = new Characteristic().setKey("PORTABILITY"); - Characteristic characteristic = new Characteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); + DefaultCharacteristic defaultRootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + new DefaultCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); defaultModel.addRootCharacteristic(defaultRootCharacteristic); // No db model when(dao.selectEnabledCharacteristics()).thenReturn(Lists.<CharacteristicDto>newArrayList()); // Java model - TechnicalDebtModel javaModel = new TechnicalDebtModel(); - Characteristic javaRootCharacteristic = new Characteristic().setKey("PORTABILITY"); - Characteristic javaCharacteristic = new Characteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(javaRootCharacteristic); + DefaultTechnicalDebtModel javaModel = new DefaultTechnicalDebtModel(); + DefaultCharacteristic javaRootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + DefaultCharacteristic javaCharacteristic = new DefaultCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(javaRootCharacteristic); javaModel.addRootCharacteristic(javaRootCharacteristic); Rule rule = Rule.create(); rule.setId(10); RuleKey ruleKey = RuleKey.of("checkstyle", "import"); when(ruleCache.getByRuleKey(ruleKey)).thenReturn(rule); - new Requirement().setRuleKey(ruleKey) + new DefaultRequirement().setRuleKey(ruleKey) .setFunction("linear").setFactor(WorkUnit.create(30.0, WorkUnit.MINUTES)).setCharacteristic(javaCharacteristic); Reader javaModelReader = mock(Reader.class); @@ -135,7 +135,7 @@ public class TechnicalDebtModelSynchronizerTest { when(technicalDebtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader); when(technicalDebtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); - manager.initAndMergePlugins(ValidationMessages.create(), ruleCache); + manager.synchronize(ValidationMessages.create(), ruleCache); verify(dao).selectEnabledCharacteristics(); ArgumentCaptor<CharacteristicDto> characteristicCaptor = ArgumentCaptor.forClass(CharacteristicDto.class); @@ -151,8 +151,8 @@ public class TechnicalDebtModelSynchronizerTest { @Test public void add_new_requirements_from_plugin() throws Exception { // Default model - Characteristic defaultRootCharacteristic = new Characteristic().setKey("PORTABILITY"); - new Characteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); + DefaultCharacteristic defaultRootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + new DefaultCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); defaultModel.addRootCharacteristic(defaultRootCharacteristic); // Db model @@ -169,9 +169,9 @@ public class TechnicalDebtModelSynchronizerTest { when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(requirement, dbCharacteristic, dbRootCharacteristic)); // Java model - TechnicalDebtModel javaModel = new TechnicalDebtModel(); - Characteristic javaRootCharacteristic = new Characteristic().setKey("PORTABILITY"); - Characteristic javaCharacteristic = new Characteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(javaRootCharacteristic); + DefaultTechnicalDebtModel javaModel = new DefaultTechnicalDebtModel(); + DefaultCharacteristic javaRootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + DefaultCharacteristic javaCharacteristic = new DefaultCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(javaRootCharacteristic); javaModel.addRootCharacteristic(javaRootCharacteristic); RuleKey ruleKey2 = RuleKey.of("checkstyle", "export"); @@ -180,7 +180,7 @@ public class TechnicalDebtModelSynchronizerTest { when(ruleCache.getByRuleKey(ruleKey2)).thenReturn(rule2); // New requirement - new Requirement().setRuleKey(ruleKey2) + new DefaultRequirement().setRuleKey(ruleKey2) .setFunction("linear").setFactor(WorkUnit.create(1.0, WorkUnit.HOURS)).setCharacteristic(javaCharacteristic); Reader javaModelReader = mock(Reader.class); @@ -188,7 +188,7 @@ public class TechnicalDebtModelSynchronizerTest { when(xmlImporter.importXML(eq(javaModelReader), any(ValidationMessages.class), eq(ruleCache))).thenReturn(javaModel); when(technicalDebtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); - manager.initAndMergePlugins(ValidationMessages.create(), ruleCache); + manager.synchronize(ValidationMessages.create(), ruleCache); verify(dao).selectEnabledCharacteristics(); ArgumentCaptor<CharacteristicDto> characteristicCaptor = ArgumentCaptor.forClass(CharacteristicDto.class); @@ -200,8 +200,8 @@ public class TechnicalDebtModelSynchronizerTest { @Test public void disable_requirements_on_not_existing_rules() throws Exception { // Default model - Characteristic defaultRootCharacteristic = new Characteristic().setKey("PORTABILITY"); - new Characteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); + DefaultCharacteristic defaultRootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + new DefaultCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); defaultModel.addRootCharacteristic(defaultRootCharacteristic); // Db model @@ -215,7 +215,7 @@ public class TechnicalDebtModelSynchronizerTest { when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(dbRootCharacteristic, dbCharacteristic, requirement)); - manager.initAndMergePlugins(ValidationMessages.create(), ruleCache); + manager.synchronize(ValidationMessages.create(), ruleCache); verify(dao).selectEnabledCharacteristics(); verify(dao).disable(eq(3), eq(session)); @@ -226,8 +226,8 @@ public class TechnicalDebtModelSynchronizerTest { public void fail_when_plugin_defines_characteristics_not_defined_in_default_model() throws Exception { try { // Default model - Characteristic defaultRootCharacteristic = new Characteristic().setKey("PORTABILITY"); - new Characteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); + DefaultCharacteristic defaultRootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + new DefaultCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setParent(defaultRootCharacteristic); defaultModel.addRootCharacteristic(defaultRootCharacteristic); // Db model @@ -236,9 +236,9 @@ public class TechnicalDebtModelSynchronizerTest { when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(dbRootCharacteristic, dbCharacteristic)); // Java model - TechnicalDebtModel javaModel = new TechnicalDebtModel(); - Characteristic javaRootCharacteristic = new Characteristic().setKey("PORTABILITY"); - new Characteristic().setKey("NEW_CHARACTERISTIC").setParent(javaRootCharacteristic); + DefaultTechnicalDebtModel javaModel = new DefaultTechnicalDebtModel(); + DefaultCharacteristic javaRootCharacteristic = new DefaultCharacteristic().setKey("PORTABILITY"); + new DefaultCharacteristic().setKey("NEW_CHARACTERISTIC").setParent(javaRootCharacteristic); javaModel.addRootCharacteristic(javaRootCharacteristic); Reader javaModelReader = mock(Reader.class); @@ -246,7 +246,7 @@ public class TechnicalDebtModelSynchronizerTest { when(xmlImporter.importXML(eq(javaModelReader), any(ValidationMessages.class), eq(ruleCache))).thenReturn(javaModel); when(technicalDebtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); - manager.initAndMergePlugins(ValidationMessages.create(), ruleCache); + manager.synchronize(ValidationMessages.create(), ruleCache); fail(); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The characteristic : NEW_CHARACTERISTIC cannot be used as it's not available in default characteristics."); diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java index 2ece2a34247..6b1e85d1a7c 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java @@ -29,9 +29,9 @@ import org.mockito.Mockito; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.internal.DefaultCharacteristic; +import org.sonar.api.technicaldebt.internal.DefaultRequirement; import org.sonar.api.utils.ValidationMessages; import java.io.IOException; @@ -47,13 +47,13 @@ public class TechnicalDebtXMLImporterTest { String xml = getFileContent("import_characteristics.xml"); ValidationMessages messages = ValidationMessages.create(); - TechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); + DefaultTechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); assertThat(sqale.rootCharacteristics()).hasSize(2); assertThat(sqale.rootCharacteristics().get(0).key()).isEqualTo("PORTABILITY"); assertThat(sqale.rootCharacteristics().get(1).key()).isEqualTo("MAINTAINABILITY"); - Characteristic portability = sqale.characteristicByKey("PORTABILITY"); + DefaultCharacteristic portability = sqale.characteristicByKey("PORTABILITY"); assertThat(portability.order()).isEqualTo(1); assertThat(portability.children()).hasSize(2); assertThat(portability.children().get(0).key()).isEqualTo("COMPILER_RELATED_PORTABILITY"); @@ -61,7 +61,7 @@ public class TechnicalDebtXMLImporterTest { assertThat(portability.children().get(1).key()).isEqualTo("HARDWARE_RELATED_PORTABILITY"); assertThat(sqale.characteristicByKey("HARDWARE_RELATED_PORTABILITY").parent().key()).isEqualTo("PORTABILITY"); - Characteristic maintainability = sqale.characteristicByKey("MAINTAINABILITY"); + DefaultCharacteristic maintainability = sqale.characteristicByKey("MAINTAINABILITY"); assertThat(maintainability.order()).isEqualTo(2); assertThat(maintainability.children()).hasSize(1); assertThat(maintainability.children().get(0).key()).isEqualTo("READABILITY"); @@ -75,7 +75,7 @@ public class TechnicalDebtXMLImporterTest { String xml = getFileContent("shouldImportXML_with_linear.xml"); ValidationMessages messages = ValidationMessages.create(); - TechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); + DefaultTechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); checkXmlCorrectlyImported(sqale, messages); } @@ -87,7 +87,7 @@ public class TechnicalDebtXMLImporterTest { String xml = getFileContent("shouldImportXML_with_linear_with_offset.xml"); ValidationMessages messages = ValidationMessages.create(); - TechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); + DefaultTechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); checkXmlCorrectlyImported(sqale, WorkUnit.create(1.0, "h"), messages); } @@ -99,7 +99,7 @@ public class TechnicalDebtXMLImporterTest { String xml = getFileContent("shouldImportXML_with_deprecated_linear_with_threshold.xml"); ValidationMessages messages = ValidationMessages.create(); - TechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); + DefaultTechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); checkXmlCorrectlyImported(sqale, WorkUnit.create(0.0, "h"), messages); assertThat(messages.getWarnings()).hasSize(1); @@ -112,13 +112,13 @@ public class TechnicalDebtXMLImporterTest { String xml = getFileContent("shouldImportXML_with_deprecated_constant_per_file.xml"); ValidationMessages messages = ValidationMessages.create(); - TechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); + DefaultTechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); assertThat(messages.getWarnings()).hasSize(1); // characteristics assertThat(sqale.rootCharacteristics()).hasSize(1); - Characteristic efficiency = sqale.characteristicByKey("EFFICIENCY"); + DefaultCharacteristic efficiency = sqale.characteristicByKey("EFFICIENCY"); assertThat(efficiency.requirements()).isEmpty(); } @@ -128,7 +128,7 @@ public class TechnicalDebtXMLImporterTest { String xml = getFileContent("shouldImportXML_badly-formatted.xml"); ValidationMessages messages = ValidationMessages.create(); - TechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); + DefaultTechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); checkXmlCorrectlyImported(sqale, messages); } @@ -139,14 +139,14 @@ public class TechnicalDebtXMLImporterTest { String xml = getFileContent("shouldLogWarningIfRuleNotFound.xml"); ValidationMessages messages = ValidationMessages.create(); - TechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); + DefaultTechnicalDebtModel sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache); assertThat(messages.getWarnings()).hasSize(1); assertThat(messages.getWarnings().get(0)).isEqualTo("Rule not found: [repository=findbugs, key=Foo]"); // characteristics assertThat(sqale.rootCharacteristics()).hasSize(1); - Characteristic efficiency = sqale.characteristicByKey("EFFICIENCY"); + DefaultCharacteristic efficiency = sqale.characteristicByKey("EFFICIENCY"); assertThat(efficiency.requirements()).isEmpty(); assertThat(messages.getWarnings().get(0)).contains("findbugs"); } @@ -171,26 +171,26 @@ public class TechnicalDebtXMLImporterTest { return new TechnicalDebtRuleCache(finder); } - private void checkXmlCorrectlyImported(TechnicalDebtModel sqale, ValidationMessages messages) { + private void checkXmlCorrectlyImported(DefaultTechnicalDebtModel sqale, ValidationMessages messages) { checkXmlCorrectlyImported(sqale, WorkUnit.create(), messages); } - private void checkXmlCorrectlyImported(TechnicalDebtModel sqale, WorkUnit offset, ValidationMessages messages) { + private void checkXmlCorrectlyImported(DefaultTechnicalDebtModel sqale, WorkUnit offset, ValidationMessages messages) { assertThat(messages.getErrors()).isEmpty(); // characteristics assertThat(sqale.rootCharacteristics()).hasSize(2); - Characteristic efficiency = sqale.characteristicByKey("EFFICIENCY"); + DefaultCharacteristic efficiency = sqale.characteristicByKey("EFFICIENCY"); assertThat(efficiency.name()).isEqualTo("Efficiency"); // sub-characteristics assertThat(efficiency.children()).hasSize(1); - Characteristic memoryEfficiency = sqale.characteristicByKey("MEMORY_EFFICIENCY"); + DefaultCharacteristic memoryEfficiency = sqale.characteristicByKey("MEMORY_EFFICIENCY"); assertThat(memoryEfficiency.name()).isEqualTo("Memory use"); // requirement assertThat(memoryEfficiency.requirements()).hasSize(1); - Requirement requirement = memoryEfficiency.requirements().get(0); + DefaultRequirement requirement = memoryEfficiency.requirements().get(0); assertThat(requirement.ruleKey().repository()).isEqualTo("checkstyle"); assertThat(requirement.ruleKey().rule()).isEqualTo("Regexp"); assertThat(requirement.function()).isEqualTo("linear"); diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java index b6f75bf764d..e9d39138a6e 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java @@ -119,7 +119,7 @@ public class CharacteristicDaoTest extends AbstractDaoTestCase { public void select_requirement() { setupData("shared"); - CharacteristicDto dto = dao.selectRequirement(1); + CharacteristicDto dto = dao.selectByRuleId(1); assertThat(dto).isNotNull(); assertThat(dto.getId()).isEqualTo(3); @@ -131,29 +131,29 @@ public class CharacteristicDaoTest extends AbstractDaoTestCase { public void select_characteristic_by_key() { setupData("shared"); - CharacteristicDto dto = dao.selectCharacteristic("COMPILER_RELATED_PORTABILITY"); + CharacteristicDto dto = dao.selectByKey("COMPILER_RELATED_PORTABILITY"); assertThat(dto).isNotNull(); assertThat(dto.getId()).isEqualTo(2); assertThat(dto.getParentId()).isEqualTo(1); assertThat(dto.getRootId()).isEqualTo(1); - dto = dao.selectCharacteristic("PORTABILITY"); + dto = dao.selectByKey("PORTABILITY"); assertThat(dto).isNotNull(); assertThat(dto.getId()).isEqualTo(1); assertThat(dto.getParentId()).isNull(); assertThat(dto.getRootId()).isNull(); - assertThat(dao.selectCharacteristic("UNKNOWN")).isNull(); + assertThat(dao.selectByKey("UNKNOWN")).isNull(); } @Test public void select_characteristic_by_id() { setupData("shared"); - assertThat(dao.selectCharacteristic(2)).isNotNull(); - assertThat(dao.selectCharacteristic(1)).isNotNull(); + assertThat(dao.selectById(2)).isNotNull(); + assertThat(dao.selectById(1)).isNotNull(); - assertThat(dao.selectCharacteristic(10)).isNull(); + assertThat(dao.selectById(10)).isNull(); } @Test diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java index b6a78b582ba..c47dd1f17f6 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java @@ -22,8 +22,8 @@ package org.sonar.api.measures; import com.google.common.annotations.Beta; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.math.NumberUtils; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; import javax.annotation.CheckForNull; import javax.annotation.Nullable; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java index 83e88e15a94..3b964a214e1 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java @@ -20,8 +20,8 @@ package org.sonar.api.measures; import org.sonar.api.rules.Rule; -import org.sonar.api.technicaldebt.Characteristic; -import org.sonar.api.technicaldebt.Requirement; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; import java.util.ArrayList; import java.util.Collection; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/Characteristic.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/Characteristic.java new file mode 100644 index 00000000000..1ea0eb7960d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/Characteristic.java @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt.batch; + +import javax.annotation.CheckForNull; + +import java.util.Date; +import java.util.List; + +public interface Characteristic { + + Integer id(); + + String key(); + + String name(); + + Integer order(); + + @CheckForNull + Characteristic parent(); + + List<? extends Characteristic> children(); + + List<? extends Requirement> requirements(); + + boolean isRoot(); + + Date createdAt(); + + Date updatedAt(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/Requirement.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/Requirement.java new file mode 100644 index 00000000000..080726b97af --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/Requirement.java @@ -0,0 +1,48 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt.batch; + +import org.sonar.api.rule.RuleKey; +import org.sonar.api.technicaldebt.WorkUnit; + +import java.util.Date; + +public interface Requirement { + + Integer id(); + + RuleKey ruleKey(); + + Characteristic characteristic(); + + Characteristic rootCharacteristic(); + + String function(); + + WorkUnit factor(); + + WorkUnit offset(); + + Date createdAt(); + + Date updatedAt(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/TechnicalDebtModel.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/TechnicalDebtModel.java new file mode 100644 index 00000000000..10a5b832fc8 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/TechnicalDebtModel.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt.batch; + +import org.sonar.api.rule.RuleKey; + +import javax.annotation.CheckForNull; + +import java.util.List; + +public interface TechnicalDebtModel { + + @CheckForNull + Characteristic characteristicById(Integer id); + + @CheckForNull + Requirement requirementsByRule(RuleKey ruleKey); + + @CheckForNull + Requirement requirementsById(Integer id); + + List<? extends Requirement> requirements(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/Characteristic.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/internal/DefaultCharacteristic.java index e75baf264f3..6252ab59746 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/Characteristic.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/internal/DefaultCharacteristic.java @@ -18,11 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.api.technicaldebt; +package org.sonar.api.technicaldebt.internal; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.technicaldebt.batch.Characteristic; import javax.annotation.CheckForNull; import javax.annotation.Nullable; @@ -32,21 +33,21 @@ import java.util.List; import static com.google.common.collect.Lists.newArrayList; -public class Characteristic { +public class DefaultCharacteristic implements Characteristic { private Integer id; private String key; private String name; private Integer order; - private Characteristic parent; - private Characteristic root; - private List<Characteristic> children; - private List<Requirement> requirements; + private DefaultCharacteristic parent; + private DefaultCharacteristic root; + private List<DefaultCharacteristic> children; + private List<DefaultRequirement> requirements; private Date createdAt; private Date updatedAt; - public Characteristic() { + public DefaultCharacteristic() { this.children = newArrayList(); this.requirements = newArrayList(); } @@ -55,7 +56,7 @@ public class Characteristic { return id; } - public Characteristic setId(Integer id) { + public DefaultCharacteristic setId(Integer id) { this.id = id; return this; } @@ -64,7 +65,7 @@ public class Characteristic { return key; } - public Characteristic setKey(String key) { + public DefaultCharacteristic setKey(String key) { this.key = StringUtils.trimToNull(key); return this; } @@ -73,8 +74,9 @@ public class Characteristic { return name; } - public Characteristic setName(String name) { - return setName(name, false); + public DefaultCharacteristic setName(String name) { + this.name = name; + return this; } public Characteristic setName(String s, boolean asKey) { @@ -90,17 +92,17 @@ public class Characteristic { return order; } - public Characteristic setOrder(Integer order) { + public DefaultCharacteristic setOrder(Integer order) { this.order = order; return this; } @CheckForNull - public Characteristic parent() { + public DefaultCharacteristic parent() { return parent; } - public Characteristic setParent(@Nullable Characteristic parent) { + public DefaultCharacteristic setParent(@Nullable DefaultCharacteristic parent) { if (parent != null) { this.parent = parent; parent.addChild(this); @@ -109,39 +111,34 @@ public class Characteristic { } @CheckForNull - public Characteristic getRoot() { + public DefaultCharacteristic getRoot() { return root; } - public Characteristic setRoot(@Nullable Characteristic root) { + public DefaultCharacteristic setRoot(@Nullable DefaultCharacteristic root) { this.root = root; return this; } - public List<Characteristic> children() { + public List<DefaultCharacteristic> children() { return children; } - private Characteristic addChild(Characteristic child){ + private DefaultCharacteristic addChild(DefaultCharacteristic child) { this.children.add(child); return this; } - public List<Requirement> requirements() { + public List<DefaultRequirement> requirements() { return requirements; } - protected Characteristic addRequirement(Requirement requirement){ + public DefaultCharacteristic addRequirement(DefaultRequirement requirement) { this.requirements.add(requirement); return this; } - public Characteristic removeRequirement(Requirement requirement){ - this.requirements.remove(requirement); - return this; - } - - public boolean isRoot(){ + public boolean isRoot() { return parent == null; } @@ -149,7 +146,7 @@ public class Characteristic { return createdAt; } - public Characteristic setCreatedAt(Date createdAt) { + public DefaultCharacteristic setCreatedAt(Date createdAt) { this.createdAt = createdAt; return this; } @@ -158,7 +155,7 @@ public class Characteristic { return updatedAt; } - public Characteristic setUpdatedAt(Date updatedAt) { + public DefaultCharacteristic setUpdatedAt(Date updatedAt) { this.updatedAt = updatedAt; return this; } @@ -176,7 +173,7 @@ public class Characteristic { if (o == null || getClass() != o.getClass()) { return false; } - Characteristic that = (Characteristic) o; + DefaultCharacteristic that = (DefaultCharacteristic) o; return key.equals(that.key); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/Requirement.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/internal/DefaultRequirement.java index 47d9019d51d..6ae1551b4b8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/Requirement.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/internal/DefaultRequirement.java @@ -18,28 +18,26 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.api.technicaldebt; +package org.sonar.api.technicaldebt.internal; -import com.google.common.collect.ImmutableList; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.sonar.api.rule.RuleKey; +import org.sonar.api.technicaldebt.WorkUnit; +import org.sonar.api.technicaldebt.batch.Requirement; import java.util.Date; -import java.util.List; -public class Requirement { +public class DefaultRequirement implements Requirement { public static final String FUNCTION_LINEAR = "linear"; public static final String FUNCTION_LINEAR_WITH_OFFSET = "linear_offset"; public static final String CONSTANT_ISSUE = "constant_issue"; - public static final List<String> FUNCTIONS = ImmutableList.of(FUNCTION_LINEAR, FUNCTION_LINEAR_WITH_OFFSET, CONSTANT_ISSUE); - private Integer id; private RuleKey ruleKey; - private Characteristic characteristic; - private Characteristic rootCharacteristic; + private DefaultCharacteristic characteristic; + private DefaultCharacteristic rootCharacteristic; private String function; private WorkUnit factor; @@ -48,7 +46,7 @@ public class Requirement { private Date createdAt; private Date updatedAt; - public Requirement() { + public DefaultRequirement() { this.factor = WorkUnit.create(0d, WorkUnit.DEFAULT_UNIT); this.offset = WorkUnit.create(0d, WorkUnit.DEFAULT_UNIT); } @@ -57,7 +55,7 @@ public class Requirement { return id; } - public Requirement setId(Integer id) { + public DefaultRequirement setId(Integer id) { this.id = id; return this; } @@ -66,26 +64,26 @@ public class Requirement { return ruleKey; } - public Requirement setRuleKey(RuleKey ruleKey) { + public DefaultRequirement setRuleKey(RuleKey ruleKey) { this.ruleKey = ruleKey; return this; } - public Characteristic characteristic() { + public DefaultCharacteristic characteristic() { return characteristic; } - public Requirement setCharacteristic(Characteristic characteristic) { + public DefaultRequirement setCharacteristic(DefaultCharacteristic characteristic) { this.characteristic = characteristic; this.characteristic.addRequirement(this); return this; } - public Characteristic getRootCharacteristic() { + public DefaultCharacteristic rootCharacteristic() { return rootCharacteristic; } - public Requirement setRootCharacteristic(Characteristic rootCharacteristic) { + public DefaultRequirement setRootCharacteristic(DefaultCharacteristic rootCharacteristic) { this.rootCharacteristic = rootCharacteristic; return this; } @@ -94,10 +92,7 @@ public class Requirement { return function; } - public Requirement setFunction(String function) { - if (!FUNCTIONS.contains(function)) { - throw new IllegalArgumentException("Function '"+ function +"' is unknown."); - } + public DefaultRequirement setFunction(String function) { this.function = function; return this; } @@ -106,7 +101,7 @@ public class Requirement { return factor; } - public Requirement setFactor(WorkUnit factor) { + public DefaultRequirement setFactor(WorkUnit factor) { this.factor = factor; return this; } @@ -115,7 +110,7 @@ public class Requirement { return offset; } - public Requirement setOffset(WorkUnit offset) { + public DefaultRequirement setOffset(WorkUnit offset) { this.offset = offset; return this; } @@ -124,7 +119,7 @@ public class Requirement { return createdAt; } - public Requirement setCreatedAt(Date createdAt) { + public DefaultRequirement setCreatedAt(Date createdAt) { this.createdAt = createdAt; return this; } @@ -133,7 +128,7 @@ public class Requirement { return updatedAt; } - public Requirement setUpdatedAt(Date updatedAt) { + public DefaultRequirement setUpdatedAt(Date updatedAt) { this.updatedAt = updatedAt; return this; } @@ -153,7 +148,7 @@ public class Requirement { return false; } - Requirement that = (Requirement) o; + DefaultRequirement that = (DefaultRequirement) o; if (!characteristic.equals(that.characteristic)) { return false; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/server/Characteristic.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/server/Characteristic.java new file mode 100644 index 00000000000..05cbe32ceb6 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/server/Characteristic.java @@ -0,0 +1,177 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt.server; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.technicaldebt.WorkUnit; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class Characteristic { + + private Integer id; + private String key; + private String name; + private Integer order; + private Integer parentId; + private Integer rootId; + private RuleKey ruleKey; + private String function; + private WorkUnit factor; + private WorkUnit offset; + + public Integer id() { + return id; + } + + public Characteristic setId(Integer id) { + this.id = id; + return this; + } + + public String key() { + return key; + } + + public Characteristic setKey(String key) { + this.key = key; + return this; + } + + public String name() { + return name; + } + + public Characteristic setName(String name) { + this.name = name; + return this; + } + + public Integer order() { + return order; + } + + public Characteristic setOrder(Integer order) { + this.order = order; + return this; + } + + @CheckForNull + public Integer parentId() { + return parentId; + } + + public Characteristic setParentId(@Nullable Integer parentId) { + this.parentId = parentId; + return this; + } + + @CheckForNull + public Integer rootId() { + return rootId; + } + + public Characteristic setRootId(@Nullable Integer rootId) { + this.rootId = rootId; + return this; + } + + public RuleKey ruleKey() { + return ruleKey; + } + + public Characteristic setRuleKey(RuleKey ruleKey) { + this.ruleKey = ruleKey; + return this; + } + + public String function() { + return function; + } + + public Characteristic setFunction(String function) { + this.function = function; + return this; + } + + public WorkUnit factor() { + return factor; + } + + public Characteristic setFactor(WorkUnit factor) { + this.factor = factor; + return this; + } + + public WorkUnit offset() { + return offset; + } + + public Characteristic setOffset(WorkUnit offset) { + this.offset = offset; + return this; + } + + public boolean isRoot() { + return parentId == null; + } + + public boolean isRequirement() { + return ruleKey == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Characteristic that = (Characteristic) o; + + if (key != null ? !key.equals(that.key) : that.key != null) { + return false; + } + if (ruleKey != null ? !ruleKey.equals(that.ruleKey) : that.ruleKey != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = key != null ? key.hashCode() : 0; + result = 31 * result + (ruleKey != null ? ruleKey.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/server/TechnicalDebtManager.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/server/TechnicalDebtManager.java new file mode 100644 index 00000000000..acd3e33de4f --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/server/TechnicalDebtManager.java @@ -0,0 +1,35 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt.server; + +import org.sonar.api.ServerComponent; +import org.sonar.api.rules.Rule; + +import java.util.List; + +public interface TechnicalDebtManager extends ServerComponent { + + List<Characteristic> findRootCharacteristics(); + + Characteristic findRequirementByRule(Rule rule); + + Characteristic findCharacteristicById(Integer id); +} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index d5cc3c8afd4..b6e42e65060 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -312,7 +312,7 @@ public final class Platform { servicesContainer.addSingleton(TechnicalDebtXMLImporter.class); servicesContainer.addSingleton(TechnicalDebtConverter.class); servicesContainer.addSingleton(TechnicalDebtFormatter.class); - servicesContainer.addSingleton(TechnicalDebtFinder.class); + servicesContainer.addSingleton(DefaultTechnicalDebtManager.class); // text servicesContainer.addSingleton(MacroInterpreter.class); diff --git a/sonar-server/src/main/java/org/sonar/server/startup/RegisterTechnicalDebtModel.java b/sonar-server/src/main/java/org/sonar/server/startup/RegisterTechnicalDebtModel.java index 293659b5caa..172b58cb50d 100644 --- a/sonar-server/src/main/java/org/sonar/server/startup/RegisterTechnicalDebtModel.java +++ b/sonar-server/src/main/java/org/sonar/server/startup/RegisterTechnicalDebtModel.java @@ -45,7 +45,7 @@ public final class RegisterTechnicalDebtModel { public void start() { TimeProfiler profiler = new TimeProfiler(LOGGER).start("Register Technical Debt Model"); TechnicalDebtRuleCache technicalDebtRuleCache = new TechnicalDebtRuleCache(ruleFinder); - manager.initAndMergePlugins(ValidationMessages.create(), technicalDebtRuleCache); + manager.synchronize(ValidationMessages.create(), technicalDebtRuleCache); profiler.stop(); } diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtService.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtService.java index 8d47f177fbd..6d8774403c6 100644 --- a/sonar-server/src/main/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtService.java +++ b/sonar-server/src/main/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtService.java @@ -23,35 +23,40 @@ package org.sonar.server.technicaldebt; import org.sonar.api.ServerComponent; import org.sonar.api.issue.internal.WorkDayDuration; import org.sonar.api.rules.Rule; -import org.sonar.api.technicaldebt.Requirement; -import org.sonar.core.technicaldebt.TechnicalDebtFinder; -import org.sonar.core.technicaldebt.TechnicalDebtModel; +import org.sonar.api.technicaldebt.server.Characteristic; +import org.sonar.core.technicaldebt.DefaultTechnicalDebtManager; import org.sonar.server.user.UserSession; +import java.util.List; + public class InternalRubyTechnicalDebtService implements ServerComponent { private final TechnicalDebtFormatter technicalDebtFormatter; - private final TechnicalDebtFinder finder; + private final DefaultTechnicalDebtManager finder; - public InternalRubyTechnicalDebtService(TechnicalDebtFormatter technicalDebtFormatter, TechnicalDebtFinder finder) { + public InternalRubyTechnicalDebtService(TechnicalDebtFormatter technicalDebtFormatter, DefaultTechnicalDebtManager finder) { this.technicalDebtFormatter = technicalDebtFormatter; this.finder = finder; } - public String format(WorkDayDuration technicalDebt){ + public String format(WorkDayDuration technicalDebt) { return technicalDebtFormatter.format(UserSession.get().locale(), technicalDebt); } - public WorkDayDuration toTechnicalDebt(String technicalDebtInLong){ + public WorkDayDuration toTechnicalDebt(String technicalDebtInLong) { return WorkDayDuration.fromLong(Long.parseLong(technicalDebtInLong)); } - public TechnicalDebtModel findRootCharacteristics(){ + public List<Characteristic> findRootCharacteristics() { return finder.findRootCharacteristics(); } - public Requirement findRequirement(Rule rule){ - return finder.findRequirement(rule); + public Characteristic findRequirement(Rule rule) { + return finder.findRequirementByRule(rule); + } + + public Characteristic findCharacteristic(Integer id) { + return finder.findCharacteristicById(id); } } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb index ca47f3db450..e1bfa5549a9 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb @@ -208,7 +208,9 @@ class IssueController < ApplicationController @issue = @issue_results.first() rule = @issue_results.rule(@issue) - @requirement = Internal.technical_debt.findRequirement(rule) + requirement = Internal.technical_debt.findRequirement(rule) + @characteristic = Internal.technical_debt.findCharacteristic(requirement.parentId) + @root_characteristic = Internal.technical_debt.findCharacteristic(requirement.rootId) render :partial => 'issue/technicaldebt' end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_technicaldebt.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_technicaldebt.html.erb index 1d8854b5b6a..c29835130f3 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_technicaldebt.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_technicaldebt.html.erb @@ -1,8 +1,4 @@ <div> - <% - characteristic = @requirement.characteristic - root_characteristic = characteristic.parent - %> - <%= root_characteristic.name %> > <%= characteristic.name %> + <%= @root_characteristic.name %> > <%= @characteristic.name %> </div> diff --git a/sonar-server/src/test/java/org/sonar/server/startup/RegisterTechnicalDebtModelTest.java b/sonar-server/src/test/java/org/sonar/server/startup/RegisterTechnicalDebtModelTest.java index ca8201ba9f6..1e3fcf55f91 100644 --- a/sonar-server/src/test/java/org/sonar/server/startup/RegisterTechnicalDebtModelTest.java +++ b/sonar-server/src/test/java/org/sonar/server/startup/RegisterTechnicalDebtModelTest.java @@ -38,6 +38,6 @@ public class RegisterTechnicalDebtModelTest { sqaleDefinition.start(); - verify(manger, times(1)).initAndMergePlugins(any(ValidationMessages.class), any(TechnicalDebtRuleCache.class)); + verify(manger, times(1)).synchronize(any(ValidationMessages.class), any(TechnicalDebtRuleCache.class)); } } diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java index feb9d03a9d0..b41e21919c7 100644 --- a/sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java @@ -26,12 +26,13 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.issue.internal.WorkDayDuration; import org.sonar.api.rules.Rule; -import org.sonar.api.technicaldebt.Requirement; -import org.sonar.core.technicaldebt.TechnicalDebtFinder; -import org.sonar.core.technicaldebt.TechnicalDebtModel; +import org.sonar.api.technicaldebt.server.Characteristic; +import org.sonar.core.technicaldebt.DefaultTechnicalDebtManager; +import java.util.List; import java.util.Locale; +import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; @@ -45,7 +46,7 @@ public class InternalRubyTechnicalDebtServiceTest { TechnicalDebtFormatter technicalDebtFormatter; @Mock - TechnicalDebtFinder finder; + DefaultTechnicalDebtManager finder; private InternalRubyTechnicalDebtService service; @@ -68,17 +69,24 @@ public class InternalRubyTechnicalDebtServiceTest { @Test public void find_root_characteristics() { - TechnicalDebtModel model = new TechnicalDebtModel(); - when(finder.findRootCharacteristics()).thenReturn(model); - assertThat(service.findRootCharacteristics()).isEqualTo(model); + List<Characteristic> rootCharacteristics = newArrayList(); + when(finder.findRootCharacteristics()).thenReturn(rootCharacteristics); + assertThat(service.findRootCharacteristics()).isEqualTo(rootCharacteristics); } @Test public void find_requirement() { Rule rule = Rule.create("repo", "key"); - Requirement requirement = new Requirement(); - when(finder.findRequirement(rule)).thenReturn(requirement); + Characteristic requirement = new Characteristic(); + when(finder.findRequirementByRule(rule)).thenReturn(requirement); assertThat(service.findRequirement(rule)).isEqualTo(requirement); } + @Test + public void find_characteristic() { + Characteristic characteristic = new Characteristic(); + when(finder.findCharacteristicById(1)).thenReturn(characteristic); + assertThat(service.findCharacteristic(1)).isEqualTo(characteristic); + } + } |