/* * 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.source; import java.util.Optional; import java.util.function.Function; import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.protobuf.DbFileSources; import org.sonar.db.source.FileSourceDto; import static com.google.common.base.Preconditions.checkArgument; public class SourceService { private final DbClient dbClient; private final HtmlSourceDecorator htmlDecorator; public SourceService(DbClient dbClient, HtmlSourceDecorator htmlDecorator) { this.dbClient = dbClient; this.htmlDecorator = htmlDecorator; } /** * Returns a range of lines as raw db data. User permission is not verified. * @param from starts from 1 * @param toInclusive starts from 1, must be greater than or equal param {@code from} */ public Optional<Iterable<DbFileSources.Line>> getLines(DbSession dbSession, String fileUuid, int from, int toInclusive) { return getLines(dbSession, fileUuid, from, toInclusive, Function.identity()); } /** * Returns a range of lines as raw text. * @see #getLines(DbSession, String, int, int) */ public Optional<Iterable<String>> getLinesAsRawText(DbSession dbSession, String fileUuid, int from, int toInclusive) { return getLines(dbSession, fileUuid, from, toInclusive, DbFileSources.Line::getSource); } public Optional<Iterable<String>> getLinesAsHtml(DbSession dbSession, String fileUuid, int from, int toInclusive) { return getLines(dbSession, fileUuid, from, toInclusive, lineToHtml()); } private <E> Optional<Iterable<E>> getLines(DbSession dbSession, String fileUuid, int from, int toInclusive, Function<DbFileSources.Line, E> function) { verifyLine(from); checkArgument(toInclusive >= from, String.format("Line number must greater than or equal to %d, got %d", from, toInclusive)); FileSourceDto dto = dbClient.fileSourceDao().selectSourceByFileUuid(dbSession, fileUuid); if (dto == null) { return Optional.empty(); } return Optional.of(dto.getSourceData().getLinesList().stream() .filter(line -> line.hasLine() && line.getLine() >= from) .limit((toInclusive - from) + 1L) .map(function) .collect(MoreCollectors.toList())); } private static void verifyLine(int line) { checkArgument(line >= 1, String.format("Line number must start at 1, got %d", line)); } private Function<DbFileSources.Line, String> lineToHtml() { return line -> htmlDecorator.getDecoratedSourceAsHtml(line.getSource(), line.getHighlighting(), line.getSymbols()); } }