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    }