001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.duplications.block; 021 022 import com.google.common.annotations.Beta; 023 import org.sonar.duplications.CodeFragment; 024 025 /** 026 * Represents part of source code between two lines. 027 * If two blocks have the same {@link #getBlockHash() hash}, then we assume that there is a duplication in a code, which they represent. 028 */ 029 public final class Block implements CodeFragment { 030 031 private final String resourceId; 032 private final ByteArray blockHash; 033 private final int indexInFile; 034 035 private final int startLine; 036 private final int endLine; 037 038 private int startUnit; 039 private int endUnit; 040 041 /** 042 * Cache for hash code. 043 */ 044 private int hash; 045 046 /** 047 * @since 2.14 048 */ 049 public static Builder builder() { 050 return new Builder(); 051 } 052 053 /** 054 * <p>Instances can be reused - it is safe to call {@link #build} 055 * multiple times to build multiple blocks in series.</p> 056 * 057 * @since 2.14 058 */ 059 public static final class Builder { 060 061 private String resourceId; 062 private ByteArray blockHash; 063 private int indexInFile; 064 065 private int startLine; 066 private int endLine; 067 068 private int startUnit; 069 private int endUnit; 070 071 public Builder setResourceId(String resourceId) { 072 this.resourceId = resourceId; 073 return this; 074 } 075 076 public Builder setBlockHash(ByteArray blockHash) { 077 this.blockHash = blockHash; 078 return this; 079 } 080 081 public Builder setIndexInFile(int index) { 082 this.indexInFile = index; 083 return this; 084 } 085 086 public Builder setLines(int start, int end) { 087 this.startLine = start; 088 this.endLine = end; 089 return this; 090 } 091 092 @Beta 093 public Builder setUnit(int start, int end) { 094 this.startUnit = start; 095 this.endUnit = end; 096 return this; 097 } 098 099 public Block build() { 100 return new Block(this); 101 } 102 } 103 104 private Block(Builder builder) { 105 this.resourceId = builder.resourceId; 106 this.blockHash = builder.blockHash; 107 this.indexInFile = builder.indexInFile; 108 109 this.startLine = builder.startLine; 110 this.endLine = builder.endLine; 111 112 this.startUnit = builder.startUnit; 113 this.endUnit = builder.endUnit; 114 } 115 116 public String getHashHex() { 117 return getBlockHash().toString(); 118 } 119 120 public String getResourceId() { 121 return resourceId; 122 } 123 124 public ByteArray getBlockHash() { 125 return blockHash; 126 } 127 128 public int getIndexInFile() { 129 return indexInFile; 130 } 131 132 public int getStartLine() { 133 return startLine; 134 } 135 136 public int getEndLine() { 137 return endLine; 138 } 139 140 /** 141 * @since 2.14 142 */ 143 @Beta 144 public int getStartUnit() { 145 return startUnit; 146 } 147 148 /** 149 * @since 2.14 150 */ 151 @Beta 152 public int getEndUnit() { 153 return endUnit; 154 } 155 156 @Override 157 public boolean equals(Object obj) { 158 if (!(obj instanceof Block)) { 159 return false; 160 } 161 Block other = (Block) obj; 162 return resourceId.equals(other.resourceId) 163 && blockHash.equals(other.blockHash) 164 && indexInFile == other.indexInFile 165 && startLine == other.startLine 166 && endLine == other.endLine; 167 } 168 169 @Override 170 public int hashCode() { 171 int h = hash; 172 if (h == 0) { 173 h = resourceId.hashCode(); 174 h = 31 * h + blockHash.hashCode(); 175 h = 31 * h + indexInFile; 176 h = 31 * h + startLine; 177 h = 31 * h + endLine; 178 hash = h; 179 } 180 return h; 181 } 182 183 @Override 184 public String toString() { 185 return "'" + resourceId + "'[" + indexInFile + "|" + startLine + "-" + endLine + "]:" + blockHash; 186 } 187 188 }