From b6d05fa45566092791e0b2bdc16ed0312d93c613 Mon Sep 17 00:00:00 2001 From: Freddy Mallet Date: Tue, 24 May 2011 16:15:25 +0200 Subject: [PATCH] Provide a builder to the ChannelDispatcher class and depreciate all constructors --- .../org/sonar/channel/ChannelDispatcher.java | 70 ++++++++++++++++--- .../sonar/channel/ChannelDispatcherTest.java | 56 +++++++++++++++ 2 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 sonar-channel/src/test/java/org/sonar/channel/ChannelDispatcherTest.java diff --git a/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java b/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java index dcbd5c56a74..58b8c95afba 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java +++ b/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java @@ -20,6 +20,7 @@ package org.sonar.channel; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -34,43 +35,96 @@ public class ChannelDispatcher extends Channel { @SuppressWarnings("rawtypes") private final Channel[] channels; + /** + * @deprecated please use the builder() method + */ @SuppressWarnings("rawtypes") + @Deprecated public ChannelDispatcher(List 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 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 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 channels = new ArrayList(); + 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 ChannelDispatcher build() { + return new ChannelDispatcher(this); + } + + } } \ No newline at end of file diff --git a/sonar-channel/src/test/java/org/sonar/channel/ChannelDispatcherTest.java b/sonar-channel/src/test/java/org/sonar/channel/ChannelDispatcherTest.java new file mode 100644 index 00000000000..030d82feb70 --- /dev/null +++ b/sonar-channel/src/test/java/org/sonar/channel/ChannelDispatcherTest.java @@ -0,0 +1,56 @@ +/* + * 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 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 dispatcher = ChannelDispatcher.builder().failIfNoChannelToConsumeOneCharacter().build(); + dispatcher.consume(new CodeReader("two words"), new StringBuilder()); + } + + private class SpaceDeletionChannel extends Channel { + + @Override + public boolean consume(CodeReader code, StringBuilder output) { + if (code.peek() == ' ') { + code.pop(); + } else { + output.append((char) code.pop()); + } + return true; + } + + } +} -- 2.39.5