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;
return issueFilter;
}
- public DefaultIssueFilter(Map<String, Object> mapData) {
- setData(mapData);
- }
-
public Long id() {
return id;
}
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();
- }
-
}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
}
}
- 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);
}
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);
</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>
<!-- 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}
+++ /dev/null
-/*
- * 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 org.junit.Test;
-
-import java.util.List;
-import java.util.Map;
-
-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 {
-
- DefaultIssueFilter issueFilter = new DefaultIssueFilter();
-
- @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() {
- Map<String, Object> map = newLinkedHashMap();
- map.put("issues", newArrayList("ABCDE1234"));
- map.put("severities", newArrayList("MAJOR", "MINOR"));
- map.put("resolved", true);
- map.put("pageSize", 10l);
- map.put("pageIndex", 50);
-
- String result = issueFilter.mapAsdata(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() {
- Map<String, Object> map = newLinkedHashMap();
- map.put("issues", newArrayList("ABCDE1234"));
- map.put("resolved", null);
- map.put("pageSize", "");
-
- String result = issueFilter.mapAsdata(map);
-
- assertThat(result).isEqualTo("issues=ABCDE1234");
- }
-
-}
--- /dev/null
+/*
+ * 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 org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+
+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 IssueFilterSerializerTest {
+
+ IssueFilterSerializer issueFilterSerializer = new IssueFilterSerializer();
+
+ @Test
+ public void should_serialize() {
+ Map<String, Object> map = newLinkedHashMap();
+ map.put("issues", newArrayList("ABCDE1234"));
+ map.put("severities", newArrayList("MAJOR", "MINOR"));
+ map.put("resolved", true);
+ map.put("pageSize", 10l);
+ map.put("pageIndex", 50);
+
+ 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_serializing() {
+ Map<String, Object> map = newLinkedHashMap();
+ map.put("issues", newArrayList("ABCDE1234"));
+ map.put("resolved", null);
+ map.put("pageSize", "");
+
+ 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");
+ }
+
+
+}
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
--- /dev/null
+<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>
return PublicRubyIssueService.toQuery(props);
}
+ public IssueQuery toQuery(DefaultIssueFilter issueFilter) {
+ return toQuery(issueFilterService.deserializeIssueFilterQuery(issueFilter));
+ }
+
public DefaultIssueFilter findIssueFilter(Long id) {
return issueFilterService.findById(id, UserSession.get());
}
return issueFilterService.findByUser(UserSession.get());
}
- public DefaultIssueFilter createFilterFromMap(Map<String, Object> mapData) {
- return new DefaultIssueFilter(mapData);
+ public String serializeFilterQuery(Map<String, Object> filterQuery){
+ return issueFilterService.serializeFilterQuery(filterQuery);
}
/**
/**
* Update issue filter data
*/
- public Result<DefaultIssueFilter> updateIssueFilterData(Long issueFilterId, Map<String, Object> data) {
+ public Result<DefaultIssueFilter> updateIssueFilterQuery(Long issueFilterId, Map<String, Object> data) {
Result<DefaultIssueFilter> result = Result.of();
try {
- result.set(issueFilterService.updateData(issueFilterId, data, UserSession.get()));
+ result.set(issueFilterService.updateFilterQuery(issueFilterId, data, UserSession.get()));
} catch (Exception e) {
result.addError(e.getMessage());
}
import org.sonar.api.issue.IssueQueryResult;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultIssueFilter;
+import org.sonar.core.issue.IssueFilterSerializer;
import org.sonar.core.issue.db.IssueFilterDao;
import org.sonar.core.issue.db.IssueFilterDto;
import org.sonar.core.issue.db.IssueFilterFavouriteDao;
private final IssueFilterFavouriteDao issueFilterFavouriteDao;
private final IssueFinder issueFinder;
private final AuthorizationDao authorizationDao;
+ private final IssueFilterSerializer issueFilterSerializer;
- public IssueFilterService(IssueFilterDao issueFilterDao, IssueFilterFavouriteDao issueFilterFavouriteDao, IssueFinder issueFinder, AuthorizationDao authorizationDao) {
+ public IssueFilterService(IssueFilterDao issueFilterDao, IssueFilterFavouriteDao issueFilterFavouriteDao, IssueFinder issueFinder, AuthorizationDao authorizationDao,
+ IssueFilterSerializer issueFilterSerializer) {
this.issueFilterDao = issueFilterDao;
this.issueFilterFavouriteDao = issueFilterFavouriteDao;
this.issueFinder = issueFinder;
this.authorizationDao = authorizationDao;
+ this.issueFilterSerializer = issueFilterSerializer;
}
public IssueQueryResult execute(IssueQuery issueQuery) {
IssueFilterDto issueFilterDto = findIssueFilter(issueFilterId, userSession);
DefaultIssueFilter issueFilter = issueFilterDto.toIssueFilter();
- IssueQuery issueQuery = PublicRubyIssueService.toQuery(issueFilter.dataAsMap());
+ IssueQuery issueQuery = PublicRubyIssueService.toQuery(deserializeIssueFilterQuery(issueFilter));
return issueFinder.find(issueQuery);
}
public DefaultIssueFilter save(DefaultIssueFilter issueFilter, UserSession userSession) {
verifyLoggedIn(userSession);
issueFilter.setUser(userSession.login());
- verifyNameIsNotAlreadyUsed(issueFilter, userSession);
+ validateFilter(issueFilter, userSession);
return insertIssueFilter(issueFilter, userSession.login());
}
public DefaultIssueFilter update(DefaultIssueFilter issueFilter, UserSession userSession) {
IssueFilterDto issueFilterDto = findIssueFilter(issueFilter.id(), userSession);
verifyCurrentUserCanModifyFilter(issueFilterDto, userSession);
- verifyNameIsNotAlreadyUsed(issueFilter, userSession);
+ validateFilter(issueFilter, userSession);
issueFilterDao.update(IssueFilterDto.toIssueFilter(issueFilter));
return issueFilter;
}
- public DefaultIssueFilter updateData(Long issueFilterId, Map<String, Object> mapData, UserSession userSession) {
+ public DefaultIssueFilter updateFilterQuery(Long issueFilterId, Map<String, Object> filterQuery, UserSession userSession) {
IssueFilterDto issueFilterDto = findIssueFilter(issueFilterId, userSession);
verifyCurrentUserCanModifyFilter(issueFilterDto, userSession);
DefaultIssueFilter issueFilter = issueFilterDto.toIssueFilter();
- issueFilter.setData(mapData);
+ issueFilter.setData(serializeFilterQuery(filterQuery));
issueFilterDao.update(IssueFilterDto.toIssueFilter(issueFilter));
return issueFilter;
}
IssueFilterDto issueFilterDtoToCopy = findIssueFilter(issueFilterIdToCopy, userSession);
issueFilter.setUser(userSession.login());
issueFilter.setData(issueFilterDtoToCopy.getData());
- verifyNameIsNotAlreadyUsed(issueFilter, userSession);
+ validateFilter(issueFilter, userSession);
return insertIssueFilter(issueFilter, userSession.login());
}
public List<DefaultIssueFilter> findSharedFilters(UserSession userSession) {
if (userSession.isLoggedIn() && userSession.login() != null) {
- return toIssueFilters(issueFilterDao.selectSharedForUser(userSession.login()));
+ return toIssueFilters(issueFilterDao.selectSharedWithoutUserFilters(userSession.login()));
}
return Collections.emptyList();
}
return issueFilterDto;
}
+ public String serializeFilterQuery(Map<String, Object> filterQuery){
+ return issueFilterSerializer.serialize(filterQuery);
+ }
+
+ public Map<String, Object> deserializeIssueFilterQuery(DefaultIssueFilter issueFilter){
+ return issueFilterSerializer.deserialize(issueFilter.data());
+ }
+
private void verifyLoggedIn(UserSession userSession) {
if (!userSession.isLoggedIn() && userSession.login() != null) {
throw new IllegalStateException("User is not logged in");
}
}
- private void verifyNameIsNotAlreadyUsed(DefaultIssueFilter issueFilter, UserSession userSession) {
+ private void validateFilter(DefaultIssueFilter issueFilter, UserSession userSession) {
if (issueFilterDao.selectByNameAndUser(issueFilter.name(), userSession.login(), issueFilter.id()) != null) {
throw new IllegalArgumentException("Name already exists");
}
+ if (issueFilter.shared() && issueFilterDao.selectSharedWithoutUserFiltersByName(issueFilter.name(), userSession.login(), issueFilter.id()) != null) {
+ throw new IllegalArgumentException("Other users already share filters with the same name");
+ }
}
private IssueFilterFavouriteDto findFavouriteIssueFilter(String user, Long issueFilterId) {
import org.sonar.core.i18n.GwtI18n;
import org.sonar.core.i18n.I18nManager;
import org.sonar.core.i18n.RuleI18nManager;
+import org.sonar.core.issue.IssueFilterSerializer;
import org.sonar.core.issue.IssueNotifications;
import org.sonar.core.issue.IssueUpdater;
import org.sonar.core.issue.workflow.FunctionExecutor;
servicesContainer.addSingleton(IssueNotifications.class);
servicesContainer.addSingleton(ActionService.class);
servicesContainer.addSingleton(Actions.class);
+ servicesContainer.addSingleton(IssueFilterSerializer.class);
servicesContainer.addSingleton(IssueFilterService.class);
// rules
def search
if params[:id]
@filter = find_filter(params[:id].to_i)
- else
- @filter = Internal.issues.createFilterFromMap(criteria_params)
end
- @criteria_params = Hash[@filter.dataAsMap]
+
+ @first_search = criteria_params.empty?
@issue_query = Internal.issues.toQuery(criteria_params)
@issues_result = Internal.issues.execute(@issue_query)
end
require_parameters :id
@filter = find_filter(params[:id].to_i)
- @criteria_params = Hash[@filter.dataAsMap]
- @issue_query = Internal.issues.toQuery(@filter.dataAsMap)
+ @first_search = false
+ @issue_query = Internal.issues.toQuery(@filter)
@issues_result = Internal.issues.execute(@issue_query)
@unchanged = true
# GET /issues/save_as_form?[&criteria]
def save_as_form
- @filter = Internal.issues.createFilterFromMap(criteria_params)
+ @filter_query_serialized = Internal.issues.serializeFilterQuery(criteria_params)
render :partial => 'issues/save_as_form'
end
verify_post_request
require_parameters :id
- filter_result = Internal.issues.updateIssueFilterData(params[:id].to_i, criteria_params)
+ filter_result = Internal.issues.updateIssueFilterQuery(params[:id].to_i, criteria_params)
if filter_result.ok
@filter = filter_result.get()
redirect_to :action => 'filter', :id => @filter.id.to_s
@errors = filter_result.errors
@filter = find_filter(params[:id].to_i)
+
@issue_query = Internal.issues.toQuery(@filter.dataAsMap)
@issues_result = Internal.issues.execute(@issue_query)
@unchanged = true
<form id="save-as-filter-form" method="post" action="<%= ApplicationController.root_context -%>/issues/save_as">
- <input type="hidden" name="data" value="<%= params[:data] || u(@filter.data) -%>">
+ <input type="hidden" name="data" value="<%= params[:data] || u(@filter_query_serialized) -%>">
<fieldset>
<div class="modal-head">
<h2><%= message('issue_filter.save_filter') -%></h2>
<%= render :partial => 'display_errors' %>
<div class="modal-field">
<label for="name"><%= message('issue_filter.form.name') -%> <em class="mandatory">*</em></label>
- <input id="name" name="name" type="text" size="50" maxlength="100" value="<%= params[:name] || h(@filter.name) -%>" autofocus="autofocus"/>
+ <input id="name" name="name" type="text" size="50" maxlength="100" value="<%= params[:name] || (h(@filter.name) if @filter) -%>" autofocus="autofocus"/>
</div>
<div class="modal-field">
<label for="description"><%= message('issue_filter.form.description') -%></label>
- <input id="description" name="description" type="text" size="50" maxlength="4000" value="<%= params[:description] || h(@filter.description) -%>"/>
+ <input id="description" name="description" type="text" size="50" maxlength="4000" value="<%= params[:description] || (h(@filter.description) if @filter) -%>"/>
</div>
<div class="modal-field">
<label for="shared"><%= message('issue_filter.form.share') -%></label>
<%= render :partial => 'display_errors' %>
<div class="line-block marginbottom10">
- <% if logged_in? && !@criteria_params.empty? %>
+ <% if logged_in? && !@first_search %>
<ul class="operations">
- <% if @filter.id %>
+ <% if @filter && @filter.id %>
<li><a id="copy" href="<%= url_for :action => 'copy_form', :id => @filter.id -%>" class="link-action open-modal"><%= message('copy') -%></a></li>
<% end %>
- <% if !defined?(@unchanged) && @filter.id && @filter.user == current_user.login %>
+ <% if !defined?(@unchanged) && @filter && @filter.id && @filter.user == current_user.login %>
<li>
<%= link_to message('save'), params.merge({:action => 'save', :id => @filter.id}), :class => 'link-action', :id => 'save', :method => :post -%>
</li>
<% end %>
- <% unless @filter.id %>
+ <% unless @filter %>
<li>
- <a id="save-as" href="<%= url_for params.merge({:action => 'save_as_form', :id => @filter.id}) -%>" class="link-action open-modal"><%= message('save_as') -%></a>
+ <a id="save-as" href="<%= url_for params.merge({:action => 'save_as_form'}) -%>" class="link-action open-modal"><%= message('save_as') -%></a>
</li>
<% end %>
</ul>
<div class="page_title" id="filter-title">
- <% if @filter.id && @filter.name.present? %>
+ <% if @filter && @filter.id && @filter.name.present? %>
<p>
<span class="h3"><%= h @filter.name -%></span>
<span class="note">
@Test
public void should_update_data() {
Map<String, Object> data = newHashMap();
- service.updateIssueFilterData(10L, data);
- verify(issueFilterService).updateData(eq(10L), eq(data), any(UserSession.class));
+ service.updateIssueFilterQuery(10L, data);
+ verify(issueFilterService).updateFilterQuery(eq(10L), eq(data), any(UserSession.class));
}
@Test
import org.sonar.api.issue.IssueQuery;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultIssueFilter;
+import org.sonar.core.issue.IssueFilterSerializer;
import org.sonar.core.issue.db.IssueFilterDao;
import org.sonar.core.issue.db.IssueFilterDto;
import org.sonar.core.issue.db.IssueFilterFavouriteDao;
private IssueFilterFavouriteDao issueFilterFavouriteDao;
private IssueFinder issueFinder;
private AuthorizationDao authorizationDao;
+ private IssueFilterSerializer issueFilterSerializer;
private UserSession userSession;
issueFilterFavouriteDao = mock(IssueFilterFavouriteDao.class);
issueFinder = mock(IssueFinder.class);
authorizationDao = mock(AuthorizationDao.class);
+ issueFilterSerializer = mock(IssueFilterSerializer.class);
- service = new IssueFilterService(issueFilterDao, issueFilterFavouriteDao, issueFinder, authorizationDao);
+ service = new IssueFilterService(issueFilterDao, issueFilterFavouriteDao, issueFinder, authorizationDao, issueFilterSerializer);
}
@Test
verify(issueFilterDao, never()).insert(any(IssueFilterDto.class));
}
+ @Test
+ public void should_not_save_shared_filter_if_name_already_used_by_shared_filter() {
+ when(issueFilterDao.selectByNameAndUser(eq("My Issue"), eq("john"), eq((Long) null))).thenReturn(null);
+ when(issueFilterDao.selectSharedWithoutUserFiltersByName(eq("My Issue"), eq("john"), eq((Long) null))).thenReturn(new IssueFilterDto());
+ try {
+ DefaultIssueFilter issueFilter = new DefaultIssueFilter().setName("My Issue").setShared(true);
+ service.save(issueFilter, userSession);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Other users already share filters with the same name");
+ }
+ verify(issueFilterDao, never()).insert(any(IssueFilterDto.class));
+ }
+
@Test
public void should_update() {
when(issueFilterDao.selectById(1L)).thenReturn(new IssueFilterDto().setId(1L).setName("My Old Filter").setUserLogin("john"));
@Test
public void should_update_data() {
+ when(issueFilterSerializer.serialize(anyMap())).thenReturn("componentRoots=struts");
when(issueFilterDao.selectById(1L)).thenReturn(new IssueFilterDto().setId(1L).setName("My Old Filter").setUserLogin("john"));
Map<String, Object> data = newHashMap();
data.put("componentRoots", "struts");
- DefaultIssueFilter result = service.updateData(1L, data, userSession);
+ DefaultIssueFilter result = service.updateFilterQuery(1L, data, userSession);
assertThat(result.data()).isEqualTo("componentRoots=struts");
verify(issueFilterDao).update(any(IssueFilterDto.class));
@Test
public void should_execute_from_filter_id() {
+ Map<String, Object> map = newHashMap();
+ map.put("componentRoots", "struts");
+ when(issueFilterSerializer.deserialize(anyString())).thenReturn(map);
when(issueFilterDao.selectById(1L)).thenReturn(new IssueFilterDto().setId(1L).setName("My Old Filter").setUserLogin("john").setData("componentRoots=struts"));
ArgumentCaptor<IssueQuery> issueQueryCaptor = ArgumentCaptor.forClass(IssueQuery.class);
@Test
public void should_find_shared_issue_filter() {
- when(issueFilterDao.selectSharedForUser("john")).thenReturn(newArrayList(new IssueFilterDto().setId(1L).setName("My Issue").setUserLogin("john").setShared(true)));
+ when(issueFilterDao.selectSharedWithoutUserFilters("john")).thenReturn(newArrayList(new IssueFilterDto().setId(1L).setName("My Issue").setUserLogin("john").setShared(true)));
List<DefaultIssueFilter> results = service.findSharedFilters(userSession);
assertThat(results).hasSize(1);