/* * SonarQube * Copyright (C) 2009-2017 SonarSource SA * mailto:info AT sonarsource DOT com * * This program 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. * * This program 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.duplication.ws; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import java.util.List; import java.util.Map; import javax.annotation.Nullable; import org.sonar.api.server.ServerSide; import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDao; import org.sonar.db.component.ComponentDto; import static com.google.common.collect.Maps.newHashMap; @ServerSide public class DuplicationsJsonWriter { private final ComponentDao componentDao; public DuplicationsJsonWriter(ComponentDao componentDao) { this.componentDao = componentDao; } @VisibleForTesting void write(List<DuplicationsParser.Block> blocks, JsonWriter json, DbSession session) { Map<String, String> refByComponentKey = newHashMap(); json.name("duplications").beginArray(); writeDuplications(blocks, refByComponentKey, json); json.endArray(); json.name("files").beginObject(); writeFiles(refByComponentKey, json, session); json.endObject(); } private static void writeDuplications(List<DuplicationsParser.Block> blocks, Map<String, String> refByComponentKey, JsonWriter json) { for (DuplicationsParser.Block block : blocks) { json.beginObject().name("blocks").beginArray(); for (DuplicationsParser.Duplication duplication : block.getDuplications()) { writeDuplication(refByComponentKey, duplication, json); } json.endArray().endObject(); } } private static void writeDuplication(Map<String, String> refByComponentKey, DuplicationsParser.Duplication duplication, JsonWriter json) { String ref = null; ComponentDto componentDto = duplication.file(); if (componentDto != null) { String componentKey = componentDto.key(); ref = refByComponentKey.get(componentKey); if (ref == null) { ref = Integer.toString(refByComponentKey.size() + 1); refByComponentKey.put(componentKey, ref); } } json.beginObject(); json.prop("from", duplication.from()); json.prop("size", duplication.size()); json.prop("_ref", ref); json.endObject(); } private void writeFiles(Map<String, String> refByComponentKey, JsonWriter json, DbSession session) { Map<String, ComponentDto> projectsByUuid = newHashMap(); Map<String, ComponentDto> parentProjectsByUuid = newHashMap(); for (Map.Entry<String, String> entry : refByComponentKey.entrySet()) { String componentKey = entry.getKey(); String ref = entry.getValue(); Optional<ComponentDto> fileOptional = componentDao.selectByKey(session, componentKey); if (fileOptional.isPresent()) { ComponentDto file = fileOptional.get(); json.name(ref).beginObject(); addFile(json, file); ComponentDto project = getProject(file.projectUuid(), projectsByUuid, session); ComponentDto parentProject = getParentProject(file.getRootUuid(), parentProjectsByUuid, session); addProject(json, project, parentProject); json.endObject(); } } } private static void addFile(JsonWriter json, ComponentDto file) { json.prop("key", file.key()); json.prop("uuid", file.uuid()); json.prop("name", file.longName()); } private static void addProject(JsonWriter json, @Nullable ComponentDto project, @Nullable ComponentDto subProject) { if (project != null) { json.prop("project", project.key()); json.prop("projectUuid", project.uuid()); json.prop("projectName", project.longName()); // Do not return sub project if sub project and project are the same boolean displaySubProject = subProject != null && !subProject.uuid().equals(project.uuid()); if (displaySubProject) { json.prop("subProject", subProject.key()); json.prop("subProjectUuid", subProject.uuid()); json.prop("subProjectName", subProject.longName()); } } } private ComponentDto getProject(String projectUuid, Map<String, ComponentDto> projectsByUuid, DbSession session) { ComponentDto project = projectsByUuid.get(projectUuid); if (project == null) { Optional<ComponentDto> projectOptional = componentDao.selectByUuid(session, projectUuid); if (projectOptional.isPresent()) { project = projectOptional.get(); projectsByUuid.put(project.uuid(), project); } } return project; } private ComponentDto getParentProject(String rootUuid, Map<String, ComponentDto> subProjectsByUuid, DbSession session) { ComponentDto project = subProjectsByUuid.get(rootUuid); if (project == null) { Optional<ComponentDto> projectOptional = componentDao.selectByUuid(session, rootUuid); if (projectOptional.isPresent()) { project = projectOptional.get(); subProjectsByUuid.put(project.uuid(), project); } } return project; } }