diff options
author | Julien Lancelot <julien.lancelot@gmail.com> | 2013-06-19 11:36:10 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@gmail.com> | 2013-06-19 11:36:19 +0200 |
commit | 9bdc6b392d81a344d660a16fbbced7df97291e2a (patch) | |
tree | 5eb3a6ce045f34a9668257734942c7f1332f483d /sonar-core/src | |
parent | be13d66e40f985a7e4a6843c136b15ae7b378259 (diff) | |
download | sonarqube-9bdc6b392d81a344d660a16fbbced7df97291e2a.tar.gz sonarqube-9bdc6b392d81a344d660a16fbbced7df97291e2a.zip |
SONAR-4394 shared issue filters name must be unique
Diffstat (limited to 'sonar-core/src')
-rw-r--r-- | sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueFilter.java | 95 | ||||
-rw-r--r-- | sonar-core/src/main/java/org/sonar/core/issue/IssueFilterSerializer.java | 107 | ||||
-rw-r--r-- | sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDao.java | 13 | ||||
-rw-r--r-- | sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterMapper.java | 5 | ||||
-rw-r--r-- | sonar-core/src/main/resources/org/sonar/core/issue/db/IssueFilterMapper.xml | 17 | ||||
-rw-r--r-- | sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml | 2 | ||||
-rw-r--r-- | sonar-core/src/test/java/org/sonar/core/issue/IssueFilterSerializerTest.java (renamed from sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueFilterTest.java) | 63 | ||||
-rw-r--r-- | sonar-core/src/test/java/org/sonar/core/issue/db/IssueFilterDaoTest.java | 19 | ||||
-rw-r--r-- | sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/should_select_shared_by_name.xml | 27 |
9 files changed, 214 insertions, 134 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueFilter.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueFilter.java index db2b2b9fbf7..f2269b81a3e 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueFilter.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueFilter.java @@ -20,25 +20,10 @@ package org.sonar.core.issue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; - import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import static com.google.common.collect.Lists.newArrayList; -import static com.google.common.collect.Maps.newHashMap; public class DefaultIssueFilter { - public static final String SEPARATOR = "|"; - public static final String KEY_VALUE_SEPARATOR = "="; - public static final String LIST_SEPARATOR = ","; - private Long id; private String name; private String user; @@ -60,10 +45,6 @@ public class DefaultIssueFilter { return issueFilter; } - public DefaultIssueFilter(Map<String, Object> mapData) { - setData(mapData); - } - public Long id() { return id; } @@ -136,80 +117,4 @@ public class DefaultIssueFilter { return this; } - public final DefaultIssueFilter setData(Map<String, Object> mapData) { - this.data = mapAsdata(mapData); - return this; - } - - /** - * Used by ui - */ - public Map<String, Object> dataAsMap(){ - return dataAsMap(data); - } - - @VisibleForTesting - final Map<String, Object> dataAsMap(String data) { - Map<String, Object> map = newHashMap(); - - Iterable<String> keyValues = Splitter.on(DefaultIssueFilter.SEPARATOR).split(data); - for (String keyValue : keyValues) { - String[] keyValueSplit = StringUtils.split(keyValue, DefaultIssueFilter.KEY_VALUE_SEPARATOR); - if (keyValueSplit.length == 2) { - String key = keyValueSplit[0]; - String value = keyValueSplit[1]; - String[] listValues = StringUtils.split(value, DefaultIssueFilter.LIST_SEPARATOR); - if (listValues.length > 1) { - map.put(key, newArrayList(listValues)); - } else { - map.put(key, value); - } - } - } - return map; - } - - @VisibleForTesting - final String mapAsdata(Map<String, Object> map) { - StringBuilder stringBuilder = new StringBuilder(); - - for (Map.Entry<String, Object> entries : map.entrySet()){ - String key = entries.getKey(); - Object value = entries.getValue(); - if (value != null) { - List valuesList = newArrayList(); - if (value instanceof List) { - // assume that it contains only strings - valuesList = (List) value; - } else if (value instanceof CharSequence) { - valuesList = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().split((CharSequence) value)); - } else { - stringBuilder.append(key); - stringBuilder.append(DefaultIssueFilter.KEY_VALUE_SEPARATOR); - stringBuilder.append(value); - stringBuilder.append(DefaultIssueFilter.SEPARATOR); - } - if (!valuesList.isEmpty()) { - stringBuilder.append(key); - stringBuilder.append(DefaultIssueFilter.KEY_VALUE_SEPARATOR); - for (Iterator<Object> valueListIter = valuesList.iterator(); valueListIter.hasNext();) { - Object valueList = valueListIter.next(); - stringBuilder.append(valueList); - if (valueListIter.hasNext()) { - stringBuilder.append(DefaultIssueFilter.LIST_SEPARATOR); - } - } - stringBuilder.append(DefaultIssueFilter.SEPARATOR); - } - } - } - - if (stringBuilder.length() > 0) { - // Delete useless last separator character - stringBuilder.deleteCharAt(stringBuilder.length() - 1); - } - - return stringBuilder.toString(); - } - } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueFilterSerializer.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueFilterSerializer.java new file mode 100644 index 00000000000..3a1f5d20c9c --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueFilterSerializer.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.core.issue; + +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.ServerComponent; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.newHashMap; + +public class IssueFilterSerializer implements ServerComponent { + + public static final String SEPARATOR = "|"; + public static final String KEY_VALUE_SEPARATOR = "="; + public static final String LIST_SEPARATOR = ","; + + public IssueFilterSerializer() { + + } + + public String serialize(Map<String, Object> map) { + StringBuilder stringBuilder = new StringBuilder(); + + for (Map.Entry<String, Object> entries : map.entrySet()) { + String key = entries.getKey(); + Object value = entries.getValue(); + if (value != null) { + List valuesList = newArrayList(); + if (value instanceof List) { + // assume that it contains only strings + valuesList = (List) value; + } else if (value instanceof CharSequence) { + valuesList = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().split((CharSequence) value)); + } else { + stringBuilder.append(key); + stringBuilder.append(IssueFilterSerializer.KEY_VALUE_SEPARATOR); + stringBuilder.append(value); + stringBuilder.append(IssueFilterSerializer.SEPARATOR); + } + if (!valuesList.isEmpty()) { + stringBuilder.append(key); + stringBuilder.append(IssueFilterSerializer.KEY_VALUE_SEPARATOR); + for (Iterator<Object> valueListIter = valuesList.iterator(); valueListIter.hasNext(); ) { + Object valueList = valueListIter.next(); + stringBuilder.append(valueList); + if (valueListIter.hasNext()) { + stringBuilder.append(IssueFilterSerializer.LIST_SEPARATOR); + } + } + stringBuilder.append(IssueFilterSerializer.SEPARATOR); + } + } + } + + if (stringBuilder.length() > 0) { + // Delete useless last separator character + stringBuilder.deleteCharAt(stringBuilder.length() - 1); + } + + return stringBuilder.toString(); + } + + public Map<String, Object> deserialize(String data) { + Map<String, Object> map = newHashMap(); + + Iterable<String> keyValues = Splitter.on(IssueFilterSerializer.SEPARATOR).split(data); + for (String keyValue : keyValues) { + String[] keyValueSplit = StringUtils.split(keyValue, IssueFilterSerializer.KEY_VALUE_SEPARATOR); + if (keyValueSplit.length == 2) { + String key = keyValueSplit[0]; + String value = keyValueSplit[1]; + String[] listValues = StringUtils.split(value, IssueFilterSerializer.LIST_SEPARATOR); + if (listValues.length > 1) { + map.put(key, newArrayList(listValues)); + } else { + map.put(key, value); + } + } + } + return map; + } + +} diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDao.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDao.java index b4ffcaeb880..572d23e41ed 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDao.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDao.java @@ -80,10 +80,19 @@ public class IssueFilterDao implements BatchComponent, ServerComponent { } } - public List<IssueFilterDto> selectSharedForUser(String user) { + public List<IssueFilterDto> selectSharedWithoutUserFilters(String user) { SqlSession session = mybatis.openSession(); try { - return getMapper(session).selectSharedForUser(user); + return getMapper(session).selectSharedWithoutUserFilters(user); + } finally { + MyBatis.closeQuietly(session); + } + } + + public IssueFilterDto selectSharedWithoutUserFiltersByName(String name, String user, @Nullable Long existingId) { + SqlSession session = mybatis.openSession(); + try { + return getMapper(session).selectSharedWithoutUserFiltersByName(name, user, existingId); } finally { MyBatis.closeQuietly(session); } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterMapper.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterMapper.java index 53cf2b936eb..eb634af22b6 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterMapper.java @@ -41,7 +41,10 @@ public interface IssueFilterMapper { List<IssueFilterDto> selectByUserWithOnlyFavoriteFilters(String user); - List<IssueFilterDto> selectSharedForUser(String user); + List<IssueFilterDto> selectSharedWithoutUserFilters(String user); + + @CheckForNull + IssueFilterDto selectSharedWithoutUserFiltersByName(@Param("name") String name, @Param("userLogin") String userLogin, @Nullable @Param("existingId") Long existingId); void insert(IssueFilterDto filter); diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueFilterMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueFilterMapper.xml index a31b00273c5..a85abad3bbe 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueFilterMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueFilterMapper.xml @@ -52,12 +52,25 @@ </where> </select> - <select id="selectSharedForUser" parameterType="String" resultType="IssueFilter"> + <select id="selectSharedWithoutUserFilters" parameterType="String" resultType="IssueFilter"> select <include refid="issueFilterColumns"/> from issue_filters filters <where> filters.shared=${_true} - and filters.user_login<>#{user} + and filters.user_login<>#{userLogin} + </where> + </select> + + <select id="selectSharedWithoutUserFiltersByName" parameterType="String" resultType="IssueFilter"> + select <include refid="issueFilterColumns"/> + from issue_filters filters + <where> + filters.shared=${_true} + and filters.user_login<>#{userLogin} + and filters.name=#{name} + <if test="existingId != null"> + and filters.id<>#{existingId} + </if> </where> </select> diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index 06fa350595e..a6b5c76457f 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -217,7 +217,7 @@ <!-- Oracle --> <select id="selectIssues" parameterType="map" resultType="Issue" fetchSize="100000" databaseId="oracle"> - select * from (select i.id + select id from (select i.id <include refid="sortColumn"/> <include refid="selectQueryConditions"/> ) where rownum <= #{maxResults} diff --git a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueFilterTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueFilterSerializerTest.java index 4bf9d656f50..cc7f4a7dabd 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueFilterTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueFilterSerializerTest.java @@ -29,37 +29,12 @@ import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newLinkedHashMap; import static org.fest.assertions.Assertions.assertThat; -public class DefaultIssueFilterTest { +public class IssueFilterSerializerTest { - DefaultIssueFilter issueFilter = new DefaultIssueFilter(); + IssueFilterSerializer issueFilterSerializer = new IssueFilterSerializer(); @Test - public void should_convert_data_to_map() { - String data = "issues=ABCDE1234|severities=MAJOR,MINOR|resolved=true|pageSize=10|pageIndex=50"; - - Map<String, Object> map = issueFilter.dataAsMap(data); - - assertThat(map).hasSize(5); - assertThat(map.get("issues")).isEqualTo("ABCDE1234"); - assertThat(map.get("severities")).isInstanceOf(List.class); - assertThat((List<String>) map.get("severities")).contains("MAJOR", "MINOR"); - assertThat(map.get("resolved")).isEqualTo("true"); - assertThat(map.get("pageSize")).isEqualTo("10"); - assertThat(map.get("pageIndex")).isEqualTo("50"); - } - - @Test - public void should_remove_empty_value_when_converting_data_to_map() { - String data = "issues=ABCDE1234|severities="; - - Map<String, Object> map = issueFilter.dataAsMap(data); - - assertThat(map).hasSize(1); - assertThat(map.get("issues")).isEqualTo("ABCDE1234"); - } - - @Test - public void should_convert_map_to_data() { + public void should_serialize() { Map<String, Object> map = newLinkedHashMap(); map.put("issues", newArrayList("ABCDE1234")); map.put("severities", newArrayList("MAJOR", "MINOR")); @@ -67,21 +42,47 @@ public class DefaultIssueFilterTest { map.put("pageSize", 10l); map.put("pageIndex", 50); - String result = issueFilter.mapAsdata(map); + String result = issueFilterSerializer.serialize(map); assertThat(result).isEqualTo("issues=ABCDE1234|severities=MAJOR,MINOR|resolved=true|pageSize=10|pageIndex=50"); } @Test - public void should_remove_empty_value_when_converting_convert_map_to_data() { + public void should_remove_empty_value_when_serializing() { Map<String, Object> map = newLinkedHashMap(); map.put("issues", newArrayList("ABCDE1234")); map.put("resolved", null); map.put("pageSize", ""); - String result = issueFilter.mapAsdata(map); + String result = issueFilterSerializer.serialize(map); assertThat(result).isEqualTo("issues=ABCDE1234"); } + @Test + public void should_deserialize() { + String data = "issues=ABCDE1234|severities=MAJOR,MINOR|resolved=true|pageSize=10|pageIndex=50"; + + Map<String, Object> map = issueFilterSerializer.deserialize(data); + + assertThat(map).hasSize(5); + assertThat(map.get("issues")).isEqualTo("ABCDE1234"); + assertThat(map.get("severities")).isInstanceOf(List.class); + assertThat((List<String>) map.get("severities")).contains("MAJOR", "MINOR"); + assertThat(map.get("resolved")).isEqualTo("true"); + assertThat(map.get("pageSize")).isEqualTo("10"); + assertThat(map.get("pageIndex")).isEqualTo("50"); + } + + @Test + public void should_remove_empty_value_when_deserializing() { + String data = "issues=ABCDE1234|severities="; + + Map<String, Object> map = issueFilterSerializer.deserialize(data); + + assertThat(map).hasSize(1); + assertThat(map.get("issues")).isEqualTo("ABCDE1234"); + } + + } diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueFilterDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueFilterDaoTest.java index dd832ecf550..5a2a714ec95 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueFilterDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueFilterDaoTest.java @@ -85,8 +85,23 @@ public class IssueFilterDaoTest extends AbstractDaoTestCase { public void should_select_shared() { setupData("shared"); - assertThat(dao.selectSharedForUser("michael")).hasSize(1); - assertThat(dao.selectSharedForUser("stephane")).isEmpty(); + assertThat(dao.selectSharedWithoutUserFilters("michael")).hasSize(1); + assertThat(dao.selectSharedWithoutUserFilters("stephane")).isEmpty(); + } + + @Test + public void should_select_shared_by_name() { + setupData("should_select_shared_by_name"); + + IssueFilterDto result = dao.selectSharedWithoutUserFiltersByName("Open issues", "stephane", null); + assertThat(result).isNotNull(); + assertThat(result.getId()).isEqualTo(3L); + assertThat(result.getUserLogin()).isEqualTo("michael"); + assertThat(result.isShared()).isTrue(); + assertThat(dao.selectSharedWithoutUserFiltersByName("Open issues", "stephane", 3L)).isNull(); + + assertThat(dao.selectSharedWithoutUserFiltersByName("Open issues", "michael", null)).isNull(); + assertThat(dao.selectSharedWithoutUserFiltersByName("Sonar issues", "stephane", null)).isNull(); } @Test diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/should_select_shared_by_name.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/should_select_shared_by_name.xml new file mode 100644 index 00000000000..0dc50ff3f04 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/should_select_shared_by_name.xml @@ -0,0 +1,27 @@ +<dataset> + + <issue_filters + id="1" + name="Sonar Issues" + user_login="stephane" + shared="[true]" + created_at="2013-06-10" + updated_at="2013-06-10" /> + + <issue_filters + id="2" + name="Open issues" + user_login="stephane" + shared="[false]" + created_at="2013-06-10" + updated_at="2013-06-10" /> + + <issue_filters + id="3" + name="Open issues" + user_login="michael" + shared="[true]" + created_at="2013-06-10" + updated_at="2013-06-10" /> + +</dataset> |