All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.exadatum.xsuite.xmaven.bash.doc.DocBlockIterator Maven / Gradle / Ivy

Go to download

Bash Maven Plugin is used to generate documentation as well as to run unit test for bash scripts.

There is a newer version: 1.0.7
Show newest version
package com.exadatum.xsuite.xmaven.bash.doc;

/*-
 * #%L
 * Bash Unit Test Plugin
 * %%
 * Copyright (C) 2016 - 2017 Exadatum Software Services Pvt. Ltd.
 * %%
 * 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.
 * #L%
 */

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.commons.lang3.StringUtils;

public class DocBlockIterator implements Iterator {

	private static final String LINE_SEPARATOR = System.getProperty("line.separator");

	private static final int INDEX_OF_STAR = 1;

	private String[] lines;

	private int cursor = -1;

	private ArrayList docBlockLines = new ArrayList<>();

	private String target;

	private DocBlockParser blockParser;

	public DocBlockIterator(String contents) {
		this.lines = contents.split(LINE_SEPARATOR);
		blockParser = new DocBlockParser();
	}

	/**
	 * Checks if there is any next valid documentation block is available or
	 * not.
	 * 
	 * @return
	 */
	@Override
	public boolean hasNext() {
		// Doc block consists of start tag, end tag and the element for which
		// the doc block has been written.
		boolean startTagFound = false;
		boolean endTagFound = false;
		if (cursor == -1) {
			// this is first call to hasNext.
			cursor = 0;
		}
		docBlockLines.clear();
		while (cursor < lines.length && !endTagFound) {
			// Start and End tag are expected to be on its own line.
			if (isValidStartTag()) {
				startTagFound = true;
				docBlockLines.add(DocBlockStructure.START.keyword.substring(1).concat(LINE_SEPARATOR));
			} else if (isValidEndTag()) {
				if (!startTagFound) {
					throwInvalidBlockStructureException("Doc block end tag found with no matching start tag at [%d]",
							cursor);
				}
				endTagFound = true;
				docBlockLines.add(DocBlockStructure.END.keyword.substring(1));
			} else if (isValidContinuationTag()) {
				if (!startTagFound) {
					throwInvalidBlockStructureException(
							"Doc block continuation tag found with no matching start tag at [%d]", cursor);
				}
				docBlockLines.add(lines[cursor].substring(INDEX_OF_STAR).concat(LINE_SEPARATOR));
			}
			cursor++;
		}
		if (startTagFound && !endTagFound) {
			throwInvalidBlockStructureException("No end tag found in the Doc block");
		}
		int tempCursor = cursor;
		while (tempCursor < lines.length) {
			String trimmedLine = lines[tempCursor].trim();
			if (!StringUtils.isBlank(trimmedLine)) {
				if (trimmedLine.startsWith("function ")) {
					target = trimmedLine.substring(trimmedLine.indexOf(" "), trimmedLine.indexOf("("));
					break;
				} else if (trimmedLine.indexOf("=") != -1) {
					target = trimmedLine;
					break;
				} else {
					throwInvalidBlockStructureException(
							"Function or constant declaration shall follow document block. But found otherwise at [%d]",
							cursor);
				}
			}
			tempCursor++;
		}
		return endTagFound;
	}

	private void throwInvalidBlockStructureException(String message, Object... args) {
		throw new InvalidDocBlockStructure(String.format(message, args));
	}

	/**
	 * A valid start tag only contains {@link DocBlockStructure.START} and
	 * nothing else.
	 * 
	 * @return
	 */
	private boolean isValidStartTag() {
		return isValidTag(DocBlockStructure.START, true);
	}

	/**
	 * A valid end tag only contains {@link DocBlockStructure.END} and nothing
	 * else.
	 * 
	 * @return
	 */
	private boolean isValidEndTag() {
		return isValidTag(DocBlockStructure.END, true);
	}

	/**
	 * A valid end tag only contains {@link DocBlockStructure.END} and nothing
	 * else.
	 * 
	 * @return
	 */
	private boolean isValidContinuationTag() {
		return isValidTag(DocBlockStructure.CONTINUATION, false);
	}

	/**
	 * Validate if tag structure is correct
	 * 
	 * @return if the tag structure is valid of not
	 */
	private boolean isValidTag(DocBlockStructure tag, boolean soloTag) {
		boolean isValid = false;
		String trimmedLine = lines[cursor].trim();
		// check if the line starts with the tag
		if (trimmedLine.startsWith(tag.keyword)) {
			// check if the line only contains the tag or is solo tag( start and
			// end tags are solo as they come on their own line)
			if (trimmedLine.length() == tag.keyword.length() || !soloTag) {
				isValid = true;
			} else {
				isValid = false;
				throwInvalidBlockStructureException(
						"Invalid [%1$s] tag at [%d]. [%1$s] tag shall always be on its own line. "
								+ "But some other characters found.",
						tag.name(), cursor);
			}
		}
		return isValid;
	}

	@Override
	public DocBlock next() {
		if (cursor == -1) {
			// developer forgot to call hasNext. Blocks are read in hasNext
			// method.
			throw new IllegalStateException("hasNext() method is not called. cursor is not open");
		}
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		for (String docBlockLine : docBlockLines) {
			try {
				baos.write(StringUtils.stripStart(docBlockLine, null).getBytes());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		try {
			DocBlock docBlock = blockParser.parse(new ByteArrayInputStream(baos.toByteArray()));
			docBlock.setTarget(target);
			return docBlock;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy