/* * 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.duplications.block; import org.sonar.duplications.CodeFragment; /** * Represents part of source code between two lines. * If two blocks have the same {@link #getBlockHash() hash}, then we assume that there is a duplication in a code, which they represent. */ public final class Block implements CodeFragment { private final String resourceId; private final ByteArray blockHash; private final int indexInFile; private final int startLine; private final int endLine; private int startUnit; private int endUnit; /** * Cache for hash code. */ private int hash; /** * @since 2.14 */ public static Builder builder() { return new Builder(); } /** * <p>Instances can be reused - it is safe to call {@link #build} * multiple times to build multiple blocks in series.</p> * * @since 2.14 */ public static final class Builder { private String resourceId; private ByteArray blockHash; private int indexInFile; private int startLine; private int endLine; private int startUnit; private int endUnit; public Builder setResourceId(String resourceId) { this.resourceId = resourceId; return this; } public Builder setBlockHash(ByteArray blockHash) { this.blockHash = blockHash; return this; } public Builder setIndexInFile(int index) { this.indexInFile = index; return this; } public Builder setLines(int start, int end) { this.startLine = start; this.endLine = end; return this; } public Builder setUnit(int start, int end) { this.startUnit = start; this.endUnit = end; return this; } public Block build() { return new Block(this); } } private Block(Builder builder) { this.resourceId = builder.resourceId; this.blockHash = builder.blockHash; this.indexInFile = builder.indexInFile; this.startLine = builder.startLine; this.endLine = builder.endLine; this.startUnit = builder.startUnit; this.endUnit = builder.endUnit; } public String getHashHex() { return getBlockHash().toString(); } public String getResourceId() { return resourceId; } public ByteArray getBlockHash() { return blockHash; } public int getIndexInFile() { return indexInFile; } @Override public int getStartLine() { return startLine; } @Override public int getEndLine() { return endLine; } /** * @since 2.14 */ public int getStartUnit() { return startUnit; } /** * @since 2.14 */ public int getEndUnit() { return endUnit; } @Override public boolean equals(Object obj) { if (!(obj instanceof Block)) { return false; } Block other = (Block) obj; return resourceId.equals(other.resourceId) && blockHash.equals(other.blockHash) && indexInFile == other.indexInFile && startLine == other.startLine && endLine == other.endLine; } @Override public int hashCode() { int h = hash; if (h == 0) { h = resourceId.hashCode(); h = 31 * h + blockHash.hashCode(); h = 31 * h + indexInFile; h = 31 * h + startLine; h = 31 * h + endLine; hash = h; } return h; } @Override public String toString() { return "'" + resourceId + "'[" + indexInFile + "|" + startLine + "-" + endLine + "]:" + blockHash; } }