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 }