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