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 */
020 package org.sonar.channel;
021
022 import java.io.IOException;
023 import java.io.Reader;
024
025 /**
026 * This class is a special CodeReaderFilter that uses Channels to filter the character stream before it is passed to the main channels
027 * declared for the CodeReader.
028 *
029 */
030 public final class ChannelCodeReaderFilter<OUTPUT> extends CodeReaderFilter<OUTPUT> {
031
032 @SuppressWarnings("unchecked")
033 private Channel<OUTPUT>[] channels = new Channel[0];
034
035 private CodeReader internalCodeReader;
036
037 /**
038 * Creates a CodeReaderFilter that will use the provided Channels to filter the character stream it gets from its reader.
039 *
040 * @param channels
041 * the different channels
042 */
043 public ChannelCodeReaderFilter(Channel<OUTPUT>... channels) {
044 super();
045 this.channels = channels;
046 }
047
048 /**
049 * Creates a CodeReaderFilter that will use the provided Channels to filter the character stream it gets from its reader. And optionally,
050 * it can push token to the provided output object.
051 *
052 * @param output
053 * the object that may accept tokens
054 * @param channels
055 * the different channels
056 */
057 public ChannelCodeReaderFilter(OUTPUT output, Channel<OUTPUT>... channels) {
058 super(output);
059 this.channels = channels;
060 }
061
062 /**
063 * {@inheritDoc}
064 */
065 @Override
066 public void setReader(Reader reader) {
067 super.setReader(reader);
068 internalCodeReader = new CodeReader(reader, getConfiguration());
069 }
070
071 /**
072 * {@inheritDoc}
073 */
074 @Override
075 public int read(char[] filteredBuffer, int offset, int length) throws IOException {
076 if (internalCodeReader.peek() == -1) {
077 return -1;
078 }
079 int initialOffset = offset;
080 while (offset < filteredBuffer.length) {
081 if (internalCodeReader.peek() == -1) {
082 break;
083 }
084 boolean consumed = false;
085 for (Channel<OUTPUT> channel : channels) {
086 if (channel.consume(internalCodeReader, getOutput())) {
087 consumed = true;
088 break;
089 }
090 }
091 if ( !consumed) {
092 int charRead = internalCodeReader.pop();
093 filteredBuffer[offset++] = (char) charRead;
094 }
095 }
096 return offset - initialOffset;
097 }
098
099 }