
hope.kola.contract.converter.FeatureConverter Maven / Gradle / Ivy
package hope.kola.contract.converter;
import groovy.lang.GroovyShell;
import hope.kola.contract.Feature;
import hope.kola.contract.exception.FeatureParseException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
@SuppressWarnings("Duplicates")
public class FeatureConverter {
private static final Logger LOG = LoggerFactory.getLogger(FeatureConverter.class);
private static final Pattern PACKAGE_PATTERN =
Pattern.compile(".*package (.+?);.+?", Pattern.DOTALL);
public static Collection convertAsCollection(File rootFolder, File dsl) {
ClassLoader classLoader = FeatureConverter.class.getClassLoader();
try {
ClassLoader urlCl = updatedClassLoader(rootFolder, classLoader);
Object object = toObject(urlCl, rootFolder, dsl);
return listOfFeatures(dsl, object);
} catch (FeatureParseException e) {
throw e;
} catch (Exception e) {
LOG.error(
"Exception occurred while trying to evaluate the feature at path [" + dsl.getPath() + "]",
e);
throw new FeatureParseException(e);
} finally {
Thread.currentThread().setContextClassLoader(classLoader);
}
}
private static Collection listOfFeatures(File file, Object object) {
if (object == null) {
return Collections.emptyList();
} else if (isACollectionOfFeatures(object)) {
return withName(file, (Collection) object);
} else if (!(object instanceof Feature)) {
throw new FeatureParseException("Feature is not returning a Feature or list of Features");
}
return withName(file, Collections.singletonList((Feature) object));
}
private static boolean isACollectionOfFeatures(Object object) {
return object instanceof Collection
&& ((Collection) object).stream().allMatch(it -> it instanceof Feature);
}
private static Collection withName(File file, Collection features) {
AtomicInteger counter = new AtomicInteger(0);
return features.stream()
.peek(
it -> {
if (featureNameEmpty(it)) {
it.name(defaultFeatureName(file, features, counter.get()));
}
counter.getAndIncrement();
})
.collect(Collectors.toList());
}
private static boolean featureNameEmpty(Feature it) {
return it != null && ObjectUtils.isEmpty(it.getName());
}
/**
* @param file - file with contracts
* @param features - collection of contracts
* @param counter - given contract index
* @return the default contract name, resolved from file name, taking * into consideration also
* the index of contract (for multiple contracts * stored in a single file).
*/
public static String defaultFeatureName(File file, Collection features, int counter) {
int lastIndexOfDot = file.getName().lastIndexOf(".");
String tillExtension = file.getName().substring(0, lastIndexOfDot);
return tillExtension + (counter > 0 || features.size() > 1 ? "_" + counter : "");
}
public static Object toObject(ClassLoader cl, File rootFolder, File dsl) throws IOException {
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setSourceEncoding("UTF-8");
compilerConfiguration.setClasspathList(Collections.singletonList(rootFolder.getAbsolutePath()));
return new GroovyShell(cl, compilerConfiguration).evaluate(dsl);
}
public static ClassLoader updatedClassLoader(File rootFolder, ClassLoader classLoader) {
ClassLoader urlCl;
try {
urlCl =
URLClassLoader.newInstance(
Collections.singletonList(rootFolder.toURI().toURL()).toArray(new URL[0]),
classLoader);
} catch (MalformedURLException e) {
LOG.error(
"Exception occurred while trying to construct the URL from the root folder at path ["
+ rootFolder.getPath()
+ "]",
e);
throw new FeatureParseException(e);
}
updateTheThreadClassLoader(urlCl);
return urlCl;
}
private static void updateTheThreadClassLoader(ClassLoader urlCl) {
Thread.currentThread().setContextClassLoader(urlCl);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy