package org.netbeans.gradle.project.output; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.jtrim.utils.ExceptionHelper; import org.openide.windows.IOColorPrint; import org.openide.windows.InputOutput; import org.openide.windows.OutputWriter; public final class OutputLinkPrinter implements SmartOutputHandler.Consumer { private final OutputLinkFinder[] linkFinders; public OutputLinkPrinter(OutputLinkFinder... linkFinders) { this.linkFinders = linkFinders.clone(); ExceptionHelper.checkNotNullElements(this.linkFinders, "linkFinders"); } private void findLinkDefs(String line, int startIndex, int endIndex, List<OutputLinkDef> linkDefs) { if (startIndex >= endIndex || startIndex >= line.length()) { return; } String subStr = line.substring(startIndex, endIndex); for (OutputLinkFinder linkFinder: linkFinders) { OutputLinkDef linkDef = linkFinder.tryFindLink(subStr); // Empty links are unreasonable and may cause an infinite recursion. if (linkDef != null && !linkDef.isEmptyLink()) { OutputLinkDef baseLinkDef = linkDef.offsetLinkDef(startIndex); findLinkDefs(line, startIndex, baseLinkDef.getStartIndex(), linkDefs); linkDefs.add(baseLinkDef); findLinkDefs(line, baseLinkDef.getEndIndex(), endIndex, linkDefs); return; } } } private List<OutputLinkDef> findLinkDefs(String line) { // Note that in the majority of cases, the line is not a link, so we // spare creating a list when not needed. for (OutputLinkFinder linkFinder: linkFinders) { if (linkFinder.tryFindLink(line) != null) { List<OutputLinkDef> result = new ArrayList<>(linkFinders.length); findLinkDefs(line, 0, line.length(), result); return result; } } return null; } @Override public boolean tryConsumeLine(String line, InputOutput ioParent, OutputWriter output) throws IOException { List<OutputLinkDef> linkDefs = findLinkDefs(line); if (linkDefs == null) { return false; } int prevEndIndex = 0; for (OutputLinkDef linkDef: linkDefs) { int startIndex = linkDef.getStartIndex(); int endIndex = linkDef.getEndIndex(); if (prevEndIndex < startIndex) { output.print(line.substring(prevEndIndex, startIndex)); } String link = line.substring(startIndex, endIndex); IOColorPrint.print(ioParent, link, linkDef.toOutputListener(), false, null); prevEndIndex = endIndex; } output.println(line.substring(prevEndIndex)); return true; } }