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    }