Changing Closures to various functional interfaces.

This commit is contained in:
JesseBrault0709 2023-04-26 10:00:15 +02:00
parent a8c6955ca8
commit 2ce269bbdc
15 changed files with 100 additions and 119 deletions

View File

@ -38,7 +38,7 @@ final class DefaultBuildScriptConfiguratorFactory implements BuildScriptConfigur
taskFactories { sourceProviders ->
register('textToHtml', TextToHtmlTaskFactory::new) {
it.specProvider += CollectionProviders.from {
it.specProvider += CollectionProviders.fromSupplier {
def templates = sourceProviders.templatesProvider.provide()
sourceProviders.textsProvider.provide().collect {
def frontMatterResult = it.type.frontMatterGetter.get(it)

View File

@ -1,10 +1,6 @@
package com.jessebrault.ssg.model
import groovy.io.FileType
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromString
import java.nio.file.Path
import java.util.function.Supplier
final class Models {
@ -12,33 +8,8 @@ final class Models {
new SimpleModel<>(name, t)
}
static <T> Model<T> from(String name, Closure<T> tClosure) {
new ClosureBasedModel<>(name, tClosure)
}
/**
* Takes a directory and iterates recursively through all files present in the directory and sub-directories,
* supplying each File along with a String representing that File's path relative to the base Directory to the
* given Closure, which then returns a Model containing T, all of which are collected and then returned together.
*
* @param directory The base directory in which to search for Files to process.
* @param fileToModelClosure A Closure which receives two params: the File being processed,
* and a String representing the path of that File relative to the base directory. Must return
* a Model containing T.
* @return A Collection of Models containing Ts.
*/
static <T> Collection<Model<T>> fromDirectory(
File directory,
@ClosureParams(value = FromString, options = ['java.io.File, java.lang.String'])
Closure<Model<T>> fileToModelClosure
) {
final Collection<Model<T>> models = []
def directoryPath = Path.of(directory.path)
directory.eachFileRecurse(FileType.FILES) {
def relativePath = directoryPath.relativize(Path.of(it.path)).toString()
models << fileToModelClosure(it, relativePath)
}
models
static <T> Model<T> fromSupplier(String name, Supplier<T> tClosure) {
new SupplierBasedModel<>(name, tClosure)
}
private Models() {}

View File

@ -5,18 +5,20 @@ import groovy.transform.NullCheck
import groovy.transform.PackageScope
import groovy.transform.TupleConstructor
import java.util.function.Supplier
@PackageScope
@TupleConstructor(includeFields = true, defaults = false)
@NullCheck(includeGenerated = true)
@EqualsAndHashCode(includeFields = true)
final class ClosureBasedModel<T> implements Model<T> {
final class SupplierBasedModel<T> implements Model<T> {
final String name
private final Closure<T> tClosure
private final Supplier<T> supplier
@Override
T get() {
this.tClosure()
this.supplier.get()
}
}

View File

@ -3,7 +3,6 @@ package com.jessebrault.ssg.page
import com.jessebrault.ssg.provider.CollectionProvider
import com.jessebrault.ssg.provider.CollectionProviders
import com.jessebrault.ssg.util.ExtensionUtil
import com.jessebrault.ssg.util.PathUtil
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -12,14 +11,19 @@ final class PagesProviders {
private static final Logger logger = LoggerFactory.getLogger(PagesProviders)
static CollectionProvider<Page> from(File pagesDirectory, Collection<PageType> pageTypes) {
CollectionProviders.from(pagesDirectory) {
def extension = ExtensionUtil.getExtension(it.path)
def pageType = pageTypes.find { it.ids.contains(extension) }
if (!pageType) {
logger.warn('there is no PageType for file {}; skipping', it)
null
CollectionProviders.fromDirectory(pagesDirectory) { file, relativePath ->
def extension = ExtensionUtil.getExtension(relativePath)
if (extension) {
def pageType = pageTypes.find { it.ids.contains(extension) }
if (!pageType) {
logger.debug('there is no PageType for file {}; skipping', file)
return null
} else {
return new Page(relativePath, pageType, file.getText())
}
} else {
new Page(PathUtil.relative(pagesDirectory.path, it.path), pageType, it.getText())
logger.debug('there is no extension for file {}; skipping', file)
return null
}
}
}

View File

@ -3,7 +3,6 @@ package com.jessebrault.ssg.part
import com.jessebrault.ssg.provider.CollectionProvider
import com.jessebrault.ssg.provider.CollectionProviders
import com.jessebrault.ssg.util.ExtensionUtil
import com.jessebrault.ssg.util.PathUtil
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -12,14 +11,19 @@ final class PartsProviders {
private static final Logger logger = LoggerFactory.getLogger(PartsProviders)
static CollectionProvider<Part> of(File partsDir, Collection<PartType> partTypes) {
CollectionProviders.from(partsDir) {
def extension = ExtensionUtil.getExtension(it.path)
def partType = partTypes.find { it.ids.contains(extension) }
if (!partType) {
logger.warn('there is no PartType for file {}; skipping', it)
null
CollectionProviders.fromDirectory(partsDir) { file, relativePath ->
def extension = ExtensionUtil.getExtension(relativePath)
if (extension) {
def partType = partTypes.find { it.ids.contains(extension) }
if (!partType) {
logger.debug('there is no PartType for file {}; skipping', file)
return null
} else {
return new Part(relativePath, partType, file.getText())
}
} else {
new Part(PathUtil.relative(partsDir.path, it.path), partType, it.getText())
logger.debug('there is no extension for file {}; skipping', file)
return null
}
}
}

View File

@ -6,7 +6,7 @@ abstract class AbstractCollectionProvider<T> implements CollectionProvider<T> {
CollectionProvider<T> cp0,
CollectionProvider<T> cp1
) {
ClosureBasedCollectionProvider.get {
SupplierBasedCollectionProvider.get {
cp0.provide() + cp1.provide()
}
}

View File

@ -6,7 +6,7 @@ abstract class AbstractProvider<T> implements Provider<T> {
Provider<T> p0,
Provider<T> p1
) {
ClosureBasedCollectionProvider.get {
SupplierBasedCollectionProvider.get {
[p0.provide(), p1.provide()]
}
}
@ -18,7 +18,7 @@ abstract class AbstractProvider<T> implements Provider<T> {
@Override
CollectionProvider<T> asType(Class<CollectionProvider> collectionProviderClass) {
ClosureBasedCollectionProvider.get {
SupplierBasedCollectionProvider.get {
[this.provide() as T]
}
}

View File

@ -1,29 +1,29 @@
package com.jessebrault.ssg.provider
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromString
import org.jetbrains.annotations.Nullable
import java.util.function.BiFunction
import java.util.function.Supplier
final class CollectionProviders {
static <T> CollectionProvider<T> getEmpty() {
new SimpleCollectionProvider<>([])
}
static <T> CollectionProvider<T> of(Collection<T> ts) {
static <T> CollectionProvider<T> fromCollection(Collection<T> ts) {
new SimpleCollectionProvider<T>(ts)
}
static <T> CollectionProvider<T> from(Closure<Collection<T>> closure) {
ClosureBasedCollectionProvider.get(closure)
static <T> CollectionProvider<T> fromSupplier(Supplier<Collection<T>> supplier) {
new SupplierBasedCollectionProvider<>(supplier)
}
static <T> CollectionProvider<T> from(
File dir,
@ClosureParams(value = FromString, options = 'java.io.File')
Closure<@Nullable T> fileToElementClosure
static <T> CollectionProvider<T> fromDirectory(
File baseDirectory,
BiFunction<File, String, @Nullable T> elementFunction
) {
new FileBasedCollectionProvider<>(dir, fileToElementClosure)
new FileBasedCollectionProvider<>(baseDirectory, elementFunction)
}
private CollectionProviders() {}

View File

@ -1,43 +1,37 @@
package com.jessebrault.ssg.provider
import com.jessebrault.ssg.util.PathUtil
import groovy.io.FileType
import groovy.transform.EqualsAndHashCode
import groovy.transform.NullCheck
import groovy.transform.PackageScope
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromString
import groovy.transform.TupleConstructor
import org.jetbrains.annotations.Nullable
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.util.function.BiFunction
@PackageScope
@NullCheck
@TupleConstructor(includeFields = true, defaults = false)
@NullCheck(includeGenerated = true)
@EqualsAndHashCode(includeFields = true)
final class FileBasedCollectionProvider<T> extends AbstractCollectionProvider<T> {
private static final Logger logger = LoggerFactory.getLogger(FileBasedCollectionProvider)
private final File dir
private final Closure<@Nullable T> fileToElementClosure
FileBasedCollectionProvider(
File dir,
@ClosureParams(value = FromString, options = 'java.io.File')
Closure<@Nullable T> fileToElementClosure
) {
this.dir = dir
this.fileToElementClosure = fileToElementClosure
}
private final File baseDirectory
private final BiFunction<File, String, @Nullable T> elementFunction
@Override
Collection<T> provide() {
if (!this.dir.isDirectory()) {
logger.error('{} does not exist or is not a directory; returning empty collection', this.dir)
if (!this.baseDirectory.isDirectory()) {
logger.error('{} does not exist or is not a directory; returning empty collection', this.baseDirectory)
[]
} else {
def ts = []
this.dir.eachFileRecurse(FileType.FILES) {
def t = this.fileToElementClosure(it)
final Collection<T> ts = []
this.baseDirectory.eachFileRecurse(FileType.FILES) {
def t = this.elementFunction.apply(it, PathUtil.relative(this.baseDirectory.path, it.path)) as T
if (t) {
ts << t
}

View File

@ -1,6 +1,6 @@
package com.jessebrault.ssg.provider
import org.codehaus.groovy.runtime.InvokerHelper
import java.util.function.Supplier
final class Providers {
@ -8,8 +8,8 @@ final class Providers {
new SimpleProvider<>(t)
}
static <T> Provider<T> from(Closure<T> closure) {
ClosureBasedProvider.of(closure)
static <T> Provider<T> fromSupplier(Supplier<T> supplier) {
new SupplierBasedProvider<>(supplier)
}
static <T> CollectionProvider<T> concat(Provider<T> ...providers) {

View File

@ -5,21 +5,19 @@ import groovy.transform.NullCheck
import groovy.transform.PackageScope
import groovy.transform.TupleConstructor
import java.util.function.Supplier
@PackageScope
@TupleConstructor(defaults = false, includeFields = true)
@NullCheck(includeGenerated = true)
@EqualsAndHashCode(includeFields = true)
final class ClosureBasedCollectionProvider<T> extends AbstractCollectionProvider<T> {
final class SupplierBasedCollectionProvider<T> extends AbstractCollectionProvider<T> {
static <T> CollectionProvider<T> get(Closure<Collection<T>> closure) {
new ClosureBasedCollectionProvider<>(closure)
}
private final Closure<Collection<T>> closure
private final Supplier<Collection<T>> supplier
@Override
Collection<T> provide() {
this.closure()
this.supplier.get()
}
}

View File

@ -5,21 +5,19 @@ import groovy.transform.NullCheck
import groovy.transform.PackageScope
import groovy.transform.TupleConstructor
import java.util.function.Supplier
@PackageScope
@TupleConstructor(includeFields = true, defaults = false)
@NullCheck(includeGenerated = true)
@EqualsAndHashCode(includeFields = true)
final class ClosureBasedProvider<T> extends AbstractProvider<T> {
final class SupplierBasedProvider<T> extends AbstractProvider<T> {
static <T> Provider<T> of(Closure<T> closure) {
new ClosureBasedProvider<>(closure)
}
private final Closure<T> closure
private final Supplier<T> supplier
@Override
T provide() {
this.closure()
this.supplier.get()
}
}

View File

@ -3,7 +3,6 @@ package com.jessebrault.ssg.template
import com.jessebrault.ssg.provider.CollectionProvider
import com.jessebrault.ssg.provider.CollectionProviders
import com.jessebrault.ssg.util.ExtensionUtil
import com.jessebrault.ssg.util.PathUtil
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -12,14 +11,19 @@ final class TemplatesProviders {
private static final Logger logger = LoggerFactory.getLogger(TemplatesProviders)
static CollectionProvider<Template> from(File templatesDir, Collection<TemplateType> templateTypes) {
CollectionProviders.from(templatesDir) {
def extension = ExtensionUtil.getExtension(it.path)
def templateType = templateTypes.find { it.ids.contains(extension) }
if (!templateType) {
logger.warn('there is no TemplateType for file {}; skipping', it)
null
CollectionProviders.fromDirectory(templatesDir) { file, relativePath ->
def extension = ExtensionUtil.getExtension(relativePath)
if (extension) {
def templateType = templateTypes.find { it.ids.contains(extension) }
if (!templateType) {
logger.debug('there is no TemplateType for file {}; skipping', file)
return null
} else {
return new Template(relativePath, templateType, file.getText())
}
} else {
new Template(PathUtil.relative(templatesDir.path, it.path), templateType, it.getText())
logger.debug('there is no extension for file {}; skipping', file)
return null
}
}
}

View File

@ -3,7 +3,6 @@ package com.jessebrault.ssg.text
import com.jessebrault.ssg.provider.CollectionProvider
import com.jessebrault.ssg.provider.CollectionProviders
import com.jessebrault.ssg.util.ExtensionUtil
import com.jessebrault.ssg.util.PathUtil
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -12,14 +11,19 @@ final class TextsProviders {
private static final Logger logger = LoggerFactory.getLogger(TextsProviders)
static CollectionProvider<Text> from(File textsDir, Collection<TextType> types) {
CollectionProviders.from(textsDir) {
def extension = ExtensionUtil.getExtension(it.path)
def textType = types.find { it.ids.contains(extension) }
if (!textType) {
logger.warn('there is no TextType for file {}; skipping', it)
null
CollectionProviders.fromDirectory(textsDir) { file, relativePath ->
def extension = ExtensionUtil.getExtension(relativePath)
if (extension) {
def textType = types.find { it.ids.contains(extension) }
if (!textType) {
logger.warn('there is no TextType for file {}; skipping', file)
return null
} else {
return new Text(relativePath, textType, file.getText())
}
} else {
new Text(PathUtil.relative(textsDir.path, it.path), textType, it.text)
logger.debug('there is no extension for file {}; skipping', file)
return null
}
}
}

View File

@ -1,5 +1,7 @@
package com.jessebrault.ssg.util
import org.jetbrains.annotations.Nullable
import java.util.regex.Pattern
final class ExtensionUtil {
@ -12,12 +14,12 @@ final class ExtensionUtil {
m.matches() ? m.group(1) : path
}
static String getExtension(String path) {
static @Nullable String getExtension(String path) {
def m = getExtensionPattern.matcher(path)
if (m.matches()) {
m.group(1)
} else {
throw new IllegalArgumentException("cannot get extension for path: ${ path }")
null
}
}