]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4714 Move classes to sonar-server
authorJulien Lancelot <julien.lancelot@gmail.com>
Wed, 25 Sep 2013 08:19:00 +0000 (10:19 +0200)
committerJulien Lancelot <julien.lancelot@gmail.com>
Wed, 25 Sep 2013 08:19:00 +0000 (10:19 +0200)
60 files changed:
sonar-core/src/main/java/com/sonar/sqale/technical-debt-model.xml [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/RuleCache.java [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtManager.java [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModel.java [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelDefinition.java [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelFinder.java [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/XMLConstants.java [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/XMLImporter.java [deleted file]
sonar-core/src/main/java/org/sonar/core/technicaldebt/package-info.java [deleted file]
sonar-core/src/test/java/org/sonar/core/technicaldebt/RuleCacheTest.java [deleted file]
sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtManagerTest.java [deleted file]
sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelDefinitionTest.java [deleted file]
sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest.java [deleted file]
sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelTest.java [deleted file]
sonar-core/src/test/java/org/sonar/core/technicaldebt/XMLImporterTest.java [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/fake-default-model.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/fake-java-model.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_merge-result.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_merge.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_restore-result.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_restore.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/reset_model.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule-result.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest/csharp-model.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest/java-model.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldImportXML.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldImportXML_badly-formatted.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldLogWarningIfRuleNotFound.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldRejectXML_with_invalid_value.xml [deleted file]
sonar-server/src/main/java/com/sonar/sqale/technical-debt-model.xml [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/RuleCache.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtManager.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModel.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModelDefinition.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModelFinder.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/XMLConstants.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/XMLImporter.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/technicaldebt/package-info.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/technicaldebt/RuleCacheTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtManagerTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelDefinitionTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/technicaldebt/XMLImporterTest.java [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/fake-default-model.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/fake-java-model.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_merge-result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_merge.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_restore-result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_restore.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/reset_model.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule-result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest/csharp-model.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest/java-model.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldImportXML.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldImportXML_badly-formatted.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldLogWarningIfRuleNotFound.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldRejectXML_with_invalid_value.xml [new file with mode: 0644]

diff --git a/sonar-core/src/main/java/com/sonar/sqale/technical-debt-model.xml b/sonar-core/src/main/java/com/sonar/sqale/technical-debt-model.xml
deleted file mode 100644 (file)
index 2a35e4f..0000000
+++ /dev/null
@@ -1,159 +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.
-
--->
-<sqale>
-  <chc>
-    <key>PORTABILITY</key>
-    <name>Portability</name>
-    <chc>
-      <key>COMPILER_RELATED_PORTABILITY</key>
-      <name>Compiler</name>
-    </chc>
-    <chc>
-      <key>HARDWARE_RELATED_PORTABILITY</key>
-      <name>Hardware</name>
-    </chc>
-    <chc>
-      <key>LANGUAGE_RELATED_PORTABILITY</key>
-      <name>Language</name>
-    </chc>
-    <chc>
-      <key>OS_RELATED_PORTABILITY</key>
-      <name>OS</name>
-    </chc>
-    <chc>
-      <key>SOFTWARE_RELATED_PORTABILITY</key>
-      <name>Software</name>
-    </chc>
-    <chc>
-      <key>TIME_ZONE_RELATED_PORTABILITY</key>
-      <name>Time zone</name>
-    </chc>
-  </chc>
-  <chc>
-    <key>MAINTAINABILITY</key>
-    <name>Maintainability</name>
-    <chc>
-      <key>READABILITY</key>
-      <name>Readability</name>
-    </chc>
-    <chc>
-      <key>UNDERSTANDABILITY</key>
-      <name>Understandability</name>
-    </chc>
-  </chc>
-  <chc>
-    <key>SECURITY</key>
-    <name>Security</name>
-    <chc>
-      <key>API_ABUSE</key>
-      <name>API abuse</name>
-    </chc>
-    <chc>
-      <key>ERRORS</key>
-      <name>Errors</name>
-    </chc>
-    <chc>
-      <key>INPUT_VALIDATION_AND_REPRESENTATION</key>
-      <name>Input validation and representation</name>
-    </chc>
-    <chc>
-      <key>SECURITY_FEATURES</key>
-      <name>Security features</name>
-    </chc>
-  </chc>
-  <chc>
-    <key>EFFICIENCY</key>
-    <name>Efficiency</name>
-    <chc>
-      <key>MEMORY_EFFICIENCY</key>
-      <name>Memory use</name>
-    </chc>
-    <chc>
-      <key>CPU_EFFICIENCY</key>
-      <name>Processor use</name>
-    </chc>
-  </chc>
-  <chc>
-    <key>CHANGEABILITY</key>
-    <name>Changeability</name>
-    <chc>
-      <key>ARCHITECTURE_CHANGEABILITY</key>
-      <name>Architecture</name>
-    </chc>
-    <chc>
-      <key>DATA_CHANGEABILITY</key>
-      <name>Data</name>
-    </chc>
-    <chc>
-      <key>LOGIC_CHANGEABILITY</key>
-      <name>Logic</name>
-    </chc>
-  </chc>
-  <chc>
-    <key>RELIABILITY</key>
-    <name>Reliability</name>
-    <chc>
-      <key>ARCHITECTURE_RELIABILITY</key>
-      <name>Architecture</name>
-    </chc>
-    <chc>
-      <key>DATA_RELIABILITY</key>
-      <name>Data</name>
-    </chc>
-    <chc>
-      <key>EXCEPTION_HANDLING</key>
-      <name>Exception handling</name>
-    </chc>
-    <chc>
-      <key>FAULT_TOLERANCE</key>
-      <name>Fault tolerance</name>
-    </chc>
-    <chc>
-      <key>INSTRUCTION_RELIABILITY</key>
-      <name>Instruction</name>
-    </chc>
-    <chc>
-      <key>LOGIC_RELIABILITY</key>
-      <name>Logic</name>
-    </chc>
-    <chc>
-      <key>SYNCHRONIZATION_RELIABILITY</key>
-      <name>Synchronization</name>
-    </chc>
-    <chc>
-      <key>UNIT_TESTS</key>
-      <name>Unit tests</name>
-    </chc>
-  </chc>
-  <chc>
-    <key>TESTABILITY</key>
-    <name>Testability</name>
-    <chc>
-      <key>INTEGRATION_TESTABILITY</key>
-      <name>Integration level</name>
-    </chc>
-    <chc>
-      <key>UNIT_TESTABILITY</key>
-      <name>Unit level</name>
-    </chc>
-  </chc>
-</sqale>
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/RuleCache.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/RuleCache.java
deleted file mode 100644 (file)
index bc47046..0000000
+++ /dev/null
@@ -1,72 +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 com.google.common.collect.Maps;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.RuleQuery;
-
-import javax.annotation.CheckForNull;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-public class RuleCache {
-
-  private final RuleFinder ruleFinder;
-
-  private Map<String, Map<String, Rule>> cachedRules;
-
-  public RuleCache(RuleFinder ruleFinder) {
-    this.ruleFinder = ruleFinder;
-  }
-
-  @CheckForNull
-  public Rule getRule(String repository, String ruleKey) {
-    if(cachedRules == null) {
-      loadRules();
-    }
-    return lookUpRuleInCache(repository, ruleKey);
-  }
-
-  private void loadRules() {
-    cachedRules = Maps.newHashMap();
-    Collection<Rule> rules = ruleFinder.findAll(RuleQuery.create());
-    for (Rule rule : rules) {
-      if(!cachedRules.containsKey(rule.getRepositoryKey())) {
-        cachedRules.put(rule.getRepositoryKey(), new HashMap<String, Rule>());
-      }
-      Map<String, Rule> cachedRepository = cachedRules.get(rule.getRepositoryKey());
-      if(!cachedRepository.containsKey(rule.getKey())) {
-        cachedRepository.put(rule.getKey(), rule);
-      }
-    }
-  }
-
-  private Rule lookUpRuleInCache(String repository, String ruleKey) {
-    Map<String, Rule> cachedRepository = cachedRules.get(repository);
-    if(cachedRepository != null) {
-      return cachedRepository.get(ruleKey);
-    }
-    return null;
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtManager.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtManager.java
deleted file mode 100644 (file)
index 6f93eb0..0000000
+++ /dev/null
@@ -1,160 +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.commons.io.IOUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.ServerExtension;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.qualitymodel.Characteristic;
-import org.sonar.api.qualitymodel.Model;
-import org.sonar.api.qualitymodel.ModelFinder;
-import org.sonar.api.utils.ValidationMessages;
-import org.sonar.jpa.session.DatabaseSessionFactory;
-
-import java.io.Reader;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * TODO test merge properties + property.value + text_value
- */
-
-public class TechnicalDebtManager implements ServerExtension {
-
-  private static final Logger LOG = LoggerFactory.getLogger(TechnicalDebtManager.class);
-
-  private DatabaseSessionFactory sessionFactory;
-  private ModelFinder modelFinder;
-  private TechnicalDebtModelFinder languageModelFinder;
-  private XMLImporter importer;
-
-  public TechnicalDebtManager(DatabaseSessionFactory sessionFactory, ModelFinder modelFinder,
-                              TechnicalDebtModelFinder languageModelFinder, XMLImporter importer) {
-    this.sessionFactory = sessionFactory;
-    this.modelFinder = modelFinder;
-    this.languageModelFinder = languageModelFinder;
-    this.importer = importer;
-  }
-
-  public void restore(Model model, ValidationMessages messages, RuleCache rulesCache) {
-    Model persisted = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    if (persisted != null) {
-      disable(persisted);
-    }
-    merge(model, messages, rulesCache);
-  }
-
-  public Model resetModel(ValidationMessages messages, RuleCache ruleCache) {
-    Model persisted = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    if (persisted != null) {
-      disable(persisted);
-    }
-
-    Model model = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    importDefaultSqaleModel(model, messages, ruleCache);
-    populateModelWithInitialValues(model, messages, ruleCache);
-
-    DatabaseSession session = sessionFactory.getSession();
-    session.save(model);
-    session.commit();
-
-    return model;
-  }
-
-  public Model createInitialModel(ValidationMessages messages, RuleCache ruleCache) {
-    Model initialModel = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    importDefaultSqaleModel(initialModel, messages, ruleCache);
-    populateModelWithInitialValues(initialModel, messages, ruleCache);
-    return initialModel;
-  }
-
-  public void merge(List<String> pluginKeys, ValidationMessages messages, RuleCache ruleCache) {
-    for (String pluginKey : pluginKeys) {
-      ValidationMessages currentMessages = ValidationMessages.create();
-      Model model = null;
-      Reader xmlFileReader = null;
-      try {
-        xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey);
-        model = importer.importXML(xmlFileReader, currentMessages, ruleCache);
-      } finally {
-        IOUtils.closeQuietly(xmlFileReader);
-      }
-      if (!currentMessages.hasErrors()) {
-        merge(model, messages, ruleCache);
-      } else {
-        for (String error : currentMessages.getErrors()) {
-          messages.addErrorText(error);
-        }
-      }
-    }
-  }
-
-  public void merge(Model with, ValidationMessages messages, RuleCache ruleCache) {
-    DatabaseSession session = sessionFactory.getSession();
-    Model sqale = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    if (sqale == null) {
-      sqale = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-      session.saveWithoutFlush(sqale);
-    }
-    new TechnicalDebtModel(sqale).mergeWith(with, messages, ruleCache);
-    session.saveWithoutFlush(sqale);
-    session.commit();
-  }
-
-  private void populateModelWithInitialValues(Model initialModel, ValidationMessages messages, RuleCache ruleCache) {
-    for (String pluginKey : getContributingPluginListWithoutSqale()) {
-      mergePlugin(initialModel, pluginKey, messages, ruleCache);
-    }
-  }
-
-  private void mergePlugin(Model initialModel, String pluginKey, ValidationMessages messages, RuleCache ruleCache) {
-    Model model = null;
-    Reader xmlFileReader = null;
-    try {
-      xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey);
-
-      model = importer.importXML(xmlFileReader, messages, ruleCache);
-    } finally {
-      IOUtils.closeQuietly(xmlFileReader);
-    }
-    messages.log(LOG);
-    if (!messages.hasErrors()) {
-      new TechnicalDebtModel(initialModel).mergeWith(model, messages, ruleCache);
-      messages.log(LOG);
-    }
-  }
-
-  private void disable(Model persisted) {
-    for (Characteristic root : persisted.getRootCharacteristics()) {
-      persisted.removeCharacteristic(root);
-    }
-    sessionFactory.getSession().commit();
-  }
-
-  private Collection<String> getContributingPluginListWithoutSqale(){
-    return languageModelFinder.getContributingPluginList();
-  }
-
-  private void importDefaultSqaleModel(Model initialModel, ValidationMessages messages, RuleCache ruleCache) {
-    mergePlugin(initialModel, TechnicalDebtModelFinder.DEFAULT_MODEL, messages, ruleCache);
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModel.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModel.java
deleted file mode 100644 (file)
index cb5d8f9..0000000
+++ /dev/null
@@ -1,90 +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.sonar.api.qualitymodel.Characteristic;
-import org.sonar.api.qualitymodel.CharacteristicProperty;
-import org.sonar.api.qualitymodel.Model;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.utils.ValidationMessages;
-
-public class TechnicalDebtModel {
-
-  private Model model;
-
-  public TechnicalDebtModel(Model model) {
-    this.model = model;
-  }
-
-  public void mergeWith(Model with, ValidationMessages messages, RuleCache ruleCache) {
-    for (Characteristic characteristic : with.getCharacteristics()) {
-      if (isRequirement(characteristic)) {
-        mergeRequirement(model, characteristic, messages, ruleCache);
-      } else {
-        mergeCharacteristic(model, characteristic, messages);
-      }
-    }
-  }
-
-  private Characteristic mergeCharacteristic(Model target, Characteristic characteristic, ValidationMessages messages) {
-    Characteristic targetCharacteristic = target.getCharacteristicByKey(characteristic.getKey());
-    if (targetCharacteristic == null) {
-      targetCharacteristic = target.addCharacteristic(clone(characteristic));
-      if (!characteristic.getParents().isEmpty()) {
-        Characteristic parentTargetCharacteristic = mergeCharacteristic(target, characteristic.getParents().get(0), messages);
-        parentTargetCharacteristic.addChild(targetCharacteristic);
-      }
-    }
-    return targetCharacteristic;
-  }
-
-  private void mergeRequirement(Model target, Characteristic requirement, ValidationMessages messages,
-                                RuleCache ruleCache) {
-    Characteristic targetRequirement = target.getCharacteristicByRule(requirement.getRule());
-    if (targetRequirement == null && !requirement.getParents().isEmpty()) {
-      Rule rule = ruleCache.getRule(requirement.getRule().getRepositoryKey(), requirement.getRule().getKey());
-      if (rule == null) {
-        messages.addWarningText("The rule " + requirement.getRule() + " does not exist.");
-
-      } else {
-        Characteristic parent = mergeCharacteristic(target, requirement.getParents().get(0), messages);
-        requirement = target.addCharacteristic(clone(requirement));
-        requirement.setRule(rule);
-        parent.addChild(requirement);
-      }
-    }
-  }
-
-  private boolean isRequirement(Characteristic characteristic) {
-    return characteristic.hasRule();
-  }
-
-  private Characteristic clone(Characteristic c) {
-    Characteristic clone = Characteristic.create();
-    clone.setRule(c.getRule());
-    clone.setDescription(c.getDescription());
-    clone.setKey(c.getKey());
-    clone.setName(c.getName(), false);
-    for (CharacteristicProperty property : c.getProperties()) {
-      clone.setProperty(property.getKey(), property.getTextValue()).setValue(property.getValue());
-    }
-    return clone;
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelDefinition.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelDefinition.java
deleted file mode 100644 (file)
index fbb167f..0000000
+++ /dev/null
@@ -1,46 +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.sonar.api.qualitymodel.Model;
-import org.sonar.api.qualitymodel.ModelDefinition;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.utils.ValidationMessages;
-
-public final class TechnicalDebtModelDefinition extends ModelDefinition {
-
-  public static final String TECHNICAL_DEBT_MODEL = "TECHNICAL_DEBT";
-
-  private final TechnicalDebtManager technicalDebtManager;
-  private final RuleFinder ruleFinder;
-
-  public TechnicalDebtModelDefinition(TechnicalDebtManager technicalDebtManager, RuleFinder ruleFinder) {
-    super(TECHNICAL_DEBT_MODEL);
-    this.technicalDebtManager = technicalDebtManager;
-    this.ruleFinder = ruleFinder;
-  }
-
-  @Override
-  public Model createModel() {
-    RuleCache ruleCache = new RuleCache(ruleFinder);
-    return technicalDebtManager.createInitialModel(ValidationMessages.create(), ruleCache);
-  }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelFinder.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtModelFinder.java
deleted file mode 100644 (file)
index 926dadd..0000000
+++ /dev/null
@@ -1,136 +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 com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-import org.picocontainer.Startable;
-import org.sonar.api.ServerExtension;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
-
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import static com.google.common.collect.Lists.newArrayList;
-
-/**
- * <p>This class is used to find which technical debt model XML files exist in the Sonar instance.</p>
- * <p>
- * Those XML files are provided by language plugins that embed their own contribution to the definition of the Technical debt model.
- * They must be located in the classpath of those language plugins, more specifically in the "com.sonar.sqale" package, and
- * they must be named "<pluginKey>-model.xml".
- * </p>
- */
-public class TechnicalDebtModelFinder implements ServerExtension, Startable {
-
-  public static final String DEFAULT_MODEL = "technical-debt";
-
-  private static final String XML_FILE_SUFFIX = "-model.xml";
-  private static final String XML_FILE_PREFIX = "com/sonar/sqale/";
-
-  private String xmlFilePrefix;
-
-  private PluginRepository pluginRepository;
-  private Map<String, ClassLoader> contributingPluginKeyToClassLoader;
-
-  /**
-   *
-   * @param pluginRepository
-   */
-  public TechnicalDebtModelFinder(PluginRepository pluginRepository) {
-    this.pluginRepository = pluginRepository;
-    this.xmlFilePrefix = XML_FILE_PREFIX;
-  }
-
-  @VisibleForTesting
-  TechnicalDebtModelFinder(PluginRepository pluginRepository, String xmlFilePrefix) {
-    this.pluginRepository = pluginRepository;
-    this.xmlFilePrefix = xmlFilePrefix;
-  }
-
-  @VisibleForTesting
-  TechnicalDebtModelFinder(Map<String, ClassLoader> contributingPluginKeyToClassLoader, String xmlFilePrefix) {
-    this.contributingPluginKeyToClassLoader = contributingPluginKeyToClassLoader;
-    this.xmlFilePrefix = xmlFilePrefix;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public void start() {
-    findAvailableXMLFiles();
-  }
-
-  protected void findAvailableXMLFiles() {
-    if (contributingPluginKeyToClassLoader == null) {
-      contributingPluginKeyToClassLoader = Maps.newTreeMap();
-      for (PluginMetadata metadata : pluginRepository.getMetadata()) {
-        String pluginKey = metadata.getKey();
-        ClassLoader classLoader = pluginRepository.getPlugin(pluginKey).getClass().getClassLoader();
-        if (classLoader.getResource(getXMLFilePathForPlugin(pluginKey)) != null) {
-          contributingPluginKeyToClassLoader.put(pluginKey, classLoader);
-        }
-      }
-    }
-    contributingPluginKeyToClassLoader = Collections.unmodifiableMap(contributingPluginKeyToClassLoader);
-  }
-
-  protected String getXMLFilePathForPlugin(String pluginKey) {
-    return xmlFilePrefix + pluginKey + XML_FILE_SUFFIX;
-  }
-
-  /**
-   * Returns the list of plugins that can contribute to the SQALE model (without the default model provided by this plugin).
-   *
-   * @return the list of plugin keys
-   */
-  public Collection<String> getContributingPluginList() {
-    Collection<String> contributingPlugins = newArrayList(contributingPluginKeyToClassLoader.keySet());
-    contributingPlugins.remove(DEFAULT_MODEL);
-    return contributingPlugins;
-  }
-
-  /**
-   * Creates a new {@link java.io.Reader} for the XML file that contains the model contributed by the given plugin.
-   * 
-   * @param pluginKey the key of the plugin that contributes the XML file
-   * @return the reader, that must be closed once its use is finished.
-   */
-  public Reader createReaderForXMLFile(String pluginKey) {
-    ClassLoader classLoader = contributingPluginKeyToClassLoader.get(pluginKey);
-    String xmlFilePath = getXMLFilePathForPlugin(pluginKey);
-    return new InputStreamReader(classLoader.getResourceAsStream(xmlFilePath));
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public void stop() {
-    // Nothing to do
-  }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/XMLConstants.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/XMLConstants.java
deleted file mode 100644 (file)
index 206edb0..0000000
+++ /dev/null
@@ -1,36 +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;
-
-public final class XMLConstants {
-
-  private XMLConstants(){
-    // Utility class
-  }
-
-  public static final String CHARACTERISTIC = "chc";
-  public static final String CHARACTERISTIC_KEY = "key";
-  public static final String CHARACTERISTIC_NAME = "name";
-  public static final String CHARACTERISTIC_DESCRIPTION = "desc";
-  public static final String PROPERTY = "prop";
-  public static final String PROPERTY_KEY = "key";
-  public static final String PROPERTY_VALUE = "val";
-  public static final String PROPERTY_TEXT_VALUE = "txt";
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/XMLImporter.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/XMLImporter.java
deleted file mode 100644 (file)
index d5ae51a..0000000
+++ /dev/null
@@ -1,173 +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 com.google.common.collect.Lists;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
-import org.codehaus.stax2.XMLInputFactory2;
-import org.codehaus.staxmate.SMInputFactory;
-import org.codehaus.staxmate.in.SMHierarchicCursor;
-import org.codehaus.staxmate.in.SMInputCursor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.ServerExtension;
-import org.sonar.api.qualitymodel.Characteristic;
-import org.sonar.api.qualitymodel.Model;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.utils.ValidationMessages;
-
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.List;
-
-public class XMLImporter implements ServerExtension {
-
-  private static final Logger LOG = LoggerFactory.getLogger(XMLImporter.class);
-
-  public Model importXML(String xml, ValidationMessages messages, RuleCache ruleCache) {
-    return importXML(new StringReader(xml), messages, ruleCache);
-  }
-
-  public Model importXML(Reader xml, ValidationMessages messages, RuleCache repositoryCache) {
-    Model sqale = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    try {
-      SMInputFactory inputFactory = initStax();
-      SMHierarchicCursor cursor = inputFactory.rootElementCursor(xml);
-
-      // advance to <sqale>
-      cursor.advance();
-      SMInputCursor chcCursor = cursor.childElementCursor(XMLConstants.CHARACTERISTIC);
-
-      while (chcCursor.getNext() != null) {
-        processCharacteristic(sqale, chcCursor, messages, repositoryCache);
-      }
-
-      cursor.getStreamReader().closeCompletely();
-
-    } catch (XMLStreamException e) {
-      LOG.error("XML is not valid", e);
-      messages.addErrorText("XML is not valid: " + e.getMessage());
-    }
-    return sqale;
-  }
-
-  private SMInputFactory initStax() {
-    XMLInputFactory xmlFactory = XMLInputFactory2.newInstance();
-    xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
-    xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
-    xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
-    xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
-    return new SMInputFactory(xmlFactory);
-  }
-
-  private Characteristic processCharacteristic(Model sqale, SMInputCursor chcCursor, ValidationMessages messages,
-                                               RuleCache ruleCache) throws XMLStreamException {
-    Characteristic characteristic = Characteristic.create();
-    SMInputCursor cursor = chcCursor.childElementCursor();
-
-    String ruleRepositoryKey = null, ruleKey = null;
-    List<Characteristic> children = Lists.newArrayList();
-    while (cursor.getNext() != null) {
-      String node = cursor.getLocalName();
-      if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC_KEY)) {
-        characteristic.setKey(cursor.collectDescendantText().trim());
-
-      } else if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC_NAME)) {
-        characteristic.setName(cursor.collectDescendantText().trim(), false);
-
-      } else if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC_DESCRIPTION)) {
-        characteristic.setDescription(cursor.collectDescendantText().trim());
-
-      } else if (StringUtils.equals(node, XMLConstants.PROPERTY)) {
-        processProperty(characteristic, cursor, messages);
-
-      } else if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC)) {
-        children.add(processCharacteristic(sqale, cursor, messages, ruleCache));
-
-      } else if (StringUtils.equals(node, "rule-repo")) {
-        ruleRepositoryKey = cursor.collectDescendantText().trim();
-
-      } else if (StringUtils.equals(node, "rule-key")) {
-        ruleKey = cursor.collectDescendantText().trim();
-      }
-    }
-    fillRule(characteristic, ruleRepositoryKey, ruleKey, messages, ruleCache);
-
-    if (StringUtils.isNotBlank(characteristic.getKey()) || characteristic.getRule() != null) {
-      addCharacteristicToModel(sqale, characteristic, children);
-      return characteristic;
-    }
-    return null;
-  }
-
-  private void fillRule(Characteristic characteristic, String ruleRepositoryKey, String ruleKey, ValidationMessages messages,
-                        RuleCache ruleCache) {
-    if (StringUtils.isNotBlank(ruleRepositoryKey) && StringUtils.isNotBlank(ruleKey)) {
-      Rule rule = ruleCache.getRule(ruleRepositoryKey, ruleKey);
-      if (rule != null) {
-        characteristic.setRule(rule);
-      } else {
-        messages.addWarningText("Rule not found: [repository=" + ruleRepositoryKey + ", key=" + ruleKey + "]");
-      }
-    }
-  }
-
-  private void addCharacteristicToModel(Model sqale, Characteristic characteristic, List<Characteristic> children) {
-    sqale.addCharacteristic(characteristic);
-    for (Characteristic child : children) {
-      if (child != null) {
-        sqale.addCharacteristic(child);
-        characteristic.addChild(child);
-      }
-    }
-  }
-
-  private void processProperty(Characteristic characteristic, SMInputCursor cursor, ValidationMessages messages) throws XMLStreamException {
-    SMInputCursor c = cursor.childElementCursor();
-    String key = null;
-    Double value = null;
-    String textValue = null;
-    while (c.getNext() != null) {
-      String node = c.getLocalName();
-      if (StringUtils.equals(node, XMLConstants.PROPERTY_KEY)) {
-        key = c.collectDescendantText().trim();
-
-      } else if (StringUtils.equals(node, XMLConstants.PROPERTY_VALUE)) {
-        String s = c.collectDescendantText().trim();
-        try {
-          value = NumberUtils.createDouble(s);
-        } catch (NumberFormatException ex) {
-          String message = String.format("Cannot import value '%s' for field %s - Expected a numeric value instead", s, key);
-          LOG.error(message, ex);
-          messages.addErrorText(message);
-        }
-      } else if (StringUtils.equals(node, XMLConstants.PROPERTY_TEXT_VALUE)) {
-        textValue = c.collectDescendantText().trim();
-      }
-    }
-    if (StringUtils.isNotBlank(key)) {
-      characteristic.setProperty(key, textValue).setValue(value);
-    }
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/package-info.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/package-info.java
deleted file mode 100644 (file)
index 9c4f50f..0000000
+++ /dev/null
@@ -1,25 +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.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonar.core.technicaldebt;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/RuleCacheTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/RuleCacheTest.java
deleted file mode 100644 (file)
index a4d5c61..0000000
+++ /dev/null
@@ -1,65 +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 com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.RuleQuery;
-
-import java.util.Collections;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
-public class RuleCacheTest {
-
-  @Test
-  public void should_lazy_load_rules_on_first_call() throws Exception {
-
-    RuleFinder ruleFinder = mock(RuleFinder.class);
-    when(ruleFinder.findAll(any(RuleQuery.class))).thenReturn(Collections.EMPTY_LIST);
-
-    RuleCache ruleCache = new RuleCache(ruleFinder);
-    ruleCache.getRule("", "");
-    ruleCache.getRule("", "");
-
-    verify(ruleFinder, times(1)).findAll(any(RuleQuery.class));
-  }
-
-  @Test
-  public void should_return_matching_rule() throws Exception {
-
-    Rule rule1 = Rule.create("repo1", "rule1");
-    Rule rule2 = Rule.create("repo2", "rule2");
-
-    RuleFinder ruleFinder = mock(RuleFinder.class);
-    when(ruleFinder.findAll(any(RuleQuery.class))).thenReturn(Lists.newArrayList(rule1, rule2));
-
-    RuleCache ruleCache = new RuleCache(ruleFinder);
-    Rule actualRule1 = ruleCache.getRule("repo1", "rule1");
-    Rule actualRule2 = ruleCache.getRule("repo2", "rule2");
-
-    assertThat(actualRule1).isEqualTo(rule1);
-    assertThat(actualRule2).isEqualTo(rule2);
-  }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtManagerTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtManagerTest.java
deleted file mode 100644 (file)
index 53b1c33..0000000
+++ /dev/null
@@ -1,197 +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 com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.io.Resources;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.qualitymodel.Characteristic;
-import org.sonar.api.qualitymodel.Model;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.utils.ValidationMessages;
-import org.sonar.core.qualitymodel.DefaultModelFinder;
-import org.sonar.core.rule.DefaultRuleFinder;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class TechnicalDebtManagerTest extends AbstractDbUnitTestCase {
-
-  private TechnicalDebtManager manager;
-  private TechnicalDebtModelFinder TechnicalDebtModelFinder;
-
-  @Before
-  public void init() throws Exception {
-    TechnicalDebtModelFinder = mock(TechnicalDebtModelFinder.class);
-    when(TechnicalDebtModelFinder.getContributingPluginList()).thenReturn(ImmutableList.of("java", "technical-debt"));
-    when(TechnicalDebtModelFinder.createReaderForXMLFile("java")).thenReturn(
-      new FileReader(Resources.getResource(TechnicalDebtManagerTest.class, "TechnicalDebtManagerTest/fake-java-model.xml").getPath()));
-    // Mock default sqale model
-    when(TechnicalDebtModelFinder.createReaderForXMLFile("technical-debt")).thenReturn(
-      new FileReader(Resources.getResource(TechnicalDebtManagerTest.class, "TechnicalDebtManagerTest/fake-default-model.xml").getPath()));
-
-    manager = new TechnicalDebtManager(getSessionFactory(), new DefaultModelFinder(getSessionFactory()), TechnicalDebtModelFinder, new XMLImporter());
-  }
-
-  @Test
-  public void reset_model() {
-    setupData("reset_model");
-
-    Model model = manager.resetModel(ValidationMessages.create(), defaultRuleCache());
-    assertThat(model.getCharacteristics().size()).isGreaterThan(3);
-    assertThat(model.getCharacteristics().size()).isGreaterThan(model.getRootCharacteristics().size());
-    for (Characteristic portabilityCharacteristic : model.getCharacteristicByKey("PORTABILITY").getChildren()) {
-      assertThat(portabilityCharacteristic.getName()).contains("portability");
-      Characteristic requirement = portabilityCharacteristic.getChildren().get(0);
-      assertThat(requirement).isNotNull();
-      Rule rule = requirement.getRule();
-      assertThat(rule).isNotNull();
-      assertThat(rule.getName()).isEqualTo("Regular exp");
-    }
-    assertThat(model.getCharacteristicByKey("testability")).isNull();
-    assertThat(model.getCharacteristicByKey("unit_testability")).isNull();
-  }
-
-  @Test
-  public void provided_plugin_should_not_override_default_model_when_resetting_model() throws FileNotFoundException {
-    setupData("reset_model");
-
-    Model model = manager.resetModel(ValidationMessages.create(), defaultRuleCache());
-    // Default model values
-    assertThat(model.getCharacteristicByKey("PORTABILITY").getName()).isEqualTo("Portability");
-    assertThat(model.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").getName()).isEqualTo("Compiler related portability");
-    assertThat(model.getCharacteristicByKey("HARDWARE_RELATED_PORTABILITY").getName()).isEqualTo("Hardware related portability");
-    assertThat(model.getCharacteristicByKey("MAINTAINABILITY").getName()).isEqualTo("Maintainability");
-
-    // Plugin has renamed it the value stay as defined by default model
-    assertThat(model.getCharacteristicByKey("READABILITY").getName()).isEqualTo("Readability");
-
-    // Characteristic provided only by the plugin
-    assertThat(model.getCharacteristicByKey("UNDERSTANDABILITY").getName()).isEqualTo("Understandability related maintainability");
-  }
-
-  @Test
-  public void not_fail_if_unknown_rule_when_resetting_model() {
-    setupData("reset_model");
-
-    RuleFinder ruleFinder = mock(RuleFinder.class);
-    when(ruleFinder.findByKey(anyString(), anyString())).thenReturn(null);
-
-    manager = new TechnicalDebtManager(getSessionFactory(), new DefaultModelFinder(getSessionFactory()),
-      TechnicalDebtModelFinder, new XMLImporter());
-
-    Model model = manager.resetModel(ValidationMessages.create(), new RuleCache(ruleFinder));
-    assertThat(model.getCharacteristics().size()).isGreaterThanOrEqualTo(3);
-    assertThat(model.getCharacteristics().size()).isGreaterThan(model.getRootCharacteristics().size());
-    List<Characteristic> hardwareControls = model.getCharacteristicByKey("HARDWARE_RELATED_PORTABILITY").getChildren();
-    assertThat(hardwareControls.isEmpty()).isTrue();
-  }
-
-  @Test
-  public void create_initial_model() {
-    Model model = manager.createInitialModel(ValidationMessages.create(), defaultRuleCache());
-
-    // Default model values
-    assertThat(model.getCharacteristicByKey("PORTABILITY").getName()).isEqualTo("Portability");
-    assertThat(model.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").getName()).isEqualTo("Compiler related portability");
-    assertThat(model.getCharacteristicByKey("HARDWARE_RELATED_PORTABILITY").getName()).isEqualTo("Hardware related portability");
-    assertThat(model.getCharacteristicByKey("MAINTAINABILITY").getName()).isEqualTo("Maintainability");
-
-    // Plugin has renamed it the value stay as defined by default model
-    assertThat(model.getCharacteristicByKey("READABILITY").getName()).isEqualTo("Readability");
-
-    // Characteristic provided only by the plugin
-    assertThat(model.getCharacteristicByKey("UNDERSTANDABILITY").getName()).isEqualTo("Understandability related maintainability");
-  }
-
-  @Test
-  public void persist_merge() {
-    setupData("persist_merge");
-
-    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
-    Characteristic ramEfficiency = with.createCharacteristicByKey("ram-efficiency", "RAM Efficiency");
-    efficiency.addChild(ramEfficiency);
-    ramEfficiency.addChild(with.createCharacteristicByRule(newRegexpRule()));
-
-    manager.merge(with, ValidationMessages.create(), defaultRuleCache());
-
-    checkTables("persist_merge", "quality_models", "characteristics", "characteristic_edges");
-  }
-
-  @Test
-  public void persist_merge_with_plugin_files() throws Exception {
-    setupData("persist_merge");
-
-    manager.merge(Lists.newArrayList("java"), ValidationMessages.create(), defaultRuleCache());
-
-    Model model = (new DefaultModelFinder(getSessionFactory())).findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    assertThat(model.getCharacteristics()).contains(Characteristic.createByKey("PORTABILITY", "Portability"));
-  }
-
-  @Test
-  public void persist_restore() {
-    setupData("persist_restore");
-
-    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
-    Characteristic ramEfficiency = with.createCharacteristicByKey("ram-efficiency", "RAM Efficiency");
-    efficiency.addChild(ramEfficiency);
-    ramEfficiency.addChild(with.createCharacteristicByRule(newRegexpRule()));
-
-    manager.restore(with, ValidationMessages.create(), defaultRuleCache());
-
-    checkTables("persist_restore", "quality_models", "characteristics", "characteristic_edges");
-  }
-
-  @Test
-  public void warn_when_restoring_unknown_rule() {
-    setupData("warn_when_restoring_unknown_rule");
-
-    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
-    efficiency.addChild(with.createCharacteristicByRule(newRegexpRule()));
-
-    ValidationMessages messages = ValidationMessages.create();
-    manager.restore(with, messages, defaultRuleCache());
-
-    checkTables("warn_when_restoring_unknown_rule", "quality_models", "characteristics", "characteristic_edges");
-    assertThat(messages.getWarnings()).hasSize(1);
-    assertThat(messages.getWarnings().get(0)).contains("regexp");
-  }
-
-  private RuleCache defaultRuleCache() {
-    return new RuleCache(new DefaultRuleFinder(getSessionFactory()));
-  }
-
-  private Rule newRegexpRule() {
-    return Rule.create("checkstyle", "regexp", "Regular expression");
-  }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelDefinitionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelDefinitionTest.java
deleted file mode 100644 (file)
index 443b071..0000000
+++ /dev/null
@@ -1,41 +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.junit.Test;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.utils.ValidationMessages;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
-public class TechnicalDebtModelDefinitionTest {
-
-  @Test
-  public void shouldCreateModel() throws Exception {
-    TechnicalDebtManager technicalDebtManager = mock(TechnicalDebtManager.class);
-    RuleFinder ruleFinder = mock(RuleFinder.class);
-    TechnicalDebtModelDefinition sqaleDefinition = new TechnicalDebtModelDefinition(technicalDebtManager, ruleFinder);
-
-    sqaleDefinition.createModel();
-
-    verify(technicalDebtManager, times(1)).createInitialModel(any(ValidationMessages.class), any(RuleCache.class));
-  }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest.java
deleted file mode 100644 (file)
index ba9bcd1..0000000
+++ /dev/null
@@ -1,134 +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 com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.io.Resources;
-import org.apache.commons.io.IOUtils;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.SonarPlugin;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
-
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.Reader;
-import java.net.MalformedURLException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class TechnicalDebtModelFinderTest {
-
-  private static final String TEST_XML_PREFIX_PATH = "org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest/";
-
-  private TechnicalDebtModelFinder modelFinder;
-
-  @Test
-  public void test_component_initialization() throws Exception {
-    // we do have the "csharp-model.xml" file in src/test/resources
-    PluginMetadata csharpPluginMetadata = mock(PluginMetadata.class);
-    when(csharpPluginMetadata.getKey()).thenReturn("csharp");
-
-    // but we don' have the "php-model.xml" one
-    PluginMetadata phpPluginMetadata = mock(PluginMetadata.class);
-    when(phpPluginMetadata.getKey()).thenReturn("php");
-
-    PluginRepository repository = mock(PluginRepository.class);
-    when(repository.getMetadata()).thenReturn(Lists.newArrayList(csharpPluginMetadata, phpPluginMetadata));
-    FakePlugin fakePlugin = new FakePlugin();
-    when(repository.getPlugin(anyString())).thenReturn(fakePlugin);
-    modelFinder = new TechnicalDebtModelFinder(repository, TEST_XML_PREFIX_PATH);
-
-    // when
-    modelFinder.start();
-
-    // assert
-    Collection<String> contributingPluginList = modelFinder.getContributingPluginList();
-    assertThat(contributingPluginList.size()).isEqualTo(1);
-    assertThat(contributingPluginList).containsOnly("csharp");
-  }
-
-  @Test
-  public void contributing_plugin_list() throws Exception {
-    initModel();
-    Collection<String> contributingPluginList = modelFinder.getContributingPluginList();
-    assertThat(contributingPluginList.size()).isEqualTo(2);
-    assertThat(contributingPluginList).contains("csharp", "java");
-  }
-
-  @Test
-  public void get_content_for_xml_file() throws Exception {
-    initModel();
-    Reader xmlFileReader = null;
-    try {
-      xmlFileReader = modelFinder.createReaderForXMLFile("csharp");
-      assertNotNull(xmlFileReader);
-      List<String> lines = IOUtils.readLines(xmlFileReader);
-      assertThat(lines.size()).isEqualTo(25);
-      assertThat(lines.get(0)).isEqualTo("<sqale>");
-    } catch (Exception e) {
-      fail("Should be able to read the XML file.");
-    } finally {
-      IOUtils.closeQuietly(xmlFileReader);
-    }
-  }
-
-  @Test
-  public void return_xml_file_path_for_plugin() throws Exception {
-    initModel();
-    assertThat(modelFinder.getXMLFilePathForPlugin("foo")).isEqualTo(TEST_XML_PREFIX_PATH + "foo-model.xml");
-  }
-
-  private void initModel() throws MalformedURLException {
-    Map<String, ClassLoader> contributingPluginKeyToClassLoader = Maps.newHashMap();
-    contributingPluginKeyToClassLoader.put("csharp", newClassLoader());
-    contributingPluginKeyToClassLoader.put("java", newClassLoader());
-    modelFinder = new TechnicalDebtModelFinder(contributingPluginKeyToClassLoader, TEST_XML_PREFIX_PATH);
-  }
-
-  private ClassLoader newClassLoader() throws MalformedURLException {
-    ClassLoader loader = mock(ClassLoader.class);
-    when(loader.getResourceAsStream(anyString())).thenAnswer(new Answer<InputStream>() {
-      public InputStream answer(InvocationOnMock invocation) throws Throwable {
-        return new FileInputStream(Resources.getResource((String) invocation.getArguments()[0]).getPath());
-      }
-    });
-    return loader;
-  }
-
-  class FakePlugin extends SonarPlugin {
-    public List getExtensions() {
-      return null;
-    }
-  }
-
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelTest.java
deleted file mode 100644 (file)
index 07c0100..0000000
+++ /dev/null
@@ -1,108 +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 com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.qualitymodel.Characteristic;
-import org.sonar.api.qualitymodel.Model;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.RuleQuery;
-import org.sonar.api.utils.ValidationMessages;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class TechnicalDebtModelTest {
-
-  private Model model;
-  private TechnicalDebtModel technicalDebtModel;
-
-  @Before
-  public void setUpModel() {
-    model = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    technicalDebtModel = new TechnicalDebtModel(model);
-  }
-
-  @Test
-  public void shouldMergeWithEmptyModel() {
-    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
-    efficiency.addChild(with.createCharacteristicByKey("ram-efficiency", "RAM Efficiency"));
-    with.createCharacteristicByKey("usability", "Usability");
-
-    ValidationMessages messages = ValidationMessages.create();
-
-    technicalDebtModel.mergeWith(with, messages, mockRuleCache());
-
-    assertThat(model.getCharacteristics()).hasSize(3);
-    assertThat(model.getRootCharacteristics()).hasSize(2);
-    assertThat(model.getCharacteristicByKey("ram-efficiency").getDepth()).isEqualTo(Characteristic.ROOT_DEPTH + 1);
-    assertThat(messages.getErrors()).isEmpty();
-  }
-
-  @Test
-  public void shouldNotUpdateExistingCharacteristics() {
-    model.createCharacteristicByKey("efficiency", "Efficiency");
-
-    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    with.createCharacteristicByKey("efficiency", "New efficiency");
-
-    technicalDebtModel.mergeWith(with, ValidationMessages.create(), mockRuleCache());
-
-    assertThat(model.getCharacteristics()).hasSize(1);
-    assertThat(model.getRootCharacteristics()).hasSize(1);
-    assertThat(model.getCharacteristicByKey("efficiency").getName()).isEqualTo("Efficiency");
-  }
-
-  @Test
-  public void shouldWarnOnMissingRule() {
-    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
-    Rule fooRule = Rule.create("foo", "bar", "Bar");
-    Characteristic requirement = with.createCharacteristicByRule(fooRule);
-    efficiency.addChild(requirement);
-
-    ValidationMessages messages = ValidationMessages.create();
-
-    technicalDebtModel.mergeWith(with, messages, mockRuleCache());
-
-    assertThat(model.getCharacteristics()).hasSize(1);
-    assertThat(model.getCharacteristicByKey("efficiency").getName()).isEqualTo("Efficiency");
-    assertThat(model.getCharacteristicByRule(fooRule)).isNull();
-    assertThat(messages.getWarnings()).hasSize(1);
-    assertThat(messages.getWarnings().get(0)).contains("foo"); // warning: the rule foo does not exist
-  }
-
-  private RuleCache mockRuleCache() {
-    RuleFinder ruleFinder = mock(RuleFinder.class);
-    when(ruleFinder.findAll(any(RuleQuery.class))).thenReturn(Lists.newArrayList(newRegexpRule()));
-    return new RuleCache(ruleFinder);
-  }
-
-  private Rule newRegexpRule() {
-    return Rule.create("checkstyle", "regexp", "Regular expression");
-  }
-}
-
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/XMLImporterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/XMLImporterTest.java
deleted file mode 100644 (file)
index 916d44e..0000000
+++ /dev/null
@@ -1,130 +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 com.google.common.base.Charsets;
-import com.google.common.collect.Lists;
-import com.google.common.io.Resources;
-import org.junit.Test;
-import org.sonar.api.qualitymodel.Characteristic;
-import org.sonar.api.qualitymodel.Model;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.RuleQuery;
-import org.sonar.api.utils.ValidationMessages;
-
-import java.io.IOException;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class XMLImporterTest {
-
-  @Test
-  public void shouldImportXML() {
-    RuleCache ruleCache = mockRuleCache();
-
-    String xml = getFileContent("shouldImportXML.xml");
-
-    ValidationMessages messages = ValidationMessages.create();
-    Model sqale = new XMLImporter().importXML(xml, messages, ruleCache);
-
-    checkXmlCorrectlyImported(sqale, messages);
-  }
-
-  @Test
-  public void shouldBadlyFormattedImportXML() {
-    RuleCache ruleCache = mockRuleCache();
-    String xml = getFileContent("shouldImportXML_badly-formatted.xml");
-
-    ValidationMessages messages = ValidationMessages.create();
-    Model sqale = new XMLImporter().importXML(xml, messages, ruleCache);
-
-    checkXmlCorrectlyImported(sqale, messages);
-  }
-
-  @Test
-  public void shouldLogWarningIfRuleNotFound() {
-    RuleCache ruleCache = mockRuleCache();
-    String xml = getFileContent("shouldLogWarningIfRuleNotFound.xml");
-    ValidationMessages messages = ValidationMessages.create();
-
-    Model sqale = new XMLImporter().importXML(xml, messages, ruleCache);
-
-    assertThat(messages.getWarnings()).hasSize(1);
-
-    // characteristics
-    assertThat(sqale.getRootCharacteristics()).hasSize(1);
-    Characteristic efficiency = sqale.getCharacteristicByKey("EFFICIENCY");
-    assertThat(efficiency.getChildren()).isEmpty();
-    assertThat(messages.getWarnings().get(0)).contains("findbugs");
-  }
-
-  @Test
-  public void shouldNotifyOnUnexpectedValueTypeInXml() throws Exception {
-
-    RuleCache ruleCache = mockRuleCache();
-
-    String xml = getFileContent("shouldRejectXML_with_invalid_value.xml");
-    ValidationMessages messages = ValidationMessages.create();
-
-    new XMLImporter().importXML(xml, messages, ruleCache);
-
-    assertThat(messages.getErrors()).hasSize(1);
-    assertThat(messages.getErrors().get(0)).isEqualTo("Cannot import value 'abc' for field factor - Expected a numeric value instead");
-  }
-
-  private RuleCache mockRuleCache() {
-    RuleFinder finder = mock(RuleFinder.class);
-    when(finder.findAll(any(RuleQuery.class))).thenReturn(Lists.newArrayList(Rule.create("checkstyle", "Regexp", "Regular expression")));
-    return new RuleCache(finder);
-  }
-
-  private void checkXmlCorrectlyImported(Model sqale, ValidationMessages messages) {
-
-    assertThat(messages.getErrors()).isEmpty();
-    assertThat(sqale.getName()).isEqualTo(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
-
-    // characteristics
-    assertThat(sqale.getRootCharacteristics()).hasSize(2);
-    assertThat(sqale.getCharacteristicByKey("USABILITY").getDescription()).isEqualTo("Estimate usability");
-    Characteristic efficiency = sqale.getCharacteristicByKey("EFFICIENCY");
-    assertThat(efficiency.getName()).isEqualTo("Efficiency");
-
-    // sub-characteristics
-    assertThat(efficiency.getChildren()).hasSize(1);
-    Characteristic requirement = efficiency.getChildren().get(0);
-    assertThat(requirement.getRule().getRepositoryKey()).isEqualTo("checkstyle");
-    assertThat(requirement.getRule().getKey()).isEqualTo("Regexp");
-    assertThat(requirement.getPropertyTextValue("function", null)).isEqualTo("linear");
-    assertThat(requirement.getPropertyValue("factor", null)).isEqualTo(3.2);
-  }
-
-  private String getFileContent(String file) {
-    try {
-      return Resources.toString(Resources.getResource(XMLImporterTest.class, "XMLImporterTest/" + file), Charsets.UTF_8);
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-}
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/fake-default-model.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/fake-default-model.xml
deleted file mode 100644 (file)
index 839e019..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<sqale>
-  <chc>
-    <key>PORTABILITY</key>
-    <name>Portability</name>
-    <chc>
-      <key>COMPILER_RELATED_PORTABILITY</key>
-      <name>Compiler related portability</name>
-    </chc>
-    <chc>
-      <key>HARDWARE_RELATED_PORTABILITY</key>
-      <name>Hardware related portability</name>
-    </chc>
-  </chc>
-  <chc>
-    <chc>
-      <key>MAINTAINABILITY</key>
-      <name>Maintainability</name>
-      <chc>
-        <key>READABILITY</key>
-        <name>Readability</name>
-      </chc>
-    </chc>
-  </chc>
-</sqale>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/fake-java-model.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/fake-java-model.xml
deleted file mode 100644 (file)
index 6d61008..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<sqale>
-  <chc>
-    <key>PORTABILITY</key>
-    <name>Portability</name>
-    <chc>
-      <key>COMPILER_RELATED_PORTABILITY</key>
-      <name>Compiler related portability</name>
-      <chc>
-        <rule-repo>checkstyle</rule-repo>
-        <rule-key>import</rule-key>
-        <prop>
-          <key>remediationFactor</key>
-          <val>30.0</val>
-          <txt>mn</txt>
-        </prop>
-        <prop>
-          <key>remediationFunction</key>
-          <txt>linear</txt>
-        </prop>
-      </chc>
-    </chc>
-    <chc>
-      <key>HARDWARE_RELATED_PORTABILITY</key>
-      <name>Hardware related portability</name>
-      <chc>
-        <rule-repo>checkstyle</rule-repo>
-        <rule-key>export</rule-key>
-        <prop>
-          <key>remediationFactor</key>
-          <val>1.0</val>
-          <txt>h</txt>
-        </prop>
-        <prop>
-          <key>remediationFunction</key>
-          <txt>linear</txt>
-        </prop>
-      </chc>
-    </chc>
-  </chc>
-  <chc>
-    <key>MAINTAINABILITY</key>
-    <name>Maintainability</name>
-    <chc>
-      <key>READABILITY</key>
-      <name>Readability related maintainability</name>
-      <chc>
-        <rule-repo>checkstyle</rule-repo>
-        <rule-key>ConstantNameCheck</rule-key>
-        <prop>
-          <key>remediationFactor</key>
-          <val>10.0</val>
-          <txt>mn</txt>
-        </prop>
-        <prop>
-          <key>remediationFunction</key>
-          <txt>linear</txt>
-        </prop>
-      </chc>
-    </chc>
-    <chc>
-      <key>UNDERSTANDABILITY</key>
-      <name>Understandability related maintainability</name>
-      <chc>
-        <rule-repo>checkstyle</rule-repo>
-        <rule-key>JavadocMethodCheck</rule-key>
-        <prop>
-          <key>remediationFactor</key>
-          <val>30.0</val>
-          <txt>mn</txt>
-        </prop>
-        <prop>
-          <key>remediationFunction</key>
-          <txt>linear</txt>
-        </prop>
-      </chc>
-    </chc>
-  </chc>
-</sqale>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_merge-result.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_merge-result.xml
deleted file mode 100644 (file)
index 3f84f54..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<dataset>
-  <!-- existing models -->
-  <quality_models id="1" name="TECHNICAL_DEBT" />
-  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
-  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
-
-  <characteristics id="3" kee="efficiency" name="Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="3" depth="1" description="[null]" enabled="true" />
-  <characteristics id="4" kee="ram-efficiency" name="RAM Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="4" depth="2" description="[null]" enabled="true" />
-  <characteristics id="5" kee="[null]" name="[null]" quality_model_id="1" rule_id="2" characteristic_order="5" depth="3" description="[null]" enabled="true" />
-
-  <characteristic_edges child_id="2" parent_id="1"/>
-  <characteristic_edges child_id="4" parent_id="3"/>
-  <characteristic_edges child_id="5" parent_id="4"/>
-  
-  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
-
-  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_merge.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_merge.xml
deleted file mode 100644 (file)
index 4e2fb09..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<dataset>
-  <!-- existing models -->
-  <quality_models id="1" name="TECHNICAL_DEBT" />
-
-  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
-  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
-  <characteristic_edges child_id="2" parent_id="1"/>
-  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
-
-  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_restore-result.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_restore-result.xml
deleted file mode 100644 (file)
index 612de62..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<dataset>
-  <quality_models id="1" name="TECHNICAL_DEBT" />
-
-  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="false" />
-  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="false" />
-  <characteristics id="3" kee="[null]" name="[null]" quality_model_id="1" rule_id="1" characteristic_order="3" depth="3" description="[null]" enabled="false" />
-
-  <characteristics id="4" kee="efficiency" name="Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="4" depth="1" description="[null]" enabled="true" />
-  <characteristics id="5" kee="ram-efficiency" name="RAM Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="5" depth="2" description="[null]" enabled="true" />
-  <characteristics id="6" kee="[null]" name="[null]" quality_model_id="1" rule_id="2" characteristic_order="6" depth="3" description="[null]" enabled="true" />
-
-  <characteristic_edges child_id="2" parent_id="1"/>
-  <characteristic_edges child_id="3" parent_id="2"/>
-  <characteristic_edges child_id="5" parent_id="4"/>
-  <characteristic_edges child_id="6" parent_id="5"/>
-
-  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
-
-  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_restore.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/persist_restore.xml
deleted file mode 100644 (file)
index 1561bdb..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<dataset>
-  <quality_models id="1" name="TECHNICAL_DEBT" />
-
-  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
-  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
-  <characteristics id="3" kee="[null]" name="[null]" quality_model_id="1" rule_id="1" characteristic_order="3" depth="3" description="[null]" enabled="true" />
-
-  <characteristic_edges child_id="2" parent_id="1"/>
-  <characteristic_edges child_id="3" parent_id="2"/>
-  
-  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
-
-  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/reset_model.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/reset_model.xml
deleted file mode 100644 (file)
index 4c82f6e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<dataset>
-  <!-- existing models -->
-  <quality_models id="1" name="TECHNICAL_DEBT" />
-  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
-  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
-  <characteristic_edges child_id="2" parent_id="1"/>
-
-  <rules id="1" plugin_rule_key="import" plugin_config_key="import" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-  <rules id="2" plugin_rule_key="export" plugin_config_key="export" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-  <rules id="3" plugin_rule_key="ConstantNameCheck" plugin_config_key="ConstantNameCheck" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-  <rules id="4" plugin_rule_key="JavadocMethodCheck" plugin_config_key="JavadocMethodCheck" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule-result.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule-result.xml
deleted file mode 100644 (file)
index 7566ea2..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-  <quality_models id="1" name="foo" />
-  <quality_models id="2" name="TECHNICAL_DEBT" />
-
-  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
-  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
-
-  <characteristics id="3" kee="efficiency" name="Efficiency" quality_model_id="2" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
-
-  <characteristic_edges child_id="2" parent_id="1"/>
-  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
-
-  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule.xml
deleted file mode 100644 (file)
index 619ad9e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<dataset>
-  <quality_models id="1" name="foo" />
-  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
-  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
-  <characteristic_edges child_id="2" parent_id="1"/>
-  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
-
-  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest/csharp-model.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest/csharp-model.xml
deleted file mode 100644 (file)
index e4569a2..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<sqale>
-  <chc>
-    <key>USABILITY</key>
-    <name>Usability</name>
-    <desc>Estimate usability</desc>
-  </chc>
-  <chc>
-    <key>EFFICIENCY</key>
-    <name>Efficiency</name>
-    <chc>
-      <rule-repo>gendarme</rule-repo>
-      <rule-key>EnsureLocalDisposalRule</rule-key>
-      <prop>
-        <key>remediationFactor</key>
-        <val>0.125</val>
-        <txt>d</txt>
-      </prop>
-      <prop>
-        <key>remediationFunction</key>
-        <txt>linear</txt>
-      </prop>
-    </chc>
-  </chc>
-
-</sqale>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest/java-model.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtModelFinderTest/java-model.xml
deleted file mode 100644 (file)
index 0b37f56..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<sqale>
-  <chc>
-    <key>USABILITY</key>
-    <name>Usability</name>
-    <desc>Estimate usability</desc>
-  </chc>
-  <chc>
-    <key>EFFICIENCY</key>
-    <name>Efficiency</name>
-    <chc>
-      <rule-repo>squid-cobol</rule-repo>
-      <rule-key>CheckLoop</rule-key>
-      <prop>
-        <key>remediationFactor</key>
-        <val>0.125</val>
-        <txt>d</txt>
-      </prop>
-      <prop>
-        <key>remediationFunction</key>
-        <txt>linear</txt>
-      </prop>
-    </chc>
-  </chc>
-
-</sqale>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldImportXML.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldImportXML.xml
deleted file mode 100644 (file)
index e405189..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<sqale>
-  <chc>
-    <key>USABILITY</key>
-    <name>Usability</name>
-    <desc>Estimate usability</desc>
-  </chc>
-  <chc>
-    <key>EFFICIENCY</key>
-    <name>Efficiency</name>
-
-    <chc>
-      <rule-repo>checkstyle</rule-repo>
-      <rule-key>Regexp</rule-key>
-      <prop>
-        <key>factor</key>
-        <val>3.2</val>
-      </prop>
-      <prop>
-        <key>function</key>
-        <txt>linear</txt>
-      </prop>
-    </chc>
-  </chc>
-
-</sqale>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldImportXML_badly-formatted.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldImportXML_badly-formatted.xml
deleted file mode 100644 (file)
index 373959f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<sqale>
-  <chc>
-    <key>USABILITY
-    </key>
-    <name>Usability
-    </name>
-    <desc>Estimate usability
-    </desc>
-  </chc>
-  <chc>
-    <key>EFFICIENCY
-    </key>
-    <name>Efficiency
-    </name>
-
-    <chc>
-      <rule-repo>checkstyle
-      </rule-repo>
-      <rule-key>Regexp
-      </rule-key>
-      <prop>
-        <key>factor
-        </key>
-        <val>3.2
-        </val>
-      </prop>
-      <prop>
-        <key>function
-        </key>
-        <txt>linear
-        </txt>
-      </prop>
-    </chc>
-  </chc>
-
-</sqale>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldLogWarningIfRuleNotFound.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldLogWarningIfRuleNotFound.xml
deleted file mode 100644 (file)
index bd459f6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<sqale>
-  <chc>
-    <key>EFFICIENCY</key>
-    <name>Efficiency</name>
-
-    <chc>
-      <rule-repo>findbugs</rule-repo>
-      <rule-key>Foo</rule-key>
-    </chc>
-  </chc>
-
-</sqale>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldRejectXML_with_invalid_value.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/XMLImporterTest/shouldRejectXML_with_invalid_value.xml
deleted file mode 100644 (file)
index 638f00e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<sqale>
-  <chc>
-    <key>USABILITY</key>
-    <name>Usability</name>
-    <desc>Estimate usability</desc>
-  </chc>
-  <chc>
-    <key>EFFICIENCY</key>
-    <name>Efficiency</name>
-
-    <chc>
-      <rule-repo>checkstyle</rule-repo>
-      <rule-key>Regexp</rule-key>
-      <prop>
-        <key>factor</key>
-        <val>abc</val>
-      </prop>
-      <prop>
-        <key>function</key>
-        <txt>linear</txt>
-      </prop>
-    </chc>
-  </chc>
-
-</sqale>
diff --git a/sonar-server/src/main/java/com/sonar/sqale/technical-debt-model.xml b/sonar-server/src/main/java/com/sonar/sqale/technical-debt-model.xml
new file mode 100644 (file)
index 0000000..2a35e4f
--- /dev/null
@@ -0,0 +1,159 @@
+<!--
+
+    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.
+
+-->
+<sqale>
+  <chc>
+    <key>PORTABILITY</key>
+    <name>Portability</name>
+    <chc>
+      <key>COMPILER_RELATED_PORTABILITY</key>
+      <name>Compiler</name>
+    </chc>
+    <chc>
+      <key>HARDWARE_RELATED_PORTABILITY</key>
+      <name>Hardware</name>
+    </chc>
+    <chc>
+      <key>LANGUAGE_RELATED_PORTABILITY</key>
+      <name>Language</name>
+    </chc>
+    <chc>
+      <key>OS_RELATED_PORTABILITY</key>
+      <name>OS</name>
+    </chc>
+    <chc>
+      <key>SOFTWARE_RELATED_PORTABILITY</key>
+      <name>Software</name>
+    </chc>
+    <chc>
+      <key>TIME_ZONE_RELATED_PORTABILITY</key>
+      <name>Time zone</name>
+    </chc>
+  </chc>
+  <chc>
+    <key>MAINTAINABILITY</key>
+    <name>Maintainability</name>
+    <chc>
+      <key>READABILITY</key>
+      <name>Readability</name>
+    </chc>
+    <chc>
+      <key>UNDERSTANDABILITY</key>
+      <name>Understandability</name>
+    </chc>
+  </chc>
+  <chc>
+    <key>SECURITY</key>
+    <name>Security</name>
+    <chc>
+      <key>API_ABUSE</key>
+      <name>API abuse</name>
+    </chc>
+    <chc>
+      <key>ERRORS</key>
+      <name>Errors</name>
+    </chc>
+    <chc>
+      <key>INPUT_VALIDATION_AND_REPRESENTATION</key>
+      <name>Input validation and representation</name>
+    </chc>
+    <chc>
+      <key>SECURITY_FEATURES</key>
+      <name>Security features</name>
+    </chc>
+  </chc>
+  <chc>
+    <key>EFFICIENCY</key>
+    <name>Efficiency</name>
+    <chc>
+      <key>MEMORY_EFFICIENCY</key>
+      <name>Memory use</name>
+    </chc>
+    <chc>
+      <key>CPU_EFFICIENCY</key>
+      <name>Processor use</name>
+    </chc>
+  </chc>
+  <chc>
+    <key>CHANGEABILITY</key>
+    <name>Changeability</name>
+    <chc>
+      <key>ARCHITECTURE_CHANGEABILITY</key>
+      <name>Architecture</name>
+    </chc>
+    <chc>
+      <key>DATA_CHANGEABILITY</key>
+      <name>Data</name>
+    </chc>
+    <chc>
+      <key>LOGIC_CHANGEABILITY</key>
+      <name>Logic</name>
+    </chc>
+  </chc>
+  <chc>
+    <key>RELIABILITY</key>
+    <name>Reliability</name>
+    <chc>
+      <key>ARCHITECTURE_RELIABILITY</key>
+      <name>Architecture</name>
+    </chc>
+    <chc>
+      <key>DATA_RELIABILITY</key>
+      <name>Data</name>
+    </chc>
+    <chc>
+      <key>EXCEPTION_HANDLING</key>
+      <name>Exception handling</name>
+    </chc>
+    <chc>
+      <key>FAULT_TOLERANCE</key>
+      <name>Fault tolerance</name>
+    </chc>
+    <chc>
+      <key>INSTRUCTION_RELIABILITY</key>
+      <name>Instruction</name>
+    </chc>
+    <chc>
+      <key>LOGIC_RELIABILITY</key>
+      <name>Logic</name>
+    </chc>
+    <chc>
+      <key>SYNCHRONIZATION_RELIABILITY</key>
+      <name>Synchronization</name>
+    </chc>
+    <chc>
+      <key>UNIT_TESTS</key>
+      <name>Unit tests</name>
+    </chc>
+  </chc>
+  <chc>
+    <key>TESTABILITY</key>
+    <name>Testability</name>
+    <chc>
+      <key>INTEGRATION_TESTABILITY</key>
+      <name>Integration level</name>
+    </chc>
+    <chc>
+      <key>UNIT_TESTABILITY</key>
+      <name>Unit level</name>
+    </chc>
+  </chc>
+</sqale>
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/RuleCache.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/RuleCache.java
new file mode 100644 (file)
index 0000000..dfdce6e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.collect.Maps;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RuleQuery;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class RuleCache {
+
+  private final RuleFinder ruleFinder;
+
+  private Map<String, Map<String, Rule>> cachedRules;
+
+  public RuleCache(RuleFinder ruleFinder) {
+    this.ruleFinder = ruleFinder;
+  }
+
+  @CheckForNull
+  public Rule getRule(String repository, String ruleKey) {
+    if(cachedRules == null) {
+      loadRules();
+    }
+    return lookUpRuleInCache(repository, ruleKey);
+  }
+
+  private void loadRules() {
+    cachedRules = Maps.newHashMap();
+    Collection<Rule> rules = ruleFinder.findAll(RuleQuery.create());
+    for (Rule rule : rules) {
+      if(!cachedRules.containsKey(rule.getRepositoryKey())) {
+        cachedRules.put(rule.getRepositoryKey(), new HashMap<String, Rule>());
+      }
+      Map<String, Rule> cachedRepository = cachedRules.get(rule.getRepositoryKey());
+      if(!cachedRepository.containsKey(rule.getKey())) {
+        cachedRepository.put(rule.getKey(), rule);
+      }
+    }
+  }
+
+  private Rule lookUpRuleInCache(String repository, String ruleKey) {
+    Map<String, Rule> cachedRepository = cachedRules.get(repository);
+    if(cachedRepository != null) {
+      return cachedRepository.get(ruleKey);
+    }
+    return null;
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtManager.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtManager.java
new file mode 100644 (file)
index 0000000..e4bf7f7
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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.server.technicaldebt;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.qualitymodel.ModelFinder;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.jpa.session.DatabaseSessionFactory;
+
+import java.io.Reader;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * TODO test merge properties + property.value + text_value
+ */
+
+public class TechnicalDebtManager implements ServerExtension {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TechnicalDebtManager.class);
+
+  private DatabaseSessionFactory sessionFactory;
+  private ModelFinder modelFinder;
+  private TechnicalDebtModelFinder languageModelFinder;
+  private XMLImporter importer;
+
+  public TechnicalDebtManager(DatabaseSessionFactory sessionFactory, ModelFinder modelFinder,
+                              TechnicalDebtModelFinder languageModelFinder, XMLImporter importer) {
+    this.sessionFactory = sessionFactory;
+    this.modelFinder = modelFinder;
+    this.languageModelFinder = languageModelFinder;
+    this.importer = importer;
+  }
+
+  public void restore(Model model, ValidationMessages messages, RuleCache rulesCache) {
+    Model persisted = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    if (persisted != null) {
+      disable(persisted);
+    }
+    merge(model, messages, rulesCache);
+  }
+
+  public Model resetModel(ValidationMessages messages, RuleCache ruleCache) {
+    Model persisted = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    if (persisted != null) {
+      disable(persisted);
+    }
+
+    Model model = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    importDefaultSqaleModel(model, messages, ruleCache);
+    populateModelWithInitialValues(model, messages, ruleCache);
+
+    DatabaseSession session = sessionFactory.getSession();
+    session.save(model);
+    session.commit();
+
+    return model;
+  }
+
+  public Model createInitialModel(ValidationMessages messages, RuleCache ruleCache) {
+    Model initialModel = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    importDefaultSqaleModel(initialModel, messages, ruleCache);
+    populateModelWithInitialValues(initialModel, messages, ruleCache);
+    return initialModel;
+  }
+
+  public void merge(List<String> pluginKeys, ValidationMessages messages, RuleCache ruleCache) {
+    for (String pluginKey : pluginKeys) {
+      ValidationMessages currentMessages = ValidationMessages.create();
+      Model model = null;
+      Reader xmlFileReader = null;
+      try {
+        xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey);
+        model = importer.importXML(xmlFileReader, currentMessages, ruleCache);
+      } finally {
+        IOUtils.closeQuietly(xmlFileReader);
+      }
+      if (!currentMessages.hasErrors()) {
+        merge(model, messages, ruleCache);
+      } else {
+        for (String error : currentMessages.getErrors()) {
+          messages.addErrorText(error);
+        }
+      }
+    }
+  }
+
+  public void merge(Model with, ValidationMessages messages, RuleCache ruleCache) {
+    DatabaseSession session = sessionFactory.getSession();
+    Model sqale = modelFinder.findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    if (sqale == null) {
+      sqale = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+      session.saveWithoutFlush(sqale);
+    }
+    new TechnicalDebtModel(sqale).mergeWith(with, messages, ruleCache);
+    session.saveWithoutFlush(sqale);
+    session.commit();
+  }
+
+  private void populateModelWithInitialValues(Model initialModel, ValidationMessages messages, RuleCache ruleCache) {
+    for (String pluginKey : getContributingPluginListWithoutSqale()) {
+      mergePlugin(initialModel, pluginKey, messages, ruleCache);
+    }
+  }
+
+  private void mergePlugin(Model initialModel, String pluginKey, ValidationMessages messages, RuleCache ruleCache) {
+    Model model = null;
+    Reader xmlFileReader = null;
+    try {
+      xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey);
+
+      model = importer.importXML(xmlFileReader, messages, ruleCache);
+    } finally {
+      IOUtils.closeQuietly(xmlFileReader);
+    }
+    messages.log(LOG);
+    if (!messages.hasErrors()) {
+      new TechnicalDebtModel(initialModel).mergeWith(model, messages, ruleCache);
+      messages.log(LOG);
+    }
+  }
+
+  private void disable(Model persisted) {
+    for (Characteristic root : persisted.getRootCharacteristics()) {
+      persisted.removeCharacteristic(root);
+    }
+    sessionFactory.getSession().commit();
+  }
+
+  private Collection<String> getContributingPluginListWithoutSqale(){
+    return languageModelFinder.getContributingPluginList();
+  }
+
+  private void importDefaultSqaleModel(Model initialModel, ValidationMessages messages, RuleCache ruleCache) {
+    mergePlugin(initialModel, TechnicalDebtModelFinder.DEFAULT_MODEL, messages, ruleCache);
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModel.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModel.java
new file mode 100644 (file)
index 0000000..ea288fc
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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.server.technicaldebt;
+
+import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.CharacteristicProperty;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.utils.ValidationMessages;
+
+public class TechnicalDebtModel {
+
+  private Model model;
+
+  public TechnicalDebtModel(Model model) {
+    this.model = model;
+  }
+
+  public void mergeWith(Model with, ValidationMessages messages, RuleCache ruleCache) {
+    for (Characteristic characteristic : with.getCharacteristics()) {
+      if (isRequirement(characteristic)) {
+        mergeRequirement(model, characteristic, messages, ruleCache);
+      } else {
+        mergeCharacteristic(model, characteristic, messages);
+      }
+    }
+  }
+
+  private Characteristic mergeCharacteristic(Model target, Characteristic characteristic, ValidationMessages messages) {
+    Characteristic targetCharacteristic = target.getCharacteristicByKey(characteristic.getKey());
+    if (targetCharacteristic == null) {
+      targetCharacteristic = target.addCharacteristic(clone(characteristic));
+      if (!characteristic.getParents().isEmpty()) {
+        Characteristic parentTargetCharacteristic = mergeCharacteristic(target, characteristic.getParents().get(0), messages);
+        parentTargetCharacteristic.addChild(targetCharacteristic);
+      }
+    }
+    return targetCharacteristic;
+  }
+
+  private void mergeRequirement(Model target, Characteristic requirement, ValidationMessages messages,
+                                RuleCache ruleCache) {
+    Characteristic targetRequirement = target.getCharacteristicByRule(requirement.getRule());
+    if (targetRequirement == null && !requirement.getParents().isEmpty()) {
+      Rule rule = ruleCache.getRule(requirement.getRule().getRepositoryKey(), requirement.getRule().getKey());
+      if (rule == null) {
+        messages.addWarningText("The rule " + requirement.getRule() + " does not exist.");
+
+      } else {
+        Characteristic parent = mergeCharacteristic(target, requirement.getParents().get(0), messages);
+        requirement = target.addCharacteristic(clone(requirement));
+        requirement.setRule(rule);
+        parent.addChild(requirement);
+      }
+    }
+  }
+
+  private boolean isRequirement(Characteristic characteristic) {
+    return characteristic.hasRule();
+  }
+
+  private Characteristic clone(Characteristic c) {
+    Characteristic clone = Characteristic.create();
+    clone.setRule(c.getRule());
+    clone.setDescription(c.getDescription());
+    clone.setKey(c.getKey());
+    clone.setName(c.getName(), false);
+    for (CharacteristicProperty property : c.getProperties()) {
+      clone.setProperty(property.getKey(), property.getTextValue()).setValue(property.getValue());
+    }
+    return clone;
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModelDefinition.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModelDefinition.java
new file mode 100644 (file)
index 0000000..17da4ae
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.server.technicaldebt;
+
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.qualitymodel.ModelDefinition;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.utils.ValidationMessages;
+
+public final class TechnicalDebtModelDefinition extends ModelDefinition {
+
+  public static final String TECHNICAL_DEBT_MODEL = "TECHNICAL_DEBT";
+
+  private final TechnicalDebtManager technicalDebtManager;
+  private final RuleFinder ruleFinder;
+
+  public TechnicalDebtModelDefinition(TechnicalDebtManager technicalDebtManager, RuleFinder ruleFinder) {
+    super(TECHNICAL_DEBT_MODEL);
+    this.technicalDebtManager = technicalDebtManager;
+    this.ruleFinder = ruleFinder;
+  }
+
+  @Override
+  public Model createModel() {
+    RuleCache ruleCache = new RuleCache(ruleFinder);
+    return technicalDebtManager.createInitialModel(ValidationMessages.create(), ruleCache);
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModelFinder.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/TechnicalDebtModelFinder.java
new file mode 100644 (file)
index 0000000..f893f4c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Maps;
+import org.picocontainer.Startable;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * <p>This class is used to find which technical debt model XML files exist in the Sonar instance.</p>
+ * <p>
+ * Those XML files are provided by language plugins that embed their own contribution to the definition of the Technical debt model.
+ * They must be located in the classpath of those language plugins, more specifically in the "com.sonar.sqale" package, and
+ * they must be named "<pluginKey>-model.xml".
+ * </p>
+ */
+public class TechnicalDebtModelFinder implements ServerExtension, Startable {
+
+  public static final String DEFAULT_MODEL = "technical-debt";
+
+  private static final String XML_FILE_SUFFIX = "-model.xml";
+  private static final String XML_FILE_PREFIX = "com/sonar/sqale/";
+
+  private String xmlFilePrefix;
+
+  private PluginRepository pluginRepository;
+  private Map<String, ClassLoader> contributingPluginKeyToClassLoader;
+
+  /**
+   *
+   * @param pluginRepository
+   */
+  public TechnicalDebtModelFinder(PluginRepository pluginRepository) {
+    this.pluginRepository = pluginRepository;
+    this.xmlFilePrefix = XML_FILE_PREFIX;
+  }
+
+  @VisibleForTesting
+  TechnicalDebtModelFinder(PluginRepository pluginRepository, String xmlFilePrefix) {
+    this.pluginRepository = pluginRepository;
+    this.xmlFilePrefix = xmlFilePrefix;
+  }
+
+  @VisibleForTesting
+  TechnicalDebtModelFinder(Map<String, ClassLoader> contributingPluginKeyToClassLoader, String xmlFilePrefix) {
+    this.contributingPluginKeyToClassLoader = contributingPluginKeyToClassLoader;
+    this.xmlFilePrefix = xmlFilePrefix;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void start() {
+    findAvailableXMLFiles();
+  }
+
+  protected void findAvailableXMLFiles() {
+    if (contributingPluginKeyToClassLoader == null) {
+      contributingPluginKeyToClassLoader = Maps.newTreeMap();
+      for (PluginMetadata metadata : pluginRepository.getMetadata()) {
+        String pluginKey = metadata.getKey();
+        ClassLoader classLoader = pluginRepository.getPlugin(pluginKey).getClass().getClassLoader();
+        if (classLoader.getResource(getXMLFilePathForPlugin(pluginKey)) != null) {
+          contributingPluginKeyToClassLoader.put(pluginKey, classLoader);
+        }
+      }
+    }
+    contributingPluginKeyToClassLoader = Collections.unmodifiableMap(contributingPluginKeyToClassLoader);
+  }
+
+  protected String getXMLFilePathForPlugin(String pluginKey) {
+    return xmlFilePrefix + pluginKey + XML_FILE_SUFFIX;
+  }
+
+  /**
+   * Returns the list of plugins that can contribute to the SQALE model (without the default model provided by this plugin).
+   *
+   * @return the list of plugin keys
+   */
+  public Collection<String> getContributingPluginList() {
+    Collection<String> contributingPlugins = newArrayList(contributingPluginKeyToClassLoader.keySet());
+    contributingPlugins.remove(DEFAULT_MODEL);
+    return contributingPlugins;
+  }
+
+  /**
+   * Creates a new {@link java.io.Reader} for the XML file that contains the model contributed by the given plugin.
+   * 
+   * @param pluginKey the key of the plugin that contributes the XML file
+   * @return the reader, that must be closed once its use is finished.
+   */
+  public Reader createReaderForXMLFile(String pluginKey) {
+    ClassLoader classLoader = contributingPluginKeyToClassLoader.get(pluginKey);
+    String xmlFilePath = getXMLFilePathForPlugin(pluginKey);
+    return new InputStreamReader(classLoader.getResourceAsStream(xmlFilePath));
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void stop() {
+    // Nothing to do
+  }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/XMLConstants.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/XMLConstants.java
new file mode 100644 (file)
index 0000000..6228da4
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.server.technicaldebt;
+
+public final class XMLConstants {
+
+  private XMLConstants(){
+    // Utility class
+  }
+
+  public static final String CHARACTERISTIC = "chc";
+  public static final String CHARACTERISTIC_KEY = "key";
+  public static final String CHARACTERISTIC_NAME = "name";
+  public static final String CHARACTERISTIC_DESCRIPTION = "desc";
+  public static final String PROPERTY = "prop";
+  public static final String PROPERTY_KEY = "key";
+  public static final String PROPERTY_VALUE = "val";
+  public static final String PROPERTY_TEXT_VALUE = "txt";
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/XMLImporter.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/XMLImporter.java
new file mode 100644 (file)
index 0000000..95e81e2
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.NumberUtils;
+import org.codehaus.stax2.XMLInputFactory2;
+import org.codehaus.staxmate.SMInputFactory;
+import org.codehaus.staxmate.in.SMHierarchicCursor;
+import org.codehaus.staxmate.in.SMInputCursor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.utils.ValidationMessages;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.List;
+
+public class XMLImporter implements ServerExtension {
+
+  private static final Logger LOG = LoggerFactory.getLogger(XMLImporter.class);
+
+  public Model importXML(String xml, ValidationMessages messages, RuleCache ruleCache) {
+    return importXML(new StringReader(xml), messages, ruleCache);
+  }
+
+  public Model importXML(Reader xml, ValidationMessages messages, RuleCache repositoryCache) {
+    Model sqale = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    try {
+      SMInputFactory inputFactory = initStax();
+      SMHierarchicCursor cursor = inputFactory.rootElementCursor(xml);
+
+      // advance to <sqale>
+      cursor.advance();
+      SMInputCursor chcCursor = cursor.childElementCursor(XMLConstants.CHARACTERISTIC);
+
+      while (chcCursor.getNext() != null) {
+        processCharacteristic(sqale, chcCursor, messages, repositoryCache);
+      }
+
+      cursor.getStreamReader().closeCompletely();
+
+    } catch (XMLStreamException e) {
+      LOG.error("XML is not valid", e);
+      messages.addErrorText("XML is not valid: " + e.getMessage());
+    }
+    return sqale;
+  }
+
+  private SMInputFactory initStax() {
+    XMLInputFactory xmlFactory = XMLInputFactory2.newInstance();
+    xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
+    xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
+    xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+    xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
+    return new SMInputFactory(xmlFactory);
+  }
+
+  private Characteristic processCharacteristic(Model sqale, SMInputCursor chcCursor, ValidationMessages messages,
+                                               RuleCache ruleCache) throws XMLStreamException {
+    Characteristic characteristic = Characteristic.create();
+    SMInputCursor cursor = chcCursor.childElementCursor();
+
+    String ruleRepositoryKey = null, ruleKey = null;
+    List<Characteristic> children = Lists.newArrayList();
+    while (cursor.getNext() != null) {
+      String node = cursor.getLocalName();
+      if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC_KEY)) {
+        characteristic.setKey(cursor.collectDescendantText().trim());
+
+      } else if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC_NAME)) {
+        characteristic.setName(cursor.collectDescendantText().trim(), false);
+
+      } else if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC_DESCRIPTION)) {
+        characteristic.setDescription(cursor.collectDescendantText().trim());
+
+      } else if (StringUtils.equals(node, XMLConstants.PROPERTY)) {
+        processProperty(characteristic, cursor, messages);
+
+      } else if (StringUtils.equals(node, XMLConstants.CHARACTERISTIC)) {
+        children.add(processCharacteristic(sqale, cursor, messages, ruleCache));
+
+      } else if (StringUtils.equals(node, "rule-repo")) {
+        ruleRepositoryKey = cursor.collectDescendantText().trim();
+
+      } else if (StringUtils.equals(node, "rule-key")) {
+        ruleKey = cursor.collectDescendantText().trim();
+      }
+    }
+    fillRule(characteristic, ruleRepositoryKey, ruleKey, messages, ruleCache);
+
+    if (StringUtils.isNotBlank(characteristic.getKey()) || characteristic.getRule() != null) {
+      addCharacteristicToModel(sqale, characteristic, children);
+      return characteristic;
+    }
+    return null;
+  }
+
+  private void fillRule(Characteristic characteristic, String ruleRepositoryKey, String ruleKey, ValidationMessages messages,
+                        RuleCache ruleCache) {
+    if (StringUtils.isNotBlank(ruleRepositoryKey) && StringUtils.isNotBlank(ruleKey)) {
+      Rule rule = ruleCache.getRule(ruleRepositoryKey, ruleKey);
+      if (rule != null) {
+        characteristic.setRule(rule);
+      } else {
+        messages.addWarningText("Rule not found: [repository=" + ruleRepositoryKey + ", key=" + ruleKey + "]");
+      }
+    }
+  }
+
+  private void addCharacteristicToModel(Model sqale, Characteristic characteristic, List<Characteristic> children) {
+    sqale.addCharacteristic(characteristic);
+    for (Characteristic child : children) {
+      if (child != null) {
+        sqale.addCharacteristic(child);
+        characteristic.addChild(child);
+      }
+    }
+  }
+
+  private void processProperty(Characteristic characteristic, SMInputCursor cursor, ValidationMessages messages) throws XMLStreamException {
+    SMInputCursor c = cursor.childElementCursor();
+    String key = null;
+    Double value = null;
+    String textValue = null;
+    while (c.getNext() != null) {
+      String node = c.getLocalName();
+      if (StringUtils.equals(node, XMLConstants.PROPERTY_KEY)) {
+        key = c.collectDescendantText().trim();
+
+      } else if (StringUtils.equals(node, XMLConstants.PROPERTY_VALUE)) {
+        String s = c.collectDescendantText().trim();
+        try {
+          value = NumberUtils.createDouble(s);
+        } catch (NumberFormatException ex) {
+          String message = String.format("Cannot import value '%s' for field %s - Expected a numeric value instead", s, key);
+          LOG.error(message, ex);
+          messages.addErrorText(message);
+        }
+      } else if (StringUtils.equals(node, XMLConstants.PROPERTY_TEXT_VALUE)) {
+        textValue = c.collectDescendantText().trim();
+      }
+    }
+    if (StringUtils.isNotBlank(key)) {
+      characteristic.setProperty(key, textValue).setValue(value);
+    }
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/package-info.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/package-info.java
new file mode 100644 (file)
index 0000000..1b1dff8
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.technicaldebt;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/RuleCacheTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/RuleCacheTest.java
new file mode 100644 (file)
index 0000000..9d9a09c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RuleQuery;
+
+import java.util.Collections;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+public class RuleCacheTest {
+
+  @Test
+  public void should_lazy_load_rules_on_first_call() throws Exception {
+
+    RuleFinder ruleFinder = mock(RuleFinder.class);
+    when(ruleFinder.findAll(any(RuleQuery.class))).thenReturn(Collections.EMPTY_LIST);
+
+    RuleCache ruleCache = new RuleCache(ruleFinder);
+    ruleCache.getRule("", "");
+    ruleCache.getRule("", "");
+
+    verify(ruleFinder, times(1)).findAll(any(RuleQuery.class));
+  }
+
+  @Test
+  public void should_return_matching_rule() throws Exception {
+
+    Rule rule1 = Rule.create("repo1", "rule1");
+    Rule rule2 = Rule.create("repo2", "rule2");
+
+    RuleFinder ruleFinder = mock(RuleFinder.class);
+    when(ruleFinder.findAll(any(RuleQuery.class))).thenReturn(Lists.newArrayList(rule1, rule2));
+
+    RuleCache ruleCache = new RuleCache(ruleFinder);
+    Rule actualRule1 = ruleCache.getRule("repo1", "rule1");
+    Rule actualRule2 = ruleCache.getRule("repo2", "rule2");
+
+    assertThat(actualRule1).isEqualTo(rule1);
+    assertThat(actualRule2).isEqualTo(rule2);
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtManagerTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtManagerTest.java
new file mode 100644 (file)
index 0000000..2472c1d
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.io.Resources;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.core.qualitymodel.DefaultModelFinder;
+import org.sonar.core.rule.DefaultRuleFinder;
+import org.sonar.jpa.test.AbstractDbUnitTestCase;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class TechnicalDebtManagerTest extends AbstractDbUnitTestCase {
+
+  private TechnicalDebtManager manager;
+  private TechnicalDebtModelFinder TechnicalDebtModelFinder;
+
+  @Before
+  public void init() throws Exception {
+    TechnicalDebtModelFinder = mock(TechnicalDebtModelFinder.class);
+    when(TechnicalDebtModelFinder.getContributingPluginList()).thenReturn(ImmutableList.of("java", "technical-debt"));
+    when(TechnicalDebtModelFinder.createReaderForXMLFile("java")).thenReturn(
+      new FileReader(Resources.getResource(TechnicalDebtManagerTest.class, "TechnicalDebtManagerTest/fake-java-model.xml").getPath()));
+    // Mock default sqale model
+    when(TechnicalDebtModelFinder.createReaderForXMLFile("technical-debt")).thenReturn(
+      new FileReader(Resources.getResource(TechnicalDebtManagerTest.class, "TechnicalDebtManagerTest/fake-default-model.xml").getPath()));
+
+    manager = new TechnicalDebtManager(getSessionFactory(), new DefaultModelFinder(getSessionFactory()), TechnicalDebtModelFinder, new XMLImporter());
+  }
+
+  @Test
+  public void reset_model() {
+    setupData("reset_model");
+
+    Model model = manager.resetModel(ValidationMessages.create(), defaultRuleCache());
+    assertThat(model.getCharacteristics().size()).isGreaterThan(3);
+    assertThat(model.getCharacteristics().size()).isGreaterThan(model.getRootCharacteristics().size());
+    for (Characteristic portabilityCharacteristic : model.getCharacteristicByKey("PORTABILITY").getChildren()) {
+      assertThat(portabilityCharacteristic.getName()).contains("portability");
+      Characteristic requirement = portabilityCharacteristic.getChildren().get(0);
+      assertThat(requirement).isNotNull();
+      Rule rule = requirement.getRule();
+      assertThat(rule).isNotNull();
+      assertThat(rule.getName()).isEqualTo("Regular exp");
+    }
+    assertThat(model.getCharacteristicByKey("testability")).isNull();
+    assertThat(model.getCharacteristicByKey("unit_testability")).isNull();
+  }
+
+  @Test
+  public void provided_plugin_should_not_override_default_model_when_resetting_model() throws FileNotFoundException {
+    setupData("reset_model");
+
+    Model model = manager.resetModel(ValidationMessages.create(), defaultRuleCache());
+    // Default model values
+    assertThat(model.getCharacteristicByKey("PORTABILITY").getName()).isEqualTo("Portability");
+    assertThat(model.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").getName()).isEqualTo("Compiler related portability");
+    assertThat(model.getCharacteristicByKey("HARDWARE_RELATED_PORTABILITY").getName()).isEqualTo("Hardware related portability");
+    assertThat(model.getCharacteristicByKey("MAINTAINABILITY").getName()).isEqualTo("Maintainability");
+
+    // Plugin has renamed it the value stay as defined by default model
+    assertThat(model.getCharacteristicByKey("READABILITY").getName()).isEqualTo("Readability");
+
+    // Characteristic provided only by the plugin
+    assertThat(model.getCharacteristicByKey("UNDERSTANDABILITY").getName()).isEqualTo("Understandability related maintainability");
+  }
+
+  @Test
+  public void not_fail_if_unknown_rule_when_resetting_model() {
+    setupData("reset_model");
+
+    RuleFinder ruleFinder = mock(RuleFinder.class);
+    when(ruleFinder.findByKey(anyString(), anyString())).thenReturn(null);
+
+    manager = new TechnicalDebtManager(getSessionFactory(), new DefaultModelFinder(getSessionFactory()),
+      TechnicalDebtModelFinder, new XMLImporter());
+
+    Model model = manager.resetModel(ValidationMessages.create(), new RuleCache(ruleFinder));
+    assertThat(model.getCharacteristics().size()).isGreaterThanOrEqualTo(3);
+    assertThat(model.getCharacteristics().size()).isGreaterThan(model.getRootCharacteristics().size());
+    List<Characteristic> hardwareControls = model.getCharacteristicByKey("HARDWARE_RELATED_PORTABILITY").getChildren();
+    assertThat(hardwareControls.isEmpty()).isTrue();
+  }
+
+  @Test
+  public void create_initial_model() {
+    Model model = manager.createInitialModel(ValidationMessages.create(), defaultRuleCache());
+
+    // Default model values
+    assertThat(model.getCharacteristicByKey("PORTABILITY").getName()).isEqualTo("Portability");
+    assertThat(model.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").getName()).isEqualTo("Compiler related portability");
+    assertThat(model.getCharacteristicByKey("HARDWARE_RELATED_PORTABILITY").getName()).isEqualTo("Hardware related portability");
+    assertThat(model.getCharacteristicByKey("MAINTAINABILITY").getName()).isEqualTo("Maintainability");
+
+    // Plugin has renamed it the value stay as defined by default model
+    assertThat(model.getCharacteristicByKey("READABILITY").getName()).isEqualTo("Readability");
+
+    // Characteristic provided only by the plugin
+    assertThat(model.getCharacteristicByKey("UNDERSTANDABILITY").getName()).isEqualTo("Understandability related maintainability");
+  }
+
+  @Test
+  public void persist_merge() {
+    setupData("persist_merge");
+
+    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
+    Characteristic ramEfficiency = with.createCharacteristicByKey("ram-efficiency", "RAM Efficiency");
+    efficiency.addChild(ramEfficiency);
+    ramEfficiency.addChild(with.createCharacteristicByRule(newRegexpRule()));
+
+    manager.merge(with, ValidationMessages.create(), defaultRuleCache());
+
+    checkTables("persist_merge", "quality_models", "characteristics", "characteristic_edges");
+  }
+
+  @Test
+  public void persist_merge_with_plugin_files() throws Exception {
+    setupData("persist_merge");
+
+    manager.merge(Lists.newArrayList("java"), ValidationMessages.create(), defaultRuleCache());
+
+    Model model = (new DefaultModelFinder(getSessionFactory())).findByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    assertThat(model.getCharacteristics()).contains(Characteristic.createByKey("PORTABILITY", "Portability"));
+  }
+
+  @Test
+  public void persist_restore() {
+    setupData("persist_restore");
+
+    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
+    Characteristic ramEfficiency = with.createCharacteristicByKey("ram-efficiency", "RAM Efficiency");
+    efficiency.addChild(ramEfficiency);
+    ramEfficiency.addChild(with.createCharacteristicByRule(newRegexpRule()));
+
+    manager.restore(with, ValidationMessages.create(), defaultRuleCache());
+
+    checkTables("persist_restore", "quality_models", "characteristics", "characteristic_edges");
+  }
+
+  @Test
+  public void warn_when_restoring_unknown_rule() {
+    setupData("warn_when_restoring_unknown_rule");
+
+    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
+    efficiency.addChild(with.createCharacteristicByRule(newRegexpRule()));
+
+    ValidationMessages messages = ValidationMessages.create();
+    manager.restore(with, messages, defaultRuleCache());
+
+    checkTables("warn_when_restoring_unknown_rule", "quality_models", "characteristics", "characteristic_edges");
+    assertThat(messages.getWarnings()).hasSize(1);
+    assertThat(messages.getWarnings().get(0)).contains("regexp");
+  }
+
+  private RuleCache defaultRuleCache() {
+    return new RuleCache(new DefaultRuleFinder(getSessionFactory()));
+  }
+
+  private Rule newRegexpRule() {
+    return Rule.create("checkstyle", "regexp", "Regular expression");
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelDefinitionTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelDefinitionTest.java
new file mode 100644 (file)
index 0000000..5864323
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.server.technicaldebt;
+
+import org.junit.Test;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.utils.ValidationMessages;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+public class TechnicalDebtModelDefinitionTest {
+
+  @Test
+  public void shouldCreateModel() throws Exception {
+    TechnicalDebtManager technicalDebtManager = mock(TechnicalDebtManager.class);
+    RuleFinder ruleFinder = mock(RuleFinder.class);
+    TechnicalDebtModelDefinition sqaleDefinition = new TechnicalDebtModelDefinition(technicalDebtManager, ruleFinder);
+
+    sqaleDefinition.createModel();
+
+    verify(technicalDebtManager, times(1)).createInitialModel(any(ValidationMessages.class), any(RuleCache.class));
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest.java
new file mode 100644 (file)
index 0000000..83cecc0
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.io.Resources;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.sonar.api.SonarPlugin;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class TechnicalDebtModelFinderTest {
+
+  private static final String TEST_XML_PREFIX_PATH = "org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest/";
+
+  private TechnicalDebtModelFinder modelFinder;
+
+  @Test
+  public void test_component_initialization() throws Exception {
+    // we do have the "csharp-model.xml" file in src/test/resources
+    PluginMetadata csharpPluginMetadata = mock(PluginMetadata.class);
+    when(csharpPluginMetadata.getKey()).thenReturn("csharp");
+
+    // but we don' have the "php-model.xml" one
+    PluginMetadata phpPluginMetadata = mock(PluginMetadata.class);
+    when(phpPluginMetadata.getKey()).thenReturn("php");
+
+    PluginRepository repository = mock(PluginRepository.class);
+    when(repository.getMetadata()).thenReturn(Lists.newArrayList(csharpPluginMetadata, phpPluginMetadata));
+    FakePlugin fakePlugin = new FakePlugin();
+    when(repository.getPlugin(anyString())).thenReturn(fakePlugin);
+    modelFinder = new TechnicalDebtModelFinder(repository, TEST_XML_PREFIX_PATH);
+
+    // when
+    modelFinder.start();
+
+    // assert
+    Collection<String> contributingPluginList = modelFinder.getContributingPluginList();
+    assertThat(contributingPluginList.size()).isEqualTo(1);
+    assertThat(contributingPluginList).containsOnly("csharp");
+  }
+
+  @Test
+  public void contributing_plugin_list() throws Exception {
+    initModel();
+    Collection<String> contributingPluginList = modelFinder.getContributingPluginList();
+    assertThat(contributingPluginList.size()).isEqualTo(2);
+    assertThat(contributingPluginList).contains("csharp", "java");
+  }
+
+  @Test
+  public void get_content_for_xml_file() throws Exception {
+    initModel();
+    Reader xmlFileReader = null;
+    try {
+      xmlFileReader = modelFinder.createReaderForXMLFile("csharp");
+      assertNotNull(xmlFileReader);
+      List<String> lines = IOUtils.readLines(xmlFileReader);
+      assertThat(lines.size()).isEqualTo(25);
+      assertThat(lines.get(0)).isEqualTo("<sqale>");
+    } catch (Exception e) {
+      fail("Should be able to read the XML file.");
+    } finally {
+      IOUtils.closeQuietly(xmlFileReader);
+    }
+  }
+
+  @Test
+  public void return_xml_file_path_for_plugin() throws Exception {
+    initModel();
+    assertThat(modelFinder.getXMLFilePathForPlugin("foo")).isEqualTo(TEST_XML_PREFIX_PATH + "foo-model.xml");
+  }
+
+  private void initModel() throws MalformedURLException {
+    Map<String, ClassLoader> contributingPluginKeyToClassLoader = Maps.newHashMap();
+    contributingPluginKeyToClassLoader.put("csharp", newClassLoader());
+    contributingPluginKeyToClassLoader.put("java", newClassLoader());
+    modelFinder = new TechnicalDebtModelFinder(contributingPluginKeyToClassLoader, TEST_XML_PREFIX_PATH);
+  }
+
+  private ClassLoader newClassLoader() throws MalformedURLException {
+    ClassLoader loader = mock(ClassLoader.class);
+    when(loader.getResourceAsStream(anyString())).thenAnswer(new Answer<InputStream>() {
+      public InputStream answer(InvocationOnMock invocation) throws Throwable {
+        return new FileInputStream(Resources.getResource((String) invocation.getArguments()[0]).getPath());
+      }
+    });
+    return loader;
+  }
+
+  class FakePlugin extends SonarPlugin {
+    public List getExtensions() {
+      return null;
+    }
+  }
+
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtModelTest.java
new file mode 100644 (file)
index 0000000..747871a
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RuleQuery;
+import org.sonar.api.utils.ValidationMessages;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class TechnicalDebtModelTest {
+
+  private Model model;
+  private TechnicalDebtModel technicalDebtModel;
+
+  @Before
+  public void setUpModel() {
+    model = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    technicalDebtModel = new TechnicalDebtModel(model);
+  }
+
+  @Test
+  public void shouldMergeWithEmptyModel() {
+    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
+    efficiency.addChild(with.createCharacteristicByKey("ram-efficiency", "RAM Efficiency"));
+    with.createCharacteristicByKey("usability", "Usability");
+
+    ValidationMessages messages = ValidationMessages.create();
+
+    technicalDebtModel.mergeWith(with, messages, mockRuleCache());
+
+    assertThat(model.getCharacteristics()).hasSize(3);
+    assertThat(model.getRootCharacteristics()).hasSize(2);
+    assertThat(model.getCharacteristicByKey("ram-efficiency").getDepth()).isEqualTo(Characteristic.ROOT_DEPTH + 1);
+    assertThat(messages.getErrors()).isEmpty();
+  }
+
+  @Test
+  public void shouldNotUpdateExistingCharacteristics() {
+    model.createCharacteristicByKey("efficiency", "Efficiency");
+
+    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    with.createCharacteristicByKey("efficiency", "New efficiency");
+
+    technicalDebtModel.mergeWith(with, ValidationMessages.create(), mockRuleCache());
+
+    assertThat(model.getCharacteristics()).hasSize(1);
+    assertThat(model.getRootCharacteristics()).hasSize(1);
+    assertThat(model.getCharacteristicByKey("efficiency").getName()).isEqualTo("Efficiency");
+  }
+
+  @Test
+  public void shouldWarnOnMissingRule() {
+    Model with = Model.createByName(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+    Characteristic efficiency = with.createCharacteristicByKey("efficiency", "Efficiency");
+    Rule fooRule = Rule.create("foo", "bar", "Bar");
+    Characteristic requirement = with.createCharacteristicByRule(fooRule);
+    efficiency.addChild(requirement);
+
+    ValidationMessages messages = ValidationMessages.create();
+
+    technicalDebtModel.mergeWith(with, messages, mockRuleCache());
+
+    assertThat(model.getCharacteristics()).hasSize(1);
+    assertThat(model.getCharacteristicByKey("efficiency").getName()).isEqualTo("Efficiency");
+    assertThat(model.getCharacteristicByRule(fooRule)).isNull();
+    assertThat(messages.getWarnings()).hasSize(1);
+    assertThat(messages.getWarnings().get(0)).contains("foo"); // warning: the rule foo does not exist
+  }
+
+  private RuleCache mockRuleCache() {
+    RuleFinder ruleFinder = mock(RuleFinder.class);
+    when(ruleFinder.findAll(any(RuleQuery.class))).thenReturn(Lists.newArrayList(newRegexpRule()));
+    return new RuleCache(ruleFinder);
+  }
+
+  private Rule newRegexpRule() {
+    return Rule.create("checkstyle", "regexp", "Regular expression");
+  }
+}
+
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/XMLImporterTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/XMLImporterTest.java
new file mode 100644 (file)
index 0000000..75ac440
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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.server.technicaldebt;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.Lists;
+import com.google.common.io.Resources;
+import org.junit.Test;
+import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RuleQuery;
+import org.sonar.api.utils.ValidationMessages;
+
+import java.io.IOException;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class XMLImporterTest {
+
+  @Test
+  public void shouldImportXML() {
+    RuleCache ruleCache = mockRuleCache();
+
+    String xml = getFileContent("shouldImportXML.xml");
+
+    ValidationMessages messages = ValidationMessages.create();
+    Model sqale = new XMLImporter().importXML(xml, messages, ruleCache);
+
+    checkXmlCorrectlyImported(sqale, messages);
+  }
+
+  @Test
+  public void shouldBadlyFormattedImportXML() {
+    RuleCache ruleCache = mockRuleCache();
+    String xml = getFileContent("shouldImportXML_badly-formatted.xml");
+
+    ValidationMessages messages = ValidationMessages.create();
+    Model sqale = new XMLImporter().importXML(xml, messages, ruleCache);
+
+    checkXmlCorrectlyImported(sqale, messages);
+  }
+
+  @Test
+  public void shouldLogWarningIfRuleNotFound() {
+    RuleCache ruleCache = mockRuleCache();
+    String xml = getFileContent("shouldLogWarningIfRuleNotFound.xml");
+    ValidationMessages messages = ValidationMessages.create();
+
+    Model sqale = new XMLImporter().importXML(xml, messages, ruleCache);
+
+    assertThat(messages.getWarnings()).hasSize(1);
+
+    // characteristics
+    assertThat(sqale.getRootCharacteristics()).hasSize(1);
+    Characteristic efficiency = sqale.getCharacteristicByKey("EFFICIENCY");
+    assertThat(efficiency.getChildren()).isEmpty();
+    assertThat(messages.getWarnings().get(0)).contains("findbugs");
+  }
+
+  @Test
+  public void shouldNotifyOnUnexpectedValueTypeInXml() throws Exception {
+
+    RuleCache ruleCache = mockRuleCache();
+
+    String xml = getFileContent("shouldRejectXML_with_invalid_value.xml");
+    ValidationMessages messages = ValidationMessages.create();
+
+    new XMLImporter().importXML(xml, messages, ruleCache);
+
+    assertThat(messages.getErrors()).hasSize(1);
+    assertThat(messages.getErrors().get(0)).isEqualTo("Cannot import value 'abc' for field factor - Expected a numeric value instead");
+  }
+
+  private RuleCache mockRuleCache() {
+    RuleFinder finder = mock(RuleFinder.class);
+    when(finder.findAll(any(RuleQuery.class))).thenReturn(Lists.newArrayList(Rule.create("checkstyle", "Regexp", "Regular expression")));
+    return new RuleCache(finder);
+  }
+
+  private void checkXmlCorrectlyImported(Model sqale, ValidationMessages messages) {
+
+    assertThat(messages.getErrors()).isEmpty();
+    assertThat(sqale.getName()).isEqualTo(TechnicalDebtModelDefinition.TECHNICAL_DEBT_MODEL);
+
+    // characteristics
+    assertThat(sqale.getRootCharacteristics()).hasSize(2);
+    assertThat(sqale.getCharacteristicByKey("USABILITY").getDescription()).isEqualTo("Estimate usability");
+    Characteristic efficiency = sqale.getCharacteristicByKey("EFFICIENCY");
+    assertThat(efficiency.getName()).isEqualTo("Efficiency");
+
+    // sub-characteristics
+    assertThat(efficiency.getChildren()).hasSize(1);
+    Characteristic requirement = efficiency.getChildren().get(0);
+    assertThat(requirement.getRule().getRepositoryKey()).isEqualTo("checkstyle");
+    assertThat(requirement.getRule().getKey()).isEqualTo("Regexp");
+    assertThat(requirement.getPropertyTextValue("function", null)).isEqualTo("linear");
+    assertThat(requirement.getPropertyValue("factor", null)).isEqualTo(3.2);
+  }
+
+  private String getFileContent(String file) {
+    try {
+      return Resources.toString(Resources.getResource(XMLImporterTest.class, "XMLImporterTest/" + file), Charsets.UTF_8);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+}
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/fake-default-model.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/fake-default-model.xml
new file mode 100644 (file)
index 0000000..839e019
--- /dev/null
@@ -0,0 +1,24 @@
+<sqale>
+  <chc>
+    <key>PORTABILITY</key>
+    <name>Portability</name>
+    <chc>
+      <key>COMPILER_RELATED_PORTABILITY</key>
+      <name>Compiler related portability</name>
+    </chc>
+    <chc>
+      <key>HARDWARE_RELATED_PORTABILITY</key>
+      <name>Hardware related portability</name>
+    </chc>
+  </chc>
+  <chc>
+    <chc>
+      <key>MAINTAINABILITY</key>
+      <name>Maintainability</name>
+      <chc>
+        <key>READABILITY</key>
+        <name>Readability</name>
+      </chc>
+    </chc>
+  </chc>
+</sqale>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/fake-java-model.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/fake-java-model.xml
new file mode 100644 (file)
index 0000000..6d61008
--- /dev/null
@@ -0,0 +1,78 @@
+<sqale>
+  <chc>
+    <key>PORTABILITY</key>
+    <name>Portability</name>
+    <chc>
+      <key>COMPILER_RELATED_PORTABILITY</key>
+      <name>Compiler related portability</name>
+      <chc>
+        <rule-repo>checkstyle</rule-repo>
+        <rule-key>import</rule-key>
+        <prop>
+          <key>remediationFactor</key>
+          <val>30.0</val>
+          <txt>mn</txt>
+        </prop>
+        <prop>
+          <key>remediationFunction</key>
+          <txt>linear</txt>
+        </prop>
+      </chc>
+    </chc>
+    <chc>
+      <key>HARDWARE_RELATED_PORTABILITY</key>
+      <name>Hardware related portability</name>
+      <chc>
+        <rule-repo>checkstyle</rule-repo>
+        <rule-key>export</rule-key>
+        <prop>
+          <key>remediationFactor</key>
+          <val>1.0</val>
+          <txt>h</txt>
+        </prop>
+        <prop>
+          <key>remediationFunction</key>
+          <txt>linear</txt>
+        </prop>
+      </chc>
+    </chc>
+  </chc>
+  <chc>
+    <key>MAINTAINABILITY</key>
+    <name>Maintainability</name>
+    <chc>
+      <key>READABILITY</key>
+      <name>Readability related maintainability</name>
+      <chc>
+        <rule-repo>checkstyle</rule-repo>
+        <rule-key>ConstantNameCheck</rule-key>
+        <prop>
+          <key>remediationFactor</key>
+          <val>10.0</val>
+          <txt>mn</txt>
+        </prop>
+        <prop>
+          <key>remediationFunction</key>
+          <txt>linear</txt>
+        </prop>
+      </chc>
+    </chc>
+    <chc>
+      <key>UNDERSTANDABILITY</key>
+      <name>Understandability related maintainability</name>
+      <chc>
+        <rule-repo>checkstyle</rule-repo>
+        <rule-key>JavadocMethodCheck</rule-key>
+        <prop>
+          <key>remediationFactor</key>
+          <val>30.0</val>
+          <txt>mn</txt>
+        </prop>
+        <prop>
+          <key>remediationFunction</key>
+          <txt>linear</txt>
+        </prop>
+      </chc>
+    </chc>
+  </chc>
+</sqale>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_merge-result.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_merge-result.xml
new file mode 100644 (file)
index 0000000..3f84f54
--- /dev/null
@@ -0,0 +1,19 @@
+<dataset>
+  <!-- existing models -->
+  <quality_models id="1" name="TECHNICAL_DEBT" />
+  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
+
+  <characteristics id="3" kee="efficiency" name="Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="3" depth="1" description="[null]" enabled="true" />
+  <characteristics id="4" kee="ram-efficiency" name="RAM Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="4" depth="2" description="[null]" enabled="true" />
+  <characteristics id="5" kee="[null]" name="[null]" quality_model_id="1" rule_id="2" characteristic_order="5" depth="3" description="[null]" enabled="true" />
+
+  <characteristic_edges child_id="2" parent_id="1"/>
+  <characteristic_edges child_id="4" parent_id="3"/>
+  <characteristic_edges child_id="5" parent_id="4"/>
+  
+  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+
+  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_merge.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_merge.xml
new file mode 100644 (file)
index 0000000..4e2fb09
--- /dev/null
@@ -0,0 +1,12 @@
+<dataset>
+  <!-- existing models -->
+  <quality_models id="1" name="TECHNICAL_DEBT" />
+
+  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
+  <characteristic_edges child_id="2" parent_id="1"/>
+  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+
+  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_restore-result.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_restore-result.xml
new file mode 100644 (file)
index 0000000..612de62
--- /dev/null
@@ -0,0 +1,21 @@
+<dataset>
+  <quality_models id="1" name="TECHNICAL_DEBT" />
+
+  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="false" />
+  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="false" />
+  <characteristics id="3" kee="[null]" name="[null]" quality_model_id="1" rule_id="1" characteristic_order="3" depth="3" description="[null]" enabled="false" />
+
+  <characteristics id="4" kee="efficiency" name="Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="4" depth="1" description="[null]" enabled="true" />
+  <characteristics id="5" kee="ram-efficiency" name="RAM Efficiency" quality_model_id="1" rule_id="[null]" characteristic_order="5" depth="2" description="[null]" enabled="true" />
+  <characteristics id="6" kee="[null]" name="[null]" quality_model_id="1" rule_id="2" characteristic_order="6" depth="3" description="[null]" enabled="true" />
+
+  <characteristic_edges child_id="2" parent_id="1"/>
+  <characteristic_edges child_id="3" parent_id="2"/>
+  <characteristic_edges child_id="5" parent_id="4"/>
+  <characteristic_edges child_id="6" parent_id="5"/>
+
+  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+
+  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_restore.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/persist_restore.xml
new file mode 100644 (file)
index 0000000..1561bdb
--- /dev/null
@@ -0,0 +1,15 @@
+<dataset>
+  <quality_models id="1" name="TECHNICAL_DEBT" />
+
+  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
+  <characteristics id="3" kee="[null]" name="[null]" quality_model_id="1" rule_id="1" characteristic_order="3" depth="3" description="[null]" enabled="true" />
+
+  <characteristic_edges child_id="2" parent_id="1"/>
+  <characteristic_edges child_id="3" parent_id="2"/>
+  
+  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+
+  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+  <rules id="2" plugin_rule_key="regexp" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/reset_model.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/reset_model.xml
new file mode 100644 (file)
index 0000000..4c82f6e
--- /dev/null
@@ -0,0 +1,12 @@
+<dataset>
+  <!-- existing models -->
+  <quality_models id="1" name="TECHNICAL_DEBT" />
+  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
+  <characteristic_edges child_id="2" parent_id="1"/>
+
+  <rules id="1" plugin_rule_key="import" plugin_config_key="import" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+  <rules id="2" plugin_rule_key="export" plugin_config_key="export" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+  <rules id="3" plugin_rule_key="ConstantNameCheck" plugin_config_key="ConstantNameCheck" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+  <rules id="4" plugin_rule_key="JavadocMethodCheck" plugin_config_key="JavadocMethodCheck" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule-result.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule-result.xml
new file mode 100644 (file)
index 0000000..7566ea2
--- /dev/null
@@ -0,0 +1,14 @@
+<dataset>
+  <quality_models id="1" name="foo" />
+  <quality_models id="2" name="TECHNICAL_DEBT" />
+
+  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
+
+  <characteristics id="3" kee="efficiency" name="Efficiency" quality_model_id="2" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+
+  <characteristic_edges child_id="2" parent_id="1"/>
+  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+
+  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtManagerTest/warn_when_restoring_unknown_rule.xml
new file mode 100644 (file)
index 0000000..619ad9e
--- /dev/null
@@ -0,0 +1,9 @@
+<dataset>
+  <quality_models id="1" name="foo" />
+  <characteristics id="1" kee="testability" name="Testability" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+  <characteristics id="2" kee="unit_testability" name="Unit tests" quality_model_id="1" rule_id="[null]" characteristic_order="2" depth="2" description="[null]" enabled="true" />
+  <characteristic_edges child_id="2" parent_id="1"/>
+  <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+
+  <rules id="1" plugin_rule_key="import" plugin_config_key="regexp" plugin_name="checkstyle" description="[null]" priority="3" status="READY" cardinality="SINGLE" parent_id="[null]" name="Regular exp"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest/csharp-model.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest/csharp-model.xml
new file mode 100644 (file)
index 0000000..e4569a2
--- /dev/null
@@ -0,0 +1,25 @@
+<sqale>
+  <chc>
+    <key>USABILITY</key>
+    <name>Usability</name>
+    <desc>Estimate usability</desc>
+  </chc>
+  <chc>
+    <key>EFFICIENCY</key>
+    <name>Efficiency</name>
+    <chc>
+      <rule-repo>gendarme</rule-repo>
+      <rule-key>EnsureLocalDisposalRule</rule-key>
+      <prop>
+        <key>remediationFactor</key>
+        <val>0.125</val>
+        <txt>d</txt>
+      </prop>
+      <prop>
+        <key>remediationFunction</key>
+        <txt>linear</txt>
+      </prop>
+    </chc>
+  </chc>
+
+</sqale>
\ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest/java-model.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/TechnicalDebtModelFinderTest/java-model.xml
new file mode 100644 (file)
index 0000000..0b37f56
--- /dev/null
@@ -0,0 +1,25 @@
+<sqale>
+  <chc>
+    <key>USABILITY</key>
+    <name>Usability</name>
+    <desc>Estimate usability</desc>
+  </chc>
+  <chc>
+    <key>EFFICIENCY</key>
+    <name>Efficiency</name>
+    <chc>
+      <rule-repo>squid-cobol</rule-repo>
+      <rule-key>CheckLoop</rule-key>
+      <prop>
+        <key>remediationFactor</key>
+        <val>0.125</val>
+        <txt>d</txt>
+      </prop>
+      <prop>
+        <key>remediationFunction</key>
+        <txt>linear</txt>
+      </prop>
+    </chc>
+  </chc>
+
+</sqale>
\ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldImportXML.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldImportXML.xml
new file mode 100644 (file)
index 0000000..e405189
--- /dev/null
@@ -0,0 +1,25 @@
+<sqale>
+  <chc>
+    <key>USABILITY</key>
+    <name>Usability</name>
+    <desc>Estimate usability</desc>
+  </chc>
+  <chc>
+    <key>EFFICIENCY</key>
+    <name>Efficiency</name>
+
+    <chc>
+      <rule-repo>checkstyle</rule-repo>
+      <rule-key>Regexp</rule-key>
+      <prop>
+        <key>factor</key>
+        <val>3.2</val>
+      </prop>
+      <prop>
+        <key>function</key>
+        <txt>linear</txt>
+      </prop>
+    </chc>
+  </chc>
+
+</sqale>
\ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldImportXML_badly-formatted.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldImportXML_badly-formatted.xml
new file mode 100644 (file)
index 0000000..373959f
--- /dev/null
@@ -0,0 +1,36 @@
+<sqale>
+  <chc>
+    <key>USABILITY
+    </key>
+    <name>Usability
+    </name>
+    <desc>Estimate usability
+    </desc>
+  </chc>
+  <chc>
+    <key>EFFICIENCY
+    </key>
+    <name>Efficiency
+    </name>
+
+    <chc>
+      <rule-repo>checkstyle
+      </rule-repo>
+      <rule-key>Regexp
+      </rule-key>
+      <prop>
+        <key>factor
+        </key>
+        <val>3.2
+        </val>
+      </prop>
+      <prop>
+        <key>function
+        </key>
+        <txt>linear
+        </txt>
+      </prop>
+    </chc>
+  </chc>
+
+</sqale>
\ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldLogWarningIfRuleNotFound.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldLogWarningIfRuleNotFound.xml
new file mode 100644 (file)
index 0000000..bd459f6
--- /dev/null
@@ -0,0 +1,12 @@
+<sqale>
+  <chc>
+    <key>EFFICIENCY</key>
+    <name>Efficiency</name>
+
+    <chc>
+      <rule-repo>findbugs</rule-repo>
+      <rule-key>Foo</rule-key>
+    </chc>
+  </chc>
+
+</sqale>
\ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldRejectXML_with_invalid_value.xml b/sonar-server/src/test/resources/org/sonar/server/technicaldebt/XMLImporterTest/shouldRejectXML_with_invalid_value.xml
new file mode 100644 (file)
index 0000000..638f00e
--- /dev/null
@@ -0,0 +1,25 @@
+<sqale>
+  <chc>
+    <key>USABILITY</key>
+    <name>Usability</name>
+    <desc>Estimate usability</desc>
+  </chc>
+  <chc>
+    <key>EFFICIENCY</key>
+    <name>Efficiency</name>
+
+    <chc>
+      <rule-repo>checkstyle</rule-repo>
+      <rule-key>Regexp</rule-key>
+      <prop>
+        <key>factor</key>
+        <val>abc</val>
+      </prop>
+      <prop>
+        <key>function</key>
+        <txt>linear</txt>
+      </prop>
+    </chc>
+  </chc>
+
+</sqale>