001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 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.colorizer; 021 022 import java.util.List; 023 024 public class ColorizationEngine { 025 026 private List<Tokenizer> tokenizers; 027 private CharacterTransformer charTransformer; 028 029 public ColorizationEngine(List<Tokenizer> tokenizers) { 030 this(tokenizers, new NoTransformer()); 031 } 032 033 public ColorizationEngine(List<Tokenizer> tokenizers, CharacterTransformer charTransformer) { 034 this.tokenizers = tokenizers; 035 this.charTransformer = charTransformer; 036 } 037 038 public final String colorize(String code) { 039 return colorize(new CodeReader(code)); 040 } 041 042 public final String colorize(CodeReader code) { 043 StringBuilder colorizedCode = new StringBuilder(); 044 appendBeginOfFile(colorizedCode); 045 nextChar: 046 while (code.peek() != -1) { 047 for (Tokenizer codeTokenizer : tokenizers) { 048 if (codeTokenizer.hasNextToken(code)) { 049 appendNextToken(code, codeTokenizer, colorizedCode); 050 continue nextChar; 051 } 052 } 053 054 transformAndAppend((char) code.pop(), colorizedCode); 055 } 056 appendEndOfFile(colorizedCode); 057 code.close(); 058 return colorizedCode.toString(); 059 } 060 061 private void appendBeginOfFile(StringBuilder colorizedCode) { 062 for (Tokenizer tokenizer : tokenizers) { 063 colorizedCode.append(tokenizer.getTagBeginOfFile()); 064 } 065 } 066 067 private void appendEndOfFile(StringBuilder colorizedCode) { 068 for (Tokenizer tokenizer : tokenizers) { 069 colorizedCode.append(tokenizer.getTagEndOfFile()); 070 } 071 } 072 073 private void appendNextToken(CodeReader code, Tokenizer codeTokenizer, StringBuilder colorizedCode) { 074 colorizedCode.append(codeTokenizer.getTagBefore()); 075 transformAndAppend(codeTokenizer.nextToken(code), colorizedCode); 076 colorizedCode.append(codeTokenizer.getTagAfter()); 077 } 078 079 private void transformAndAppend(String code, StringBuilder output) { 080 char[] chars = code.toCharArray(); 081 for (char character : chars) { 082 transformAndAppend(character, output); 083 } 084 } 085 086 private void transformAndAppend(char character, StringBuilder output) { 087 if (charTransformer.canTransform((int) character)) { 088 output.append(charTransformer.transform((int) character)); 089 } else { 090 output.append(character); 091 } 092 } 093 094 095 private static class NoTransformer extends CharacterTransformer { 096 @Override 097 boolean canTransform(int character) { 098 return false; 099 } 100 101 @Override 102 String transform(int character) { 103 throw new IllegalStateException("This method should not be called."); 104 } 105 } 106 }