aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2014-02-25 18:45:43 +0100
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2014-02-25 22:18:59 +0100
commit567b62a799271d1479417c5358fe52b75fd015ae (patch)
treec1e85ecdd81aadf4901f8785eb106ff5098d8cba /sonar-core
parenta9ddba7e83499d2d1f2d8356c39742045438cb87 (diff)
downloadsonarqube-567b62a799271d1479417c5358fe52b75fd015ae.tar.gz
sonarqube-567b62a799271d1479417c5358fe52b75fd015ae.zip
SONAR-4366 Add WS to manage project/qgate associations
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/ComponentQuery.java63
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/db/ComponentDao.java56
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java34
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/db/package-info.java23
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java9
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociation.java79
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDao.java55
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDto.java68
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.java28
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQuery.java171
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualitygate/db/package-info.java23
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml56
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.xml34
-rw-r--r--sonar-core/src/test/java/org/sonar/core/component/db/ComponentDaoTest.java49
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest.java84
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDtoTest.java55
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQueryTest.java57
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualitygate/db/QualityGateDaoTest.java1
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/component/db/ComponentDaoTest/selectComponent.xml5
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest/shared.xml37
20 files changed, 981 insertions, 6 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/component/ComponentQuery.java b/sonar-core/src/main/java/org/sonar/core/component/ComponentQuery.java
new file mode 100644
index 00000000000..cb882a87221
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/component/ComponentQuery.java
@@ -0,0 +1,63 @@
+/*
+ * 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.component;
+
+import com.google.common.collect.Sets;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @since 4.3
+ */
+public class ComponentQuery {
+
+ private Collection<Long> ids;
+
+ private Collection<String> qualifiers;
+
+ private ComponentQuery() {
+ this.ids = Sets.newHashSet();
+ this.qualifiers = Sets.newHashSet();
+ }
+
+ public static ComponentQuery create() {
+ return new ComponentQuery();
+ }
+
+ public Collection<Long> ids() {
+ return Collections.unmodifiableCollection(ids);
+ }
+
+ public ComponentQuery addIds(Long... ids) {
+ this.ids.addAll(Arrays.asList(ids));
+ return this;
+ }
+
+ public Collection<String> qualifiers() {
+ return Collections.unmodifiableCollection(qualifiers);
+ }
+
+ public ComponentQuery addQualifiers(String... qualifiers) {
+ this.qualifiers.addAll(Arrays.asList(qualifiers));
+ return this;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentDao.java b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentDao.java
new file mode 100644
index 00000000000..0dd6a089cc6
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentDao.java
@@ -0,0 +1,56 @@
+/*
+ * 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.component.db;
+
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.ComponentQuery;
+import org.sonar.core.persistence.MyBatis;
+
+import java.util.Collection;
+
+/**
+ * @since 4.3
+ */
+public class ComponentDao {
+
+ private final MyBatis myBatis;
+
+ public ComponentDao(MyBatis myBatis) {
+ this.myBatis = myBatis;
+ }
+
+ public Collection<ComponentDto> selectComponent(ComponentQuery query) {
+ SqlSession session = myBatis.openSession();
+ try {
+ return select(query, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public Collection<ComponentDto> select(ComponentQuery query, SqlSession session) {
+ return getMapper(session).selectComponents(query);
+ }
+
+ private ComponentMapper getMapper(SqlSession session) {
+ return session.getMapper(ComponentMapper.class);
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java
new file mode 100644
index 00000000000..48e98c35c19
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java
@@ -0,0 +1,34 @@
+/*
+ * 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.component.db;
+
+import org.apache.ibatis.annotations.Param;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.ComponentQuery;
+
+import java.util.Collection;
+
+/**
+ * @since 4.3
+ */
+public interface ComponentMapper {
+
+ Collection<ComponentDto> selectComponents(@Param("query") ComponentQuery query);
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/component/db/package-info.java b/sonar-core/src/main/java/org/sonar/core/component/db/package-info.java
new file mode 100644
index 00000000000..ae9b843d18f
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/component/db/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.core.component.db;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
index 85adbd63778..8325bd831cd 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
@@ -33,6 +33,7 @@ import org.sonar.api.ServerComponent;
import org.sonar.api.database.model.MeasureMapper;
import org.sonar.api.database.model.MeasureModel;
import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.db.ComponentMapper;
import org.sonar.core.config.Logback;
import org.sonar.core.dashboard.*;
import org.sonar.core.dependency.DependencyDto;
@@ -55,10 +56,7 @@ import org.sonar.core.properties.PropertiesMapper;
import org.sonar.core.properties.PropertyDto;
import org.sonar.core.purge.PurgeMapper;
import org.sonar.core.purge.PurgeableSnapshotDto;
-import org.sonar.core.qualitygate.db.QualityGateConditionDto;
-import org.sonar.core.qualitygate.db.QualityGateConditionMapper;
-import org.sonar.core.qualitygate.db.QualityGateDto;
-import org.sonar.core.qualitygate.db.QualityGateMapper;
+import org.sonar.core.qualitygate.db.*;
import org.sonar.core.qualityprofile.db.*;
import org.sonar.core.resource.*;
import org.sonar.core.rule.*;
@@ -113,6 +111,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
loadAlias(conf, "PurgeableSnapshot", PurgeableSnapshotDto.class);
loadAlias(conf, "QualityGate", QualityGateDto.class);
loadAlias(conf, "QualityGateCondition", QualityGateConditionDto.class);
+ loadAlias(conf, "ProjectQgateAssociation", ProjectQgateAssociationDto.class);
loadAlias(conf, "Resource", ResourceDto.class);
loadAlias(conf, "ResourceIndex", ResourceIndexDto.class);
loadAlias(conf, "ResourceSnapshot", ResourceSnapshotDto.class);
@@ -161,7 +160,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
MeasureMapper.class, SnapshotDataMapper.class, SnapshotSourceMapper.class, ActionPlanMapper.class, ActionPlanStatsMapper.class,
NotificationQueueMapper.class, CharacteristicMapper.class, RuleTagMapper.class,
GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class,
- MeasureDataMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class
+ MeasureDataMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, ProjectQgateAssociationMapper.class
};
loadMappers(conf, mappers);
configureLogback(mappers);
diff --git a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociation.java b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociation.java
new file mode 100644
index 00000000000..234e01f0302
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociation.java
@@ -0,0 +1,79 @@
+/*
+ * 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.qualitygate.db;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+public class ProjectQgateAssociation {
+
+ private Long id;
+ private String name;
+ private boolean isMember;
+
+ public Long id() {
+ return id;
+ }
+
+ public ProjectQgateAssociation setId(Long id) {
+ this.id = id;
+ return this;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public ProjectQgateAssociation setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public boolean isMember() {
+ return isMember;
+ }
+
+ public ProjectQgateAssociation setMember(boolean isMember) {
+ this.isMember = isMember;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ProjectQgateAssociation that = (ProjectQgateAssociation) o;
+ return name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDao.java b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDao.java
new file mode 100644
index 00000000000..743b5b98ef9
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDao.java
@@ -0,0 +1,55 @@
+/*
+ * 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.qualitygate.db;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+import org.apache.ibatis.session.RowBounds;
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.core.persistence.MyBatis;
+
+import java.util.List;
+import java.util.Map;
+
+public class ProjectQgateAssociationDao {
+
+ private final MyBatis mybatis;
+
+ public ProjectQgateAssociationDao(MyBatis mybatis) {
+ this.mybatis = mybatis;
+ }
+
+ public List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query, Long gateId, int offset, int limit) {
+ SqlSession session = mybatis.openSession();
+ try {
+ Map<String, Object> params = ImmutableMap.of("query", query, "gateId", gateId.toString());
+ return session.selectList("org.sonar.core.qualitygate.db.ProjectQgateAssociationMapper.selectProjects", params, new RowBounds(offset, limit));
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @VisibleForTesting
+ List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query, Long gateId) {
+ return selectProjects(query, gateId, 0, Integer.MAX_VALUE);
+ }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDto.java b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDto.java
new file mode 100644
index 00000000000..039e8c4da90
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDto.java
@@ -0,0 +1,68 @@
+/*
+ * 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.qualitygate.db;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+/**
+ * @since 4.3
+ */
+public class ProjectQgateAssociationDto {
+
+ private Long id;
+ private String name;
+ private String gateId;
+
+ public Long getId() {
+ return id;
+ }
+
+ public ProjectQgateAssociationDto setId(Long id) {
+ this.id = id;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ProjectQgateAssociationDto setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @CheckForNull
+ public String getGateId() {
+ return gateId;
+ }
+
+ public ProjectQgateAssociationDto setGateId(@Nullable String gateId) {
+ this.gateId = gateId;
+ return this;
+ }
+
+ public ProjectQgateAssociation toQgateAssociation() {
+ return new ProjectQgateAssociation()
+ .setId(id)
+ .setName(name)
+ .setMember(gateId != null);
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.java b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.java
new file mode 100644
index 00000000000..493102e1f9b
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.java
@@ -0,0 +1,28 @@
+/*
+ * 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.qualitygate.db;
+
+import java.util.List;
+
+public interface ProjectQgateAssociationMapper {
+
+ List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query);
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQuery.java b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQuery.java
new file mode 100644
index 00000000000..74f23807955
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQuery.java
@@ -0,0 +1,171 @@
+/*
+ * 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.qualitygate.db;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.lang.StringUtils;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.util.Set;
+
+public class ProjectQgateAssociationQuery {
+
+ public static final int DEFAULT_PAGE_INDEX = 1;
+ public static final int DEFAULT_PAGE_SIZE = 100;
+
+ public static final String ANY = "ANY";
+ public static final String IN = "IN";
+ public static final String OUT = "OUT";
+ public static final Set<String> AVAILABLE_MEMBERSHIP = ImmutableSet.of(ANY, IN, OUT);
+
+ private final String gateId;
+ private final String membership;
+
+ private final String projectSearch;
+
+ // for internal use in MyBatis
+ final String projectSearchSql;
+
+ // max results per page
+ private final int pageSize;
+
+ // index of selected page. Start with 1.
+ private final int pageIndex;
+
+
+ private ProjectQgateAssociationQuery(Builder builder) {
+ this.gateId = builder.gateId;
+ this.membership = builder.membership;
+ this.projectSearch = builder.projectSearch;
+ this.projectSearchSql = projectSearchToSql(projectSearch);
+
+ this.pageSize = builder.pageSize;
+ this.pageIndex = builder.pageIndex;
+ }
+
+ private String projectSearchToSql(@Nullable String s) {
+ String sql = null;
+ if (s != null) {
+ sql = StringUtils.replace(StringUtils.lowerCase(s), "%", "/%");
+ sql = StringUtils.replace(sql, "_", "/_");
+ sql = sql + "%";
+ }
+ return sql;
+ }
+
+ public String gateId() {
+ return gateId;
+ }
+
+ @CheckForNull
+ public String membership() {
+ return membership;
+ }
+
+ /**
+ * Search for projects containing a given string
+ */
+ @CheckForNull
+ public String projectSearch() {
+ return projectSearch;
+ }
+
+ public int pageSize() {
+ return pageSize;
+ }
+
+ public int pageIndex() {
+ return pageIndex;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String gateId;
+ private String membership;
+ private String projectSearch;
+
+ private Integer pageIndex = DEFAULT_PAGE_INDEX;
+ private Integer pageSize = DEFAULT_PAGE_SIZE;
+
+ private Builder() {
+ }
+
+ public Builder gateId(String gateId) {
+ this.gateId = gateId;
+ return this;
+ }
+
+ public Builder membership(@Nullable String membership) {
+ this.membership = membership;
+ return this;
+ }
+
+ public Builder projectSearch(@Nullable String s) {
+ this.projectSearch = StringUtils.defaultIfBlank(s, null);
+ return this;
+ }
+
+ public Builder pageSize(@Nullable Integer i) {
+ this.pageSize = i;
+ return this;
+ }
+
+ public Builder pageIndex(@Nullable Integer i) {
+ this.pageIndex = i;
+ return this;
+ }
+
+ private void initMembership() {
+ if (membership == null) {
+ membership = ProjectQgateAssociationQuery.ANY;
+ } else {
+ Preconditions.checkArgument(AVAILABLE_MEMBERSHIP.contains(membership),
+ "Membership is not valid (got " + membership + "). Availables values are " + AVAILABLE_MEMBERSHIP);
+ }
+ }
+
+ private void initPageSize() {
+ if (pageSize == null) {
+ pageSize = DEFAULT_PAGE_SIZE;
+ }
+ }
+
+ private void initPageIndex() {
+ if (pageIndex == null) {
+ pageIndex = DEFAULT_PAGE_INDEX;
+ }
+ Preconditions.checkArgument(pageIndex > 0, "Page index must be greater than 0 (got " + pageIndex + ")");
+ }
+
+ public ProjectQgateAssociationQuery build() {
+ Preconditions.checkNotNull(gateId, "Gate ID cant be null.");
+ initMembership();
+ initPageIndex();
+ initPageSize();
+ return new ProjectQgateAssociationQuery(this);
+ }
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/package-info.java b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/package-info.java
new file mode 100644
index 00000000000..09a7a7446b8
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.core.qualitygate.db;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml
new file mode 100644
index 00000000000..3a505fdb17c
--- /dev/null
+++ b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.sonar.core.component.db.ComponentMapper">
+
+ <sql id="componentColumns">
+ p.id,
+ p.kee as kee,
+ p.qualifier
+ </sql>
+
+ <sql id="sortColumn">
+ <if test="query.sort() != null">,
+ <choose>
+ <when test="'SEVERITY'.equals(query.sort())">
+ p.severity as severity
+ </when>
+ <when test="'STATUS'.equals(query.sort())">
+ p.status as status
+ </when>
+ <when test="'ASSIGNEE'.equals(query.sort())">
+ p.assignee as assignee
+ </when>
+ <when test="'CREATION_DATE'.equals(query.sort())">
+ p.issue_creation_date as issueCreationDate
+ </when>
+ <when test="'UPDATE_DATE'.equals(query.sort())">
+ p.issue_update_date as issueUpdateDate
+ </when>
+ <when test="'CLOSE_DATE'.equals(query.sort())">
+ p.issue_close_date as issueCloseDate
+ </when>
+ </choose>
+ </if>
+ </sql>
+
+ <select id="selectComponents" parameterType="map" resultType="Issue">
+ select <include refid="componentColumns"/>
+ from projects p
+ <include refid="selectQueryConditions"/>
+ </select>
+
+ <sql id="selectQueryConditions">
+ <where>
+ <if test="query.ids().size()>0">
+ and <foreach item="id" index="index" collection="query.ids()" open="(" separator=" or " close=")">p.id=#{id}
+ </foreach>
+ </if>
+ <if test="query.qualifiers().size()>0">
+ and <foreach item="qualifier" index="index" collection="query.qualifiers()" open="(" separator=" or " close=")">p.qualifier=#{qualifier}
+ </foreach>
+ </if>
+ </where>
+ </sql>
+
+</mapper>
+
diff --git a/sonar-core/src/main/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.xml b/sonar-core/src/main/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.xml
new file mode 100644
index 00000000000..8ab0864e363
--- /dev/null
+++ b/sonar-core/src/main/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.core.qualitygate.db.ProjectQgateAssociationMapper">
+
+ <select id="selectProjects" parameterType="map" resultType="ProjectQgateAssociation">
+ SELECT proj.id as id, proj.name as name, prop.text_value as gateId
+ FROM projects proj
+ <if test="query.projectSearch() != null">
+ JOIN resource_index ind ON ind.root_project_id=proj.id
+ </if>
+ LEFT JOIN properties prop ON prop.resource_id=proj.id AND prop.prop_key='sonar.qualitygate' AND prop.text_value=#{gateId}
+ <where>
+ <choose>
+ <when test="query.membership() == 'IN'">
+ AND prop.text_value IS NOT NULL
+ </when>
+ <when test="query.membership() == 'OUT'">
+ AND prop.text_value IS NULL
+ </when>
+ </choose>
+ <if test="query.projectSearch() != null">
+ AND ind.kee LIKE #{query.projectSearchSql}
+ </if>
+ AND proj.qualifier='TRK'
+ AND proj.scope='PRJ'
+ <if test="query.projectSearch() != null">
+ AND ind.qualifier='TRK'
+ </if>
+ </where>
+ ORDER BY proj.name
+ </select>
+
+</mapper>
diff --git a/sonar-core/src/test/java/org/sonar/core/component/db/ComponentDaoTest.java b/sonar-core/src/test/java/org/sonar/core/component/db/ComponentDaoTest.java
new file mode 100644
index 00000000000..a28d11d9c81
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/component/db/ComponentDaoTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.component.db;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.core.component.ComponentQuery;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ComponentDaoTest extends AbstractDaoTestCase {
+
+ private ComponentDao dao;
+
+ @Before
+ public void createDao() throws Exception {
+ dao = new ComponentDao(getMyBatis());
+ }
+
+ @Test
+ public void should_select_component() {
+ setupData("selectComponent");
+ assertThat(dao.selectComponent(ComponentQuery.create())).hasSize(3);
+ assertThat(dao.selectComponent(ComponentQuery.create().addIds(1L))).hasSize(1);
+ assertThat(dao.selectComponent(ComponentQuery.create().addQualifiers(Qualifiers.PROJECT))).hasSize(2);
+ assertThat(dao.selectComponent(ComponentQuery.create().addQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW))).hasSize(3);
+ assertThat(dao.selectComponent(ComponentQuery.create().addIds(1L).addQualifiers(Qualifiers.PROJECT))).hasSize(1);
+ assertThat(dao.selectComponent(ComponentQuery.create().addIds(1L).addQualifiers(Qualifiers.VIEW))).hasSize(0);
+ }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest.java b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest.java
new file mode 100644
index 00000000000..17672b6e5e5
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.qualitygate.db;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ProjectQgateAssociationDaoTest extends AbstractDaoTestCase {
+
+ private ProjectQgateAssociationDao dao;
+
+ @Before
+ public void setUp() {
+ dao = new ProjectQgateAssociationDao(getMyBatis());
+ }
+
+ @Test
+ public void select_all_projects_by_query() throws Exception {
+ setupData("shared");
+
+ ProjectQgateAssociationQuery query = ProjectQgateAssociationQuery.builder().gateId("42").build();
+ List<ProjectQgateAssociationDto> result = dao.selectProjects(query, 42L);
+ assertThat(result).hasSize(5);
+ }
+
+ @Test
+ public void select_projects_by_query() throws Exception {
+ setupData("shared");
+
+ assertThat(dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.IN).build(), 42L)).hasSize(3);
+ assertThat(dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.OUT).build(), 42L)).hasSize(2);
+ }
+
+ @Test
+ public void search_by_project_name() throws Exception {
+ setupData("shared");
+
+ List<ProjectQgateAssociationDto> result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build(), 42L);
+ assertThat(result).hasSize(1);
+
+ assertThat(result.get(0).getName()).isEqualTo("Project One");
+
+ result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build(), 42L);
+ assertThat(result).hasSize(1);
+ result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("project").build(), 42L);
+ assertThat(result).hasSize(2);
+ }
+
+ @Test
+ public void should_be_sorted_by_project_name() throws Exception {
+ setupData("shared");
+
+ List<ProjectQgateAssociationDto> result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").build(), 42L);
+ assertThat(result).hasSize(5);
+ assertThat(result.get(0).getName()).isEqualTo("Project Five");
+ assertThat(result.get(1).getName()).isEqualTo("Project Four");
+ assertThat(result.get(2).getName()).isEqualTo("Project One");
+ assertThat(result.get(3).getName()).isEqualTo("Project Three");
+ assertThat(result.get(4).getName()).isEqualTo("Project Two");
+ }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDtoTest.java b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDtoTest.java
new file mode 100644
index 00000000000..ff061188afc
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationDtoTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.qualitygate.db;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ProjectQgateAssociationDtoTest {
+
+ @Test
+ public void to_assoc_with_project_having_assoc() throws Exception {
+ ProjectQgateAssociation project = new ProjectQgateAssociationDto()
+ .setId(1L)
+ .setName("polop")
+ .setGateId("10")
+ .toQgateAssociation();
+
+ assertThat(project.id()).isEqualTo(1);
+ assertThat(project.name()).isEqualTo("polop");
+ assertThat(project.isMember()).isTrue();
+ }
+
+ @Test
+ public void to_assoc_with_project_not_having_assoc() throws Exception {
+ ProjectQgateAssociation project = new ProjectQgateAssociationDto()
+ .setId(1L)
+ .setName("polop")
+ .setGateId(null)
+ .toQgateAssociation();
+
+ assertThat(project.id()).isEqualTo(1);
+ assertThat(project.name()).isEqualTo("polop");
+ assertThat(project.isMember()).isFalse();
+ }
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQueryTest.java b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQueryTest.java
new file mode 100644
index 00000000000..982795cea75
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/ProjectQgateAssociationQueryTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.qualitygate.db;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ProjectQgateAssociationQueryTest {
+
+ @Test
+ public void fail_on_null_login() throws Exception {
+ ProjectQgateAssociationQuery.Builder builder = ProjectQgateAssociationQuery.builder();
+ builder.gateId(null);
+
+ try {
+ builder.build();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(NullPointerException.class).hasMessage("Gate ID cant be null.");
+ }
+ }
+
+ @Test
+ public void fail_on_invalid_membership() throws Exception {
+ ProjectQgateAssociationQuery.Builder builder = ProjectQgateAssociationQuery.builder();
+ builder.gateId("nelson");
+ builder.membership("unknwown");
+
+ try {
+ builder.build();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Membership is not valid (got unknwown). Availables values are [ANY, IN, OUT]");
+ }
+ }
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/qualitygate/db/QualityGateDaoTest.java b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/QualityGateDaoTest.java
index e3a80132e38..be1a4ffa84d 100644
--- a/sonar-core/src/test/java/org/sonar/core/qualitygate/db/QualityGateDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/qualitygate/db/QualityGateDaoTest.java
@@ -84,5 +84,4 @@ public class QualityGateDaoTest extends AbstractDaoTestCase {
dao.update(new QualityGateDto().setId(1L).setName("Not so strict"));
checkTable("update", "quality_gates", "id", "name");
}
-
}
diff --git a/sonar-core/src/test/resources/org/sonar/core/component/db/ComponentDaoTest/selectComponent.xml b/sonar-core/src/test/resources/org/sonar/core/component/db/ComponentDaoTest/selectComponent.xml
new file mode 100644
index 00000000000..63650b2b7bb
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/component/db/ComponentDaoTest/selectComponent.xml
@@ -0,0 +1,5 @@
+<dataset>
+ <projects id="1" kee="project1" qualifier="TRK"/>
+ <projects id="2" kee="project2" qualifier="TRK"/>
+ <projects id="3" kee="view3" qualifier="VW"/>
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest/shared.xml
new file mode 100644
index 00000000000..2d16d699a44
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualitygate/db/ProjectQgateAssociationDaoTest/shared.xml
@@ -0,0 +1,37 @@
+<dataset>
+
+ <quality_gates id="42" name="Golden"/>
+ <quality_gates id="43" name="Ninth"/>
+
+ <projects id="1" name="Project One" qualifier="TRK" scope="PRJ"/>
+ <projects id="2" name="Project Two" qualifier="TRK" scope="PRJ"/>
+ <projects id="3" name="Project Three" qualifier="TRK" scope="PRJ"/>
+ <projects id="4" name="Project Four" qualifier="TRK" scope="PRJ"/>
+ <projects id="5" name="Project Five" qualifier="TRK" scope="PRJ"/>
+ <projects id="6" name="View Six" qualifier="VW" scope="PRJ"/>
+ <projects id="7" name="Project One" qualifier="TRK" scope="FIL"/>
+
+ <resource_index kee="project one" resource_id="1" root_project_id="1" position="0" name_size="11" qualifier="TRK"/>
+ <resource_index kee="roject one" resource_id="1" root_project_id="1" position="1" name_size="11" qualifier="TRK"/>
+ <resource_index kee="oject one" resource_id="1" root_project_id="1" position="2" name_size="11" qualifier="TRK"/>
+ <resource_index kee="ject one" resource_id="1" root_project_id="1" position="3" name_size="11" qualifier="TRK"/>
+ <resource_index kee="ect one" resource_id="1" root_project_id="1" position="4" name_size="11" qualifier="TRK"/>
+ <resource_index kee="ct one" resource_id="1" root_project_id="1" position="5" name_size="11" qualifier="TRK"/>
+ <resource_index kee="t one" resource_id="1" root_project_id="1" position="6" name_size="11" qualifier="TRK"/>
+ <resource_index kee=" one" resource_id="1" root_project_id="1" position="7" name_size="11" qualifier="TRK"/>
+ <resource_index kee="one" resource_id="1" root_project_id="1" position="8" name_size="11" qualifier="TRK"/>
+ <resource_index kee="project two" resource_id="2" root_project_id="2" position="0" name_size="11" qualifier="TRK"/>
+ <resource_index kee="roject two" resource_id="2" root_project_id="2" position="1" name_size="11" qualifier="TRK"/>
+ <resource_index kee="oject two" resource_id="2" root_project_id="2" position="2" name_size="11" qualifier="TRK"/>
+ <resource_index kee="ject two" resource_id="2" root_project_id="2" position="3" name_size="11" qualifier="TRK"/>
+ <resource_index kee="ect two" resource_id="2" root_project_id="2" position="4" name_size="11" qualifier="TRK"/>
+ <resource_index kee="ct two" resource_id="2" root_project_id="2" position="5" name_size="11" qualifier="TRK"/>
+ <resource_index kee="t two" resource_id="2" root_project_id="2" position="6" name_size="11" qualifier="TRK"/>
+ <resource_index kee=" two" resource_id="2" root_project_id="2" position="7" name_size="11" qualifier="TRK"/>
+
+ <properties prop_key="sonar.qualitygate" resource_id="[null]" text_value="43"/>
+ <properties prop_key="sonar.qualitygate" resource_id="1" text_value="42"/>
+ <properties prop_key="sonar.qualitygate" resource_id="2" text_value="42"/>
+ <properties prop_key="sonar.qualitygate" resource_id="3" text_value="42"/>
+
+</dataset>