001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright (c) 2005-2019 The ConQAT Project                               |
004|                                                                          |
005| Licensed under the Apache License, Version 2.0 (the "License");          |
006| you may not use this file except in compliance with the License.         |
007| You may obtain a copy of the License at                                  |
008|                                                                          |
009|    http://www.apache.org/licenses/LICENSE-2.0                            |
010|                                                                          |
011| Unless required by applicable law or agreed to in writing, software      |
012| distributed under the License is distributed on an "AS IS" BASIS,        |
013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
014| See the License for the specific language governing permissions and      |
015| limitations under the License.                                           |
016|                                                                          |
017+-------------------------------------------------------------------------*/
018package org.conqat.lib.commons.io;
019
020import static java.util.Objects.requireNonNull;
021
022import java.io.IOException;
023import java.io.Writer;
024
025/**
026 * A {@link Writer} that delegates to another {@link Writer} until a given
027 * maximum number of characters has been written. It then writes a final
028 * ellipsis and stops delegating.
029 */
030public class LimitedWriter extends Writer {
031
032        private final Writer delegate;
033
034        /**
035         * The number of remaining characters that can still be
036         * {@linkplain #write(char[], int, int) written} until the limit is reached. A
037         * value of {@code -1} denotes the fact the the final ellipsis has already been
038         * written to the {@link #delegate}.
039         */
040        private int charsRemaining;
041
042        public LimitedWriter(Writer delegate, int maxChars) {
043                if (maxChars < 0) {
044                        throw new IllegalArgumentException("Negative number of maximum characters");
045                }
046                this.delegate = requireNonNull(delegate);
047                this.charsRemaining = maxChars;
048        }
049
050        @Override
051        public void write(char[] buffer, int offset, int length) throws IOException {
052                if (charsRemaining >= length) {
053                        delegate.write(buffer, offset, length);
054                        charsRemaining -= length;
055                } else if (charsRemaining >= 0) {
056                        delegate.write(buffer, offset, charsRemaining);
057                        delegate.write("[...]");
058                        charsRemaining = -1;
059                }
060        }
061
062        @Override
063        public void flush() throws IOException {
064                delegate.flush();
065        }
066
067        @Override
068        public void close() throws IOException {
069                delegate.close();
070        }
071
072        @Override
073        public String toString() {
074                return delegate.toString();
075        }
076}