001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar 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 * Sonar 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 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.plugins.cpd.index; 021 022 import com.google.common.collect.Lists; 023 import com.google.common.collect.Maps; 024 import org.sonar.api.database.model.Snapshot; 025 import org.sonar.api.resources.Project; 026 import org.sonar.api.resources.Resource; 027 import org.sonar.batch.index.ResourcePersister; 028 import org.sonar.core.duplication.DuplicationDao; 029 import org.sonar.core.duplication.DuplicationUnitDto; 030 import org.sonar.duplications.block.Block; 031 import org.sonar.duplications.block.ByteArray; 032 033 import java.util.Collection; 034 import java.util.Collections; 035 import java.util.List; 036 import java.util.Map; 037 038 public class DbDuplicationsIndex { 039 040 private final Map<ByteArray, Collection<Block>> cache = Maps.newHashMap(); 041 042 private final ResourcePersister resourcePersister; 043 private final int currentProjectSnapshotId; 044 private final Integer lastSnapshotId; 045 private final String languageKey; 046 047 private DuplicationDao dao; 048 049 public DbDuplicationsIndex(ResourcePersister resourcePersister, Project currentProject, DuplicationDao dao) { 050 this.dao = dao; 051 this.resourcePersister = resourcePersister; 052 Snapshot currentSnapshot = resourcePersister.getSnapshotOrFail(currentProject); 053 Snapshot lastSnapshot = resourcePersister.getLastSnapshot(currentSnapshot, false); 054 this.currentProjectSnapshotId = currentSnapshot.getId(); 055 this.lastSnapshotId = lastSnapshot == null ? null : lastSnapshot.getId(); 056 this.languageKey = currentProject.getLanguageKey(); 057 } 058 059 int getSnapshotIdFor(Resource resource) { 060 return resourcePersister.getSnapshotOrFail(resource).getId(); 061 } 062 063 public void prepareCache(Resource resource) { 064 int resourceSnapshotId = getSnapshotIdFor(resource); 065 List<DuplicationUnitDto> units = dao.selectCandidates(resourceSnapshotId, lastSnapshotId, languageKey); 066 cache.clear(); 067 // TODO Godin: maybe remove conversion of units to blocks? 068 for (DuplicationUnitDto unit : units) { 069 String hash = unit.getHash(); 070 String resourceKey = unit.getResourceKey(); 071 int indexInFile = unit.getIndexInFile(); 072 int startLine = unit.getStartLine(); 073 int endLine = unit.getEndLine(); 074 075 // TODO Godin: in fact we could work directly with id instead of key - this will allow to decrease memory consumption 076 Block block = Block.builder() 077 .setResourceId(resourceKey) 078 .setBlockHash(new ByteArray(hash)) 079 .setIndexInFile(indexInFile) 080 .setLines(startLine, endLine) 081 .build(); 082 083 // Group blocks by hash 084 Collection<Block> sameHash = cache.get(block.getBlockHash()); 085 if (sameHash == null) { 086 sameHash = Lists.newArrayList(); 087 cache.put(block.getBlockHash(), sameHash); 088 } 089 sameHash.add(block); 090 } 091 } 092 093 public Collection<Block> getByHash(ByteArray hash) { 094 Collection<Block> result = cache.get(hash); 095 if (result != null) { 096 return result; 097 } else { 098 return Collections.emptyList(); 099 } 100 } 101 102 public void insert(Resource resource, Collection<Block> blocks) { 103 int resourceSnapshotId = getSnapshotIdFor(resource); 104 105 // TODO Godin: maybe remove conversion of blocks to units? 106 List<DuplicationUnitDto> units = Lists.newArrayList(); 107 for (Block block : blocks) { 108 DuplicationUnitDto unit = new DuplicationUnitDto( 109 currentProjectSnapshotId, 110 resourceSnapshotId, 111 block.getBlockHash().toString(), 112 block.getIndexInFile(), 113 block.getStartLine(), 114 block.getEndLine()); 115 units.add(unit); 116 } 117 118 dao.insert(units); 119 } 120 121 }