]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5121 Add restore from XMl actions
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 24 Mar 2014 12:28:04 +0000 (13:28 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 24 Mar 2014 12:28:13 +0000 (13:28 +0100)
19 files changed:
sonar-core/src/main/java/org/sonar/core/rule/RuleDao.java
sonar-core/src/main/java/org/sonar/core/rule/RuleMapper.java
sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java
sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java
sonar-core/src/main/resources/org/sonar/core/rule/RuleMapper.xml
sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml
sonar-core/src/test/java/org/sonar/core/rule/RuleDaoTest.java
sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java
sonar-core/src/test/resources/org/sonar/core/rule/RuleDaoTest/select_overriding_debt_rules.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_next_and_previous.xml [deleted file]
sonar-server/src/main/java/org/sonar/server/debt/DebtModelRestore.java
sonar-server/src/main/java/org/sonar/server/debt/DebtModelService.java
sonar-server/src/main/java/org/sonar/server/debt/DebtModelSynchronizer.java
sonar-server/src/main/java/org/sonar/server/debt/DebtRulesXMLImporter.java
sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinition.java
sonar-server/src/test/java/org/sonar/server/debt/DebtModelRestoreTest.java
sonar-server/src/test/java/org/sonar/server/debt/DebtModelServiceTest.java
sonar-server/src/test/java/org/sonar/server/debt/DebtRulesXMLImporterTest.java
sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionTest.java

index 74878a71ff6d723c2bfd3469383d8ade6f724f6a..b0ea59de07e301d4747e6ae37a30fca1e71974ea 100644 (file)
@@ -53,12 +53,16 @@ public class RuleDao implements BatchComponent, ServerComponent {
   public List<RuleDto> selectEnablesAndNonManual() {
     SqlSession session = mybatis.openSession();
     try {
-      return getMapper(session).selectEnablesAndNonManual();
+      return selectEnablesAndNonManual(session);
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
+  public List<RuleDto> selectEnablesAndNonManual(SqlSession session) {
+    return getMapper(session).selectEnablesAndNonManual();
+  }
+
   public List<RuleDto> selectNonManual(SqlSession session) {
     return getMapper(session).selectNonManual();
   }
@@ -76,19 +80,6 @@ public class RuleDao implements BatchComponent, ServerComponent {
     return getMapper(session).selectBySubCharacteristicId(characteristicOrSubCharacteristicId);
   }
 
-  public List<RuleDto> selectOverridingDebt(List<String> repositories) {
-    SqlSession session = mybatis.openSession();
-    try {
-      return selectOverridingDebt(repositories, session);
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  public List<RuleDto> selectOverridingDebt(List<String> repositories, SqlSession session) {
-    return getMapper(session).selectOverridingDebt(repositories);
-  }
-
   @CheckForNull
   public RuleDto selectById(Integer id, SqlSession session) {
     return getMapper(session).selectById(id);
index 5976f9c2dd22bdb876952dfb90a09d108b43bd02..920b825c138583ce6d948cca0bf40cc5e4c0415e 100644 (file)
@@ -32,8 +32,6 @@ public interface RuleMapper {
 
   List<RuleDto> selectBySubCharacteristicId(int characteristicId);
 
-  List<RuleDto> selectOverridingDebt(@Param("repositories") List<String> repositories);
-
   RuleDto selectById(Integer id);
 
   RuleDto selectByName(String name);
index 355442d90ac754ee534fa758b0296ab633897dcf..59a84d38c036f4e342038bcfa192ca46efabd812 100644 (file)
@@ -146,38 +146,6 @@ public class CharacteristicDao implements BatchComponent, ServerComponent {
     return session.getMapper(CharacteristicMapper.class).selectByName(name);
   }
 
-  @CheckForNull
-  public CharacteristicDto selectNext(int order, SqlSession session) {
-    List<CharacteristicDto> dtos = session.getMapper(CharacteristicMapper.class).selectNext(order);
-    return dtos.isEmpty() ? null : dtos.get(0);
-  }
-
-  @CheckForNull
-  public CharacteristicDto selectNext(int order) {
-    SqlSession session = mybatis.openSession();
-    try {
-      return selectNext(order, session);
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  @CheckForNull
-  public CharacteristicDto selectPrevious(int order, SqlSession session) {
-    List<CharacteristicDto> dtos = session.getMapper(CharacteristicMapper.class).selectPrevious(order);
-    return dtos.isEmpty() ? null : dtos.get(0);
-  }
-
-  @CheckForNull
-  public CharacteristicDto selectPrevious(int order) {
-    SqlSession session = mybatis.openSession();
-    try {
-      return selectPrevious(order, session);
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
   public int selectMaxCharacteristicOrder() {
     SqlSession session = mybatis.openSession();
     try {
index 2767ef3eb771f11e1199506cb5f43f94ff3de2a2..910f2df84b08da8582de35be1454a1bb382ceabf 100644 (file)
@@ -38,10 +38,6 @@ public interface CharacteristicMapper {
 
   CharacteristicDto selectByName(String name);
 
-  List<CharacteristicDto> selectNext(int order);
-
-  List<CharacteristicDto> selectPrevious(int order);
-
   Integer selectMaxCharacteristicOrder();
 
   void insert(CharacteristicDto characteristic);
index 16d37d6a426220df5b6f62db9b6364de59bb65b3..c376bb984ebc9da78bb13a79da257bae7d9335cc 100644 (file)
     </where>
   </select>
 
-  <select id="selectOverridingDebt" resultType="Rule">
-    SELECT <include refid="selectColumns"/> FROM rules r
-    <where>
-      AND (r.characteristic_id is NOT NULL or r.remediation_function IS NOT NULL)
-      <if test="repositories.size()>0">
-        AND
-        <foreach item="repo" index="index" collection="repositories" open="(" separator=" or " close=")">
-          r.plugin_name=#{repo}
-        </foreach>
-      </if>
-    </where>
-  </select>
-
   <update id="update" parameterType="Rule">
     UPDATE rules SET
     plugin_rule_key=#{ruleKey},
index 5a600667933281a27d3cc875c59e1803171def47..0bae9e151fde14d19372dbc91a21f71a89ce17d0 100644 (file)
     </where>
   </select>
 
-  <select id="selectNext" parameterType="Integer" resultType="Characteristic">
-    select <include refid="characteristicColumns"/>
-    from characteristics c
-    <where>
-      and c.characteristic_order&gt;#{order}
-      and c.parent_id is null
-      and c.enabled=${_true}
-    </where>
-    order by characteristic_order asc
-  </select>
-
-  <select id="selectPrevious" parameterType="Integer" resultType="Characteristic">
-    select <include refid="characteristicColumns"/>
-    from characteristics c
-    <where>
-      and c.characteristic_order&lt;#{order}
-      and c.parent_id is null
-      and c.enabled=${_true}
-    </where>
-    order by characteristic_order asc
-  </select>
-
   <select id="selectMaxCharacteristicOrder" resultType="Integer">
     select max(c.characteristic_order)
     from characteristics c
index 48fc65093c05cfb5c8c2da9b679bc4898f813f47..b0711dc5214e1322a7bb4cfd9b1db5624445c37f 100644 (file)
@@ -31,7 +31,6 @@ import org.sonar.api.utils.DateUtils;
 import org.sonar.check.Cardinality;
 import org.sonar.core.persistence.AbstractDaoTestCase;
 
-import java.util.Collections;
 import java.util.List;
 
 import static com.google.common.collect.Lists.newArrayList;
@@ -154,18 +153,6 @@ public class RuleDaoTest extends AbstractDaoTestCase {
     assertThat(idsFromRuleDtos(ruleDtos)).containsExactly(3);
   }
 
-  @Test
-  public void select_overriding_debt_rules() throws Exception {
-    setupData("select_overriding_debt_rules");
-
-    assertThat(dao.selectOverridingDebt(Collections.<String>emptyList())).hasSize(3);
-
-    assertThat(dao.selectOverridingDebt(newArrayList("squid"))).hasSize(2);
-    assertThat(dao.selectOverridingDebt(newArrayList("java"))).hasSize(1);
-    assertThat(dao.selectOverridingDebt(newArrayList("squid", "java"))).hasSize(3);
-    assertThat(dao.selectOverridingDebt(newArrayList("unknown"))).isEmpty();
-  }
-
   @Test
   public void update() {
     setupData("update");
index 1f76fe6327d4f82605978d6987b787df8ba30807..d4647c2b403cb2a9d713157e5c57ea28dcf43c09 100644 (file)
@@ -145,17 +145,6 @@ public class CharacteristicDaoTest extends AbstractDaoTestCase {
     assertThat(dao.selectById(10)).isNull();
   }
 
-  @Test
-  public void select_next_and_previous_characteristic() {
-    setupData("select_next_and_previous");
-
-    assertThat(dao.selectNext(1)).isNotNull();
-    assertThat(dao.selectNext(2)).isNull();
-
-    assertThat(dao.selectPrevious(1)).isNull();
-    assertThat(dao.selectPrevious(2)).isNotNull();
-  }
-
   @Test
   public void select_max_characteristic_order() {
     setupData("shared");
diff --git a/sonar-core/src/test/resources/org/sonar/core/rule/RuleDaoTest/select_overriding_debt_rules.xml b/sonar-core/src/test/resources/org/sonar/core/rule/RuleDaoTest/select_overriding_debt_rules.xml
deleted file mode 100644 (file)
index 2dbc816..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<dataset>
-
-  <!-- Rule overriding debt and with default debt -->
-  <rules id="1" plugin_rule_key="UselessImportCheck" plugin_name="squid" name="UselessImportCheck" description="Useless imports should be removed" status="READY"
-         characteristic_id="2" default_characteristic_id="50"
-         remediation_function="LINEAR_OFFSET" default_remediation_function="LINEAR_OFFSET"
-         remediation_factor="5d" default_remediation_factor="5d"
-         remediation_offset="10h" default_remediation_offset="10h" updated_at="2014-02-19"/>
-
-  <!-- Rule only overriding debt -->
-  <rules id="2" plugin_rule_key="LeftCurlyBraceStartLineCheck" plugin_name="squid" name="LeftCurlyBraceStartLineCheck" description="Left curly braces should be located at the beginning of lines of code" status="READY"
-         characteristic_id="3" default_characteristic_id="[null]"
-         remediation_function="LINEAR_OFFSET" default_remediation_function="[null]"
-         remediation_factor="5d" default_remediation_factor="[null]"
-         remediation_offset="10h" default_remediation_offset="[null]" updated_at="2014-02-19"/>
-
-  <!-- Rule with only default debt : never been returned -->
-  <rules id="3" plugin_rule_key="CallToFileDeleteOnExitMethod" plugin_name="squid" name="CallToFileDeleteOnExitMethod" description="CallToFileDeleteOnExitMethod" status="READY"
-         characteristic_id="[null]" default_characteristic_id="50"
-         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
-         remediation_factor="[null]" default_remediation_factor="5d"
-         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"/>
-
-  <!-- Removed rule overriding debt -->
-  <rules id="4" plugin_rule_key="ObjectFinalizeOverridenCallsSuperFinalizeCheck" plugin_name="java" name="ObjectFinalizeOverridenCallsSuperFinalizeCheck" description="super.finalize() should be called at the end of Object.finalize() implementations" status="REMOVED"
-         characteristic_id="3" default_characteristic_id="50"
-         remediation_function="LINEAR" default_remediation_function="LINEAR_OFFSET"
-         remediation_factor="5d" default_remediation_factor="5min"
-         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"/>
-
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_next_and_previous.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_next_and_previous.xml
deleted file mode 100644 (file)
index 8f96903..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<dataset>
-
-  <!-- Root characteristic -->
-  <characteristics id="1" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1"
-                   enabled="[true]"
-                   created_at="2013-11-20" updated_at="2013-11-22"/>
-
-  <!-- Disabled root characteristic -->
-  <characteristics id="4" kee="MAINTAINABILITY" name="Maintainability" parent_id="[null]" characteristic_order="2"
-                   enabled="[true]"
-                   created_at="2013-11-20" updated_at="2013-11-22"/>
-
-</dataset>
index 380d4d5a3797000cb0c5f20ebe3a879393c8906c..205850d4f6713734852a8ae78eeb33e903cc2580 100644 (file)
@@ -25,10 +25,12 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.ibatis.session.SqlSession;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.server.debt.DebtCharacteristic;
 import org.sonar.api.utils.System2;
+import org.sonar.api.utils.ValidationMessages;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.rule.RuleDao;
@@ -58,17 +60,18 @@ public class DebtModelRestore implements ServerComponent {
   private final DebtModelOperations debtModelOperations;
   private final TechnicalDebtModelRepository debtModelPluginRepository;
   private final RuleRepositories ruleRepositories;
-  private final DebtCharacteristicsXMLImporter importer;
+  private final DebtCharacteristicsXMLImporter characteristicsXMLImporter;
+  private final DebtRulesXMLImporter rulesXMLImporter;
   private final System2 system2;
 
   public DebtModelRestore(MyBatis mybatis, CharacteristicDao dao, RuleDao ruleDao, DebtModelOperations debtModelOperations, TechnicalDebtModelRepository debtModelPluginRepository,
-                          RuleRepositories ruleRepositories, DebtCharacteristicsXMLImporter importer) {
-    this(mybatis, dao, ruleDao, debtModelOperations, debtModelPluginRepository, ruleRepositories, importer, System2.INSTANCE);
+                          RuleRepositories ruleRepositories, DebtCharacteristicsXMLImporter characteristicsXMLImporter, DebtRulesXMLImporter rulesXMLImporter) {
+    this(mybatis, dao, ruleDao, debtModelOperations, debtModelPluginRepository, ruleRepositories, characteristicsXMLImporter, rulesXMLImporter, System2.INSTANCE);
   }
 
   @VisibleForTesting
   DebtModelRestore(MyBatis mybatis, CharacteristicDao dao, RuleDao ruleDao, DebtModelOperations debtModelOperations, TechnicalDebtModelRepository debtModelPluginRepository,
-                   RuleRepositories ruleRepositories, DebtCharacteristicsXMLImporter importer,
+                   RuleRepositories ruleRepositories, DebtCharacteristicsXMLImporter characteristicsXMLImporter, DebtRulesXMLImporter rulesXMLImporter,
                    System2 system2) {
     this.mybatis = mybatis;
     this.dao = dao;
@@ -76,34 +79,63 @@ public class DebtModelRestore implements ServerComponent {
     this.debtModelOperations = debtModelOperations;
     this.debtModelPluginRepository = debtModelPluginRepository;
     this.ruleRepositories = ruleRepositories;
-    this.importer = importer;
+    this.characteristicsXMLImporter = characteristicsXMLImporter;
+    this.rulesXMLImporter = rulesXMLImporter;
     this.system2 = system2;
   }
 
   /**
    * Restore from provided model
    */
-  public void restore() {
-    restore(Collections.<RuleRepositories.Repository>emptyList());
+  public ValidationMessages restore() {
+    ValidationMessages validationMessages = ValidationMessages.create();
+    restore(loadModelFromPlugin(TechnicalDebtModelRepository.DEFAULT_MODEL), Collections.<DebtRulesXMLImporter.RuleDebt>emptyList(),
+      Collections.<RuleRepositories.Repository>emptyList(), false, validationMessages);
+    return validationMessages;
   }
 
   /**
    * Restore from plugins providing rules for a given language
    */
-  public void restore(String languageKey) {
-    restore(ruleRepositories.repositoriesForLang(languageKey));
+  public ValidationMessages restore(String languageKey) {
+    ValidationMessages validationMessages = ValidationMessages.create();
+    restore(loadModelFromPlugin(TechnicalDebtModelRepository.DEFAULT_MODEL), Collections.<DebtRulesXMLImporter.RuleDebt>emptyList(),
+      ruleRepositories.repositoriesForLang(languageKey), false, validationMessages);
+    return validationMessages;
   }
 
-  private void restore(Collection<RuleRepositories.Repository> repositories) {
+  /**
+   * Restore model from a given XML model
+   */
+  public ValidationMessages restoreFromXml(String xml) {
+    DebtModel debtModel = characteristicsXMLImporter.importXML(xml);
+    ValidationMessages validationMessages = ValidationMessages.create();
+    List<DebtRulesXMLImporter.RuleDebt> ruleDebts = rulesXMLImporter.importXML(xml, validationMessages);
+    restore(debtModel, ruleDebts, Collections.<RuleRepositories.Repository>emptyList(), true, validationMessages);
+    return validationMessages;
+  }
+
+  /**
+   * Restore model from a given XML model and a given language
+   */
+  public ValidationMessages restoreFromXml(String xml, String languageKey) {
+    DebtModel debtModel = characteristicsXMLImporter.importXML(xml);
+    ValidationMessages validationMessages = ValidationMessages.create();
+    List<DebtRulesXMLImporter.RuleDebt> ruleDebts = rulesXMLImporter.importXML(xml, validationMessages);
+    restore(debtModel, ruleDebts, ruleRepositories.repositoriesForLang(languageKey), true, validationMessages);
+    return validationMessages;
+  }
+
+  private void restore(DebtModel modelToImport, List<DebtRulesXMLImporter.RuleDebt> ruleDebts, Collection<RuleRepositories.Repository> repositories,
+                       boolean disableCharacteristicWhenRuleNotFound, ValidationMessages validationMessages) {
     checkPermission();
 
     Date updateDate = new Date(system2.now());
     SqlSession session = mybatis.openSession();
     try {
       List<CharacteristicDto> persisted = dao.selectEnabledCharacteristics();
-      DebtModel providedModel = loadModelFromXml(TechnicalDebtModelRepository.DEFAULT_MODEL);
-      restoreCharacteristics(providedModel, persisted, updateDate, session);
-      resetOverridingRuleDebt(repositories, updateDate, session);
+      List<CharacteristicDto> characteristicDtos = restoreCharacteristics(modelToImport, persisted, updateDate, session);
+      restoreRules(characteristicDtos, repositories, ruleDebts, disableCharacteristicWhenRuleNotFound, validationMessages, updateDate, session);
 
       session.commit();
     } finally {
@@ -111,31 +143,64 @@ public class DebtModelRestore implements ServerComponent {
     }
   }
 
-  private void resetOverridingRuleDebt(Collection<RuleRepositories.Repository> repositories, Date updateDate, SqlSession session) {
+  private void restoreRules(List<CharacteristicDto> characteristicDtos, Collection<RuleRepositories.Repository> repositories, List<DebtRulesXMLImporter.RuleDebt> ruleDebts,
+                            boolean disableCharacteristicWhenRuleNotFound, ValidationMessages validationMessages, Date updateDate, SqlSession session) {
     List<String> repositoryKeys = newArrayList(Iterables.transform(repositories, new Function<RuleRepositories.Repository, String>() {
       @Override
       public String apply(RuleRepositories.Repository input) {
         return input.getKey();
       }
     }));
-    for (RuleDto rule : ruleDao.selectOverridingDebt(repositoryKeys, session)) {
-      rule.setCharacteristicId(null);
-      rule.setRemediationFunction(null);
-      rule.setRemediationFactor(null);
-      rule.setRemediationOffset(null);
-      rule.setUpdatedAt(updateDate);
-      ruleDao.update(rule, session);
-      // TODO index rules in E/S
+    for (RuleDto rule : ruleDao.selectEnablesAndNonManual(session)) {
+      if (repositories.isEmpty() || repositoryKeys.contains(rule.getRepositoryKey())) {
+        DebtRulesXMLImporter.RuleDebt ruleDebt = ruleDebtByRule(rule, ruleDebts);
+        if (ruleDebt == null) {
+          rule.setCharacteristicId(disableCharacteristicWhenRuleNotFound ? RuleDto.DISABLED_CHARACTERISTIC_ID : null);
+          rule.setRemediationFunction(null);
+          rule.setRemediationFactor(null);
+          rule.setRemediationOffset(null);
+        } else {
+          CharacteristicDto characteristicDto = characteristicByKey(ruleDebt.characteristicKey(), characteristicDtos, false);
+          // Characteristic cannot be null as it has been created just before
+
+          boolean isSameCharacteristic = characteristicDto.getId().equals(rule.getDefaultCharacteristicId());
+          boolean isSameFunction = isSameRemediationFunction(ruleDebt, rule);
+          rule.setCharacteristicId((!isSameCharacteristic ? characteristicDto.getId() : null));
+          rule.setRemediationFunction((!isSameFunction ? ruleDebt.function().name() : null));
+          rule.setRemediationFactor((!isSameFunction ? ruleDebt.factor() : null));
+          rule.setRemediationOffset((!isSameFunction ? ruleDebt.offset() : null));
+        }
+
+        ruleDebts.remove(ruleDebt);
+        rule.setUpdatedAt(updateDate);
+        ruleDao.update(rule, session);
+        // TODO index rules in E/S
+      }
+    }
+
+    for (DebtRulesXMLImporter.RuleDebt ruleDebt : ruleDebts) {
+      validationMessages.addWarningText(String.format("The rule '%s' does not exist.", ruleDebt.ruleKey()));
     }
   }
 
+  static boolean isSameRemediationFunction(DebtRulesXMLImporter.RuleDebt ruleDebt, RuleDto rule) {
+    return new EqualsBuilder()
+      .append(ruleDebt.function().name(), rule.getDefaultRemediationFunction())
+      .append(ruleDebt.factor(), rule.getDefaultRemediationFactor())
+      .append(ruleDebt.offset(), rule.getDefaultRemediationOffset())
+      .isEquals();
+  }
+
   @VisibleForTesting
-  void restoreCharacteristics(DebtModel targetModel, List<CharacteristicDto> sourceCharacteristics, Date updateDate, SqlSession session) {
+  List<CharacteristicDto> restoreCharacteristics(DebtModel targetModel, List<CharacteristicDto> sourceCharacteristics, Date updateDate, SqlSession session) {
+    List<CharacteristicDto> result = newArrayList();
+
     // Restore not existing characteristics
     for (DebtCharacteristic characteristic : targetModel.rootCharacteristics()) {
       CharacteristicDto rootCharacteristicDto = restoreCharacteristic(characteristic, null, sourceCharacteristics, updateDate, session);
+      result.add(rootCharacteristicDto);
       for (DebtCharacteristic subCharacteristic : targetModel.subCharacteristics(characteristic.key())) {
-        restoreCharacteristic(subCharacteristic, rootCharacteristicDto.getId(), sourceCharacteristics, updateDate, session);
+        result.add(restoreCharacteristic(subCharacteristic, rootCharacteristicDto.getId(), sourceCharacteristics, updateDate, session));
       }
     }
     // Disable no more existing characteristics
@@ -144,11 +209,12 @@ public class DebtModelRestore implements ServerComponent {
         debtModelOperations.disableCharacteristic(sourceCharacteristic, updateDate, session);
       }
     }
+    return result;
   }
 
   private CharacteristicDto restoreCharacteristic(DebtCharacteristic targetCharacteristic, @Nullable Integer parentId, List<CharacteristicDto> sourceCharacteristics,
                                                   Date updateDate, SqlSession session) {
-    CharacteristicDto sourceCharacteristic = dtoByKey(sourceCharacteristics, targetCharacteristic.key());
+    CharacteristicDto sourceCharacteristic = characteristicByKey(targetCharacteristic.key(), sourceCharacteristics, true);
     if (sourceCharacteristic == null) {
       CharacteristicDto newCharacteristic = toDto(targetCharacteristic, parentId).setCreatedAt(updateDate);
       dao.insert(newCharacteristic, session);
@@ -166,24 +232,40 @@ public class DebtModelRestore implements ServerComponent {
     }
   }
 
-  private DebtModel loadModelFromXml(String pluginKey) {
+  private DebtModel loadModelFromPlugin(String pluginKey) {
     Reader xmlFileReader = null;
     try {
       xmlFileReader = debtModelPluginRepository.createReaderForXMLFile(pluginKey);
-      return importer.importXML(xmlFileReader);
+      return characteristicsXMLImporter.importXML(xmlFileReader);
     } finally {
       IOUtils.closeQuietly(xmlFileReader);
     }
   }
 
-  @CheckForNull
-  private CharacteristicDto dtoByKey(List<CharacteristicDto> existingModel, final String key) {
-    return Iterables.find(existingModel, new Predicate<CharacteristicDto>() {
+  private CharacteristicDto characteristicByKey(final String key, List<CharacteristicDto> existingModel, boolean canByNull) {
+    CharacteristicDto dto = Iterables.find(existingModel, new Predicate<CharacteristicDto>() {
       @Override
       public boolean apply(CharacteristicDto input) {
         return key.equals(input.getKey());
       }
     }, null);
+    if (dto == null && !canByNull) {
+      throw new IllegalStateException(String.format("Characteristic with key '%s' has not been found ", key));
+    }
+    return dto;
+  }
+
+  @CheckForNull
+  private DebtRulesXMLImporter.RuleDebt ruleDebtByRule(final RuleDto rule, List<DebtRulesXMLImporter.RuleDebt> ruleDebts) {
+    if (ruleDebts.isEmpty()) {
+      return null;
+    }
+    return Iterables.find(ruleDebts, new Predicate<DebtRulesXMLImporter.RuleDebt>() {
+      @Override
+      public boolean apply(DebtRulesXMLImporter.RuleDebt input) {
+        return rule.getRepositoryKey().equals(input.ruleKey().repository()) && rule.getRuleKey().equals(input.ruleKey().rule());
+      }
+    }, null);
   }
 
   private static CharacteristicDto toDto(DebtCharacteristic characteristic, @Nullable Integer parentId) {
index 483f4fa5c28b10ae00fad50402d77f5e45a4e731..a0777d8f528c7d8fb7619e27270f69a78bd97542 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.debt;
 
 import org.sonar.api.server.debt.DebtCharacteristic;
 import org.sonar.api.server.debt.DebtModel;
+import org.sonar.api.utils.ValidationMessages;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
@@ -84,15 +85,29 @@ public class DebtModelService implements DebtModel {
   /**
    * Restore from provided model
    */
-  public void restore(){
-    debtModelRestore.restore();
+  public ValidationMessages restore(){
+    return debtModelRestore.restore();
   }
 
   /**
    * Restore from plugins providing rules for a given language
    */
-  public void restore(String languageKey) {
-    debtModelRestore.restore(languageKey);
+  public ValidationMessages restoreFromLanguage(String languageKey) {
+    return debtModelRestore.restore(languageKey);
+  }
+
+  /**
+   * Restore from XML
+   */
+  public ValidationMessages restoreFromXml(String xml){
+    return debtModelRestore.restoreFromXml(xml);
+  }
+
+  /**
+   * Restore from XML and a given language
+   */
+  public ValidationMessages restoreFromXmlAndLanguage(String xml, String languageKey) {
+    return debtModelRestore.restoreFromXml(xml, languageKey);
   }
 
 }
index e8ea229be1857548404ca70a7ffdc108fb35690f..f6e3f8b331c11fe794d8ee115b1d66513b81e9c4 100644 (file)
@@ -36,6 +36,7 @@ import java.util.List;
 
 import static com.google.common.collect.Lists.newArrayList;
 
+// TODO replace this by DebtModelRestore
 public class DebtModelSynchronizer implements ServerExtension {
 
   private final MyBatis mybatis;
index fb08a965599171f58a813dd0524092e650d7cf76..762b11deacba385c00d43d4bd5750f654ad1ca51 100644 (file)
@@ -29,12 +29,11 @@ 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.rule.RuleKey;
 import org.sonar.api.server.rule.DebtRemediationFunction;
 import org.sonar.api.utils.Duration;
+import org.sonar.api.utils.ValidationMessages;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
@@ -49,8 +48,6 @@ import static com.google.common.collect.Lists.newArrayList;
 
 public class DebtRulesXMLImporter implements ServerExtension {
 
-  private static final Logger LOG = LoggerFactory.getLogger(DebtRulesXMLImporter.class);
-
   public static final String CHARACTERISTIC = "chc";
   public static final String CHARACTERISTIC_KEY = "key";
   public static final String PROPERTY = "prop";
@@ -66,11 +63,11 @@ public class DebtRulesXMLImporter implements ServerExtension {
   public static final String PROPERTY_FACTOR = "remediationFactor";
   public static final String PROPERTY_OFFSET = "offset";
 
-  public List<RuleDebt> importXML(String xml) {
-    return importXML(new StringReader(xml));
+  public List<RuleDebt> importXML(String xml, ValidationMessages validationMessages) {
+    return importXML(new StringReader(xml), validationMessages);
   }
 
-  public List<RuleDebt> importXML(Reader xml) {
+  public List<RuleDebt> importXML(Reader xml, ValidationMessages validationMessages) {
     List<RuleDebt> ruleDebts = newArrayList();
     try {
       SMInputFactory inputFactory = initStax();
@@ -80,7 +77,7 @@ public class DebtRulesXMLImporter implements ServerExtension {
       cursor.advance();
       SMInputCursor rootCursor = cursor.childElementCursor(CHARACTERISTIC);
       while (rootCursor.getNext() != null) {
-        process(ruleDebts, null, null, rootCursor);
+        process(ruleDebts, null, null, validationMessages, rootCursor);
       }
 
       cursor.getStreamReader().closeCompletely();
@@ -99,7 +96,7 @@ public class DebtRulesXMLImporter implements ServerExtension {
     return new SMInputFactory(xmlFactory);
   }
 
-  private void process(List<RuleDebt> ruleDebts, @Nullable String rootKey, @Nullable String parentKey, SMInputCursor chcCursor) throws XMLStreamException {
+  private void process(List<RuleDebt> ruleDebts, @Nullable String rootKey, @Nullable String parentKey, ValidationMessages validationMessages, SMInputCursor chcCursor) throws XMLStreamException {
     String currentCharacteristicKey = null;
     SMInputCursor cursor = chcCursor.childElementCursor();
     while (cursor.getNext() != null) {
@@ -107,15 +104,15 @@ public class DebtRulesXMLImporter implements ServerExtension {
       if (StringUtils.equals(node, CHARACTERISTIC_KEY)) {
         currentCharacteristicKey = cursor.collectDescendantText().trim();
       } else if (StringUtils.equals(node, CHARACTERISTIC)) {
-        process(ruleDebts, parentKey, currentCharacteristicKey, cursor);
+        process(ruleDebts, parentKey, currentCharacteristicKey, validationMessages, cursor);
       } else if (StringUtils.equals(node, REPOSITORY_KEY)) {
-        RuleDebt ruleDebt = processRule(cursor);
+        RuleDebt ruleDebt = processRule(validationMessages, cursor);
         if (ruleDebt != null) {
           if (rootKey != null) {
             ruleDebt.characteristicKey = parentKey;
             ruleDebts.add(ruleDebt);
           } else {
-            LOG.warn("Rule '" + ruleDebt.ruleKey + "' is ignored because it's defined directly under a root characteristic.");
+            validationMessages.addWarningText("Rule '" + ruleDebt.ruleKey + "' is ignored because it's defined directly under a root characteristic.");
           }
         }
       }
@@ -123,7 +120,7 @@ public class DebtRulesXMLImporter implements ServerExtension {
   }
 
   @CheckForNull
-  private RuleDebt processRule(SMInputCursor cursor) throws XMLStreamException {
+  private RuleDebt processRule(ValidationMessages validationMessages, SMInputCursor cursor) throws XMLStreamException {
 
     String ruleRepositoryKey = cursor.collectDescendantText().trim();
     String ruleKey = null;
@@ -131,18 +128,18 @@ public class DebtRulesXMLImporter implements ServerExtension {
     while (cursor.getNext() != null) {
       String node = cursor.getLocalName();
       if (StringUtils.equals(node, PROPERTY)) {
-        properties.add(processProperty(cursor));
+        properties.add(processProperty(validationMessages, cursor));
       } else if (StringUtils.equals(node, RULE_KEY)) {
         ruleKey = cursor.collectDescendantText().trim();
       }
     }
     if (StringUtils.isNotBlank(ruleRepositoryKey) && StringUtils.isNotBlank(ruleKey)) {
-      return createRule(RuleKey.of(ruleRepositoryKey, ruleKey), properties);
+      return createRule(RuleKey.of(ruleRepositoryKey, ruleKey), properties, validationMessages);
     }
     return null;
   }
 
-  private Property processProperty(SMInputCursor cursor) throws XMLStreamException {
+  private Property processProperty(ValidationMessages validationMessages, SMInputCursor cursor) throws XMLStreamException {
     SMInputCursor c = cursor.childElementCursor();
     String key = null;
     int value = 0;
@@ -158,7 +155,7 @@ public class DebtRulesXMLImporter implements ServerExtension {
           Double valueDouble = NumberUtils.createDouble(s);
           value = valueDouble.intValue();
         } catch (NumberFormatException ex) {
-          LOG.error(String.format("Cannot import value '%s' for field %s - Expected a numeric value instead", s, key));
+          validationMessages.addErrorText(String.format("Cannot import value '%s' for field %s - Expected a numeric value instead", s, key));
         }
       } else if (StringUtils.equals(node, PROPERTY_TEXT_VALUE)) {
         textValue = c.collectDescendantText().trim();
@@ -169,7 +166,7 @@ public class DebtRulesXMLImporter implements ServerExtension {
   }
 
   @CheckForNull
-  private RuleDebt createRule(RuleKey ruleKey, Properties properties) {
+  private RuleDebt createRule(RuleKey ruleKey, Properties properties, ValidationMessages validationMessages) {
     Property function = properties.function();
     if (function != null) {
 
@@ -178,22 +175,22 @@ public class DebtRulesXMLImporter implements ServerExtension {
       Property offsetProperty = properties.offset();
       String offset = offsetProperty != null ? offsetProperty.toDuration() : null;
 
-      return createRuleDebt(ruleKey, function.getTextValue(), factor, offset);
+      return createRuleDebt(ruleKey, function.getTextValue(), factor, offset, validationMessages);
     }
     return null;
   }
 
   @CheckForNull
-  private RuleDebt createRuleDebt(RuleKey ruleKey, String function, @Nullable String factor, @Nullable String offset) {
+  private RuleDebt createRuleDebt(RuleKey ruleKey, String function, @Nullable String factor, @Nullable String offset, ValidationMessages validationMessages) {
     if ("linear_threshold".equals(function) && factor != null) {
-      LOG.warn(String.format("Linear with threshold function is no longer used, remediation function of '%s' is replaced by linear.", ruleKey));
-      return new RuleDebt().setRuleKey(ruleKey).setType(DebtRemediationFunction.Type.LINEAR).setFactor(factor);
+      validationMessages.addWarningText(String.format("Linear with threshold function is no longer used, remediation function of '%s' is replaced by linear.", ruleKey));
+      return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.LINEAR).setFactor(factor);
     } else if ("constant_resource".equals(function)) {
-      LOG.warn(String.format("Constant/file function is no longer used, technical debt definitions on '%s' are ignored.", ruleKey));
+      validationMessages.addWarningText(String.format("Constant/file function is no longer used, technical debt definitions on '%s' are ignored.", ruleKey));
     } else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.name().equalsIgnoreCase(function) && factor != null && offset == null) {
-      return new RuleDebt().setRuleKey(ruleKey).setType(DebtRemediationFunction.Type.CONSTANT_ISSUE).setOffset(factor);
+      return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE).setOffset(factor);
     } else {
-      return new RuleDebt().setRuleKey(ruleKey).setType(DebtRemediationFunction.Type.valueOf(function.toUpperCase())).setFactor(factor).setOffset(offset);
+      return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.valueOf(function.toUpperCase())).setFactor(factor).setOffset(offset);
     }
     return null;
   }
@@ -291,11 +288,11 @@ public class DebtRulesXMLImporter implements ServerExtension {
       return this;
     }
 
-    public DebtRemediationFunction.Type type() {
+    public DebtRemediationFunction.Type function() {
       return type;
     }
 
-    public RuleDebt setType(DebtRemediationFunction.Type type) {
+    public RuleDebt setFunction(DebtRemediationFunction.Type type) {
       this.type = type;
       return this;
     }
index 84c0d5b7c60272f81fbb85af91cc57e858fb5dba..59b8b8f0a581ace6490e7ab88ff2fc3facdc835b 100644 (file)
@@ -23,12 +23,15 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rules.RuleParam;
 import org.sonar.api.rules.RuleRepository;
 import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.utils.ValidationMessages;
 import org.sonar.check.Cardinality;
 import org.sonar.core.i18n.RuleI18nManager;
 import org.sonar.core.technicaldebt.TechnicalDebtModelRepository;
@@ -49,6 +52,8 @@ import static com.google.common.collect.Lists.newArrayList;
  */
 public class DeprecatedRulesDefinition implements RulesDefinition {
 
+  private static final Logger LOG = LoggerFactory.getLogger(DeprecatedRulesDefinition.class);
+
   private final RuleI18nManager i18n;
   private final RuleRepository[] repositories;
 
@@ -105,7 +110,7 @@ public class DeprecatedRulesDefinition implements RulesDefinition {
     DebtRulesXMLImporter.RuleDebt ruleDebt = findRequirement(ruleDebts, repoKey, ruleKey);
     if (ruleDebt != null) {
       newRule.setDebtCharacteristic(ruleDebt.characteristicKey());
-      switch (ruleDebt.type()) {
+      switch (ruleDebt.function()) {
         case LINEAR :
           newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linear(ruleDebt.factor()));
           break;
@@ -116,7 +121,7 @@ public class DeprecatedRulesDefinition implements RulesDefinition {
           newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().constantPerIssue(ruleDebt.offset()));
           break;
         default :
-          throw new IllegalArgumentException(String.format("The type '%s' is unknown", ruleDebt.type()));
+          throw new IllegalArgumentException(String.format("The type '%s' is unknown", ruleDebt.function()));
       }
     }
   }
@@ -160,7 +165,10 @@ public class DeprecatedRulesDefinition implements RulesDefinition {
     Reader xmlFileReader = null;
     try {
       xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey);
-      return importer.importXML(xmlFileReader);
+      ValidationMessages validationMessages = ValidationMessages.create();
+      List<DebtRulesXMLImporter.RuleDebt> rules = importer.importXML(xmlFileReader, validationMessages);
+      validationMessages.log(LOG);
+      return rules;
     } finally {
       IOUtils.closeQuietly(xmlFileReader);
     }
index 4c96c20172e03702cef9a2f3883d2667bc6eac37..05b8ac50a92995998d05c787b10e97945bb4daca 100644 (file)
@@ -29,9 +29,12 @@ import org.mockito.Mock;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.mockito.stubbing.Answer;
+import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
+import org.sonar.api.server.rule.DebtRemediationFunction;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
+import org.sonar.api.utils.ValidationMessages;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.rule.RuleDao;
@@ -45,6 +48,7 @@ import org.sonar.server.user.MockUserSession;
 import java.io.Reader;
 import java.util.Collections;
 import java.util.Date;
+import java.util.List;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
@@ -76,6 +80,9 @@ public class DebtModelRestoreTest {
   @Mock
   DebtCharacteristicsXMLImporter characteristicsXMLImporter;
 
+  @Mock
+  DebtRulesXMLImporter rulesXMLImporter;
+
   @Mock
   RuleRepositories ruleRepositories;
 
@@ -86,7 +93,8 @@ public class DebtModelRestoreTest {
 
   int currentId;
 
-  DebtModel defaultModel = new DebtModel();
+  DebtModel characteristics = new DebtModel();
+  List<DebtRulesXMLImporter.RuleDebt> rules = newArrayList();
 
   DebtModelRestore debtModelRestore;
 
@@ -111,9 +119,12 @@ public class DebtModelRestoreTest {
 
     Reader defaultModelReader = mock(Reader.class);
     when(debtModelPluginRepository.createReaderForXMLFile("technical-debt")).thenReturn(defaultModelReader);
-    when(characteristicsXMLImporter.importXML(eq(defaultModelReader))).thenReturn(defaultModel);
+    when(characteristicsXMLImporter.importXML(eq(defaultModelReader))).thenReturn(characteristics);
+    when(characteristicsXMLImporter.importXML(anyString())).thenReturn(characteristics);
+    when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class))).thenReturn(rules);
 
-    debtModelRestore = new DebtModelRestore(myBatis, dao, ruleDao, debtModelOperations, debtModelPluginRepository, ruleRepositories, characteristicsXMLImporter, system2);
+    debtModelRestore = new DebtModelRestore(myBatis, dao, ruleDao, debtModelOperations, debtModelPluginRepository, ruleRepositories, characteristicsXMLImporter, rulesXMLImporter,
+      system2);
   }
 
   @Test
@@ -121,7 +132,7 @@ public class DebtModelRestoreTest {
     debtModelRestore.restoreCharacteristics(
       new DebtModel()
         .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
-        .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler"), "PORTABILITY"),
+        .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY"),
       Collections.<CharacteristicDto>emptyList(),
       now,
       session
@@ -141,7 +152,7 @@ public class DebtModelRestoreTest {
 
     CharacteristicDto dto2 = characteristicArgument.getAllValues().get(1);
     assertThat(dto2.getId()).isEqualTo(11);
-    assertThat(dto2.getKey()).isEqualTo("COMPILER_RELATED_PORTABILITY");
+    assertThat(dto2.getKey()).isEqualTo("COMPILER");
     assertThat(dto2.getName()).isEqualTo("Compiler");
     assertThat(dto2.getParentId()).isEqualTo(10);
     assertThat(dto2.getOrder()).isNull();
@@ -156,10 +167,10 @@ public class DebtModelRestoreTest {
     debtModelRestore.restoreCharacteristics(
       new DebtModel()
         .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
-        .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler"), "PORTABILITY"),
+        .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY"),
       newArrayList(
         new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability updated").setOrder(2).setCreatedAt(oldDate).setUpdatedAt(oldDate),
-        new CharacteristicDto().setId(2).setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler updated").setParentId(1).setCreatedAt(oldDate).setUpdatedAt(oldDate)
+        new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler updated").setParentId(1).setCreatedAt(oldDate).setUpdatedAt(oldDate)
       ),
       now,
       session
@@ -179,7 +190,7 @@ public class DebtModelRestoreTest {
 
     CharacteristicDto dto2 = characteristicArgument.getAllValues().get(1);
     assertThat(dto2.getId()).isEqualTo(2);
-    assertThat(dto2.getKey()).isEqualTo("COMPILER_RELATED_PORTABILITY");
+    assertThat(dto2.getKey()).isEqualTo("COMPILER");
     assertThat(dto2.getName()).isEqualTo("Compiler");
     assertThat(dto2.getParentId()).isEqualTo(1);
     assertThat(dto2.getOrder()).isNull();
@@ -190,7 +201,7 @@ public class DebtModelRestoreTest {
   @Test
   public void disable_no_more_existing_characteristics_when_restoring_characteristics() throws Exception {
     CharacteristicDto dto1 = new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1);
-    CharacteristicDto dto2 = new CharacteristicDto().setId(2).setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler").setParentId(1);
+    CharacteristicDto dto2 = new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1);
 
     debtModelRestore.restoreCharacteristics(new DebtModel(), newArrayList(dto1, dto2), now, session);
 
@@ -202,17 +213,17 @@ public class DebtModelRestoreTest {
   public void restore_from_provided_model() throws Exception {
     Date oldDate = DateUtils.parseDate("2014-01-01");
 
-    defaultModel
+    characteristics
       .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
-      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler"), "PORTABILITY");
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
 
     when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
       new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability updated").setOrder(2).setCreatedAt(oldDate),
-      new CharacteristicDto().setId(2).setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler updated").setParentId(1).setCreatedAt(oldDate)
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler updated").setParentId(1).setCreatedAt(oldDate)
     ));
 
-    when(ruleDao.selectOverridingDebt(Collections.<String>emptyList(), session)).thenReturn(newArrayList(
-      new RuleDto().setCharacteristicId(10).setRemediationFunction("LINEAR_OFFSET").setRemediationFactor("2h").setRemediationOffset("15min")
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
+      new RuleDto().setRepositoryKey("squid").setCharacteristicId(2).setRemediationFunction("LINEAR_OFFSET").setRemediationFactor("2h").setRemediationOffset("15min")
         .setCreatedAt(oldDate).setUpdatedAt(oldDate)
     ));
 
@@ -222,7 +233,7 @@ public class DebtModelRestoreTest {
     verify(dao, times(2)).update(any(CharacteristicDto.class), eq(session));
     verifyNoMoreInteractions(dao);
 
-    verify(ruleDao).selectOverridingDebt(Collections.<String>emptyList(), session);
+    verify(ruleDao).selectEnablesAndNonManual(session);
     ArgumentCaptor<RuleDto> ruleArgument = ArgumentCaptor.forClass(RuleDto.class);
     verify(ruleDao).update(ruleArgument.capture(), eq(session));
     verifyNoMoreInteractions(ruleDao);
@@ -241,18 +252,22 @@ public class DebtModelRestoreTest {
   public void restore_from_language() throws Exception {
     Date oldDate = DateUtils.parseDate("2014-01-01");
 
-    defaultModel
+    characteristics
       .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
-      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler"), "PORTABILITY");
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
 
     when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
       new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability updated").setOrder(2).setCreatedAt(oldDate),
-      new CharacteristicDto().setId(2).setKey("COMPILER_RELATED_PORTABILITY").setName("Compiler updated").setParentId(1).setCreatedAt(oldDate)
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler updated").setParentId(1).setCreatedAt(oldDate)
     ));
 
-    when(ruleDao.selectOverridingDebt(newArrayList("squid"), session)).thenReturn(newArrayList(
-      new RuleDto().setRepositoryKey("squid")
-        .setCharacteristicId(10).setRemediationFunction("LINEAR_OFFSET").setRemediationFactor("2h").setRemediationOffset("15min")
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
+      new RuleDto().setId(1).setRepositoryKey("squid")
+        .setCharacteristicId(2).setRemediationFunction("LINEAR_OFFSET").setRemediationFactor("2h").setRemediationOffset("15min")
+        .setCreatedAt(oldDate).setUpdatedAt(oldDate),
+      // Should be ignored
+      new RuleDto().setId(2).setRepositoryKey("checkstyle")
+        .setCharacteristicId(3).setRemediationFunction("LINEAR").setRemediationFactor("2h")
         .setCreatedAt(oldDate).setUpdatedAt(oldDate)
     ));
 
@@ -266,11 +281,237 @@ public class DebtModelRestoreTest {
     verify(dao, times(2)).update(any(CharacteristicDto.class), eq(session));
     verifyNoMoreInteractions(dao);
 
-    verify(ruleDao).selectOverridingDebt(newArrayList("squid"), session);
+    verify(ruleDao).selectEnablesAndNonManual(session);
+    ArgumentCaptor<RuleDto> ruleArgument = ArgumentCaptor.forClass(RuleDto.class);
+    verify(ruleDao).update(ruleArgument.capture(), eq(session));
+    verifyNoMoreInteractions(ruleDao);
+
+    RuleDto rule = ruleArgument.getValue();
+    assertThat(rule.getId()).isEqualTo(1);
+
+    verify(session).commit();
+  }
+
+  @Test
+  public void restore_from_xml_with_different_characteristic_and_same_function() throws Exception {
+    Date oldDate = DateUtils.parseDate("2014-01-01");
+
+    characteristics
+      .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
+
+    when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
+      new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1).setCreatedAt(oldDate),
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));
+
+    rules.add(new DebtRulesXMLImporter.RuleDebt()
+      .setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("2h"));
+
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
+      new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
+        .setDefaultCharacteristicId(10).setDefaultRemediationFunction("LINEAR").setDefaultRemediationFactor("2h")
+        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
+    ));
+
+    debtModelRestore.restoreFromXml("<xml/>");
+
+    verify(ruleDao).selectEnablesAndNonManual(session);
+    ArgumentCaptor<RuleDto> ruleArgument = ArgumentCaptor.forClass(RuleDto.class);
+    verify(ruleDao).update(ruleArgument.capture(), eq(session));
+    verifyNoMoreInteractions(ruleDao);
+
+    RuleDto rule = ruleArgument.getValue();
+    assertThat(rule.getId()).isEqualTo(1);
+    assertThat(rule.getCharacteristicId()).isEqualTo(2);
+    assertThat(rule.getRemediationFunction()).isNull();
+    assertThat(rule.getRemediationFactor()).isNull();
+    assertThat(rule.getRemediationOffset()).isNull();
+    assertThat(rule.getUpdatedAt()).isEqualTo(now);
+
+    verify(session).commit();
+  }
+
+  @Test
+  public void restore_from_xml_with_same_characteristic_and_different_function() throws Exception {
+    Date oldDate = DateUtils.parseDate("2014-01-01");
+
+    characteristics
+      .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
+
+    when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
+      new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1).setCreatedAt(oldDate),
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));
+
+    rules.add(new DebtRulesXMLImporter.RuleDebt()
+      .setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setFactor("12h").setOffset("11min"));
+
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
+      new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
+        .setDefaultCharacteristicId(2).setDefaultRemediationFunction("LINEAR").setDefaultRemediationFactor("2h")
+        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
+    ));
+
+    debtModelRestore.restoreFromXml("<xml/>");
+
+    verify(ruleDao).selectEnablesAndNonManual(session);
+    ArgumentCaptor<RuleDto> ruleArgument = ArgumentCaptor.forClass(RuleDto.class);
+    verify(ruleDao).update(ruleArgument.capture(), eq(session));
+    verifyNoMoreInteractions(ruleDao);
+
+    RuleDto rule = ruleArgument.getValue();
+    assertThat(rule.getId()).isEqualTo(1);
+    assertThat(rule.getCharacteristicId()).isNull();
+    assertThat(rule.getRemediationFunction()).isEqualTo("LINEAR_OFFSET");
+    assertThat(rule.getRemediationFactor()).isEqualTo("12h");
+    assertThat(rule.getRemediationOffset()).isEqualTo("11min");
+    assertThat(rule.getUpdatedAt()).isEqualTo(now);
+
+    verify(session).commit();
+  }
+
+  @Test
+  public void restore_from_xml_with_same_characteristic_and_same_function() throws Exception {
+    Date oldDate = DateUtils.parseDate("2014-01-01");
+
+    characteristics
+      .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
+
+    when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
+      new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1).setCreatedAt(oldDate),
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));
+
+    rules.add(new DebtRulesXMLImporter.RuleDebt()
+      .setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setFactor("2h").setOffset("15min"));
+
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
+      new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
+        .setDefaultCharacteristicId(2).setDefaultRemediationFunction("LINEAR_OFFSET").setDefaultRemediationFactor("2h").setDefaultRemediationOffset("15min")
+        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
+    ));
+
+    debtModelRestore.restoreFromXml("<xml/>");
+
+    verify(ruleDao).selectEnablesAndNonManual(session);
     ArgumentCaptor<RuleDto> ruleArgument = ArgumentCaptor.forClass(RuleDto.class);
     verify(ruleDao).update(ruleArgument.capture(), eq(session));
     verifyNoMoreInteractions(ruleDao);
 
+    RuleDto rule = ruleArgument.getValue();
+    assertThat(rule.getId()).isEqualTo(1);
+    assertThat(rule.getCharacteristicId()).isNull();
+    assertThat(rule.getRemediationFunction()).isNull();
+    assertThat(rule.getRemediationFactor()).isNull();
+    assertThat(rule.getRemediationOffset()).isNull();
+    assertThat(rule.getUpdatedAt()).isEqualTo(now);
+
+    verify(session).commit();
+  }
+
+  @Test
+  public void restore_from_xml_disable_rule_debt_when_not_in_xml() throws Exception {
+    Date oldDate = DateUtils.parseDate("2014-01-01");
+
+    characteristics
+      .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
+
+    when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
+      new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1).setCreatedAt(oldDate),
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));
+
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
+      new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
+        .setDefaultCharacteristicId(2).setDefaultRemediationFunction("LINEAR_OFFSET").setDefaultRemediationFactor("2h").setDefaultRemediationOffset("15min")
+        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
+    ));
+
+    debtModelRestore.restoreFromXml("<xml/>");
+
+    verify(ruleDao).selectEnablesAndNonManual(session);
+    ArgumentCaptor<RuleDto> ruleArgument = ArgumentCaptor.forClass(RuleDto.class);
+    verify(ruleDao).update(ruleArgument.capture(), eq(session));
+    verifyNoMoreInteractions(ruleDao);
+
+    RuleDto rule = ruleArgument.getValue();
+    assertThat(rule.getId()).isEqualTo(1);
+    assertThat(rule.getCharacteristicId()).isEqualTo(-1);
+    assertThat(rule.getRemediationFunction()).isNull();
+    assertThat(rule.getRemediationFactor()).isNull();
+    assertThat(rule.getRemediationOffset()).isNull();
+    assertThat(rule.getUpdatedAt()).isEqualTo(now);
+
     verify(session).commit();
   }
+
+  @Test
+  public void restore_from_xml_and_language() throws Exception {
+    Date oldDate = DateUtils.parseDate("2014-01-01");
+
+    characteristics
+      .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
+
+    when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
+      new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1).setCreatedAt(oldDate),
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));
+
+    rules.add(new DebtRulesXMLImporter.RuleDebt()
+      .setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("2h"));
+
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
+      new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
+        .setDefaultCharacteristicId(10).setDefaultRemediationFunction("LINEAR").setDefaultRemediationFactor("2h")
+        .setCreatedAt(oldDate).setUpdatedAt(oldDate),
+      // Should be ignored
+      new RuleDto().setId(2).setRepositoryKey("checkstyle")
+        .setCharacteristicId(3).setRemediationFunction("LINEAR").setRemediationFactor("2h")
+        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
+    ));
+
+    RuleRepositories.Repository squid = mock(RuleRepositories.Repository.class);
+    when(squid.getKey()).thenReturn("squid");
+    when(ruleRepositories.repositoriesForLang("java")).thenReturn(newArrayList(squid));
+
+    debtModelRestore.restoreFromXml("<xml/>", "java");
+
+    verify(ruleDao).selectEnablesAndNonManual(session);
+    ArgumentCaptor<RuleDto> ruleArgument = ArgumentCaptor.forClass(RuleDto.class);
+    verify(ruleDao).update(ruleArgument.capture(), eq(session));
+    verifyNoMoreInteractions(ruleDao);
+
+    RuleDto rule = ruleArgument.getValue();
+    assertThat(rule.getId()).isEqualTo(1);
+
+    verify(session).commit();
+  }
+
+  @Test
+  public void add_warning_message_when_rule_from_xml_is_not_found() throws Exception {
+    Date oldDate = DateUtils.parseDate("2014-01-01");
+
+    characteristics
+      .addRootCharacteristic(new DefaultDebtCharacteristic().setKey("PORTABILITY").setName("Portability").setOrder(1))
+      .addSubCharacteristic(new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"), "PORTABILITY");
+
+    when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(
+      new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1).setCreatedAt(oldDate),
+      new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));
+
+    rules.add(new DebtRulesXMLImporter.RuleDebt()
+      .setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("2h"));
+
+    when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(Collections.<RuleDto>emptyList());
+
+    ValidationMessages validationMessages = debtModelRestore.restoreFromXml("<xml/>");
+
+    assertThat(validationMessages.getWarnings()).hasSize(1);
+
+    verify(ruleDao).selectEnablesAndNonManual(session);
+    verifyNoMoreInteractions(ruleDao);
+
+    verify(session).commit();
+  }
+
 }
index 9c044e6508af258d5bfed03d0165326b0f9d82c6..59051abf5f6fdb088abbbfa98a78bfb34f18e71f 100644 (file)
@@ -102,8 +102,20 @@ public class DebtModelServiceTest {
 
   @Test
   public void restore_from_language() {
-    service.restore("xoo");
+    service.restoreFromLanguage("xoo");
     verify(debtModelRestore).restore("xoo");
   }
 
+  @Test
+  public void restore_xml() {
+    service.restoreFromXml("<xml/>");
+    verify(debtModelRestore).restoreFromXml("<xml/>");
+  }
+
+  @Test
+  public void restore_from_xml_and_language() {
+    service.restoreFromXmlAndLanguage("<xml/>", "xoo");
+    verify(debtModelRestore).restoreFromXml("<xml/>", "xoo");
+  }
+
 }
index d2ddfde267bf7a9a4d8de726480eba57b117538b..e1e8f82b2bc8a33c5e9e095b43230847c229e783 100644 (file)
@@ -25,6 +25,7 @@ import com.google.common.io.Resources;
 import org.junit.Test;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.utils.ValidationMessages;
 
 import java.io.IOException;
 import java.util.List;
@@ -34,27 +35,31 @@ import static org.fest.assertions.Fail.fail;
 
 public class DebtRulesXMLImporterTest {
 
+  ValidationMessages validationMessages = ValidationMessages.create();
   DebtRulesXMLImporter importer = new DebtRulesXMLImporter();
 
   @Test
   public void import_rules() {
     String xml = getFileContent("import_rules.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
+    
     assertThat(results).hasSize(2);
+    assertThat(validationMessages.getErrors()).isEmpty();
+    assertThat(validationMessages.getWarnings()).isEmpty();
   }
 
   @Test
   public void import_linear() {
     String xml = getFileContent("import_linear.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
     assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
     assertThat(ruleDebt.factor()).isEqualTo("3h");
     assertThat(ruleDebt.offset()).isNull();
   }
@@ -63,13 +68,13 @@ public class DebtRulesXMLImporterTest {
   public void import_linear_having_offset_to_zero() {
     String xml = getFileContent("import_linear_having_offset_to_zero.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
     assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
     assertThat(ruleDebt.factor()).isEqualTo("3h");
     assertThat(ruleDebt.offset()).isNull();
   }
@@ -78,12 +83,12 @@ public class DebtRulesXMLImporterTest {
   public void import_linear_with_offset() {
     String xml = getFileContent("import_linear_with_offset.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
     assertThat(ruleDebt.factor()).isEqualTo("3h");
     assertThat(ruleDebt.offset()).isEqualTo("1min");
   }
@@ -92,12 +97,12 @@ public class DebtRulesXMLImporterTest {
   public void import_constant_issue() {
     String xml = getFileContent("import_constant_issue.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE);
     assertThat(ruleDebt.factor()).isNull();
     assertThat(ruleDebt.offset()).isEqualTo("3d");
   }
@@ -106,12 +111,12 @@ public class DebtRulesXMLImporterTest {
   public void use_default_unit_when_no_unit() {
     String xml = getFileContent("use_default_unit_when_no_unit.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
     assertThat(ruleDebt.factor()).isEqualTo("3d");
     assertThat(ruleDebt.offset()).isEqualTo("1d");
   }
@@ -120,12 +125,12 @@ public class DebtRulesXMLImporterTest {
   public void replace_mn_by_min() {
     String xml = getFileContent("replace_mn_by_min.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
     assertThat(ruleDebt.factor()).isEqualTo("3min");
     assertThat(ruleDebt.offset()).isNull();
   }
@@ -134,26 +139,28 @@ public class DebtRulesXMLImporterTest {
   public void convert_deprecated_linear_with_threshold_function_by_linear_function() {
     String xml = getFileContent("convert_deprecated_linear_with_threshold_function_by_linear_function.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
     assertThat(ruleDebt.factor()).isEqualTo("3h");
     assertThat(ruleDebt.offset()).isNull();
+
+    assertThat(validationMessages.getWarnings()).isNotEmpty();
   }
 
   @Test
   public void convert_constant_per_issue_with_factor_by_constant_by_issue_with_offset() {
     String xml = getFileContent("convert_constant_per_issue_with_factor_by_constant_by_issue_with_offset.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
-    assertThat(ruleDebt.type()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE);
+    assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE);
     assertThat(ruleDebt.factor()).isNull();
     assertThat(ruleDebt.offset()).isEqualTo("3h");
   }
@@ -162,29 +169,33 @@ public class DebtRulesXMLImporterTest {
   public void ignore_deprecated_constant_per_file_function() {
     String xml = getFileContent("ignore_deprecated_constant_per_file_function.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).isEmpty();
+
+    assertThat(validationMessages.getWarnings()).isNotEmpty();
   }
 
   @Test
   public void ignore_rule_on_root_characteristics() {
     String xml = getFileContent("ignore_rule_on_root_characteristics.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).isEmpty();
+
+    assertThat(validationMessages.getWarnings()).isNotEmpty();
   }
 
   @Test
   public void import_badly_formatted_xml() {
     String xml = getFileContent("import_badly_formatted_xml.xml");
 
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).hasSize(1);
 
     DebtRulesXMLImporter.RuleDebt ruleDebt = results.get(0);
     assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
     assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
-    assertThat(ruleDebt.type()).isEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.Type.LINEAR);
+    assertThat(ruleDebt.function()).isEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.Type.LINEAR);
     assertThat(ruleDebt.factor()).isEqualTo("3h");
     assertThat(ruleDebt.offset()).isNull();
   }
@@ -192,8 +203,10 @@ public class DebtRulesXMLImporterTest {
   @Test
   public void ignore_invalid_value() throws Exception {
     String xml = getFileContent("ignore_invalid_value.xml");
-    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml);
+    List<DebtRulesXMLImporter.RuleDebt> results = importer.importXML(xml, validationMessages);
     assertThat(results).isEmpty();
+
+    assertThat(validationMessages.getErrors()).isNotEmpty();
   }
 
   @Test
index 636b5f757deadf656c93ed3152d7f8dbc3364d77..cfad5d4927b5f4feb5020b902cfdad949fbb1e5c 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.api.rules.RulePriority;
 import org.sonar.api.rules.RuleRepository;
 import org.sonar.api.server.rule.DebtRemediationFunction;
 import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.utils.ValidationMessages;
 import org.sonar.core.i18n.RuleI18nManager;
 import org.sonar.core.technicaldebt.TechnicalDebtModelRepository;
 import org.sonar.server.debt.DebtRulesXMLImporter;
@@ -41,6 +42,7 @@ import java.util.List;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -158,7 +160,7 @@ public class DeprecatedRulesDefinitionTest {
       new DebtRulesXMLImporter.RuleDebt()
         .setCharacteristicKey("MEMORY_EFFICIENCY")
         .setRuleKey(RuleKey.of("checkstyle", "ConstantName"))
-        .setType(DebtRemediationFunction.Type.LINEAR_OFFSET)
+        .setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET)
         .setFactor("1d")
         .setOffset("10min")
     );
@@ -166,7 +168,7 @@ public class DeprecatedRulesDefinitionTest {
     Reader javaModelReader = mock(Reader.class);
     when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader);
     when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java"));
-    when(importer.importXML(eq(javaModelReader))).thenReturn(ruleDebts);
+    when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts);
 
     new DeprecatedRulesDefinition(i18n, new RuleRepository[]{new CheckstyleRules()}, debtModelRepository, importer).define(context);