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.squid.bridges;
021
022 import com.google.common.collect.Lists;
023 import org.sonar.api.measures.CoreMetrics;
024 import org.sonar.api.measures.Measure;
025 import org.sonar.api.measures.PersistenceMode;
026 import org.sonar.api.resources.Qualifiers;
027 import org.sonar.api.resources.Resource;
028 import org.sonar.java.bytecode.asm.AsmField;
029 import org.sonar.java.bytecode.asm.AsmMethod;
030 import org.sonar.java.bytecode.asm.AsmResource;
031 import org.sonar.squid.api.SourceFile;
032 import org.sonar.squid.measures.Metric;
033
034 import java.util.Collections;
035 import java.util.Comparator;
036 import java.util.List;
037 import java.util.Set;
038
039 public class Lcom4BlocksBridge extends Bridge {
040
041 protected Lcom4BlocksBridge() {
042 super(true);
043 }
044
045 @Override
046 public void onFile(SourceFile squidFile, Resource sonarFile) {
047 List<Set<AsmResource>> blocks = (List<Set<AsmResource>>) squidFile.getData(Metric.LCOM4_BLOCKS);
048
049 // This measure includes AsmResource objects and it is used only by this bridge, so
050 // it can be removed from memory.
051 squidFile.removeMeasure(Metric.LCOM4_BLOCKS);
052
053 if (blocks != null && !blocks.isEmpty()) {
054 Measure measure = new Measure(CoreMetrics.LCOM4_BLOCKS, serialize(blocks));
055 measure.setPersistenceMode(PersistenceMode.DATABASE);
056 context.saveMeasure(sonarFile, measure);
057 }
058 }
059
060 protected void sortBlocks(List<Set<AsmResource>> blocks) {
061 Collections.sort(blocks, new Comparator<Set>() {
062 public int compare(Set set1, Set set2) {
063 return set1.size() - set2.size();
064 }
065 });
066 }
067
068 protected String serialize(List<Set<AsmResource>> blocks) {
069 sortBlocks(blocks);
070
071 StringBuilder sb = new StringBuilder();
072 sb.append('[');
073
074 for (int indexBlock = 0; indexBlock < blocks.size(); indexBlock++) {
075 blocks.get(indexBlock);
076 Set<AsmResource> block = blocks.get(indexBlock);
077 if (!block.isEmpty()) {
078 if (indexBlock > 0) {
079 sb.append(',');
080 }
081 sb.append('[');
082 serializeBlock(block, sb);
083 sb.append(']');
084 }
085 }
086 sb.append(']');
087 return sb.toString();
088 }
089
090 private void serializeBlock(Set<AsmResource> block, StringBuilder sb) {
091 List<AsmResource> sortedResources = sortResourcesInBlock(block);
092 int indexResource = 0;
093 for (AsmResource resource : sortedResources) {
094 if (indexResource++ > 0) {
095 sb.append(',');
096 }
097 serializeResource(resource, sb);
098 }
099 }
100
101 private void serializeResource(AsmResource resource, StringBuilder sb) {
102 sb.append("{\"q\":\"");
103 sb.append(toQualifier(resource));
104 sb.append("\",\"n\":\"");
105 sb.append(resource.toString());
106 sb.append("\"}");
107 }
108
109 protected List<AsmResource> sortResourcesInBlock(Set<AsmResource> block) {
110 List<AsmResource> result = Lists.newArrayList();
111 result.addAll(block);
112
113 Collections.sort(result, new Comparator<AsmResource>() {
114 public int compare(AsmResource asmResource1, AsmResource asmResource2) {
115 int result = compareType(asmResource1, asmResource2);
116 if (result == 0) {
117 result = asmResource1.toString().compareTo(asmResource2.toString());
118 }
119 return result;
120 }
121
122 private int compareType(AsmResource asmResource1, AsmResource asmResource2) {
123 if (asmResource1 instanceof AsmField) {
124 return (asmResource2 instanceof AsmField) ? 0 : -1;
125 }
126 return (asmResource2 instanceof AsmMethod) ? 0 : 1;
127 }
128 });
129
130 return result;
131 }
132
133 private static String toQualifier(AsmResource asmResource) {
134 if (asmResource instanceof AsmField) {
135 return Qualifiers.FIELD;
136 }
137 if (asmResource instanceof AsmMethod) {
138 return Qualifiers.METHOD;
139 }
140 throw new IllegalArgumentException("Wrong ASM resource: " + asmResource.getClass());
141 }
142 }