]> source.dussan.org Git - sonarqube.git/commitdiff
Create a Rule with a Builder
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 5 Feb 2014 08:16:14 +0000 (09:16 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 5 Feb 2014 08:16:14 +0000 (09:16 +0100)
sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRule.java
sonar-server/src/main/java/org/sonar/server/rule/Rule.java
sonar-server/src/main/java/org/sonar/server/rule/RuleDocumentParser.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java
sonar-server/src/main/java/org/sonar/server/rule/ws/RuleShowWsHandler.java
sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java
sonar-server/src/test/java/org/sonar/server/rule/ws/RuleShowWsHandlerTest.java

index 3b49c1dcfcb766c8f41517a5a24f5c46ce2d7904..96967b2f9011d700c28c4ce4898058d5aa3a6e5e 100644 (file)
@@ -24,11 +24,13 @@ import org.elasticsearch.common.collect.Lists;
 import org.elasticsearch.common.collect.Maps;
 import org.elasticsearch.common.joda.time.format.ISODateTimeFormat;
 import org.sonar.server.rule.Rule;
+import org.sonar.server.rule.RuleDocumentParser;
 import org.sonar.server.rule.RuleNote;
 import org.sonar.server.rule.RuleParam;
 
 import javax.annotation.CheckForNull;
 
+import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -47,10 +49,9 @@ public class QProfileRule {
   private final RuleNote activeRuleNote;
   private final List<QProfileRuleParam> params;
 
+  // TODO move this in a parser class
   public QProfileRule(Map<String, Object> ruleSource, Map<String, Object> activeRuleSource) {
-
-    rule = new Rule(ruleSource);
-
+    rule = RuleDocumentParser.parse(ruleSource);
     if (activeRuleSource.isEmpty()) {
       activeRuleId = null;
       severity = (String) ruleSource.get(ActiveRuleDocument.FIELD_SEVERITY);
@@ -68,8 +69,8 @@ public class QProfileRule {
         activeRuleNote = new RuleNote(
           (String) ruleNoteDocument.get(ActiveRuleDocument.FIELD_NOTE_DATA),
           (String) ruleNoteDocument.get(ActiveRuleDocument.FIELD_NOTE_USER_LOGIN),
-          Rule.parseOptionalDate(ActiveRuleDocument.FIELD_NOTE_CREATED_AT, ruleNoteDocument),
-          Rule.parseOptionalDate(ActiveRuleDocument.FIELD_NOTE_UPDATED_AT, ruleNoteDocument)
+          RuleDocumentParser.parseOptionalDate(ActiveRuleDocument.FIELD_NOTE_CREATED_AT, ruleNoteDocument),
+          RuleDocumentParser.parseOptionalDate(ActiveRuleDocument.FIELD_NOTE_UPDATED_AT, ruleNoteDocument)
         );
       } else {
         activeRuleNote = null;
@@ -97,11 +98,11 @@ public class QProfileRule {
   }
 
   public String key() {
-    return rule.key();
+    return rule.ruleKey().rule();
   }
 
   public String repositoryKey() {
-    return rule.repositoryKey();
+    return rule.ruleKey().repository();
   }
 
   public String language() {
@@ -156,11 +157,11 @@ public class QProfileRule {
     return rule.ruleNote();
   }
 
-  public List<String> systemTags() {
+  public Collection<String> systemTags() {
     return rule.systemTags();
   }
 
-  public List<String> adminTags() {
+  public Collection<String> adminTags() {
     return rule.adminTags();
   }
 
index 9e084358159bcd0345ffa700c2a652e5b28c099c..a6bb4e2e1b35af3579932ebc20858f33f91720c6 100644 (file)
  */
 package org.sonar.server.rule;
 
-import org.elasticsearch.common.collect.Lists;
-import org.elasticsearch.common.collect.Maps;
-import org.elasticsearch.common.joda.time.format.ISODateTimeFormat;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.check.Cardinality;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import static com.google.common.collect.Lists.newArrayList;
 
 public class Rule {
 
   private int id;
-  private String key;
+  private RuleKey ruleKey;
   private String language;
   private String name;
   private String description;
-  private Integer templateId;
-  private String repositoryKey;
   private String severity;
   private String status;
   private String cardinality;
+  private Integer templateId;
+  private RuleNote ruleNote;
+  private Collection<String> systemTags;
+  private Collection<String> adminTags;
+  private Collection<RuleParam> params;
   private Date createdAt;
   private Date updatedAt;
-  private List<String> systemTags;
-  private List<String> adminTags;
-  private RuleNote ruleNote;
-  private List<RuleParam> params;
-
-  /**
-   * Used to create manual rule
-   */
-  public Rule(String key, String name, String description, String repositoryKey, String severity, String status, Date createdAt, Date updatedAt) {
-    this.key = key;
-    this.name = name;
-    this.description = description;
-    this.repositoryKey = repositoryKey;
-    this.severity = severity;
-    this.status = status;
-    this.createdAt = createdAt;
-    this.updatedAt = updatedAt;
-    this.systemTags = newArrayList();
-    this.adminTags = newArrayList();
-
-  }
-
-  public Rule(Map<String, Object> ruleSource) {
-    id = (Integer) ruleSource.get(RuleDocument.FIELD_ID);
-    key = (String) ruleSource.get(RuleDocument.FIELD_KEY);
-    language = (String) ruleSource.get(RuleDocument.FIELD_LANGUAGE);
-    repositoryKey = (String) ruleSource.get(RuleDocument.FIELD_REPOSITORY_KEY);
-    severity = (String) ruleSource.get(RuleDocument.FIELD_SEVERITY);
-    name = (String) ruleSource.get(RuleDocument.FIELD_NAME);
-    description = (String) ruleSource.get(RuleDocument.FIELD_DESCRIPTION);
-    status = (String) ruleSource.get(RuleDocument.FIELD_STATUS);
-    cardinality = (String) ruleSource.get("cardinality");
-    templateId = (Integer) ruleSource.get(RuleDocument.FIELD_TEMPLATE_ID);
-    createdAt = parseOptionalDate(RuleDocument.FIELD_CREATED_AT, ruleSource);
-    updatedAt = parseOptionalDate(RuleDocument.FIELD_UPDATED_AT, ruleSource);
-
-    if (ruleSource.containsKey(RuleDocument.FIELD_NOTE)) {
-      Map<String, Object> ruleNoteDocument = (Map<String, Object>) ruleSource.get(RuleDocument.FIELD_NOTE);
-      ruleNote = new RuleNote(
-        (String) ruleNoteDocument.get(RuleDocument.FIELD_NOTE_DATA),
-        (String) ruleNoteDocument.get(RuleDocument.FIELD_NOTE_USER_LOGIN),
-        parseOptionalDate(RuleDocument.FIELD_NOTE_CREATED_AT, ruleNoteDocument),
-        parseOptionalDate(RuleDocument.FIELD_NOTE_UPDATED_AT, ruleNoteDocument)
-      );
-    } else {
-      ruleNote = null;
-    }
-
-    params = Lists.newArrayList();
-    if (ruleSource.containsKey(RuleDocument.FIELD_PARAMS)) {
-      Map<String, Map<String, Object>> ruleParams = Maps.newHashMap();
-      for (Map<String, Object> ruleParam: (List<Map<String, Object>>) ruleSource.get(RuleDocument.FIELD_PARAMS)) {
-        ruleParams.put((String) ruleParam.get(RuleDocument.FIELD_PARAM_KEY), ruleParam);
-      }
-      for(Map.Entry<String, Map<String, Object>> ruleParam: ruleParams.entrySet()) {
-        RuleParamType type = RuleParamType.parse((String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_TYPE));
-        params.add(new RuleParam(
-          (String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_KEY),
-          (String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_DESCRIPTION),
-          (String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_DEFAULT_VALUE),
-          type
-        ));
-      }
-    }
-
-    systemTags = Lists.newArrayList();
-    if (ruleSource.containsKey(RuleDocument.FIELD_SYSTEM_TAGS)) {
-      for (String tag: (List<String>) ruleSource.get(RuleDocument.FIELD_SYSTEM_TAGS)) {
-        systemTags.add(tag);
-      }
-    }
-    adminTags = Lists.newArrayList();
-    if (ruleSource.containsKey(RuleDocument.FIELD_ADMIN_TAGS)) {
-      for (String tag: (List<String>) ruleSource.get(RuleDocument.FIELD_ADMIN_TAGS)) {
-        adminTags.add(tag);
-      }
-    }
+
+  private Rule(Builder builder) {
+    this.id = builder.id;
+    this.ruleKey = RuleKey.of(builder.repositoryKey, builder.key);
+    this.language = builder.language;
+    this.name = builder.name;
+    this.description = builder.description;
+    this.severity = builder.severity;
+    this.status = builder.status;
+    this.cardinality = builder.cardinality;
+    this.templateId = builder.templateId;
+    this.ruleNote = builder.ruleNote;
+    this.systemTags = defaultCollection(builder.systemTags);
+    this.adminTags = defaultCollection(builder.adminTags);
+    this.params = defaultCollection(builder.params);
+    this.createdAt = builder.createdAt;
+    this.updatedAt = builder.updatedAt;
   }
 
   public int id() {
     return id;
   }
 
-  public String key() {
-    return key;
-  }
-
-  public String repositoryKey() {
-    return repositoryKey;
+  public RuleKey ruleKey() {
+    return ruleKey;
   }
 
   public String language() {
@@ -151,22 +85,42 @@ public class Rule {
     return description;
   }
 
+  public String severity() {
+    return severity;
+  }
+
   public String status() {
     return status;
   }
 
-  public Date createdAt() {
-    return createdAt;
+  public String cardinality() {
+    return cardinality;
   }
 
   @CheckForNull
-  public Date updatedAt() {
-    return updatedAt;
+  public Integer templateId() {
+    return templateId;
   }
 
   @CheckForNull
-  public Integer templateId() {
-    return templateId;
+  public RuleNote ruleNote() {
+    return ruleNote;
+  }
+
+  public Collection<String> systemTags() {
+    return systemTags;
+  }
+
+  public Collection<String> adminTags() {
+    return adminTags;
+  }
+
+  public Collection<RuleParam> params() {
+    return params;
+  }
+
+  public Date createdAt() {
+    return createdAt;
   }
 
   public boolean isTemplate() {
@@ -177,37 +131,117 @@ public class Rule {
     return templateId != null;
   }
 
-  public String severity() {
-    return severity;
+  @CheckForNull
+  public Date updatedAt() {
+    return updatedAt;
   }
 
-  public static Date parseOptionalDate(String field, Map<String, Object> ruleSource) {
-    String dateValue = (String) ruleSource.get(field);
-    if (dateValue == null) {
-      return null;
-    } else {
-      return ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(dateValue).toDate();
+  public static class Builder {
+
+    private int id;
+    private String key;
+    private String repositoryKey;
+    private String language;
+    private String name;
+    private String description;
+    private String severity;
+    private String status;
+    private String cardinality;
+    private Integer templateId;
+    private RuleNote ruleNote;
+    private Collection<String> systemTags;
+    private Collection<String> adminTags;
+    private Collection<RuleParam> params;
+    private Date createdAt;
+    private Date updatedAt;
+
+    public Builder setId(int id) {
+      this.id = id;
+      return this;
     }
-  }
 
-  @CheckForNull
-  public RuleNote ruleNote() {
-    return ruleNote;
-  }
+    public Builder setKey(String key) {
+      this.key = key;
+      return this;
+    }
 
-  public List<String> systemTags() {
-    return systemTags;
-  }
+    public Builder setRepositoryKey(String repositoryKey) {
+      this.repositoryKey = repositoryKey;
+      return this;
+    }
 
-  public List<String> adminTags() {
-    return adminTags;
-  }
+    public Builder setLanguage(String language) {
+      this.language = language;
+      return this;
+    }
 
-  public List<RuleParam> params() {
-    return params;
+    public Builder setName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public Builder setDescription(String description) {
+      this.description = description;
+      return this;
+    }
+
+    public Builder setSeverity(String severity) {
+      this.severity = severity;
+      return this;
+    }
+
+    public Builder setStatus(String status) {
+      this.status = status;
+      return this;
+    }
+
+    public Builder setCardinality(String cardinality) {
+      this.cardinality = cardinality;
+      return this;
+    }
+
+    public Builder setTemplateId(@Nullable Integer templateId) {
+      this.templateId = templateId;
+      return this;
+    }
+
+    public Builder setRuleNote(@Nullable RuleNote ruleNote) {
+      this.ruleNote = ruleNote;
+      return this;
+    }
+
+    public Builder setSystemTags(Collection<String> systemTags) {
+      this.systemTags = systemTags;
+      return this;
+    }
+
+    public Builder setAdminTags(Collection<String> adminTags) {
+      this.adminTags = adminTags;
+      return this;
+    }
+
+    public Builder setParams(Collection<RuleParam> params) {
+      this.params = params;
+      return this;
+    }
+
+    public Builder setCreatedAt(Date createdAt) {
+      this.createdAt = createdAt;
+      return this;
+    }
+
+    public Builder setUpdatedAt(@Nullable Date updatedAt) {
+      this.updatedAt = updatedAt;
+      return this;
+    }
+
+    public Rule build() {
+      // TODO Add validation on mandatory key, repokey, ...
+      return new Rule(this);
+    }
   }
 
-  public RuleKey ruleKey() {
-    return RuleKey.of(repositoryKey, key);
+  private static <T> Collection<T> defaultCollection(@Nullable Collection<T> c) {
+    return c == null ? Collections.<T>emptyList() : Collections.unmodifiableCollection(c);
   }
 }
diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleDocumentParser.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleDocumentParser.java
new file mode 100644 (file)
index 0000000..d45f9f1
--- /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.rule;
+
+import org.elasticsearch.common.collect.Lists;
+import org.elasticsearch.common.collect.Maps;
+import org.elasticsearch.common.joda.time.format.ISODateTimeFormat;
+import org.sonar.api.server.rule.RuleParamType;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+public class RuleDocumentParser {
+
+  public static Rule parse(Map<String, Object> ruleSource) {
+    Rule.Builder ruleBuilder = new Rule.Builder();
+
+    ruleBuilder.setId((Integer) ruleSource.get(RuleDocument.FIELD_ID));
+    ruleBuilder.setKey((String) ruleSource.get(RuleDocument.FIELD_KEY));
+    ruleBuilder.setLanguage((String) ruleSource.get(RuleDocument.FIELD_LANGUAGE));
+    ruleBuilder.setRepositoryKey((String) ruleSource.get(RuleDocument.FIELD_REPOSITORY_KEY));
+    ruleBuilder.setSeverity((String) ruleSource.get(RuleDocument.FIELD_SEVERITY));
+    ruleBuilder.setName((String) ruleSource.get(RuleDocument.FIELD_NAME));
+    ruleBuilder.setDescription((String) ruleSource.get(RuleDocument.FIELD_DESCRIPTION));
+    ruleBuilder.setStatus((String) ruleSource.get(RuleDocument.FIELD_STATUS));
+    ruleBuilder.setCardinality((String) ruleSource.get("cardinality"));
+    ruleBuilder.setTemplateId((Integer) ruleSource.get(RuleDocument.FIELD_TEMPLATE_ID));
+    ruleBuilder.setCreatedAt(parseOptionalDate(RuleDocument.FIELD_CREATED_AT, ruleSource));
+    ruleBuilder.setUpdatedAt(parseOptionalDate(RuleDocument.FIELD_UPDATED_AT, ruleSource));
+
+    if (ruleSource.containsKey(RuleDocument.FIELD_NOTE)) {
+      Map<String, Object> ruleNoteDocument = (Map<String, Object>) ruleSource.get(RuleDocument.FIELD_NOTE);
+      ruleBuilder.setRuleNote(new RuleNote(
+        (String) ruleNoteDocument.get(RuleDocument.FIELD_NOTE_DATA),
+        (String) ruleNoteDocument.get(RuleDocument.FIELD_NOTE_USER_LOGIN),
+        parseOptionalDate(RuleDocument.FIELD_NOTE_CREATED_AT, ruleNoteDocument),
+        parseOptionalDate(RuleDocument.FIELD_NOTE_UPDATED_AT, ruleNoteDocument)
+      ));
+    }
+
+    List<RuleParam> params = Lists.newArrayList();
+    if (ruleSource.containsKey(RuleDocument.FIELD_PARAMS)) {
+      Map<String, Map<String, Object>> ruleParams = Maps.newHashMap();
+      for (Map<String, Object> ruleParam: (List<Map<String, Object>>) ruleSource.get(RuleDocument.FIELD_PARAMS)) {
+        ruleParams.put((String) ruleParam.get(RuleDocument.FIELD_PARAM_KEY), ruleParam);
+      }
+      for(Map.Entry<String, Map<String, Object>> ruleParam: ruleParams.entrySet()) {
+        RuleParamType type = RuleParamType.parse((String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_TYPE));
+        params.add(new RuleParam(
+          (String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_KEY),
+          (String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_DESCRIPTION),
+          (String) ruleParam.getValue().get(RuleDocument.FIELD_PARAM_DEFAULT_VALUE),
+          type
+        ));
+      }
+    }
+    ruleBuilder.setParams(params);
+
+    List<String> systemTags = newArrayList();
+    if (ruleSource.containsKey(RuleDocument.FIELD_SYSTEM_TAGS)) {
+      for (String tag: (List<String>) ruleSource.get(RuleDocument.FIELD_SYSTEM_TAGS)) {
+        systemTags.add(tag);
+      }
+    }
+    ruleBuilder.setSystemTags(systemTags);
+
+    List<String> adminTags = newArrayList();
+    if (ruleSource.containsKey(RuleDocument.FIELD_ADMIN_TAGS)) {
+      for (String tag: (List<String>) ruleSource.get(RuleDocument.FIELD_ADMIN_TAGS)) {
+        adminTags.add(tag);
+      }
+    }
+    ruleBuilder.setAdminTags(adminTags);
+
+    return ruleBuilder.build();
+  }
+
+  public static Date parseOptionalDate(String field, Map<String, Object> ruleSource) {
+    String dateValue = (String) ruleSource.get(field);
+    if (dateValue == null) {
+      return null;
+    } else {
+      return ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(dateValue).toDate();
+    }
+  }
+}
+
index 48c9324de885986a90949d3f62fd3c1baa0ae5c3..f89cf8ebf3f6e0227a165787e1e6b902df96a762 100644 (file)
@@ -150,7 +150,7 @@ public class RuleRegistry {
     if (hits.totalHits() == 0) {
       return null;
     } else {
-      return new Rule(hits.hits()[0].sourceAsMap());
+      return RuleDocumentParser.parse(hits.hits()[0].sourceAsMap());
     }
   }
 
index 08695984efe373ccfc03ec63e234ef7718f0b53a..627397c5ffed598909e044cc55bc71a3a91a96c7 100644 (file)
@@ -76,8 +76,15 @@ public class RuleShowWsHandler implements RequestHandler {
     if (ruleKey.repository().equals("manual")) {
       org.sonar.api.rules.Rule rule = ruleFinder.findByKey(ruleKey);
       if (rule != null) {
-        return new Rule(rule.getKey(), rule.getName(), rule.getDescription(), rule.getRepositoryKey(), rule.getSeverity().name(), rule.getStatus(),
-          rule.getCreatedAt(), rule.getUpdatedAt());
+        return new Rule.Builder()
+          .setKey(rule.getKey())
+          .setRepositoryKey(rule.getRepositoryKey())
+          .setName(rule.getName())
+          .setDescription(rule.getDescription())
+          .setSeverity(rule.getSeverity().name())
+          .setStatus(rule.getStatus())
+          .setCreatedAt(rule.getCreatedAt())
+          .setUpdatedAt(rule.getUpdatedAt()).build();
       }
       return null;
     } else {
index cedbb446375a659e436dfb68e08e17ce04c75923..92847090d327eb53ed70da364caa0c11a1f5b2d9 100644 (file)
@@ -113,21 +113,19 @@ public class RuleRegistryTest {
     assertThat(esSetup.client().admin().indices().prepareTypesExists("rules").setTypes("rule").execute().actionGet().isExists()).isTrue();
   }
 
-
   @Test
   public void should_find_rule_by_key() {
     assertThat(registry.findByKey(RuleKey.of("unknown", "RuleWithParameters"))).isNull();
     assertThat(registry.findByKey(RuleKey.of("xoo", "unknown"))).isNull();
     final Rule rule = registry.findByKey(RuleKey.of("xoo", "RuleWithParameters"));
     assertThat(rule).isNotNull();
-    assertThat(rule.repositoryKey()).isEqualTo("xoo");
-    assertThat(rule.key()).isEqualTo("RuleWithParameters");
+    assertThat(rule.ruleKey().repository()).isEqualTo("xoo");
+    assertThat(rule.ruleKey().rule()).isEqualTo("RuleWithParameters");
     assertThat(rule.params()).hasSize(5);
     assertThat(rule.adminTags()).hasSize(1);
     assertThat(rule.systemTags()).hasSize(2);
   }
 
-
   @Test
   public void should_filter_removed_rules() {
     assertThat(registry.findIds(new HashMap<String, String>())).containsOnly(1, 2);
index 3c4e934f8504aaf616ed79a26c12b7214ac7f559..c380f753f9e657689a8a4cee95f659907cf35fa4 100644 (file)
@@ -59,6 +59,12 @@ public class RuleShowWsHandlerTest {
   @Mock
   I18n i18n;
 
+  Rule.Builder ruleBuilder = new Rule.Builder()
+    .setKey("AvoidCycle")
+    .setRepositoryKey("squid")
+    .setName("Avoid cycle")
+    .setDescription("Avoid cycle between packages");
+
   WsTester tester;
 
   @Before
@@ -69,7 +75,7 @@ public class RuleShowWsHandlerTest {
   @Test
   public void show_rule() throws Exception {
     String ruleKey = "squid:AvoidCycle";
-    Rule rule = createStandardRule();
+    Rule rule = ruleBuilder.build();
 
     when(rules.findByKey(RuleKey.of("squid", "AvoidCycle"))).thenReturn(rule);
 
@@ -79,7 +85,7 @@ public class RuleShowWsHandlerTest {
   }
 
   @Test
-  public void return_not_found_on_unkwown_rule() throws Exception {
+  public void return_not_found_on_unknown_rule() throws Exception {
     String ruleKey = "squid:AvoidCycle";
 
     when(rules.findByKey(RuleKey.of("squid", "AvoidCycle"))).thenReturn(null);
@@ -99,9 +105,10 @@ public class RuleShowWsHandlerTest {
   public void show_rule_with_dates() throws Exception {
     Date date1 = DateUtils.parseDateTime("2014-01-22T19:10:03+0100");
     Date date2 = DateUtils.parseDateTime("2014-01-23T19:10:03+0100");
-    Rule rule = createStandardRule();
-    when(rule.createdAt()).thenReturn(date1);
-    when(rule.updatedAt()).thenReturn(date2);
+    Rule rule = ruleBuilder
+      .setCreatedAt(date1)
+      .setUpdatedAt(date2)
+      .build();
 
     when(rules.findByKey(RuleKey.of("squid", "AvoidCycle"))).thenReturn(rule);
     when(i18n.formatDateTime(any(Locale.class), eq(date1))).thenReturn("Jan 22, 2014 10:03 AM");
@@ -114,10 +121,11 @@ public class RuleShowWsHandlerTest {
 
   @Test
   public void show_rule_with_note() throws Exception {
-    Rule rule = createStandardRule();
     RuleNote note = mock(RuleNote.class);
     when(note.data()).thenReturn("*Extended rule description*");
-    when(rule.ruleNote()).thenReturn(note);
+    Rule rule = ruleBuilder
+      .setRuleNote(note)
+      .build();
 
     when(rules.findByKey(RuleKey.of("squid", "AvoidCycle"))).thenReturn(rule);
 
@@ -128,9 +136,10 @@ public class RuleShowWsHandlerTest {
 
   @Test
   public void show_rule_with_tags() throws Exception {
-    Rule rule = createStandardRule();
-    when(rule.adminTags()).thenReturn(ImmutableList.of("complexity"));
-    when(rule.systemTags()).thenReturn(ImmutableList.of("security"));
+    Rule rule = ruleBuilder
+      .setAdminTags(ImmutableList.of("complexity"))
+      .setSystemTags(ImmutableList.of("security"))
+      .build();
 
     when(rules.findByKey(RuleKey.of("squid", "AvoidCycle"))).thenReturn(rule);
 
@@ -167,17 +176,4 @@ public class RuleShowWsHandlerTest {
     }
   }
 
-  private Rule create(String repoKey, String key, String name, String description) {
-    Rule mockRule = mock(Rule.class);
-    when(mockRule.repositoryKey()).thenReturn(repoKey);
-    when(mockRule.key()).thenReturn(key);
-    when(mockRule.ruleKey()).thenReturn(RuleKey.of(repoKey, key));
-    when(mockRule.name()).thenReturn(name);
-    when(mockRule.description()).thenReturn(description);
-    return mockRule;
-  }
-
-  private Rule createStandardRule() {
-    return create("squid", "AvoidCycle", "Avoid cycle", "Avoid cycle between packages");
-  }
 }