Experimenting with Monoid, etc.
This commit is contained in:
parent
4fa2ba0ac9
commit
c74d80a69e
@ -1,5 +1,6 @@
|
||||
package com.jessebrault.ssg
|
||||
|
||||
import com.jessebrault.ssg.util.Monoid
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
@ -9,6 +10,11 @@ import groovy.transform.TupleConstructor
|
||||
@EqualsAndHashCode
|
||||
final class SiteSpec {
|
||||
|
||||
static final Monoid<SiteSpec> defaultSemiGroup = new Monoid<>(
|
||||
SiteSpec::concat,
|
||||
SiteSpec::getBlank
|
||||
)
|
||||
|
||||
static SiteSpec getBlank() {
|
||||
new SiteSpec('', '')
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
package com.jessebrault.ssg.buildscript.domain
|
||||
|
||||
import com.jessebrault.ssg.property.Properties
|
||||
import com.jessebrault.ssg.property.Property
|
||||
import com.jessebrault.ssg.util.Monoid
|
||||
|
||||
final class MutableSiteSpec {
|
||||
|
||||
private static final Monoid<String> nameAndBaseUrlMonoid = new Monoid<>(
|
||||
{ s0, s1 -> s1 },
|
||||
{ '' }
|
||||
)
|
||||
|
||||
static final Monoid<MutableSiteSpec> MONOID = new Monoid<>(
|
||||
MutableSiteSpec::concat,
|
||||
MutableSiteSpec::new
|
||||
)
|
||||
|
||||
private static MutableSiteSpec concat(MutableSiteSpec ms0, MutableSiteSpec ms1) {
|
||||
new MutableSiteSpec().tap {
|
||||
name.set(ms1.name.get())
|
||||
baseUrl.set(ms1.baseUrl.get())
|
||||
}
|
||||
}
|
||||
|
||||
final Property<String> name = Properties.get(nameAndBaseUrlMonoid)
|
||||
final Property<String> baseUrl = Properties.get(nameAndBaseUrlMonoid)
|
||||
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.jessebrault.ssg.property
|
||||
|
||||
interface CollectionProperty<T> extends Property<T> {
|
||||
// TODO
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package com.jessebrault.ssg.property
|
||||
|
||||
interface MapProperty<K, V> extends Property<Map<K, V>> {
|
||||
V get(K key)
|
||||
void put(K key, V value)
|
||||
void putAll(Map<? extends K, ? extends V> map)
|
||||
}
|
@ -1,32 +1,19 @@
|
||||
package com.jessebrault.ssg.property
|
||||
|
||||
import com.jessebrault.ssg.util.Monoid
|
||||
|
||||
final class Properties {
|
||||
|
||||
static <T> Property<T> get() {
|
||||
new SimpleProperty<>()
|
||||
static <T> Property<T> get(Monoid<T> semiGroup) {
|
||||
new SimpleProperty<>(semiGroup)
|
||||
}
|
||||
|
||||
static <T> Property<T> get(T convention) {
|
||||
new SimpleProperty<>(convention)
|
||||
static <T> Property<T> get(Monoid<T> semiGroup, T convention) {
|
||||
new SimpleProperty<>(semiGroup, convention)
|
||||
}
|
||||
|
||||
static <T> Property<T> get(T convention, T t) {
|
||||
new SimpleProperty<>(convention, t)
|
||||
}
|
||||
|
||||
static <K, V> MapProperty<K, V> getMap() {
|
||||
new SimpleMapProperty<K, V>()
|
||||
}
|
||||
|
||||
static <K, V> MapProperty<K, V> getMap(Map<? extends K, ? extends V> convention) {
|
||||
new SimpleMapProperty<K, V>(convention)
|
||||
}
|
||||
|
||||
static <K, V> MapProperty<K, V> getMap(
|
||||
Map<? extends K, ? extends V> convention,
|
||||
Map<? extends K, ? extends V> value
|
||||
) {
|
||||
new SimpleMapProperty<K, V>(convention, value)
|
||||
static <T> Property<T> get(Monoid<T> semiGroup, T convention, T t) {
|
||||
new SimpleProperty<>(semiGroup, convention, t)
|
||||
}
|
||||
|
||||
private Properties() {}
|
||||
|
@ -1,38 +1,19 @@
|
||||
package com.jessebrault.ssg.property
|
||||
|
||||
import com.jessebrault.ssg.provider.Provider
|
||||
|
||||
import java.util.function.Function
|
||||
import java.util.function.UnaryOperator
|
||||
|
||||
interface Property<T> extends Provider<T> {
|
||||
|
||||
interface Property<T> {
|
||||
T get()
|
||||
void set(T t)
|
||||
void set(Provider<T> provider)
|
||||
void unset()
|
||||
|
||||
default void leftShift(T t) {
|
||||
this.set(t)
|
||||
}
|
||||
|
||||
default void leftShift(Provider<T> provider) {
|
||||
this.set(provider)
|
||||
}
|
||||
|
||||
T getConvention()
|
||||
void setConvention(T t)
|
||||
void setConvention(Provider<T> provider)
|
||||
void unsetConvention()
|
||||
|
||||
void map(UnaryOperator<T> operator)
|
||||
void flatMap(Function<T, Provider<T>> function)
|
||||
|
||||
default void rightShift(UnaryOperator<T> operator) {
|
||||
this.map(operator)
|
||||
}
|
||||
|
||||
default void rightShift(Function<T, Provider<T>> function) {
|
||||
this.flatMap(function)
|
||||
}
|
||||
|
||||
void map(UnaryOperator<T> mapper)
|
||||
void merge(
|
||||
@DelegatesTo(type = 'T', strategy = Closure.DELEGATE_FIRST)
|
||||
Closure<?> configurator
|
||||
)
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package com.jessebrault.ssg.property
|
||||
|
||||
import com.jessebrault.ssg.provider.CollectionProvider
|
||||
import com.jessebrault.ssg.provider.Provider
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.PackageScope
|
||||
|
||||
import java.util.function.Function
|
||||
import java.util.function.UnaryOperator
|
||||
|
||||
@PackageScope
|
||||
@NullCheck
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
final class SimpleMapProperty<K, V> implements MapProperty<K, V> {
|
||||
|
||||
private final Map<K, V> convention = [:]
|
||||
private final Map<K, V> m = [:]
|
||||
|
||||
SimpleMapProperty(
|
||||
Map<? extends K, ? extends V> convention,
|
||||
Map<? extends K, ? extends V> m
|
||||
) {
|
||||
this.convention.putAll(convention)
|
||||
this.m.putAll(m)
|
||||
}
|
||||
|
||||
SimpleMapProperty(Map<? extends K, ? extends V> convention) {
|
||||
this(convention, [:] as Map<K, V>)
|
||||
}
|
||||
|
||||
SimpleMapProperty() {}
|
||||
|
||||
@Override
|
||||
V get(K key) {
|
||||
if (m[key] != null) {
|
||||
m[key]
|
||||
} else if (convention[key] != null) {
|
||||
convention[key]
|
||||
} else {
|
||||
throw new NullPointerException("no such key: ${ key }")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void put(K key, V value) {
|
||||
this.m.put(key, value)
|
||||
}
|
||||
|
||||
@Override
|
||||
void putAll(Map<? extends K, ? extends V> map) {
|
||||
this.m.putAll(map)
|
||||
}
|
||||
|
||||
@Override
|
||||
void set(Map<K, V> kvMap) {
|
||||
this.m.clear()
|
||||
this.m.putAll(kvMap)
|
||||
}
|
||||
|
||||
@Override
|
||||
void set(Provider<Map<K, V>> provider) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
void unset() {
|
||||
this.m.clear()
|
||||
}
|
||||
|
||||
@Override
|
||||
Map<K, V> getConvention() {
|
||||
this.convention
|
||||
}
|
||||
|
||||
@Override
|
||||
void setConvention(Map<K, V> kvMap) {
|
||||
this.convention.clear()
|
||||
this.convention.putAll(kvMap)
|
||||
}
|
||||
|
||||
@Override
|
||||
void setConvention(Provider<Map<K, V>> provider) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
void unsetConvention() {
|
||||
this.convention.clear()
|
||||
}
|
||||
|
||||
@Override
|
||||
void map(UnaryOperator<Map<K, V>> operator) {
|
||||
this.m.putAll(operator.apply(this.convention + this.m))
|
||||
}
|
||||
|
||||
@Override
|
||||
void flatMap(Function<Map<K, V>, Provider<Map<K, V>>> function) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
Map<K, V> provide() {
|
||||
this.convention + this.m
|
||||
}
|
||||
|
||||
@Override
|
||||
CollectionProvider<Map<K, V>> plus(Provider<Map<K, V>> other) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
CollectionProvider<Map<K, V>> asType(Class<CollectionProvider> collectionProviderClass) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isEmpty() {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
@ -1,93 +1,85 @@
|
||||
package com.jessebrault.ssg.property
|
||||
|
||||
import com.jessebrault.ssg.provider.AbstractProvider
|
||||
import com.jessebrault.ssg.provider.Provider
|
||||
import com.jessebrault.ssg.provider.Providers
|
||||
import com.jessebrault.ssg.util.Monoid
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.PackageScope
|
||||
|
||||
import java.util.function.Function
|
||||
import java.util.function.UnaryOperator
|
||||
|
||||
import static java.util.Objects.requireNonNull
|
||||
|
||||
@PackageScope
|
||||
@NullCheck
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
final class SimpleProperty<T> extends AbstractProvider<T> implements Property<T> {
|
||||
final class SimpleProperty<T> implements Property<T> {
|
||||
|
||||
private Provider<T> convention = Providers.getEmpty()
|
||||
private Provider<T> tProvider = Providers.getEmpty()
|
||||
private final Monoid<T> monoid
|
||||
|
||||
SimpleProperty(T convention) {
|
||||
this.convention = Providers.of(convention)
|
||||
private T t
|
||||
private T convention
|
||||
|
||||
SimpleProperty(Monoid<T> monoid) {
|
||||
this.monoid = monoid
|
||||
this.convention = this.monoid.empty.get()
|
||||
}
|
||||
|
||||
SimpleProperty(T convention, T t) {
|
||||
this.convention = Providers.of(convention)
|
||||
this.tProvider = Providers.of(t)
|
||||
SimpleProperty(Monoid<T> monoid, T convention) {
|
||||
this.monoid = monoid
|
||||
this.convention = convention
|
||||
}
|
||||
|
||||
SimpleProperty() {}
|
||||
SimpleProperty(Monoid<T> monoid, T convention, T t) {
|
||||
this.monoid = monoid
|
||||
this.t = t
|
||||
this.convention = convention
|
||||
}
|
||||
|
||||
@Override
|
||||
T provide() {
|
||||
this.tProvider.present ? this.tProvider.provide() : this.convention.provide()
|
||||
T get() {
|
||||
this.t != null ? this.t : requireNonNull(this.convention)
|
||||
}
|
||||
|
||||
@Override
|
||||
void set(T t) {
|
||||
this.tProvider = Providers.of(t)
|
||||
}
|
||||
|
||||
@Override
|
||||
void set(Provider<T> provider) {
|
||||
this.tProvider = provider
|
||||
this.t = t
|
||||
}
|
||||
|
||||
@Override
|
||||
void unset() {
|
||||
this.tProvider = Providers.getEmpty()
|
||||
this.t = null
|
||||
}
|
||||
|
||||
@Override
|
||||
T getConvention() {
|
||||
this.convention.provide()
|
||||
requireNonNull(this.convention)
|
||||
}
|
||||
|
||||
@Override
|
||||
void setConvention(T t) {
|
||||
this.convention = Providers.of(t)
|
||||
}
|
||||
|
||||
@Override
|
||||
void setConvention(Provider<T> provider) {
|
||||
this.convention = provider
|
||||
this.convention = t
|
||||
}
|
||||
|
||||
@Override
|
||||
void unsetConvention() {
|
||||
this.convention = Providers.getEmpty()
|
||||
this.t = null
|
||||
}
|
||||
|
||||
@Override
|
||||
void map(UnaryOperator<T> operator) {
|
||||
def oldTProvider = this.tProvider
|
||||
this.tProvider = Providers.fromSupplier {
|
||||
operator.apply(oldTProvider.provide())
|
||||
}
|
||||
void map(UnaryOperator<T> mapper) {
|
||||
this.t = requireNonNull(mapper.apply(this.t))
|
||||
}
|
||||
|
||||
@Override
|
||||
void flatMap(Function<T, Provider<T>> function) {
|
||||
def oldTProvider = this.tProvider
|
||||
this.tProvider = Providers.fromSupplier {
|
||||
function.apply(oldTProvider.provide()).provide()
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"SimpleProperty(convention: ${ this.convention }, tProvider: ${ this.tProvider })"
|
||||
void merge(
|
||||
@DelegatesTo(type = 'T', strategy = Closure.DELEGATE_FIRST)
|
||||
Closure<?> configurator
|
||||
) {
|
||||
def d = requireNonNull(this.monoid.empty.get())
|
||||
configurator.delegate = d
|
||||
configurator.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
configurator()
|
||||
this.t = requireNonNull(this.monoid.concat.apply(this.t != null ? this.t : this.monoid.empty.get(), d))
|
||||
}
|
||||
|
||||
}
|
||||
|
16
api/src/main/groovy/com/jessebrault/ssg/util/Monoid.groovy
Normal file
16
api/src/main/groovy/com/jessebrault/ssg/util/Monoid.groovy
Normal file
@ -0,0 +1,16 @@
|
||||
package com.jessebrault.ssg.util
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
import java.util.function.BinaryOperator
|
||||
import java.util.function.Supplier
|
||||
|
||||
@TupleConstructor(defaults = false)
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
final class Monoid<T> {
|
||||
final BinaryOperator<T> concat
|
||||
final Supplier<T> empty
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.jessebrault.ssg.property
|
||||
|
||||
import com.jessebrault.ssg.buildscript.domain.MutableSiteSpec
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals
|
||||
|
||||
final class SimplePropertyTests {
|
||||
|
||||
@Test
|
||||
void merge() {
|
||||
def p = Properties.get(MutableSiteSpec.MONOID)
|
||||
p.merge {
|
||||
name.set('Hello')
|
||||
}
|
||||
p.map {
|
||||
it.name.map { it + ', World!' }
|
||||
it
|
||||
}
|
||||
def ms = p.get()
|
||||
assertEquals('Hello, World!', ms.name.get())
|
||||
}
|
||||
|
||||
}
|
@ -1,16 +1,17 @@
|
||||
abstractBuild(name: 'redDogAll', extends: 'default') {
|
||||
siteSpec.merge {
|
||||
// siteSpec(Closure) is short for siteSpec.merge(Closure)
|
||||
siteSpec {
|
||||
name = 'Red Dog Ensemble'
|
||||
baseUrl = 'https://reddogensemble.com'
|
||||
}
|
||||
|
||||
globals.merge {
|
||||
globals {
|
||||
greeting = 'Say hello to good music!'
|
||||
}
|
||||
|
||||
sources { types ->
|
||||
models.map { acc ->
|
||||
old + someMethodThatGetsEventModels()
|
||||
acc + someMethodThatGetsEventModels()
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,11 +27,11 @@ abstractBuild(name: 'redDogAll', extends: 'default') {
|
||||
}
|
||||
|
||||
build(name: 'preview', extends: 'redDogAll') {
|
||||
siteSpec.merge {
|
||||
baseUrl += '/preview' // if possible
|
||||
siteSpec { base ->
|
||||
baseUrl = base.baseUrl + '/preview' // if possible
|
||||
}
|
||||
|
||||
globals.merge {
|
||||
globals {
|
||||
greeting = 'Hello from preview!'
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user