/**
* Copyright (c) 2010-2016 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.weather.internal.gfx;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.nio.CharBuffer;
/**
* Reads character streams and replaces tokens in the format ${...}.
*
* @author Gerhard Riegler
* @since 1.6.0
*/
public class TokenReplacingReader extends Reader {
protected PushbackReader pushbackReader;
protected TokenResolver tokenResolver;
protected StringBuilder tokenNameBuffer = new StringBuilder();
protected String tokenValue = null;
protected int tokenValueIndex = 0;
public TokenReplacingReader(Reader source, TokenResolver resolver) {
this.pushbackReader = new PushbackReader(source, 2);
this.tokenResolver = resolver;
}
/**
* {@inheritDoc}
*/
@Override
public int read(CharBuffer target) throws IOException {
throw new RuntimeException("Operation not supported");
}
/**
* {@inheritDoc}
*/
@Override
public int read() throws IOException {
if (tokenValue != null) {
if (tokenValueIndex < tokenValue.length()) {
return tokenValue.charAt(tokenValueIndex++);
}
if (tokenValueIndex == tokenValue.length()) {
tokenValue = null;
tokenValueIndex = 0;
}
}
int data = pushbackReader.read();
if (data != '$') {
return data;
}
data = pushbackReader.read();
if (data != '{') {
pushbackReader.unread(data);
return '$';
}
tokenNameBuffer.delete(0, tokenNameBuffer.length());
data = pushbackReader.read();
while (data != '}') {
tokenNameBuffer.append((char) data);
data = pushbackReader.read();
}
tokenValue = tokenResolver.resolveToken(tokenNameBuffer.toString());
if (tokenValue == null) {
tokenValue = "${" + tokenNameBuffer.toString() + "}";
}
if (tokenValue.length() == 0) {
return read();
}
return tokenValue.charAt(tokenValueIndex++);
}
/**
* {@inheritDoc}
*/
@Override
public int read(char cbuf[]) throws IOException {
return read(cbuf, 0, cbuf.length);
}
/**
* {@inheritDoc}
*/
@Override
public int read(char cbuf[], int off, int len) throws IOException {
int charsRead = 0;
for (int i = 0; i < len; i++) {
int nextChar = read();
if (nextChar == -1) {
if (charsRead == 0) {
charsRead = -1;
}
break;
}
charsRead = i + 1;
cbuf[off + i] = (char) nextChar;
}
return charsRead;
}
/**
* {@inheritDoc}
*/
@Override
public void close() throws IOException {
pushbackReader.close();
}
/**
* {@inheritDoc}
*/
@Override
public long skip(long n) throws IOException {
throw new RuntimeException("Operation not supported");
}
/**
* {@inheritDoc}
*/
@Override
public boolean ready() throws IOException {
return pushbackReader.ready();
}
/**
* {@inheritDoc}
*/
@Override
public boolean markSupported() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void mark(int readAheadLimit) throws IOException {
throw new RuntimeException("Operation not supported");
}
/**
* {@inheritDoc}
*/
@Override
public void reset() throws IOException {
throw new RuntimeException("Operation not supported");
}
}