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 */ 020package org.sonar.api.batch.sensor.duplication.internal; 021 022import org.sonar.api.batch.sensor.internal.SensorStorage; 023 024import com.google.common.base.Preconditions; 025import org.apache.commons.lang.builder.EqualsBuilder; 026import org.apache.commons.lang.builder.HashCodeBuilder; 027import org.apache.commons.lang.builder.ToStringBuilder; 028import org.apache.commons.lang.builder.ToStringStyle; 029import org.sonar.api.batch.fs.InputFile; 030import org.sonar.api.batch.fs.internal.DefaultInputFile; 031import org.sonar.api.batch.sensor.duplication.Duplication; 032import org.sonar.api.batch.sensor.duplication.NewDuplication; 033import org.sonar.api.batch.sensor.internal.DefaultStorable; 034 035import javax.annotation.Nullable; 036 037import java.util.LinkedList; 038import java.util.List; 039 040public class DefaultDuplication extends DefaultStorable implements NewDuplication, Duplication { 041 042 private Block originBlock; 043 private List<Block> duplicates = new LinkedList<Duplication.Block>(); 044 045 public DefaultDuplication() { 046 super(); 047 } 048 049 public DefaultDuplication(@Nullable SensorStorage storage) { 050 super(storage); 051 } 052 053 @Override 054 public DefaultDuplication originBlock(InputFile inputFile, int startLine, int endLine) { 055 Preconditions.checkArgument(inputFile != null, "InputFile can't be null"); 056 validateLineArgument(inputFile, startLine, "startLine"); 057 validateLineArgument(inputFile, endLine, "endLine"); 058 originBlock = new Duplication.Block(((DefaultInputFile) inputFile).key(), startLine, endLine - startLine + 1); 059 return this; 060 } 061 062 @Override 063 public DefaultDuplication isDuplicatedBy(InputFile sameOrOtherFile, int startLine, int endLine) { 064 Preconditions.checkArgument(sameOrOtherFile != null, "InputFile can't be null"); 065 validateLineArgument(sameOrOtherFile, startLine, "startLine"); 066 validateLineArgument(sameOrOtherFile, endLine, "endLine"); 067 return isDuplicatedBy(((DefaultInputFile) sameOrOtherFile).key(), startLine, endLine); 068 } 069 070 /** 071 * For internal use. Global duplications are referencing files outside of current project so 072 * no way to manipulate an InputFile. 073 */ 074 public DefaultDuplication isDuplicatedBy(String fileKey, int startLine, int endLine) { 075 Preconditions.checkNotNull(originBlock, "Call originBlock() first"); 076 duplicates.add(new Duplication.Block(fileKey, startLine, endLine - startLine + 1)); 077 return this; 078 } 079 080 @Override 081 public void doSave() { 082 Preconditions.checkNotNull(originBlock, "Call originBlock() first"); 083 Preconditions.checkState(!duplicates.isEmpty(), "No duplicates. Call isDuplicatedBy()"); 084 storage.store(this); 085 } 086 087 @Override 088 public Block originBlock() { 089 return originBlock; 090 } 091 092 public DefaultDuplication setOriginBlock(Block originBlock) { 093 this.originBlock = originBlock; 094 return this; 095 } 096 097 @Override 098 public List<Block> duplicates() { 099 return duplicates; 100 } 101 102 // Just for unit tests 103 @Override 104 public boolean equals(Object obj) { 105 if (obj == null) { 106 return false; 107 } 108 if (obj == this) { 109 return true; 110 } 111 if (obj.getClass() != getClass()) { 112 return false; 113 } 114 DefaultDuplication rhs = (DefaultDuplication) obj; 115 EqualsBuilder equalsBuilder = new EqualsBuilder() 116 .append(originBlock, rhs.originBlock) 117 .append(duplicates.size(), rhs.duplicates.size()); 118 if (duplicates.size() == rhs.duplicates.size()) { 119 for (int i = 0; i < duplicates.size(); i++) { 120 equalsBuilder.append(duplicates.get(i), rhs.duplicates.get(i)); 121 } 122 } 123 return equalsBuilder.isEquals(); 124 } 125 126 @Override 127 public int hashCode() { 128 HashCodeBuilder hcBuilder = new HashCodeBuilder(17, 37) 129 .append(originBlock) 130 .append(duplicates.size()); 131 for (int i = 0; i < duplicates.size(); i++) { 132 hcBuilder.append(duplicates.get(i)); 133 } 134 return hcBuilder.toHashCode(); 135 } 136 137 @Override 138 public String toString() { 139 return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE). 140 append("origin", originBlock). 141 append("duplicates", duplicates, true). 142 toString(); 143 } 144 145}