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 }