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 */
020package org.sonar.plugins.squid.bridges;
021
022import com.google.common.collect.Lists;
023import org.sonar.api.measures.CoreMetrics;
024import org.sonar.api.measures.Measure;
025import org.sonar.api.measures.PersistenceMode;
026import org.sonar.api.resources.Qualifiers;
027import org.sonar.api.resources.Resource;
028import org.sonar.java.bytecode.asm.AsmField;
029import org.sonar.java.bytecode.asm.AsmMethod;
030import org.sonar.java.bytecode.asm.AsmResource;
031import org.sonar.squid.api.SourceFile;
032import org.sonar.squid.measures.Metric;
033
034import java.util.Collections;
035import java.util.Comparator;
036import java.util.List;
037import java.util.Set;
038
039public 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}