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.batch.duplication;
021    
022    import com.google.common.base.Preconditions;
023    import net.sourceforge.pmd.cpd.TokenEntry;
024    import org.sonar.api.batch.fs.InputFile;
025    import org.sonar.api.batch.fs.internal.DefaultInputFile;
026    import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder;
027    import org.sonar.duplications.block.Block;
028    import org.sonar.duplications.block.FileBlocks;
029    import org.sonar.duplications.internal.pmd.PmdBlockChunker;
030    import org.sonar.duplications.internal.pmd.TokenizerBridge;
031    import org.sonar.duplications.internal.pmd.TokensLine;
032    
033    import java.util.ArrayList;
034    import java.util.List;
035    
036    public class DefaultTokenBuilder implements DuplicationTokenBuilder {
037    
038      private final BlockCache cache;
039      private final InputFile inputFile;
040      private final List<TokenEntry> tokens = new ArrayList<TokenEntry>();
041      private final PmdBlockChunker blockChunker;
042      private boolean done = false;
043      private int previousLine = 0;
044    
045      public DefaultTokenBuilder(InputFile inputFile, BlockCache cache, PmdBlockChunker blockChunker) {
046        this.inputFile = inputFile;
047        this.cache = cache;
048        this.blockChunker = blockChunker;
049        TokenEntry.clearImages();
050      }
051    
052      @Override
053      public DefaultTokenBuilder addToken(int line, String image) {
054        Preconditions.checkState(!done, "done() already called");
055        Preconditions.checkState(line >= previousLine, "Token should be created in order. Previous line was " + previousLine + " and you tried to create a token at line " + line);
056        TokenEntry cpdToken = new TokenEntry(image, inputFile.absolutePath(), line);
057        tokens.add(cpdToken);
058        previousLine = line;
059        return this;
060      }
061    
062      @Override
063      public void done() {
064        Preconditions.checkState(!done, "done() already called");
065        tokens.add(TokenEntry.getEOF());
066        TokenEntry.clearImages();
067        List<TokensLine> tokensLines = TokenizerBridge.convert(tokens);
068        List<Block> blocks = blockChunker.chunk(((DefaultInputFile) inputFile).key(), tokensLines);
069    
070        cache.put(((DefaultInputFile) inputFile).key(), new FileBlocks(((DefaultInputFile) inputFile).key(), blocks));
071        tokens.clear();
072      }
073    }