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 }