
com.exadatum.xsuite.xmaven.bash.doc.DocBlockIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bash-maven-plugin Show documentation
Show all versions of bash-maven-plugin Show documentation
Bash Maven Plugin is used to generate documentation as well as to run unit test for bash scripts.
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