From 722a02188710fe1b15229e70dc7541a3caa033c5 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 11 Jun 2013 16:44:54 +0200 Subject: [PATCH] SONAR-4383 Replace userId by user in FilterDto --- .../sonar/core/issue/DefaultIssueFilter.java | 119 ++++++++++++++++++ .../sonar/core/issue/db/IssueFilterDao.java | 8 +- .../sonar/core/issue/db/IssueFilterDto.java | 36 +++++- .../core/issue/db/IssueFilterMapper.java | 6 +- .../sonar/core/issue/db/IssueFilterMapper.xml | 16 +-- .../org/sonar/core/persistence/schema-h2.ddl | 6 +- .../core/issue/db/IssueFilterDaoTest.java | 12 +- .../issue/db/IssueFilterDaoTest/shared.xml | 4 +- .../should_delete-result.xml | 2 +- .../should_insert-result.xml | 6 +- .../should_select_by_user.xml | 6 +- .../should_update-result.xml | 4 +- .../issue/InternalRubyIssueService.java | 5 + .../server/issue/IssueFilterService.java | 112 ++++++++++++++++- .../db/migrate/410_create_issue_filters.rb | 10 +- .../411_create_issue_filter_favourites.rb | 8 +- .../server/issue/IssueFilterServiceTest.java | 48 +++++++ 17 files changed, 358 insertions(+), 50 deletions(-) create mode 100644 sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueFilter.java create mode 100644 sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java 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 new file mode 100644 index 00000000000..639dafbb62d --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueFilter.java @@ -0,0 +1,119 @@ +/* + * 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 javax.annotation.CheckForNull; + +import java.util.Date; + +public class DefaultIssueFilter { + + public static String SEPARATOR = "|"; + public static String KEY_VALUE_SEPARATOR = "="; + public static String LIST_SEPARATOR = ","; + + private Long id; + private String name; + private String user; + private Boolean shared; + private String description; + private String data; + private Date createdAt; + private Date updatedAt; + + public DefaultIssueFilter() { + + } + + public Long id() { + return id; + } + + public DefaultIssueFilter setId(Long id) { + this.id = id; + return this; + } + + public String name() { + return name; + } + + public DefaultIssueFilter setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String user() { + return user; + } + + public DefaultIssueFilter setUser(String user) { + this.user = user; + return this; + } + + public Boolean shared() { + return shared; + } + + public DefaultIssueFilter setShared(Boolean shared) { + this.shared = shared; + return this; + } + + public String description() { + return description; + } + + public DefaultIssueFilter setDescription(String description) { + this.description = description; + return this; + } + + public String data() { + return data; + } + + public DefaultIssueFilter setData(String data) { + this.data = data; + return this; + } + + public Date createdAt() { + return createdAt; + } + + public DefaultIssueFilter setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date updatedAt() { + return updatedAt; + } + + public DefaultIssueFilter setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } + +} 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 37d9790a9e8..2ac8a80265c 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 @@ -41,7 +41,7 @@ public class IssueFilterDao implements BatchComponent, ServerComponent { } @CheckForNull - public IssueFilterDto selectById(Integer id) { + public IssueFilterDto selectById(Long id) { SqlSession session = mybatis.openSession(); try { session.getMapper(IssueFilterMapper.class); @@ -51,11 +51,11 @@ public class IssueFilterDao implements BatchComponent, ServerComponent { } } - public List selectByUser(Integer userId) { + public List selectByUser(String user) { SqlSession session = mybatis.openSession(); try { session.getMapper(IssueFilterMapper.class); - return getMapper(session).selectByUser(userId); + return getMapper(session).selectByUser(user); } finally { MyBatis.closeQuietly(session); } @@ -81,7 +81,7 @@ public class IssueFilterDao implements BatchComponent, ServerComponent { } } - public void delete(Integer id) { + public void delete(Long id) { SqlSession session = mybatis.openSession(); try { getMapper(session).delete(id); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDto.java index 1e4c59c4857..29093953dc9 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDto.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueFilterDto.java @@ -19,6 +19,8 @@ */ package org.sonar.core.issue.db; +import org.sonar.core.issue.DefaultIssueFilter; + import javax.annotation.Nullable; import java.util.Date; @@ -30,7 +32,7 @@ public class IssueFilterDto { private Long id; private String name; - private Long userId; + private String user; private Boolean shared; private String description; private String data; @@ -55,12 +57,12 @@ public class IssueFilterDto { return this; } - public Long getUserId() { - return userId; + public String getUser() { + return user; } - public IssueFilterDto setUserId(@Nullable Long userId) { - this.userId = userId; + public IssueFilterDto setUser(@Nullable String user) { + this.user = user; return this; } @@ -108,4 +110,28 @@ public class IssueFilterDto { this.updatedAt = updatedAt; return this; } + + public DefaultIssueFilter toIssueFilter() { + return new DefaultIssueFilter() + .setId(id) + .setName(name) + .setUser(user) + .setDescription(description) + .setShared(shared) + .setData(data) + .setCreatedAt(createdAt) + .setUpdatedAt(updatedAt); + } + + public static IssueFilterDto toIssueFilter(DefaultIssueFilter issueFilter) { + return new IssueFilterDto() + .setId(issueFilter.id()) + .setName(issueFilter.name()) + .setUser(issueFilter.user()) + .setDescription(issueFilter.description()) + .setShared(issueFilter.shared()) + .setData(issueFilter.data()) + .setCreatedAt(issueFilter.createdAt()) + .setUpdatedAt(issueFilter.updatedAt()); + } } 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 9bf819d11cd..c4e8520febb 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 @@ -29,13 +29,13 @@ import java.util.List; public interface IssueFilterMapper { @CheckForNull - IssueFilterDto selectById(Integer id); + IssueFilterDto selectById(Long id); - List selectByUser(Integer userId); + List selectByUser(String user); void insert(IssueFilterDto filter); void update(IssueFilterDto filter); - void delete(Integer id); + void delete(Long id); } 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 d14bec6f23c..c1a1090343a 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 @@ -7,7 +7,7 @@ if.id, if.name as name, - if.user_id as userId, + if.user as user, if.shared as shared, if.description as description, if.data as data, @@ -20,14 +20,14 @@ from issue_filters if WHERE id=#{id} - select - from issue_filters if WHERE user_id=#{userId} + from issue_filters if WHERE user=#{user} - INSERT INTO issue_filters (name, user_id, shared, description, data, created_at, updated_at) - VALUES (#{name}, #{userId}, #{shared}, #{description}, #{data}, #{createdAt}, #{updatedAt}) + INSERT INTO issue_filters (name, user, shared, description, data, created_at, updated_at) + VALUES (#{name}, #{user}, #{shared}, #{description}, #{data}, #{createdAt}, #{updatedAt}) @@ -35,14 +35,14 @@ select issue_filters_seq.NEXTVAL from DUAL - INSERT INTO issue_filters (id, name, user_id, shared, description, data, created_at, updated_at) - VALUES (#{id}, #{name}, #{userId}, #{shared}, #{description}, #{data}, #{createdAt}, #{updatedAt}) + INSERT INTO issue_filters (id, name, user, shared, description, data, created_at, updated_at) + VALUES (#{id}, #{name}, #{user}, #{shared}, #{description}, #{data}, #{createdAt}, #{updatedAt}) update issue_filters set name=#{name}, - user_id=#{userId}, + user=#{user}, shared=#{shared}, description=#{description}, data=#{data}, diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl index 2e65ee3b2d5..2a7f1523100 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl @@ -508,7 +508,7 @@ CREATE TABLE "ISSUE_FILTERS" ( "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(100) NOT NULL, "SHARED" BOOLEAN NOT NULL DEFAULT FALSE, - "USER_ID" INTEGER, + "USER" VARCHAR(40), "DESCRIPTION" VARCHAR(4000), "DATA" CLOB(2147483647), "CREATED_AT" TIMESTAMP, @@ -517,7 +517,7 @@ CREATE TABLE "ISSUE_FILTERS" ( CREATE TABLE "ISSUE_FILTER_FAVOURITES" ( "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), - "USER_ID" INTEGER NOT NULL, + "USER" VARCHAR(40) NOT NULL, "ISSUE_FILTER_ID" INTEGER NOT NULL, "CREATED_AT" TIMESTAMP ); @@ -658,6 +658,6 @@ CREATE INDEX "ISSUE_CHANGES_ISSUE_KEY" ON "ISSUE_CHANGES" ("ISSUE_KEY"); CREATE INDEX "ISSUE_FILTERS_NAME" ON "ISSUE_FILTERS" ("NAME"); -CREATE INDEX "ISSUE_FILTER_FAVS_USERID" ON "ISSUE_FILTER_FAVOURITES" ("USER_ID"); +CREATE INDEX "ISSUE_FILTER_FAVS_USER" ON "ISSUE_FILTER_FAVOURITES" ("USER"); CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN"); 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 8cc8ec08558..5d5f905716a 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 @@ -41,20 +41,20 @@ public class IssueFilterDaoTest extends AbstractDaoTestCase { public void should_select_by_id() { setupData("shared"); - IssueFilterDto filter = dao.selectById(1); + IssueFilterDto filter = dao.selectById(1L); assertThat(filter.getId()).isEqualTo(1L); assertThat(filter.getName()).isEqualTo("Sonar Issues"); assertThat(filter.isShared()).isTrue(); - assertThat(dao.selectById(123)).isNull(); + assertThat(dao.selectById(123L)).isNull(); } @Test public void should_select_by_user() { setupData("should_select_by_user"); - List results = dao.selectByUser(2); + List results = dao.selectByUser("michael"); assertThat(results).hasSize(2); } @@ -65,7 +65,7 @@ public class IssueFilterDaoTest extends AbstractDaoTestCase { IssueFilterDto filterDto = new IssueFilterDto(); filterDto.setName("Sonar Open issues"); - filterDto.setUserId(2L); + filterDto.setUser("michael"); filterDto.setShared(true); filterDto.setDescription("All open issues on Sonar"); filterDto.setData("statuses=OPEN|componentRoots=org.codehaus.sonar"); @@ -82,7 +82,7 @@ public class IssueFilterDaoTest extends AbstractDaoTestCase { IssueFilterDto filterDto = new IssueFilterDto(); filterDto.setId(2L); filterDto.setName("Closed issues"); - filterDto.setUserId(3L); + filterDto.setUser("henry"); filterDto.setShared(false); filterDto.setDescription("All closed issues"); filterDto.setData("statuses=CLOSED"); @@ -96,7 +96,7 @@ public class IssueFilterDaoTest extends AbstractDaoTestCase { public void should_delete() { setupData("shared"); - dao.delete(1); + dao.delete(1l); checkTables("should_delete", new String[]{"created_at", "updated_at"}, "issue_filters"); } diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/shared.xml index 3dd5ac09a05..9cc2014c435 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/shared.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueFilterDaoTest/shared.xml @@ -3,7 +3,7 @@ props) { + return PublicRubyIssueService.toQuery(props); + } + } \ No newline at end of file diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java index d4364d26946..4dabe48119c 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java @@ -20,14 +20,124 @@ package org.sonar.server.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 org.sonar.api.ServerComponent; +import org.sonar.api.issue.IssueFinder; +import org.sonar.api.issue.IssueQuery; +import org.sonar.api.issue.IssueQueryResult; +import org.sonar.core.issue.DefaultIssueFilter; import org.sonar.core.issue.db.IssueFilterDao; +import org.sonar.core.issue.db.IssueFilterDto; +import org.sonar.server.user.UserSession; + +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 IssueFilterService implements ServerComponent { private IssueFilterDao issueFilterDao; + private final IssueFinder issueFinder; - public IssueFilterService(IssueFilterDao issueFilterDao) { + public IssueFilterService(IssueFilterDao issueFilterDao, IssueFinder issueFinder) { this.issueFilterDao = issueFilterDao; + this.issueFinder = issueFinder; + } + + public DefaultIssueFilter create(DefaultIssueFilter issueFilter, IssueQuery issueQuery, UserSession userSession) { + // TODO +// checkAuthorization(userSession, project, UserRole.ADMIN); + issueFilterDao.insert(IssueFilterDto.toIssueFilter(issueFilter)); + return issueFilter; + } + + public DefaultIssueFilter update(DefaultIssueFilter issueFilter, UserSession userSession) { + // TODO +// checkAuthorization(userSession, project, UserRole.ADMIN); + issueFilterDao.update(IssueFilterDto.toIssueFilter(issueFilter)); + return issueFilter; + } + + public void delete(Long issueFilterId, UserSession userSession) { + // TODO + //checkAuthorization(userSession, findActionPlanDto(actionPlanKey).getProjectKey(), UserRole.ADMIN); + issueFilterDao.delete(issueFilterId); + } + + public IssueQueryResult execute(IssueQuery issueQuery) { + return issueFinder.find(issueQuery); + } + + public IssueQueryResult execute(Long issueFilterId) { + IssueFilterDto issueFilterDto = issueFilterDao.selectById(issueFilterId); + if (issueFilterDto == null) { + // TODO throw 404 + throw new IllegalArgumentException("Issue filter " + issueFilterId + " has not been found."); + } + + DefaultIssueFilter issueFilter = issueFilterDto.toIssueFilter(); + // convert data to issue query + issueFilter.data(); + +// return issueFinder.find(issueQuery); + return null; + } + + @VisibleForTesting + Map dataAsMap(String data) { + Map props = newHashMap(); + + Iterable keyValues = Splitter.on(DefaultIssueFilter.SEPARATOR).split(data); + for (String keyValue : keyValues) { + String[] keyValueSplit = StringUtils.split(keyValue, DefaultIssueFilter.KEY_VALUE_SEPARATOR); + if (keyValueSplit.length != 2) { + throw new IllegalArgumentException("Key value should be separate by a '"+ DefaultIssueFilter.KEY_VALUE_SEPARATOR + "'"); + } + String key = keyValueSplit[0]; + String value = keyValueSplit[1]; + String[] listValues = StringUtils.split(value, DefaultIssueFilter.LIST_SEPARATOR); + if (listValues.length > 1) { + props.put(key, newArrayList(listValues)); + } else { + props.put(key, value); + } + } + return props; + } + + @VisibleForTesting + String mapAsdata(Map props) { + StringBuilder stringBuilder = new StringBuilder(); + + for (Map.Entry entries : props.entrySet()){ + String key = entries.getKey(); + Object value = entries.getValue(); + + stringBuilder.append(key); + stringBuilder.append(DefaultIssueFilter.KEY_VALUE_SEPARATOR); + + 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(value); + } + for (Object valueList : valuesList) { + stringBuilder.append(valueList); + stringBuilder.append(DefaultIssueFilter.LIST_SEPARATOR); + } + + stringBuilder.append(DefaultIssueFilter.SEPARATOR); + } + return stringBuilder.toString(); } + } diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/410_create_issue_filters.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/410_create_issue_filters.rb index ff63ed785b4..575d71fc90b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/db/migrate/410_create_issue_filters.rb +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/410_create_issue_filters.rb @@ -25,11 +25,11 @@ class CreateIssueFilters < ActiveRecord::Migration def self.up create_table 'issue_filters' do |t| - t.column 'name', :string, :null => false, :limit => 100 - t.column 'user_id', :integer, :null => true - t.column 'shared', :boolean, :default => false, :null => false - t.column 'description', :string, :null => true, :limit => 4000 - t.column 'data', :text, :null => true + t.column 'name', :string, :null => false, :limit => 100 + t.column 'user', :string, :null => true, :limit => 40 + t.column 'shared', :boolean, :null => false, :default => false + t.column 'description', :string, :null => true, :limit => 4000 + t.column 'data', :text, :null => true t.timestamps end add_index 'issue_filters', 'name', :name => 'issue_filters_name' diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/411_create_issue_filter_favourites.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/411_create_issue_filter_favourites.rb index 322c19aaa53..a45f1005f57 100644 --- a/sonar-server/src/main/webapp/WEB-INF/db/migrate/411_create_issue_filter_favourites.rb +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/411_create_issue_filter_favourites.rb @@ -26,11 +26,11 @@ class CreateIssueFilterFavourites < ActiveRecord::Migration def self.up create_table 'issue_filter_favourites' do |t| - t.column 'user_id', :integer, :null => false - t.column 'issue_filter_id', :integer, :null => false - t.column 'created_at', :datetime + t.column 'user', :string, :null => false, :limit => 40 + t.column 'issue_filter_id', :integer, :null => false + t.column 'created_at', :datetime end - add_index 'issue_filter_favourites', 'user_id', :name => 'issue_filter_favs_userid' + add_index 'issue_filter_favourites', 'user', :name => 'issue_filter_favs_user' end end diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java new file mode 100644 index 00000000000..df99c3df936 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java @@ -0,0 +1,48 @@ +/* + * 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.issue; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.issue.IssueFinder; +import org.sonar.core.issue.db.IssueFilterDao; + +import static org.mockito.Mockito.mock; + +public class IssueFilterServiceTest { + + IssueFilterService service; + + IssueFilterDao issueFilterDao; + IssueFinder issueFinder; + + @Before + public void before() { + issueFinder = mock(IssueFinder.class); + issueFilterDao = mock(IssueFilterDao.class); + service = new IssueFilterService(issueFilterDao, issueFinder); + } + + @Test + public void should_convert_map_to_data() { + + } +} -- 2.39.5