/**
 * Copyright (c) 2013 Source Auditor Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
*/
package org.spdx.tag;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.log4j.Logger;

/**
 * @author Gary O'Neall
 * 
 * Input stream which filters out any SPDX tag/value comments
 * Any new line which begins with a # is skipped until the end of line except
 * if it is within a <text> </text> wrapper
 *
 */
public class NoCommentInputStream extends InputStream {
	
	static final Logger logger = Logger.getLogger(NoCommentInputStream.class.getName());
	private static final CharSequence START_TEXT_TAG = "<text>";
	private static final CharSequence END_TEXT_TAG = "</text>";
	private static final char COMMENT_CHAR = '#';
	private InputStream inputStream;
	private InputStreamReader reader;
	private BufferedReader bufferedReader;
	private int lineIndex = 1;
	private String currentLine = "";
	boolean inText = false;
	

	/**
	 * @param in Input stream containing the commented data
	 * @throws IOException 
	 */
	public NoCommentInputStream(InputStream in) throws IOException {
		this.inputStream = in;
		this.reader = new InputStreamReader(inputStream, "UTF-8");
		this.bufferedReader = new BufferedReader(reader);
		readNextLine();
	}

	/**
	 * reads the next line in the input stream skipping when necessary
	 * @throws IOException 
	 */
	private void readNextLine() throws IOException {
		do {
			currentLine = bufferedReader.readLine();
			if (currentLine == null) {
				return;
			}
		} while (!inText && (currentLine.length() == 0 || currentLine.charAt(0) == COMMENT_CHAR));

		if (inText) {
			if (currentLine.contains(END_TEXT_TAG)) {
				inText = false;
			}
		} else {
			if (currentLine.contains(START_TEXT_TAG)) {
				inText = true;
			}
		}

		lineIndex = 0;
	}

	/* (non-Javadoc)
	 * @see java.io.InputStream#read()
	 */
	@Override
	public int read() throws IOException {
		while (currentLine != null && lineIndex >= currentLine.length()) {
			readNextLine();
			if (currentLine == null) {
				return -1;
			} else {
				return (int)'\n';
			}
		}
		if (currentLine == null) {
			return -1;
		}
		return (int)currentLine.charAt(lineIndex++);
	}
	
	@Override
	public void close() {
		if (this.bufferedReader != null) {
			try {
				this.bufferedReader.close();
			} catch (IOException e) {
				logger.error("IO Error closing buffered reader: "+e.getMessage());
			}
		}
		if (this.reader != null) {
			try {
				this.reader.close();
			} catch (IOException e) {
				logger.error("IO Error closing reader: "+e.getMessage());
			}
		}
		if (this.inputStream != null) {
			try {
				this.inputStream.close();
			} catch (IOException e) {
				logger.error("IO Error closing input stream: "+e.getMessage());
			}
		}
	}
	
}

@@ -1458,25 +1458,51 @@
 ate 
-int line
+String currentLine;%0A%09private int bytes
 Index
- = 1
 ;%0A%09p
@@ -1504,38 +1504,38 @@
 x;%0A%09private 
-String
+byte%5B%5D
  current
 Line = %22%22;%0A%09
@@ -1526,17 +1526,13 @@
 rent
-Line = %22%22
+Bytes
 ;%0A%09b
@@ -1884,17 +1884,17 @@
 /**%0A%09 * 
-r
+R
 eads the
@@ -1923,16 +1923,17 @@
 t stream
+,
  skippin
@@ -1938,12 +1938,35 @@
 ing 
-when
+empty lines and comments as
  nec
@@ -1971,16 +1971,17 @@
 ecessary
+.
 %0A%09 * @th
@@ -2420,20 +2420,21 @@
 %0A%09%09%7D%0A%0A%09%09
-line
+bytes
 Index = 
@@ -2436,16 +2436,64 @@
 ex = 0;%0A
+%09%09currentBytes = currentLine.getBytes(%22UTF-8%22);%0A
 %09%7D%0A%0A%09/* 
@@ -2600,21 +2600,42 @@
 ion %7B%0A%09%09
-while
+// Exit early on EOF.%0A%09%09if
  (curren
@@ -2644,23 +2644,94 @@
 ine 
-!
+=
 = null
- && line
+) %7B%0A%09%09%09return -1;%0A%09%09%7D%0A%0A%09%09// Fill the buffer if we ran out of bytes.%0A%09%09if (bytes
 Inde
@@ -2742,29 +2742,28 @@
  current
-Line
+Bytes
 .length
-()
 ) %7B%0A%09%09%09r
@@ -2784,63 +2784,127 @@
 %0A%09%09%09
-if (currentLine == null) %7B%0A%09%09%09%09return -1;%0A%09%09%09%7D else %7B%0A%09
+// Before returning bytes from the newly filled buffer, return the new%0A%09%09%09// line character that readLine() embezzled.%0A
 %09%09%09r
@@ -2926,61 +2926,80 @@
 ;%0A%09%09
-%09
 %7D%0A
-%09%09%7D%0A%09%09if (currentLine == null) %7B%0A%09%09%09return -1;%0A%09%09%7D
+%0A%09%09// Return the current byte from the buffer and increment the index.
 %0A%09%09r
@@ -3020,32 +3020,27 @@
 rent
-Line.charAt(line
+Bytes%5Bbytes
 Index++
-)
+%5D
 ;%0A%09%7D

Fix read() for multi-byte encodings