nl.openweb.hippo.groovy.Generator Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2019 Open Web IT B.V. (https://www.openweb.nl/)
*
* 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 nl.openweb.hippo.groovy;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import nl.openweb.hippo.groovy.annotations.Bootstrap;
import nl.openweb.hippo.groovy.annotations.Exclude;
import nl.openweb.hippo.groovy.annotations.Updater;
import static nl.openweb.hippo.groovy.model.Constants.Files.GROOVY_EXTENSION;
public abstract class Generator {
protected static final String NEWLINE = "\n";
private static final List> ANNOTATED_CLASSES = Arrays.asList(Exclude.class, Bootstrap.class, Updater.class, Bootstrap.ContentRoot.class);
private static final String HIPPO_CONFIGURATION_UPDATE_PATH_PREFIX = "/hippo:configuration/hippo:update/hippo:";
private static final String REGEX_WHITESPACE = "\\s*";
private static final String REGEX_ANNOTATIONS_SNIPPET = "(?:[\\w\\W]+[\\n|;]" + REGEX_WHITESPACE + "import [\\w.]+[;|\\n]+)?(?=[\\w\\W]*@[\\w.]*Updater)([\\w\\W]*)(?=(?:public )?class \\w+ extends [\\w\\W]+" + REGEX_WHITESPACE + "\\{)";
private static final String REGEX_ATTR_NAME = "([A-Za-z]\\w*)";
private static final String REGEX_ATTR_VALUE_SINGLEQUOTE = "('.*?(? getAnnotations(final String script){
//Strip comments
String codeBlock = script.replaceAll("\\s/\\*[\\w\\W]*\\*/", StringUtils.EMPTY);
if(codeBlock.startsWith("/*")) {
codeBlock = StringUtils.substringAfter(codeBlock, "*/");
}
codeBlock = codeBlock.replaceAll("\\n//.*", StringUtils.EMPTY);
final Matcher matcher = Pattern.compile(REGEX_ANNOTATIONS_SNIPPET).matcher(codeBlock);
final List annotationStrings = new ArrayList<>();
if(matcher.find()) {
final String snippet = matcher.group(1);
for (final Class> annotationClass : getAnnotationClasses()) {
final String annotation = getAnnotation(snippet, annotationClass);
if (StringUtils.isNotBlank(annotation)) {
annotationStrings.add(annotation);
}
}
}
return annotationStrings;
}
public static String stripAnnotations(final String script) {
return stripAnnotations(script, false);
}
public static String stripAnnotations(final String script, final boolean keepSpaces) {
String result = script;
for (String annotation : getAnnotations(script)) {
result = result.replace("\n" + annotation, StringUtils.EMPTY);
result = result.replace(annotation, StringUtils.EMPTY);
}
for (final Class> aClass : getAnnotationClasses()) {
result = result.replaceAll("import" + REGEX_WHITESPACE + aClass.getCanonicalName() + REGEX_WHITESPACE + "[;]?\n", StringUtils.EMPTY);
}
if (keepSpaces) {
int scriptClassStartLine = getClassStartLineNr(script);
int strippedClassStartLine = getClassStartLineNr(result);
String addition = StringUtils.repeat(NEWLINE, scriptClassStartLine - strippedClassStartLine);
result = result.replaceFirst("\nclass ", addition + "\nclass ");
} else {
result = result.replaceAll("(\n){3,}", "\n\n");
}
return result;
}
private static int getClassStartLineNr(final String script) {
int lineNr = 0;
try (BufferedReader reader = new BufferedReader(new StringReader(script))) {
for (String line = reader.readLine(); !line.startsWith("class"); line = reader.readLine()) {
lineNr++;
}
} catch (IOException e) {
//not happening
}
return lineNr;
}
public static String getAnnotation(final String script, final String className) {
final String regex = getAnnotationRegex(className);
Matcher matcher = Pattern.compile(regex).matcher(script);
return matcher.find() ? matcher.group() : StringUtils.EMPTY;
}
private static String getAnnotationRegex(final String className) {
final String annotationName = "@" + className;
return annotationName + ANNOTATION_PAYLOAD;
}
public static String getAnnotation(final String script, final Class> clazz) {
String simple = getAnnotation(script, clazz.getSimpleName());
return StringUtils.isNotBlank(simple) ?
simple :
getAnnotation(script, clazz.getCanonicalName());
}
public static Bootstrap.ContentRoot getContentroot(final Bootstrap bootstrap) {
return Bootstrap.ContentRoot.DEFAULT.equals(bootstrap.contentroot()) ? defaultContentRoot : bootstrap.contentroot();
}
/**
* Obtain groovy files from given location
*
* @param dir directory to obtain groovy files from
* @return List of groovy files
*/
public static List getGroovyFiles(final File dir) {
final File[] groovyFiles = dir.listFiles(file -> file.isFile() && file.getName().endsWith(GROOVY_EXTENSION));
final File[] directories = dir.listFiles(File::isDirectory);
final List allFiles = new ArrayList<>();
if (groovyFiles != null) {
allFiles.addAll(Arrays.asList(groovyFiles));
allFiles.sort(Comparator.comparing(File::getName));
}
if (directories != null) {
Arrays.stream(directories)
.sorted(Comparator.comparing(File::getName))
.map(Generator::getGroovyFiles).forEach(allFiles::addAll);
}
return Collections.unmodifiableList(allFiles);
}
protected static String sanitizeFileName(final String fileName) {
return FilenameUtils.removeExtension(FilenameUtils.separatorsToUnix(fileName)).replaceAll("\\s", "_");
}
protected static String getUpdatePath(Bootstrap.ContentRoot contentroot) {
return HIPPO_CONFIGURATION_UPDATE_PATH_PREFIX + contentroot;
}
/**
* Technically it's not just Annotations, it's all classes from the Annotations library This is a convenience
* method.
*
* @return a list of the annotation classes
*/
public static List> getAnnotationClasses() {
return ANNOTATED_CLASSES;
}
public static void setDefaultContentRoot(Bootstrap.ContentRoot contentRoot) {
defaultContentRoot = contentRoot;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy