Browse Source

[SONAR-1875] Improve CodeReaderFilter with channel capabilities

http://jira.codehaus.org/browse/SONAR-1875
tags/2.6
bellingard 13 years ago
parent
commit
7877c79af7

+ 88
- 0
sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java View File

@@ -0,0 +1,88 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Sonar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.channel;

import java.io.IOException;
import java.io.Reader;

/**
* This class is a special CodeReaderFilter that uses Channels to filter the character stream before it is passed to the main channels
* declared for the CodeReader.
*
*/
public final class ChannelCodeReaderFilter<OUTPUT> extends CodeReaderFilter {

@SuppressWarnings("unchecked")
private Channel<OUTPUT>[] channels = new Channel[0];

private CodeReader internalCodeReader;

private OUTPUT output;

/**
* Creates a CodeReaderFilter that will use the provided Channels to filter the character stream it gets from its reader. And optionaly,
* it can push token to the provided output object.
*
* @param output
* the object that may accept tokens
* @param channels
* the different channels
*/
public ChannelCodeReaderFilter(OUTPUT output, Channel<OUTPUT>... channels) {
super();
this.channels = channels;
this.output = output;
}

/**
* ${@inheritDoc}
*/
@Override
public void setReader(Reader reader) {
super.setReader(reader);
internalCodeReader = new CodeReader(reader);
}

/**
* ${@inheritDoc}
*/
@Override
public int read(char[] filteredBuffer, int offset, int lenght) throws IOException {
int initialOffset = offset;
while (offset < filteredBuffer.length) {
if (internalCodeReader.peek() == -1) {
break;
}
boolean consumed = false;
for (Channel<OUTPUT> channel : channels) {
if (channel.consume(internalCodeReader, output)) {
consumed = true;
break;
}
}
if ( !consumed) {
int charRead = internalCodeReader.pop();
filteredBuffer[offset++] = (char) charRead;
}
}
return offset - initialOffset;
}

}

+ 5
- 1
sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java View File

@@ -253,6 +253,9 @@ public class CodeBuffer implements CharSequence {
}
}

/**
* Bridge class between CodeBuffer and CodeReaderFilter
*/
final class Filter extends FilterReader {

private CodeReaderFilter codeReaderFilter;
@@ -260,6 +263,7 @@ public class CodeBuffer implements CharSequence {
public Filter(Reader in, CodeReaderFilter codeReaderFilter) {
super(in);
this.codeReaderFilter = codeReaderFilter;
this.codeReaderFilter.setReader(in);
}

@Override
@@ -269,7 +273,7 @@ public class CodeBuffer implements CharSequence {

@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return codeReaderFilter.read(in, cbuf, off, len);
return codeReaderFilter.read(cbuf, off, len);
}

@Override

+ 41
- 3
sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java View File

@@ -1,3 +1,22 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Sonar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.channel;

import java.io.IOException;
@@ -16,6 +35,27 @@ import java.io.Reader;
*/
public abstract class CodeReaderFilter {

private Reader reader;

/**
* Returns the reader from which this class reads the character stream.
*
* @return the reader
*/
public Reader getReader() {
return reader;
}

/**
* Sets the reader from which this class will read the character stream.
*
* @param reader
* the reader
*/
public void setReader(Reader reader) {
this.reader = reader;
}

/**
* This method implements the filtering logic, that is:
* <ul>
@@ -27,8 +67,6 @@ public abstract class CodeReaderFilter {
* and fill the given buffer to its full capacity with the filtered data.</li>
* </ul>
*
* @param reader
* the input character flow
* @param filteredBuffer
* the output buffer that must contain the filtered data
* @param offset
@@ -39,6 +77,6 @@ public abstract class CodeReaderFilter {
* @throws IOException
* If an I/O error occurs
*/
public abstract int read(Reader reader, char[] filteredBuffer, int offset, int lenght) throws IOException;
public abstract int read(char[] filteredBuffer, int offset, int lenght) throws IOException;

}

+ 52
- 5
sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java View File

@@ -24,7 +24,6 @@ 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;
@@ -175,14 +174,45 @@ public class CodeBufferTest {
assertThat((char) code.pop(), is('-'));
}

@Test
public void testChannelCodeReaderFilter() throws Exception {
// create a windowing channel that drops the 2 first characters, keeps 6 characters and drops the rest of the line
@SuppressWarnings({ "rawtypes", "unchecked" })
CodeBuffer code = new CodeBuffer("0123456789\nABCDEFGHIJ", new ChannelCodeReaderFilter(null, new WindowingChannel()));
// test #charAt
assertEquals('2', code.charAt(0));
assertEquals('7', code.charAt(5));
assertEquals('\n', code.charAt(6));
assertEquals('C', code.charAt(7));
assertEquals('H', code.charAt(12));
assertEquals( -1, code.intAt(13));
// test peek and pop
assertThat((char) code.peek(), is('2'));
assertThat((char) code.pop(), is('2'));
assertThat((char) code.pop(), is('3'));
assertThat((char) code.pop(), is('4'));
assertThat((char) code.pop(), is('5'));
assertThat((char) code.pop(), is('6'));
assertThat((char) code.pop(), is('7'));// and 8 shouldn't show up
assertThat((char) code.pop(), is('\n'));
assertThat((char) code.peek(), is('C'));
assertThat((char) code.pop(), is('C'));
assertThat((char) code.pop(), is('D'));
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(code.pop(), is( -1));
}

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 {
public int read(char[] cbuf, int off, int len) throws IOException {
char[] tempBuffer = new char[cbuf.length];
int charCount = in.read(tempBuffer, off, len);
int charCount = getReader().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);
@@ -196,9 +226,9 @@ public class CodeBufferTest {
private Pattern pattern = Pattern.compile("[a-zA-Z]");
private String REPLACEMENT = "*";

public int read(Reader in, char[] cbuf, int off, int len) throws IOException {
public int read(char[] cbuf, int off, int len) throws IOException {
char[] tempBuffer = new char[cbuf.length];
int charCount = in.read(tempBuffer, off, len);
int charCount = getReader().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);
@@ -207,4 +237,21 @@ public class CodeBufferTest {
}
}

@SuppressWarnings("rawtypes")
class WindowingChannel extends Channel {

@Override
public boolean consume(CodeReader code, Object output) {
int columnPosition = code.getColumnPosition();
if (code.peek() == '\n') {
return false;
}
if (columnPosition < 2 || columnPosition > 7) {
code.pop();
return true;
}
return false;
}
}

}

Loading…
Cancel
Save