/* * SonarQube, open source software quality management tool. * Copyright (C) 2008-2014 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.db.component; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.collect.Lists; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.ibatis.session.RowBounds; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; import org.sonar.db.Dao; import org.sonar.db.DatabaseUtils; import org.sonar.db.DbSession; import org.sonar.db.RowNotFoundException; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Maps.newHashMapWithExpectedSize; import static org.sonar.api.utils.Paging.offset; import static org.sonar.db.DatabaseUtils.executeLargeInputs; public class ComponentDao implements Dao { public ComponentDto selectOrFailById(DbSession session, long id) { Optional componentDto = selectById(session, id); if (!componentDto.isPresent()) { throw new RowNotFoundException(String.format("Component id does not exist: %d", id)); } return componentDto.get(); } public Optional selectById(DbSession session, long id) { return Optional.fromNullable(mapper(session).selectById(id)); } public Optional selectByUuid(DbSession session, String uuid) { return Optional.fromNullable(mapper(session).selectByUuid(uuid)); } public ComponentDto selectOrFailByUuid(DbSession session, String uuid) { Optional componentDto = selectByUuid(session, uuid); if (!componentDto.isPresent()) { throw new RowNotFoundException(String.format("Component with uuid '%s' not found", uuid)); } return componentDto.get(); } public List selectByQuery(DbSession session, ComponentQuery query, int offset, int limit) { return mapper(session).selectByQuery(query, new RowBounds(offset, limit)); } public int countByQuery(DbSession session, ComponentQuery query) { return mapper(session).countByQuery(query); } public boolean existsById(Long id, DbSession session) { return mapper(session).countById(id) > 0; } public List selectSubProjectsByComponentUuids(DbSession session, Collection keys) { if (keys.isEmpty()) { return Collections.emptyList(); } return mapper(session).selectSubProjectsByComponentUuids(keys); } public List selectDescendantModules(DbSession session, String rootComponentUuid) { return mapper(session).selectDescendantModules(rootComponentUuid, Scopes.PROJECT, false); } public List selectEnabledDescendantModules(DbSession session, String rootComponentUuid) { return mapper(session).selectDescendantModules(rootComponentUuid, Scopes.PROJECT, true); } public List selectEnabledDescendantFiles(DbSession session, String rootComponentUuid) { return mapper(session).selectDescendantFiles(rootComponentUuid, Scopes.FILE, true); } public List selectEnabledFilesFromProject(DbSession session, String rootComponentUuid) { return mapper(session).selectEnabledFilesFromProject(rootComponentUuid); } public List selectByIds(final DbSession session, Collection ids) { return DatabaseUtils.executeLargeInputs(ids, new Function, List>() { @Override public List apply(@Nonnull List partition) { return mapper(session).selectByIds(partition); } }); } public List selectByUuids(final DbSession session, Collection uuids) { return DatabaseUtils.executeLargeInputs(uuids, new Function, List>() { @Override public List apply(@Nonnull List partition) { return mapper(session).selectByUuids(partition); } }); } public List selectExistingUuids(final DbSession session, Collection uuids) { return DatabaseUtils.executeLargeInputs(uuids, new Function, List>() { @Override public List apply(@Nonnull List partition) { return mapper(session).selectExistingUuids(partition); } }); } /** * Return all components of a project (including disable ones) */ public List selectAllComponentsFromProjectKey(DbSession session, String projectKey) { return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, null, false); } public List selectEnabledModulesFromProjectKey(DbSession session, String projectKey) { return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, Scopes.PROJECT, true); } public List selectByKeys(DbSession session, Collection keys) { return executeLargeInputs(keys, new KeyToDto(mapper(session))); } public List selectComponentsHavingSameKeyOrderedById(DbSession session, String key) { return mapper(session).selectComponentsHavingSameKeyOrderedById(key); } public List selectDirectChildren(DbSession dbSession, ComponentTreeQuery componentQuery) { RowBounds rowBounds = new RowBounds(offset(componentQuery.getPage(), componentQuery.getPageSize()), componentQuery.getPageSize()); return mapper(dbSession).selectDirectChildren(componentQuery, rowBounds); } public List selectAllChildren(DbSession dbSession, ComponentTreeQuery componentQuery) { RowBounds rowBounds = new RowBounds(offset(componentQuery.getPage(), componentQuery.getPageSize()), componentQuery.getPageSize()); return mapper(dbSession).selectAllChildren(componentQuery, rowBounds); } public int countDirectChildren(DbSession dbSession, ComponentTreeQuery query) { return mapper(dbSession).countDirectChildren(query); } public int countAllChildren(DbSession dbSession, ComponentTreeQuery query) { return mapper(dbSession).countAllChildren(query); } private static class KeyToDto implements Function, List> { private final ComponentMapper mapper; private KeyToDto(ComponentMapper mapper) { this.mapper = mapper; } @Override public List apply(@Nonnull List partitionOfKeys) { return mapper.selectByKeys(partitionOfKeys); } } public ComponentDto selectOrFailByKey(DbSession session, String key) { Optional component = selectByKey(session, key); if (!component.isPresent()) { throw new RowNotFoundException(String.format("Component key '%s' not found", key)); } return component.get(); } public Optional selectByKey(DbSession session, String key) { return Optional.fromNullable(mapper(session).selectByKey(key)); } public List selectAllViewsAndSubViews(DbSession session) { return mapper(session).selectUuidsForQualifiers(Qualifiers.VIEW, Qualifiers.SUBVIEW); } public List selectProjectsFromView(DbSession session, String viewUuid, String projectViewUuid) { return mapper(session).selectProjectsFromView("%." + viewUuid + ".%", projectViewUuid); } /** * Returns all projects (Scope {@link org.sonar.api.resources.Scopes#PROJECT} and qualifier * {@link org.sonar.api.resources.Qualifiers#PROJECT}) which are enabled. * * Used by Views. */ public List selectProjects(DbSession session) { return mapper(session).selectProjects(); } /** * Does not return component copies */ public List selectComponents(DbSession session, Collection qualifiers, int offset, int limit, @Nullable String query) { Map parameters = newHashMapWithExpectedSize(3); addProjectQualifier(parameters); addPartialQueryParameterIfNotNull(parameters, query); addQualifiers(parameters, qualifiers); return mapper(session).selectComponents(parameters, new RowBounds(offset, limit)); } public int countRootComponents(DbSession session, Collection qualifiers, @Nullable String query) { Map parameters = newHashMapWithExpectedSize(2); addPartialQueryParameterIfNotNull(parameters, query); addQualifiers(parameters, qualifiers); return mapper(session).countRootComponents(parameters); } public List selectProvisionedProjects(DbSession session, int offset, int limit, @Nullable String query) { Map parameters = newHashMapWithExpectedSize(2); addProjectQualifier(parameters); addPartialQueryParameterIfNotNull(parameters, query); return mapper(session).selectProvisionedProjects(parameters, new RowBounds(offset, limit)); } public int countProvisionedProjects(DbSession session, @Nullable String query) { Map parameters = newHashMapWithExpectedSize(2); addProjectQualifier(parameters); addPartialQueryParameterIfNotNull(parameters, query); return mapper(session).countProvisionedProjects(parameters); } public List selectGhostProjects(DbSession session, int offset, int limit, @Nullable String query) { Map parameters = newHashMapWithExpectedSize(2); addProjectQualifier(parameters); addPartialQueryParameterIfNotNull(parameters, query); return mapper(session).selectGhostProjects(parameters, new RowBounds(offset, limit)); } public long countGhostProjects(DbSession session, @Nullable String query) { Map parameters = newHashMapWithExpectedSize(2); addProjectQualifier(parameters); addPartialQueryParameterIfNotNull(parameters, query); return mapper(session).countGhostProjects(parameters); } /** * Retrieves all components with a specific root project Uuid, no other filtering is done by this method. * * Used by Views plugin */ public List selectByProjectUuid(String projectUuid, DbSession dbSession) { return mapper(dbSession).selectByProjectUuid(projectUuid); } /** * Retrieve enabled components keys with given qualifiers * * Used by Views plugin */ public Set selectComponentsByQualifiers(DbSession dbSession, Set qualifiers) { checkArgument(!qualifiers.isEmpty(), "Qualifiers cannot be empty"); return new HashSet<>(mapper(dbSession).selectComponentsByQualifiers(qualifiers)); } private static void addPartialQueryParameterIfNotNull(Map parameters, @Nullable String keyOrNameFilter) { if (keyOrNameFilter != null) { parameters.put("query", "%" + keyOrNameFilter.toUpperCase() + "%"); } } private static void addProjectQualifier(Map parameters) { parameters.put("qualifier", Qualifiers.PROJECT); } private static void addQualifiers(Map parameters, Collection qualifiers) { parameters.put("qualifiers", qualifiers); } public void insert(DbSession session, ComponentDto item) { mapper(session).insert(item); } public void insert(DbSession session, Collection items) { for (ComponentDto item : items) { insert(session, item); } } public void insert(DbSession session, ComponentDto item, ComponentDto... others) { insert(session, Lists.asList(item, others)); } public void update(DbSession session, ComponentDto item) { mapper(session).update(item); } public void delete(DbSession session, long componentId) { mapper(session).delete(componentId); } private ComponentMapper mapper(DbSession session) { return session.getMapper(ComponentMapper.class); } }