]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8857 support organizations in QProfileReference
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 13 Mar 2017 14:34:56 +0000 (15:34 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 23 Mar 2017 16:38:34 +0000 (17:38 +0100)
 + new method QProfileWsSupport#getProfile(DbSession,QProfileRef)

server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRef.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileReference.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileWsSupport.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRefTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRefTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileReferenceTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileWsSupportTest.java [new file with mode: 0644]

index 0faeb66e1056509eb64351c6fb41d0923f686c81..73ec2fc3e6c98f7301e5d43c1da2c48ed0a815c7 100644 (file)
@@ -37,6 +37,7 @@ import org.sonar.db.qualityprofile.ActiveRuleDto;
 import org.sonar.db.qualityprofile.QualityProfileDto;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.ws.QProfileReference;
 
 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
 import static org.sonar.server.ws.WsUtils.checkFound;
@@ -160,6 +161,10 @@ public class QProfileFactory {
     db.qualityProfileDao().update(session, profile.setDefault(true));
   }
 
+  /**
+   * @deprecated replaced by {@link org.sonar.server.qualityprofile.ws.QProfileWsSupport#getProfile(DbSession, QProfileReference)}
+   */
+  @Deprecated
   public QualityProfileDto find(DbSession dbSession, QProfileRef ref) {
     if (ref.hasKey()) {
       return findByKey(dbSession, ref.getKey());
index 150fed7ad2926787e27c38a2c43dc5d11ad49e75..098b02da4d84729bfac9a38f7a3e91dc7772323e 100644 (file)
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualityprofile.ws.QProfileReference;
 import org.sonar.server.util.LanguageParamUtils;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -36,7 +37,10 @@ import static org.apache.commons.lang.StringUtils.isEmpty;
  *   <li>by its key</li>
  *   <li>by the couple {language, name}</li>
  * </ul>
+ *
+ * @deprecated replaced by {@link QProfileReference}
  */
+@Deprecated
 public class QProfileRef {
 
   public static final String PARAM_LANGUAGE = "language";
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileReference.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileReference.java
new file mode 100644 (file)
index 0000000..2a53105
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualityprofile.ws;
+
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.util.LanguageParamUtils;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.lang.StringUtils.isEmpty;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
+
+/**
+ * Reference to a Quality profile as defined by requests to web services api/qualityprofiles.
+ * The two exclusive options to reference a profile are:
+ * <ul>
+ *   <li>by its id (to be deprecated)</li>
+ *   <li>by the tuple {organizationKey, language, name}</li>
+ * </ul>
+ */
+public class QProfileReference {
+
+  public static final String DEFAULT_PARAM_PROFILE_KEY = "profileKey";
+  public static final String DEFAULT_PARAM_LANGUAGE = "language";
+  public static final String DEFAULT_PARAM_PROFILE_NAME = "profileName";
+
+  private enum Type {
+    KEY, NAME
+  }
+
+  private final Type type;
+  private final String key;
+  private final String organizationKey;
+  private final String language;
+  private final String name;
+
+  private QProfileReference(Type type, @Nullable String key, @Nullable String organizationKey, @Nullable String language, @Nullable String name) {
+    this.type = type;
+    if (type == Type.KEY) {
+      this.key = requireNonNull(key);
+      this.organizationKey = null;
+      this.language = null;
+      this.name = null;
+    } else {
+      this.key = null;
+      this.organizationKey = organizationKey;
+      this.language = requireNonNull(language);
+      this.name = requireNonNull(name);
+    }
+  }
+
+  /**
+   * @return {@code true} if key is defined and {@link #getKey()} can be called. If {@code false}, then
+   *   the couple {language, name} is defined and the methods {@link #getLanguage()}/{@link #getName()}
+   *   can be called.
+   */
+  public boolean hasKey() {
+    return type == Type.KEY;
+  }
+
+  /**
+   * @return non-null key
+   * @throws IllegalStateException if {@link #hasKey()} does not return {@code true}
+   */
+  public String getKey() {
+    checkState(key != null, "Key is not defined. Please call hasKey().");
+    return key;
+  }
+
+  /**
+   * @return key of organization. It is empty when {@link #hasKey()} is {@code true} or if {@link #hasKey()} is
+   * {@code false} and the default organization must be used.
+   */
+  public Optional<String> getOrganizationKey() {
+    checkState(type == Type.NAME, "Organization is not defined. Please call hasKey().");
+    return Optional.ofNullable(organizationKey);
+  }
+
+  /**
+   * @return non-null language
+   * @throws IllegalStateException if {@link #hasKey()} does not return {@code false}
+   */
+  public String getLanguage() {
+    checkState(type == Type.NAME, "Language is not defined. Please call hasKey().");
+    return language;
+  }
+
+  /**
+   * @return non-null name
+   * @throws IllegalStateException if {@link #hasKey()} does not return {@code false}
+   */
+  public String getName() {
+    checkState(type == Type.NAME, "Name is not defined. Please call hasKey().");
+    return name;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    QProfileReference that = (QProfileReference) o;
+    if (key != null ? !key.equals(that.key) : (that.key != null)) {
+      return false;
+    }
+    if (organizationKey != null ? !organizationKey.equals(that.organizationKey) : (that.organizationKey != null)) {
+      return false;
+    }
+    if (language != null ? !language.equals(that.language) : (that.language != null)) {
+      return false;
+    }
+    return name != null ? name.equals(that.name) : (that.name == null);
+
+  }
+
+  @Override
+  public int hashCode() {
+    int result = key != null ? key.hashCode() : 0;
+    result = 31 * result + (organizationKey != null ? organizationKey.hashCode() : 0);
+    result = 31 * result + (language != null ? language.hashCode() : 0);
+    result = 31 * result + (name != null ? name.hashCode() : 0);
+    return result;
+  }
+
+  public static QProfileReference from(Request request) {
+    String key = request.param(DEFAULT_PARAM_PROFILE_KEY);
+    String organizationKey = request.param(PARAM_ORGANIZATION);
+    String lang = request.param(DEFAULT_PARAM_LANGUAGE);
+    String name = request.param(DEFAULT_PARAM_PROFILE_NAME);
+    return from(key, organizationKey, lang, name);
+  }
+
+  public static QProfileReference from(@Nullable String key, @Nullable String organizationKey, @Nullable String lang, @Nullable String name) {
+    if (key != null) {
+      checkArgument(isEmpty(organizationKey) && isEmpty(lang) && isEmpty(name), "Either key or tuple organization/language/name must be set");
+      return fromKey(key);
+    }
+    checkArgument(!isEmpty(lang) && !isEmpty(name), "Both profile language and name must be set");
+    return fromName(organizationKey, lang, name);
+  }
+
+  public static QProfileReference fromKey(String key) {
+    return new QProfileReference(Type.KEY, key, null, null, null);
+  }
+
+  public static QProfileReference fromName(@Nullable String organizationKey, String lang, String name) {
+    return new QProfileReference(Type.NAME, null, organizationKey, requireNonNull(lang), requireNonNull(name));
+  }
+
+  public static void defineParams(WebService.NewAction action, Languages languages) {
+    action.createParam(DEFAULT_PARAM_PROFILE_KEY)
+      .setDescription("A quality profile key. Either this parameter, or a combination of profileName + language must be set.")
+      .setExampleValue("sonar-way-java-12345");
+    action.createParam(DEFAULT_PARAM_PROFILE_NAME)
+      .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
+      .setExampleValue("Sonar way");
+    action.createParam(DEFAULT_PARAM_LANGUAGE)
+      .setDescription("A quality profile language. If this parameter is set, profileKey must not be set and profileName must be set to disambiguate.")
+      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
+      .setExampleValue("js");
+  }
+}
index 98cebdae6a849acd56dc9ba75b4339f3f4afc333..17afb81bc91966dca8d65df3854b3f5904507a7e 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.server.user.UserSession;
 import org.sonar.server.ws.WsUtils;
 
 import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
+import static org.sonar.server.ws.WsUtils.checkFound;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
 
 @ServerSide
@@ -60,7 +61,7 @@ public class QProfileWsSupport {
       .orElseGet(defaultOrganizationProvider.get()::getKey);
     return WsUtils.checkFoundWithOptional(
       dbClient.organizationDao().selectByKey(dbSession, organizationOrDefaultKey),
-      "No organizationDto with key '%s'", organizationOrDefaultKey);
+      "No organization with key '%s'", organizationOrDefaultKey);
   }
 
   /**
@@ -83,11 +84,11 @@ public class QProfileWsSupport {
 
   public NewParam createOrganizationParam(NewAction create) {
     return create
-    .createParam(PARAM_ORGANIZATION)
-    .setDescription("Organization key")
-    .setRequired(false)
-    .setInternal(true)
-    .setExampleValue("my-org");
+      .createParam(PARAM_ORGANIZATION)
+      .setDescription("Organization key")
+      .setRequired(false)
+      .setInternal(true)
+      .setExampleValue("my-org");
   }
 
   /**
@@ -98,4 +99,20 @@ public class QProfileWsSupport {
     return dbClient.organizationDao().selectByKey(dbSession, defaultOrganizationProvider.get().getKey())
       .orElseThrow(() -> new IllegalStateException("Could not find default organization"));
   }
+
+  /**
+   * Get the Quality profile specified by the reference {@code ref}.
+   *
+   * @throws org.sonar.server.exceptions.NotFoundException if the specified organization or profile do not exist
+   */
+  public QualityProfileDto getProfile(DbSession dbSession, QProfileReference ref) {
+    QualityProfileDto profile;
+    if (ref.hasKey()) {
+      profile = dbClient.qualityProfileDao().selectByKey(dbSession, ref.getKey());
+    } else {
+      OrganizationDto org = getOrganizationByKey(dbSession, ref.getOrganizationKey().orElse(null));
+      profile = dbClient.qualityProfileDao().selectByNameAndLanguage(org, ref.getName(), ref.getLanguage(), dbSession);
+    }
+    return checkFound(profile, "Quality Profile does not exist");
+  }
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRefTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRefTest.java
new file mode 100644 (file)
index 0000000..1e9bbb4
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualityprofile;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.internal.SimpleGetRequest;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class QProfileRefTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void create_ref_by_key() {
+    QProfileRef ref = QProfileRef.fromKey("foo");
+    assertThat(ref.hasKey()).isTrue();
+    assertThat(ref.getKey()).isEqualTo("foo");
+  }
+
+  @Test
+  public void getLanguage_throws_ISE_if_key_ref() {
+    QProfileRef ref = QProfileRef.fromKey("foo");
+
+    expectedException.expect(IllegalStateException.class);
+    ref.getLanguage();
+  }
+
+  @Test
+  public void getName_throws_ISE_if_key_ref() {
+    QProfileRef ref = QProfileRef.fromKey("foo");
+
+    expectedException.expect(IllegalStateException.class);
+    ref.getName();
+  }
+
+  @Test
+  public void create_ref_by_name() {
+    QProfileRef ref = QProfileRef.fromName("js", "Sonar way");
+    assertThat(ref.hasKey()).isFalse();
+    assertThat(ref.getLanguage()).isEqualTo("js");
+    assertThat(ref.getName()).isEqualTo("Sonar way");
+  }
+
+  @Test
+  public void getKey_throws_ISE_if_name_ref() {
+    QProfileRef ref = QProfileRef.fromName("js", "Sonar way");
+
+    expectedException.expect(IllegalStateException.class);
+    ref.getKey();
+  }
+
+  @Test
+  public void create_key_ref_from_ws_request() {
+    SimpleGetRequest req = new SimpleGetRequest();
+    req.setParam("profileKey", "foo");
+
+    QProfileRef ref = QProfileRef.from(req);
+    assertThat(ref.getKey()).isEqualTo("foo");
+  }
+
+  @Test
+  public void create_name_ref_from_ws_request() {
+    SimpleGetRequest req = new SimpleGetRequest();
+    req.setParam("language", "js");
+    req.setParam("profileName", "Sonar way");
+
+    QProfileRef ref = QProfileRef.from(req);
+    assertThat(ref.getLanguage()).isEqualTo("js");
+    assertThat(ref.getName()).isEqualTo("Sonar way");
+  }
+
+  @Test
+  public void create_name_ref_throws_IAE_if_language_is_missing() {
+    SimpleGetRequest req = new SimpleGetRequest();
+    req.setParam(QProfileRef.PARAM_PROFILE_KEY, "the key");
+    req.setParam(QProfileRef.PARAM_PROFILE_NAME, "the name");
+
+    expectedException.expect(IllegalArgumentException.class);
+    QProfileRef.from(req);
+  }
+
+  @Test
+  public void throw_IAE_if_request_does_not_define_ref() {
+    SimpleGetRequest req = new SimpleGetRequest();
+
+    expectedException.expect(IllegalArgumentException.class);
+    QProfileRef.from(req);
+  }
+
+  @Test
+  public void define_ws_parameters() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController controller = wsTester.context().createController("api/qualityprofiles");
+    WebService.NewAction newAction = controller.createAction("do").setHandler((request, response) -> {
+    });
+
+    Languages languages = new Languages(new FakeLanguage("java"), new FakeLanguage("js"));
+    QProfileRef.defineParams(newAction, languages);
+
+    controller.done();
+    WebService.Action action = wsTester.controller("api/qualityprofiles").action("do");
+    assertThat(action.param("language")).isNotNull();
+    assertThat(action.param("language").possibleValues()).containsOnly("java", "js");
+    assertThat(action.param("profileKey")).isNotNull();
+    assertThat(action.param("profileName")).isNotNull();
+  }
+
+  @Test
+  public void test_equals_and_hashCode_of_key_ref() {
+    QProfileRef key1 = QProfileRef.fromKey("one");
+    QProfileRef key1bis = QProfileRef.fromKey("one");
+    QProfileRef key2 = QProfileRef.fromKey("two");
+    QProfileRef name = QProfileRef.fromName("js", "one");
+
+    assertThat(key1.equals(key1)).isTrue();
+    assertThat(key1.equals(key1bis)).isTrue();
+    assertThat(key1.equals(key2)).isFalse();
+    assertThat(key1.equals(name)).isFalse();
+
+    assertThat(key1.hashCode()).isEqualTo(key1.hashCode());
+    assertThat(key1.hashCode()).isEqualTo(key1bis.hashCode());
+  }
+
+  @Test
+  public void test_equals_and_hashCode_of_name_ref() {
+    QProfileRef name1 = QProfileRef.fromName("js", "one");
+    QProfileRef name1bis = QProfileRef.fromName("js", "one");
+    QProfileRef name2 = QProfileRef.fromName("js", "two");
+    QProfileRef name1OtherLang = QProfileRef.fromName("java", "one");
+    QProfileRef key = QProfileRef.fromKey("one");
+
+    assertThat(name1.equals(name1)).isTrue();
+    assertThat(name1.equals(name1bis)).isTrue();
+    assertThat(name1.equals(name2)).isFalse();
+    assertThat(name1.equals(name1OtherLang)).isFalse();
+    assertThat(name1.equals(key)).isFalse();
+
+    assertThat(name1.hashCode()).isEqualTo(name1.hashCode());
+    assertThat(name1.hashCode()).isEqualTo(name1bis.hashCode());
+  }
+
+  private static class FakeLanguage implements Language {
+    private final String key;
+
+    public FakeLanguage(String key) {
+      this.key = key;
+    }
+
+    @Override
+    public String getKey() {
+      return key;
+    }
+
+    @Override
+    public String getName() {
+      return key;
+    }
+
+    @Override
+    public String[] getFileSuffixes() {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRefTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRefTest.java
deleted file mode 100644 (file)
index 6db5c43..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.qualityprofile.ws;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.internal.SimpleGetRequest;
-import org.sonar.server.qualityprofile.QProfileRef;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-
-public class QProfileRefTest {
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void create_ref_by_key() {
-    QProfileRef ref = QProfileRef.fromKey("foo");
-    assertThat(ref.hasKey()).isTrue();
-    assertThat(ref.getKey()).isEqualTo("foo");
-  }
-
-  @Test
-  public void getLanguage_throws_ISE_if_key_ref() {
-    QProfileRef ref = QProfileRef.fromKey("foo");
-
-    expectedException.expect(IllegalStateException.class);
-    ref.getLanguage();
-  }
-
-  @Test
-  public void getName_throws_ISE_if_key_ref() {
-    QProfileRef ref = QProfileRef.fromKey("foo");
-
-    expectedException.expect(IllegalStateException.class);
-    ref.getName();
-  }
-
-  @Test
-  public void create_ref_by_name() {
-    QProfileRef ref = QProfileRef.fromName("js", "Sonar way");
-    assertThat(ref.hasKey()).isFalse();
-    assertThat(ref.getLanguage()).isEqualTo("js");
-    assertThat(ref.getName()).isEqualTo("Sonar way");
-  }
-
-  @Test
-  public void getKey_throws_ISE_if_name_ref() {
-    QProfileRef ref = QProfileRef.fromName("js", "Sonar way");
-
-    expectedException.expect(IllegalStateException.class);
-    ref.getKey();
-  }
-
-
-  @Test
-  public void create_key_ref_from_ws_request() {
-    SimpleGetRequest req = new SimpleGetRequest();
-    req.setParam("profileKey", "foo");
-
-    QProfileRef ref = QProfileRef.from(req);
-    assertThat(ref.getKey()).isEqualTo("foo");
-  }
-
-  @Test
-  public void create_name_ref_from_ws_request() {
-    SimpleGetRequest req = new SimpleGetRequest();
-    req.setParam("language", "js");
-    req.setParam("profileName", "Sonar way");
-
-    QProfileRef ref = QProfileRef.from(req);
-    assertThat(ref.getLanguage()).isEqualTo("js");
-    assertThat(ref.getName()).isEqualTo("Sonar way");
-  }
-
-  @Test
-  public void create_name_ref_throws_IAE_if_language_is_missing() {
-    SimpleGetRequest req = new SimpleGetRequest();
-    req.setParam(QProfileRef.PARAM_PROFILE_KEY, "the key");
-    req.setParam(QProfileRef.PARAM_PROFILE_NAME, "the name");
-
-    expectedException.expect(IllegalArgumentException.class);
-    QProfileRef.from(req);
-  }
-
-  @Test
-  public void throw_IAE_if_request_does_not_define_ref() {
-    SimpleGetRequest req = new SimpleGetRequest();
-
-    expectedException.expect(IllegalArgumentException.class);
-    QProfileRef.from(req);
-  }
-
-  @Test
-  public void define_ws_parameters() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController controller = wsTester.context().createController("api/qualityprofiles");
-    WebService.NewAction newAction = controller.createAction("do").setHandler((request, response) -> {
-    });
-
-    Languages languages = new Languages(new FakeLanguage("java"), new FakeLanguage("js"));
-    QProfileRef.defineParams(newAction, languages);
-
-    controller.done();
-    WebService.Action action = wsTester.controller("api/qualityprofiles").action("do");
-    assertThat(action.param("language")).isNotNull();
-    assertThat(action.param("language").possibleValues()).containsOnly("java", "js");
-    assertThat(action.param("profileKey")).isNotNull();
-    assertThat(action.param("profileName")).isNotNull();
-  }
-
-  @Test
-  public void test_equals_and_hashCode_of_key_ref() {
-    QProfileRef key1 = QProfileRef.fromKey("one");
-    QProfileRef key1bis = QProfileRef.fromKey("one");
-    QProfileRef key2 = QProfileRef.fromKey("two");
-    QProfileRef name = QProfileRef.fromName("js", "one");
-
-    assertThat(key1.equals(key1)).isTrue();
-    assertThat(key1.equals(key1bis)).isTrue();
-    assertThat(key1.equals(key2)).isFalse();
-    assertThat(key1.equals(name)).isFalse();
-
-    assertThat(key1.hashCode()).isEqualTo(key1.hashCode());
-    assertThat(key1.hashCode()).isEqualTo(key1bis.hashCode());
-  }
-
-  @Test
-  public void test_equals_and_hashCode_of_name_ref() {
-    QProfileRef name1 = QProfileRef.fromName("js", "one");
-    QProfileRef name1bis = QProfileRef.fromName("js", "one");
-    QProfileRef name2 = QProfileRef.fromName("js", "two");
-    QProfileRef name1OtherLang = QProfileRef.fromName("java", "one");
-    QProfileRef key = QProfileRef.fromKey("one");
-
-    assertThat(name1.equals(name1)).isTrue();
-    assertThat(name1.equals(name1bis)).isTrue();
-    assertThat(name1.equals(name2)).isFalse();
-    assertThat(name1.equals(name1OtherLang)).isFalse();
-    assertThat(name1.equals(key)).isFalse();
-
-    assertThat(name1.hashCode()).isEqualTo(name1.hashCode());
-    assertThat(name1.hashCode()).isEqualTo(name1bis.hashCode());
-  }
-
-  private static class FakeLanguage implements Language {
-    private final String key;
-
-    public FakeLanguage(String key) {
-      this.key = key;
-    }
-
-    @Override
-    public String getKey() {
-      return key;
-    }
-
-    @Override
-    public String getName() {
-      return key;
-    }
-
-    @Override
-    public String[] getFileSuffixes() {
-      throw new UnsupportedOperationException();
-    }
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileReferenceTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileReferenceTest.java
new file mode 100644 (file)
index 0000000..fd4b0c1
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualityprofile.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.internal.SimpleGetRequest;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.language.LanguageTesting.newLanguage;
+
+public class QProfileReferenceTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void fromKey_creates_reference_by_key() {
+    QProfileReference ref = QProfileReference.fromKey("foo");
+    assertThat(ref.hasKey()).isTrue();
+    assertThat(ref.getKey()).isEqualTo("foo");
+  }
+
+  @Test
+  public void getLanguage_throws_ISE_on_reference_by_key() {
+    QProfileReference ref = QProfileReference.fromKey("foo");
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Language is not defined. Please call hasKey().");
+    ref.getLanguage();
+  }
+
+  @Test
+  public void getName_throws_ISE_on_reference_by_key() {
+    QProfileReference ref = QProfileReference.fromKey("foo");
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Name is not defined. Please call hasKey().");
+    ref.getName();
+  }
+
+  @Test
+  public void fromName_creates_reference_by_name_on_default_organization() {
+    QProfileReference ref = QProfileReference.fromName(null, "js", "Sonar way");
+    assertThat(ref.hasKey()).isFalse();
+    assertThat(ref.getOrganizationKey()).isEmpty();
+    assertThat(ref.getLanguage()).isEqualTo("js");
+    assertThat(ref.getName()).isEqualTo("Sonar way");
+  }
+
+  @Test
+  public void fromName_creates_reference_by_name_on_specified_organization() {
+    QProfileReference ref = QProfileReference.fromName("my-org", "js", "Sonar way");
+    assertThat(ref.hasKey()).isFalse();
+    assertThat(ref.getOrganizationKey()).hasValue("my-org");
+    assertThat(ref.getLanguage()).isEqualTo("js");
+    assertThat(ref.getName()).isEqualTo("Sonar way");
+  }
+
+  @Test
+  public void getKey_throws_ISE_on_reference_by_name() {
+    QProfileReference ref = QProfileReference.fromName(null, "js", "Sonar way");
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Key is not defined. Please call hasKey().");
+
+    ref.getKey();
+  }
+
+  @Test
+  public void getOrganization_throws_ISE_on_reference_by_key() {
+    QProfileReference ref = QProfileReference.fromKey("foo");
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Organization is not defined. Please call hasKey().");
+
+    ref.getOrganizationKey();
+  }
+
+  @Test
+  public void from_reads_request_parameters_and_creates_reference_by_key() {
+    SimpleGetRequest req = new SimpleGetRequest();
+    req.setParam("profileKey", "foo");
+
+    QProfileReference ref = QProfileReference.from(req);
+    assertThat(ref.getKey()).isEqualTo("foo");
+  }
+
+  @Test
+  public void from_reads_request_parameters_and_creates_reference_by_name_on_default_organization() {
+    SimpleGetRequest req = new SimpleGetRequest();
+    req.setParam("language", "js");
+    req.setParam("profileName", "Sonar way");
+
+    QProfileReference ref = QProfileReference.from(req);
+    assertThat(ref.getOrganizationKey()).isEmpty();
+    assertThat(ref.getLanguage()).isEqualTo("js");
+    assertThat(ref.getName()).isEqualTo("Sonar way");
+  }
+
+  @Test
+  public void from_reads_request_parameters_and_creates_reference_by_name_on_specified_organization() {
+    SimpleGetRequest req = new SimpleGetRequest();
+    req.setParam("organization", "my-org");
+    req.setParam("language", "js");
+    req.setParam("profileName", "Sonar way");
+
+    QProfileReference ref = QProfileReference.from(req);
+    assertThat(ref.getOrganizationKey()).hasValue("my-org");
+    assertThat(ref.getLanguage()).isEqualTo("js");
+    assertThat(ref.getName()).isEqualTo("Sonar way");
+  }
+
+  @Test
+  public void from_reads_request_parameters_and_throws_IAE_if_language_is_missing() {
+    SimpleGetRequest req = new SimpleGetRequest();
+    req.setParam("profileName", "the name");
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Both profile language and name must be set");
+
+    QProfileReference.from(req);
+  }
+
+  @Test
+  public void throw_IAE_if_request_does_not_define_ref() {
+    SimpleGetRequest req = new SimpleGetRequest();
+
+    expectedException.expect(IllegalArgumentException.class);
+    QProfileReference.from(req);
+  }
+
+  @Test
+  public void define_ws_parameters() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController controller = wsTester.context().createController("api/qualityprofiles");
+    WebService.NewAction newAction = controller.createAction("do").setHandler((request, response) -> {
+    });
+
+    Languages languages = new Languages(newLanguage("java"), newLanguage("js"));
+    QProfileReference.defineParams(newAction, languages);
+
+    controller.done();
+    WebService.Action action = wsTester.controller("api/qualityprofiles").action("do");
+    assertThat(action.param("language")).isNotNull();
+    assertThat(action.param("language").possibleValues()).containsOnly("java", "js");
+    assertThat(action.param("profileKey")).isNotNull();
+    assertThat(action.param("profileName")).isNotNull();
+  }
+
+  @Test
+  public void test_equals_and_hashCode_of_key_ref() {
+    QProfileReference key1 = QProfileReference.fromKey("one");
+    QProfileReference key1bis = QProfileReference.fromKey("one");
+    QProfileReference key2 = QProfileReference.fromKey("two");
+    QProfileReference name = QProfileReference.fromName("my-org", "js", "one");
+
+    assertThat(key1.equals(key1)).isTrue();
+    assertThat(key1.equals(key1bis)).isTrue();
+    assertThat(key1.equals(key2)).isFalse();
+    assertThat(key1.equals(name)).isFalse();
+
+    assertThat(key1.hashCode()).isEqualTo(key1.hashCode());
+    assertThat(key1.hashCode()).isEqualTo(key1bis.hashCode());
+  }
+
+  @Test
+  public void test_equals_and_hashCode_of_name_ref() {
+    QProfileReference name1 = QProfileReference.fromName("org1", "js", "one");
+    QProfileReference name1bis = QProfileReference.fromName("org1", "js", "one");
+    QProfileReference name2 = QProfileReference.fromName("org1", "js", "two");
+    QProfileReference name1OtherLang = QProfileReference.fromName("org1", "java", "one");
+    QProfileReference key = QProfileReference.fromKey("one");
+
+    assertThat(name1.equals(name1)).isTrue();
+    assertThat(name1.equals(name1bis)).isTrue();
+    assertThat(name1.equals(name2)).isFalse();
+    assertThat(name1.equals(name1OtherLang)).isFalse();
+    assertThat(name1.equals(key)).isFalse();
+
+    assertThat(name1.hashCode()).isEqualTo(name1.hashCode());
+    assertThat(name1.hashCode()).isEqualTo(name1bis.hashCode());
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileWsSupportTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileWsSupportTest.java
new file mode 100644 (file)
index 0000000..12ca0ca
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualityprofile.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.db.qualityprofile.QualityProfileTesting;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.organization.DefaultOrganizationProvider;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.tester.UserSessionRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class QProfileWsSupportTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public DbTester db = DbTester.create();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  private DefaultOrganizationProvider defaultOrgProvider = TestDefaultOrganizationProvider.from(db);
+  private QProfileWsSupport underTest = new QProfileWsSupport(db.getDbClient(), userSession, defaultOrgProvider);
+
+  @Test
+  public void getProfile_returns_the_profile_specified_by_key() {
+    QualityProfileDto profile = db.qualityProfiles().insertQualityProfile(QualityProfileTesting.newQualityProfileDto());
+
+    QualityProfileDto loaded = underTest.getProfile(db.getSession(), QProfileReference.fromKey(profile.getKey()));
+
+    assertThat(loaded.getKey()).isEqualTo(profile.getKey());
+    assertThat(loaded.getOrganizationUuid()).isEqualTo(profile.getOrganizationUuid());
+    assertThat(loaded.getLanguage()).isEqualTo(profile.getLanguage());
+    assertThat(loaded.getName()).isEqualTo(profile.getName());
+  }
+
+  @Test
+  public void getProfile_throws_NotFoundException_if_specified_key_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Quality Profile does not exist");
+
+    underTest.getProfile(db.getSession(), QProfileReference.fromKey("missing"));
+  }
+
+  @Test
+  public void getProfile_returns_the_profile_specified_by_name_and_default_organization() {
+    QualityProfileDto profile = QualityProfileTesting.newQualityProfileDto().setOrganizationUuid(db.getDefaultOrganization().getUuid());
+    db.qualityProfiles().insertQualityProfile(profile);
+
+    QualityProfileDto loaded = underTest.getProfile(db.getSession(), QProfileReference.fromName(null, profile.getLanguage(), profile.getName()));
+
+    assertThat(loaded.getKey()).isEqualTo(profile.getKey());
+    assertThat(loaded.getOrganizationUuid()).isEqualTo(profile.getOrganizationUuid());
+    assertThat(loaded.getLanguage()).isEqualTo(profile.getLanguage());
+    assertThat(loaded.getName()).isEqualTo(profile.getName());
+  }
+
+  @Test
+  public void getProfile_throws_NotFoundException_if_specified_name_does_not_exist_on_default_organization() {
+    QualityProfileDto profile = QualityProfileTesting.newQualityProfileDto().setOrganizationUuid(db.getDefaultOrganization().getUuid());
+    db.qualityProfiles().insertQualityProfile(profile);
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Quality Profile does not exist");
+
+    underTest.getProfile(db.getSession(), QProfileReference.fromName(null, "java", "missing"));
+  }
+
+  @Test
+  public void getProfile_throws_NotFoundException_if_specified_name_does_not_exist_on_specified_organization() {
+    OrganizationDto org1 = db.organizations().insert();
+    QualityProfileDto profile = QualityProfileTesting.newQualityProfileDto().setOrganizationUuid(org1.getUuid());
+    db.qualityProfiles().insertQualityProfile(profile);
+    OrganizationDto org2 = db.organizations().insert();
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Quality Profile does not exist");
+
+    underTest.getProfile(db.getSession(), QProfileReference.fromName(org2.getKey(), profile.getLanguage(), profile.getName()));
+  }
+
+  @Test
+  public void getProfile_throws_NotFoundException_if_specified_organization_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("No organization with key 'the-org'");
+
+    underTest.getProfile(db.getSession(), QProfileReference.fromName("the-org", "java", "the-name"));
+  }
+}