diff options
author | bellingard <bellingard@gmail.com> | 2010-10-14 13:45:29 +0000 |
---|---|---|
committer | bellingard <bellingard@gmail.com> | 2010-10-14 13:45:29 +0000 |
commit | 7b0cb741b188abd0be71b5dfacbe5f3a0a5cda9f (patch) | |
tree | 5fab661c104408d8dab61dba80ecc1775aecca37 | |
parent | 4ccf48f4e76bfe9a1783aa9b17e3d4d1c5c278aa (diff) | |
download | sonarqube-7b0cb741b188abd0be71b5dfacbe5f3a0a5cda9f.tar.gz sonarqube-7b0cb741b188abd0be71b5dfacbe5f3a0a5cda9f.zip |
[SONAR-1853] Create a new CodeReaderFilter mechanism to prevent logic duplications between Channel(s)
http://jira.codehaus.org/browse/SONAR-1853
4 files changed, 152 insertions, 21 deletions
diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java b/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java index f726f0a9645..b4288bad3ce 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java @@ -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(); + } + + } } diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java index f894ca7fd15..e597385d387 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java @@ -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 index 00000000000..e65136106b6 --- /dev/null +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java @@ -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; + +} diff --git a/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java b/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java index eedf28ae0ad..05ac7704804 100644 --- a/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java +++ b/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java @@ -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; + } + } + } |