]> source.dussan.org Git - sonarqube.git/commitdiff
[SONAR-1853] Create a new CodeReaderFilter mechanism to prevent logic duplications...
authorbellingard <bellingard@gmail.com>
Thu, 14 Oct 2010 13:45:29 +0000 (13:45 +0000)
committerbellingard <bellingard@gmail.com>
Thu, 14 Oct 2010 13:45:29 +0000 (13:45 +0000)
http://jira.codehaus.org/browse/SONAR-1853

sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java
sonar-channel/src/main/java/org/sonar/channel/CodeReader.java
sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java [new file with mode: 0644]
sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java

index f726f0a964567a298a1c9b7b44c51bf909436d39..b4288bad3ceeab84b00b3d093fef5e38c94321e7 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.channel;
 
+import java.io.FilterReader;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
@@ -26,8 +27,7 @@ import java.io.StringReader;
 import org.apache.commons.io.IOUtils;
 
 /**
- * The CodeBuffer class provides all the basic features required to manipulate a source code character stream. 
- * Those features are :
+ * The CodeBuffer class provides all the basic features required to manipulate a source code character stream. Those features are :
  * <ul>
  * <li>Read and consume next source code character : pop()</li>
  * <li>Retrieve last consumed character : lastChar()</li>
@@ -51,25 +51,29 @@ public class CodeBuffer implements CharSequence {
   private boolean recordingMode = false;
   private StringBuilder recordedCharacters = new StringBuilder();
 
-  public CodeBuffer(Reader code) {
-    this(code, DEFAULT_BUFFER_CAPACITY);
+  public CodeBuffer(Reader code, CodeReaderFilter... codeReaderFilters) {
+    this(code, DEFAULT_BUFFER_CAPACITY, codeReaderFilters);
   }
 
-  private CodeBuffer(Reader code, int bufferCapacity) {
-    this.code = code;
+  private CodeBuffer(Reader initialCodeReader, int bufferCapacity, CodeReaderFilter... codeReaderFilters) {
     lastChar = -1;
     cursor = new Cursor();
     this.bufferCapacity = bufferCapacity;
     buffer = new char[bufferCapacity];
+    Reader reader = initialCodeReader;
+    for (CodeReaderFilter codeReaderFilter : codeReaderFilters) {
+      reader = new Filter(reader, codeReaderFilter);
+    }
+    this.code = reader;
     fillBuffer();
   }
 
-  public CodeBuffer(String code) {
-    this(new StringReader(code));
+  public CodeBuffer(String code, CodeReaderFilter... codeReaderFilters) {
+    this(new StringReader(code), codeReaderFilters);
   }
 
-  protected CodeBuffer(String code, int bufferCapacity) {
-    this(new StringReader(code), bufferCapacity);
+  protected CodeBuffer(String code, int bufferCapacity, CodeReaderFilter... codeReaderFilters) {
+    this(new StringReader(code), bufferCapacity, codeReaderFilters);
   }
 
   /**
@@ -248,4 +252,30 @@ public class CodeBuffer implements CharSequence {
       return clone;
     }
   }
+
+  final class Filter extends FilterReader {
+
+    private CodeReaderFilter codeReaderFilter;
+
+    public Filter(Reader in, CodeReaderFilter codeReaderFilter) {
+      super(in);
+      this.codeReaderFilter = codeReaderFilter;
+    }
+
+    @Override
+    public int read() throws IOException {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int read(char[] cbuf, int off, int len) throws IOException {
+      return codeReaderFilter.read(in, cbuf, off, len);
+    }
+
+    @Override
+    public long skip(long n) throws IOException {
+      throw new UnsupportedOperationException();
+    }
+
+  }
 }
index f894ca7fd151211d7b509c5657965d9e3a3dbb86..e597385d3879f902d8e324a570109f616801369a 100644 (file)
@@ -34,16 +34,16 @@ public class CodeReader extends CodeBuffer {
 
   private Cursor previousCursor;
 
-  public CodeReader(Reader code) {
-    super(code);
+  public CodeReader(Reader code, CodeReaderFilter... codeReaderFilters) {
+    super(code, codeReaderFilters);
   }
 
-  public CodeReader(String code) {
-    super(code);
+  public CodeReader(String code, CodeReaderFilter... codeReaderFilters) {
+    super(code, codeReaderFilters);
   }
 
-  protected CodeReader(String code, int bufferCapacity) {
-    super(code, bufferCapacity);
+  protected CodeReader(String code, int bufferCapacity, CodeReaderFilter... codeReaderFilters) {
+    super(code, bufferCapacity, codeReaderFilters);
   }
 
   /**
diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java
new file mode 100644 (file)
index 0000000..e651361
--- /dev/null
@@ -0,0 +1,10 @@
+package org.sonar.channel;
+
+import java.io.IOException;
+import java.io.Reader;
+
+public abstract class CodeReaderFilter {
+
+  public abstract int read(Reader in, char[] cbuf, int off, int len) throws IOException;
+
+}
index eedf28ae0ad55ffd08076f0473f7dadbcee3288e..05ac7704804d5c81a202e3b2d94260c3161c0b8f 100644 (file)
@@ -23,6 +23,10 @@ import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
+import java.io.IOException;
+import java.io.Reader;
+import java.util.regex.Pattern;
+
 import org.junit.Test;
 
 public class CodeBufferTest {
@@ -48,7 +52,7 @@ public class CodeBufferTest {
 
   @Test
   public void testLastCharacter() {
-    CodeReader reader = new CodeReader("bar");
+    CodeBuffer reader = new CodeBuffer("bar");
     assertThat(reader.lastChar(), is( -1));
     reader.pop();
     assertThat((char) reader.lastChar(), is('b'));
@@ -56,7 +60,7 @@ public class CodeBufferTest {
 
   @Test
   public void testGetColumnAndLinePosition() {
-    CodeReader reader = new CodeReader("pa\nc\r\ns\r\n\r\n");
+    CodeBuffer reader = new CodeBuffer("pa\nc\r\ns\r\n\r\n");
     assertThat(reader.getColumnPosition(), is(0));
     assertThat(reader.getLinePosition(), is(1));
     reader.pop(); // p
@@ -92,7 +96,7 @@ public class CodeBufferTest {
 
   @Test
   public void testStartAndStopRecording() {
-    CodeReader reader = new CodeReader("123456");
+    CodeBuffer reader = new CodeBuffer("123456");
     reader.pop();
     assertEquals("", reader.stopRecording().toString());
 
@@ -106,14 +110,101 @@ public class CodeBufferTest {
 
   @Test
   public void testCharAt() {
-    CodeReader reader = new CodeReader("123456");
+    CodeBuffer reader = new CodeBuffer("123456");
     assertEquals('1', reader.charAt(0));
     assertEquals('6', reader.charAt(5));
   }
 
   @Test
   public void testCharAtIndexOutOfBoundsException() {
-    CodeReader reader = new CodeReader("12345");
+    CodeBuffer reader = new CodeBuffer("12345");
     assertEquals(reader.charAt(5), (char) -1);
   }
+
+  @Test
+  public void testCodeReaderFilter() throws Exception {
+    CodeBuffer code = new CodeBuffer("abcd12efgh34", new ReplaceNumbersFilter());
+    // test #charAt
+    assertEquals('a', code.charAt(0));
+    assertEquals('-', code.charAt(4));
+    assertEquals('-', code.charAt(5));
+    assertEquals('e', code.charAt(6));
+    assertEquals('-', code.charAt(10));
+    assertEquals('-', code.charAt(11));
+    // test peek and pop
+    assertThat((char) code.peek(), is('a'));
+    assertThat((char) code.pop(), is('a'));
+    assertThat((char) code.pop(), is('b'));
+    assertThat((char) code.pop(), is('c'));
+    assertThat((char) code.pop(), is('d'));
+    assertThat((char) code.peek(), is('-'));
+    assertThat((char) code.pop(), is('-'));
+    assertThat((char) code.pop(), is('-'));
+    assertThat((char) code.pop(), is('e'));
+    assertThat((char) code.pop(), is('f'));
+    assertThat((char) code.pop(), is('g'));
+    assertThat((char) code.pop(), is('h'));
+    assertThat((char) code.pop(), is('-'));
+    assertThat((char) code.pop(), is('-'));
+  }
+
+  @Test
+  public void testSeveralCodeReaderFilter() throws Exception {
+    CodeBuffer code = new CodeBuffer("abcd12efgh34", new ReplaceNumbersFilter(), new ReplaceCharFilter());
+    // test #charAt
+    assertEquals('*', code.charAt(0));
+    assertEquals('-', code.charAt(4));
+    assertEquals('-', code.charAt(5));
+    assertEquals('*', code.charAt(6));
+    assertEquals('-', code.charAt(10));
+    assertEquals('-', code.charAt(11));
+    // test peek and pop
+    assertThat((char) code.peek(), is('*'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.peek(), is('-'));
+    assertThat((char) code.pop(), is('-'));
+    assertThat((char) code.pop(), is('-'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.pop(), is('*'));
+    assertThat((char) code.pop(), is('-'));
+    assertThat((char) code.pop(), is('-'));
+  }
+
+  class ReplaceNumbersFilter extends CodeReaderFilter {
+
+    private Pattern pattern = Pattern.compile("\\d");
+    private String REPLACEMENT = "-";
+
+    public int read(Reader in, char[] cbuf, int off, int len) throws IOException {
+      char[] tempBuffer = new char[cbuf.length];
+      int charCount = in.read(tempBuffer, off, len);
+      if (charCount != -1) {
+        String filteredString = pattern.matcher(new String(tempBuffer)).replaceAll(REPLACEMENT);
+        System.arraycopy(filteredString.toCharArray(), 0, cbuf, 0, tempBuffer.length);
+      }
+      return charCount;
+    }
+  }
+
+  class ReplaceCharFilter extends CodeReaderFilter {
+
+    private Pattern pattern = Pattern.compile("[a-zA-Z]");
+    private String REPLACEMENT = "*";
+
+    public int read(Reader in, char[] cbuf, int off, int len) throws IOException {
+      char[] tempBuffer = new char[cbuf.length];
+      int charCount = in.read(tempBuffer, off, len);
+      if (charCount != -1) {
+        String filteredString = pattern.matcher(new String(tempBuffer)).replaceAll(REPLACEMENT);
+        System.arraycopy(filteredString.toCharArray(), 0, cbuf, 0, tempBuffer.length);
+      }
+      return charCount;
+    }
+  }
+
 }