Skip to content

Commit

Permalink
refactor(core): New package structure to support multiple extensions …
Browse files Browse the repository at this point in the history
…in the future
  • Loading branch information
nandorholozsnyak committed Feb 9, 2023
1 parent adb2f5f commit 78251a7
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 55 deletions.
24 changes: 0 additions & 24 deletions src/main/java/org/rodnansol/asciidoctorj/CodeBlockProcessor.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

import org.asciidoctor.Asciidoctor;
import org.asciidoctor.jruby.extension.spi.ExtensionRegistry;
import org.rodnansol.asciidoctorj.javasource.JavaSourceBlockMacroProcessor;
import org.rodnansol.asciidoctorj.javasource.JavaSourceIncludeProcessor;

/**
* Extension registry.
*
* @author nandorholozsnyak
* @since 0.1.0
*/
public class JavaSourceExtension implements ExtensionRegistry {
public class CustomExtensionRegistry implements ExtensionRegistry {

@Override
public void register(Asciidoctor asciidoctor) {
asciidoctor.javaExtensionRegistry()
.blockMacro(JavaSourceBlockMacroProcessor.class);
asciidoctor.javaExtensionRegistry()
.includeProcessor(JavaMethodIncludeProcessor.class);
.includeProcessor(JavaSourceIncludeProcessor.class);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.rodnansol.asciidoctorj.javasource;

import org.asciidoctor.ast.Document;
import org.asciidoctor.extension.PreprocessorReader;

import java.util.Map;

/**
* Interface describes a block processor blueprint that can handle different attributes from the 'javasource' include macro.
*
* @author nandorholozsnyak
* @since 0.1.0
*/
public interface CodeBlockProcessor {

/**
* Checks if the current instance should be active for processing or not.
*
* @param attributes AsciiDoc attributes coming outside.
* @return <b>true</b> if the processor must be active based on the attributes, otherwise <b>false</b>
*/
boolean isActive(Map<String, Object> attributes);

/**
* Processes the incoming source code and creates and extra block into the requested document file.
*
* @param extractCommand base extract command.
* @param document AsciiDoc document instance.
* @param reader pre-processor reader.
* @param target target section.
* @param attributes AsciiDoc attributes.
* @throws JavaSourceCodeExtractionException when the source code can not be read or transformed.
*/
void process(ExtractCommand extractCommand,
Document document,
PreprocessorReader reader,
String target,
Map<String, Object> attributes);

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import java.util.Objects;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import java.util.Objects;

Expand All @@ -21,8 +21,8 @@ public ExtractFieldCommand(ExtractCommand extractCommand, String fieldName) {
* @param sourceCodePath Java source file's path.
* @param fieldName field name to extract.
* @param spaceSize space size for indentation.
* @param withJavaDoc
* @param lineLength
* @param withJavaDoc if the JavaDoc should be included or not.
* @param lineLength maximum length of the line.
*/
public ExtractFieldCommand(String sourceCodePath, String fieldName, int spaceSize, boolean withJavaDoc, int lineLength) {
super(sourceCodePath, spaceSize, withJavaDoc, lineLength);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import java.util.Arrays;
import java.util.Objects;
Expand Down Expand Up @@ -26,7 +26,7 @@ public ExtractMethodCommand(ExtractCommand extractCommand, String methodName,Str
* @param spaceSize space size for indentation.
* @param methodName method's name that should be extracted from the source code.
* @param withJavaDoc if the JavaDoc should be included or not.
* @param lineLength
* @param lineLength maximum length of the line.
* @param paramTypes list of the method argument types in String values.
*/
public ExtractMethodCommand(String sourceCodePath, int spaceSize, String methodName, boolean withJavaDoc, int lineLength, String... paramTypes) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import org.asciidoctor.ast.Document;
import org.asciidoctor.extension.PreprocessorReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
Expand All @@ -15,6 +17,8 @@
*/
public class JavaFieldCodeBlockProcessor implements CodeBlockProcessor {

private static final Logger LOGGER = LoggerFactory.getLogger(JavaFieldCodeBlockProcessor.class);

private static final String KEY_FIELD = "field";

@Override
Expand All @@ -26,6 +30,7 @@ public boolean isActive(Map<String, Object> attributes) {
public void process(ExtractCommand extractCommand, Document document, PreprocessorReader reader, String target, Map<String, Object> attributes) {
String field = (String) attributes.get(KEY_FIELD);
if (field != null && !field.isEmpty()) {
LOGGER.info("Extracting field:[{}] from source code at path:[{}]", field, extractCommand.getSourceCodePath());
try {
String fullField = JavaSourceHelper.getField(new ExtractFieldCommand(extractCommand, field));
reader.pushInclude(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import org.asciidoctor.ast.Document;
import org.asciidoctor.extension.PreprocessorReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
Expand All @@ -15,6 +17,8 @@
*/
public class JavaMethodCodeBlockProcessor implements CodeBlockProcessor {

private static final Logger LOGGER = LoggerFactory.getLogger(JavaMethodCodeBlockProcessor.class);

private static final String KEY_METHOD = "method";
private static final String KEY_METHOD_PARAM_TYPES = "types";

Expand All @@ -29,6 +33,7 @@ public void process(ExtractCommand extractCommand, Document document, Preprocess
try {
String paramTypeList = (String) attributes.getOrDefault(KEY_METHOD_PARAM_TYPES, "");
String[] paramTypes = paramTypeList.split(",");
LOGGER.info("Extracting method:[{}] with type list:[{}] from source code at path:[{}]", method, paramTypeList, extractCommand.getSourceCodePath());
String fullMethod = JavaSourceHelper.getMethod(new ExtractMethodCommand(extractCommand, method, paramTypes));

reader.pushInclude(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.BlockMacroProcessor;
Expand All @@ -20,7 +20,6 @@ public class JavaSourceBlockMacroProcessor extends BlockMacroProcessor {
@Override
public Object process(StructuralNode parent, String target, Map<String, Object> attributes) {
try {
System.out.println("### ATTRIBUTES:" + parent.getAttributes());
String method = JavaSourceHelper.getMethod(target, (String) attributes.get("method"));
String content = new StringBuilder()
.append("<div class=\"listingblock\">\n")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

/**
* Exception to be thrown when the Java Source code can not be extracted.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import org.jboss.forge.roaster.Roaster;
import org.jboss.forge.roaster._shade.org.apache.commons.lang3.StringUtils;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import org.asciidoctor.ast.Document;
import org.asciidoctor.extension.IncludeProcessor;
import org.asciidoctor.extension.PreprocessorReader;
import org.jboss.forge.roaster._shade.org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -34,10 +36,9 @@
* @author nandorholozsnyak
* @since 0.1.0
*/
public class JavaMethodIncludeProcessor extends IncludeProcessor {

private static final Logger LOGGER = LoggerFactory.getLogger(JavaMethodIncludeProcessor.class);
public class JavaSourceIncludeProcessor extends IncludeProcessor {

private static final Logger LOGGER = LoggerFactory.getLogger(JavaSourceIncludeProcessor.class);
private static final String MACRO_JAVASOURCE = "javasource";
private static final String KEY_SOURCE = "source";
private static final String KEY_SPACE_SIZE = "spaceSize";
Expand All @@ -46,11 +47,11 @@ public class JavaMethodIncludeProcessor extends IncludeProcessor {

private final List<CodeBlockProcessor> codeBlockProcessorList;

public JavaMethodIncludeProcessor() {
public JavaSourceIncludeProcessor() {
this(Arrays.asList(new JavaMethodCodeBlockProcessor(), new JavaFieldCodeBlockProcessor()));
}

public JavaMethodIncludeProcessor(List<CodeBlockProcessor> codeBlockProcessorList) {
public JavaSourceIncludeProcessor(List<CodeBlockProcessor> codeBlockProcessorList) {
this.codeBlockProcessorList = codeBlockProcessorList;
}

Expand All @@ -69,15 +70,37 @@ public void process(Document document,
if (source == null || source.isEmpty()) {
throw new JavaSourceCodeExtractionException("'source' attribute is empty.");
}
int spaceSize = Integer.parseInt((String) attributes.getOrDefault(KEY_SPACE_SIZE, String.valueOf(JavaSourceHelper.DEFAULT_SPACE_SIZE)));
int lineLength = Integer.parseInt((String) attributes.getOrDefault(KEY_LINE_LENGTH, String.valueOf(JavaSourceHelper.DEFAULT_LINE_LENGTH)));
String spaceSizeRawValue = (String) attributes.get(KEY_SPACE_SIZE);
String keyLineLengthRaw = (String) attributes.get(KEY_LINE_LENGTH);
int spaceSize = Integer.parseInt(StringUtils.isEmpty(spaceSizeRawValue) ? String.valueOf(JavaSourceHelper.DEFAULT_SPACE_SIZE) : spaceSizeRawValue);
int lineLength = Integer.parseInt(StringUtils.isEmpty(keyLineLengthRaw) ? String.valueOf(JavaSourceHelper.DEFAULT_LINE_LENGTH) : keyLineLengthRaw);
boolean withJavaDoc = Boolean.parseBoolean((String) attributes.getOrDefault(KEY_WITH_JAVA_DOC, "false"));
ExtractCommand extractCommand = new ExtractCommand(source, spaceSize, withJavaDoc, lineLength);
LOGGER.debug("Extracting items from source code with basic command:[{}]", extractCommand);
codeBlockProcessorList.stream()
.filter(codeBlockProcessor -> codeBlockProcessor.isActive(attributes))
.findFirst()
.ifPresent(codeBlockProcessor -> codeBlockProcessor.process(extractCommand, document, reader, target, attributes));
try {
codeBlockProcessorList.stream()
.filter(codeBlockProcessor -> codeBlockProcessor.isActive(attributes))
.findFirst()
.ifPresentOrElse(processor -> processor.process(extractCommand, document, reader, target, attributes),
() -> LOGGER.warn("No processor was found to handle incoming request for command:[{}]", extractCommand));
} catch (Exception e) {
renderErrorMessage(reader, target, attributes, e);
}

}

private void renderErrorMessage(PreprocessorReader reader, String target, Map<String, Object> attributes, Exception exception) {
StringBuilder errorMessageBuilder = new StringBuilder()
.append("Unable to render the requested block, please see the stack trace for more information.\n\n")
.append("Error message: ").append(exception.getMessage()).append(" \n");
if (exception.getCause() != null) {
errorMessageBuilder.append("Original error message: ").append(exception.getCause().getMessage()).append(" \n");
}
reader.pushInclude(
errorMessageBuilder.toString(),
target,
new File(".").getAbsolutePath(),
1,
attributes);
}
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
org.rodnansol.asciidoctorj.JavaSourceExtension
org.rodnansol.asciidoctorj.CustomExtensionRegistry
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.rodnansol.asciidoctorj;
package org.rodnansol.asciidoctorj.javasource;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -55,11 +55,11 @@ static Stream<Arguments> getMethodArgs() {
arguments("createUser","public final User createUser(String username, String password) {\n" +
" LOGGER.info(\"Creating new user with username:[{}]\", username);\n" +
" userRepository.save(new User(username, password));\n" +
"}",(Object) new String[]{"String","String"}),
"}", new String[]{"String","String"}),
arguments("deleteUser","protected void deleteUser(String username) {\n" +
" LOGGER.info(\"Deleting user with username:[{}]\", username);\n" +
" userRepository.deleteByUsername(username);\n" +
"}",(Object) new String[]{"String"}),
"}", new String[]{"String"}),
arguments("disableUser","void disableUser(User user) {\n" +
" LOGGER.info(\"Disabling user with username:[{}]\", user.username);\n" +
" if (user.enabled == true) {\n" +
Expand All @@ -68,7 +68,7 @@ static Stream<Arguments> getMethodArgs() {
" } else {\n" +
" logUnableToDisableUser();\n" +
" }\n" +
"}",(Object) new String[]{"User"}),
"}", new String[]{"User"}),
arguments("logUnableToDisableUser","private static void logUnableToDisableUser() {\n" +
" LOGGER.info(\"Unable to disable disabled user\");\n" +
"}", new String[]{})
Expand Down
4 changes: 4 additions & 0 deletions src/test/resources/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ protected void deleteUser(String username) {
userRepository.deleteByUsername(username);
}

/**
* Disables the incoming user.
* @param user user to disable.
*/
void disableUser(User user) {
LOGGER.info("Disabling user with username:[{}]", user.username);
if (user.enabled == true) {
Expand Down

0 comments on commit 78251a7

Please sign in to comment.