001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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 License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.api.batch.sensor.duplication;
021
022 import com.google.common.annotations.Beta;
023 import org.apache.commons.lang.builder.EqualsBuilder;
024 import org.apache.commons.lang.builder.HashCodeBuilder;
025 import org.apache.commons.lang.builder.ToStringBuilder;
026 import org.apache.commons.lang.builder.ToStringStyle;
027 import org.sonar.api.batch.sensor.SensorContext;
028
029 import java.util.ArrayList;
030 import java.util.List;
031
032 /**
033 * Experimental, do not use.
034 * <p/>
035 * A {@link DuplicationGroup} is a list of duplicated {@link Block}s. One block
036 * is considered as the original code and all others are duplicates.
037 * Use {@link SensorContext#duplicationBuilder(org.sonar.api.batch.fs.InputFile)} and
038 * {@link SensorContext#saveDuplications(org.sonar.api.batch.fs.InputFile, List)}.
039 * @since 4.5
040 */
041 @Beta
042 public class DuplicationGroup {
043
044 public static class Block {
045 private final String resourceKey;
046 private final int startLine;
047 private final int length;
048
049 public Block(String resourceKey, int startLine, int length) {
050 this.resourceKey = resourceKey;
051 this.startLine = startLine;
052 this.length = length;
053 }
054
055 public String resourceKey() {
056 return resourceKey;
057 }
058
059 public int startLine() {
060 return startLine;
061 }
062
063 public int length() {
064 return length;
065 }
066
067 // Just for unit tests
068 @Override
069 public boolean equals(Object obj) {
070 if (obj == null) {
071 return false;
072 }
073 if (obj == this) {
074 return true;
075 }
076 if (obj.getClass() != getClass()) {
077 return false;
078 }
079 Block rhs = (Block) obj;
080 return new EqualsBuilder()
081 .append(resourceKey, rhs.resourceKey)
082 .append(startLine, rhs.startLine)
083 .append(length, rhs.length).isEquals();
084 }
085
086 @Override
087 public int hashCode() {
088 return new HashCodeBuilder(13, 43)
089 .append(resourceKey)
090 .append(startLine)
091 .append(length).toHashCode();
092 }
093
094 @Override
095 public String toString() {
096 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).
097 append("resourceKey", resourceKey).
098 append("startLine", startLine).
099 append("length", length).
100 toString();
101 }
102 }
103
104 private final Block originBlock;
105 private List<Block> duplicates = new ArrayList<DuplicationGroup.Block>();
106
107 /**
108 * For unit test and internal use only.
109 */
110 public DuplicationGroup(Block originBlock) {
111 this.originBlock = originBlock;
112 }
113
114 /**
115 * For unit test and internal use only.
116 */
117 public void setDuplicates(List<Block> duplicates) {
118 this.duplicates = duplicates;
119 }
120
121 /**
122 * For unit test and internal use only.
123 */
124 public DuplicationGroup addDuplicate(Block anotherBlock) {
125 this.duplicates.add(anotherBlock);
126 return this;
127 }
128
129 public Block originBlock() {
130 return originBlock;
131 }
132
133 public List<Block> duplicates() {
134 return duplicates;
135 }
136
137 // Just for unit tests
138 @Override
139 public boolean equals(Object obj) {
140 if (obj == null) {
141 return false;
142 }
143 if (obj == this) {
144 return true;
145 }
146 if (obj.getClass() != getClass()) {
147 return false;
148 }
149 DuplicationGroup rhs = (DuplicationGroup) obj;
150 EqualsBuilder equalsBuilder = new EqualsBuilder()
151 .append(originBlock, rhs.originBlock)
152 .append(duplicates.size(), rhs.duplicates.size());
153 if (duplicates.size() == rhs.duplicates.size()) {
154 for (int i = 0; i < duplicates.size(); i++) {
155 equalsBuilder.append(duplicates.get(i), rhs.duplicates.get(i));
156 }
157 }
158 return equalsBuilder.isEquals();
159 }
160
161 @Override
162 public int hashCode() {
163 HashCodeBuilder hcBuilder = new HashCodeBuilder(17, 37)
164 .append(originBlock)
165 .append(duplicates.size());
166 for (int i = 0; i < duplicates.size(); i++) {
167 hcBuilder.append(duplicates.get(i));
168 }
169 return hcBuilder.toHashCode();
170 }
171
172 @Override
173 public String toString() {
174 return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).
175 append("origin", originBlock).
176 append("duplicates", duplicates, true).
177 toString();
178 }
179
180 }