package org.sonar.channel;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SuppressWarnings("rawtypes")
private final Channel[] channels;
+ /**
+ * @deprecated please use the builder() method
+ */
@SuppressWarnings("rawtypes")
+ @Deprecated
public ChannelDispatcher(List<Channel> channels) {
this(channels, false);
}
+ /**
+ * @deprecated please use the builder() method
+ */
@SuppressWarnings("rawtypes")
+ @Deprecated
public ChannelDispatcher(Channel... channels) {
this(Arrays.asList(channels), false);
}
+ /**
+ * @deprecated please use the builder() method
+ */
@SuppressWarnings("rawtypes")
+ @Deprecated
public ChannelDispatcher(List<Channel> channels, boolean failIfNoChannelToConsumeOneCharacter) {
this.channels = channels.toArray(new Channel[channels.size()]);
this.failIfNoChannelToConsumeOneCharacter = failIfNoChannelToConsumeOneCharacter;
}
+ private ChannelDispatcher(Builder builder) {
+ this.channels = builder.channels.toArray(new Channel[builder.channels.size()]);
+ this.failIfNoChannelToConsumeOneCharacter = builder.failIfNoChannelToConsumeOneCharacter;
+ }
+
public boolean consume(CodeReader code, OUTPUT output) {
int nextChar = code.peek();
while (nextChar != -1) {
- boolean channelConsumed = false;
+ boolean characterConsumed = false;
for (Channel<OUTPUT> channel : channels) {
if (channel.consume(code, output)) {
- channelConsumed = true;
+ characterConsumed = true;
break;
}
}
- if ( !channelConsumed) {
- String message = "None of the channel has been able to handle character '" + (char) code.peek() + "' (decimal value " + code.peek()
- + ") at line " + code.getLinePosition() + ", column " + code.getColumnPosition();
- if (failIfNoChannelToConsumeOneCharacter) {
- throw new IllegalStateException(message);
+ if ( !characterConsumed) {
+ if (logger.isDebugEnabled() || failIfNoChannelToConsumeOneCharacter) {
+ String message = "None of the channel has been able to handle character '" + (char) code.peek() + "' (decimal value "
+ + code.peek() + ") at line " + code.getLinePosition() + ", column " + code.getColumnPosition();
+ if (failIfNoChannelToConsumeOneCharacter) {
+ throw new IllegalStateException(message);
+ }
+ logger.debug(message);
}
- logger.debug(message);
code.pop();
}
nextChar = code.peek();
}
return true;
}
+
+ /**
+ * Get a Builder instance to build a new ChannelDispatcher
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+
+ private List<Channel> channels = new ArrayList<Channel>();
+ private boolean failIfNoChannelToConsumeOneCharacter = false;
+
+ private Builder() {
+ }
+
+ public Builder addChannel(Channel channel) {
+ channels.add(channel);
+ return this;
+ }
+
+ /**
+ * If this option is activated, an IllegalStateException will be thrown as soon as a character won't be consumed by any channel.
+ */
+ public Builder failIfNoChannelToConsumeOneCharacter() {
+ failIfNoChannelToConsumeOneCharacter = true;
+ return this;
+ }
+
+ public <OUTPUT> ChannelDispatcher<OUTPUT> build() {
+ return new ChannelDispatcher<OUTPUT>(this);
+ }
+
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * 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 static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+public class ChannelDispatcherTest {
+
+ @Test
+ public void shouldRemoveSpacesFromString() {
+ ChannelDispatcher<StringBuilder> dispatcher = ChannelDispatcher.builder().addChannel(new SpaceDeletionChannel()).build();
+ StringBuilder output = new StringBuilder();
+ dispatcher.consume(new CodeReader("two words"), output);
+ assertThat(output.toString(), is("twowords"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void shouldThrowExceptionWhenNoChannelToConsumeNextCharacter() {
+ ChannelDispatcher<StringBuilder> dispatcher = ChannelDispatcher.builder().failIfNoChannelToConsumeOneCharacter().build();
+ dispatcher.consume(new CodeReader("two words"), new StringBuilder());
+ }
+
+ private class SpaceDeletionChannel extends Channel<StringBuilder> {
+
+ @Override
+ public boolean consume(CodeReader code, StringBuilder output) {
+ if (code.peek() == ' ') {
+ code.pop();
+ } else {
+ output.append((char) code.pop());
+ }
+ return true;
+ }
+
+ }
+}