Created
December 12, 2020 04:08
-
-
Save theaspect/fd5dcfcfef20e54a291b260db41a2a17 to your computer and use it in GitHub Desktop.
DSL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dsl4 | |
import javax.script.Bindings | |
import javax.script.ScriptContext | |
import javax.script.ScriptEngineManager | |
class MyClass { | |
fun doAfterDelay(delay: Long, callback: Runnable) { | |
println("Java: before thread ${Thread.currentThread().id}") | |
val thread = Thread { | |
println("Java: thread begin ${Thread.currentThread().id}") | |
Thread.sleep(delay) | |
callback.run() | |
println("Java: thread end ${Thread.currentThread().id}") | |
} | |
// thread.isDaemon = true | |
thread.start() | |
// thread.join() | |
println("Java: after thread ${Thread.currentThread().id}") | |
} | |
} | |
class MyAnotherClass { | |
fun sum(a: Int, b: Int): Int { | |
println("Java: function sum") | |
return a + b | |
} | |
} | |
fun main() { | |
val engine = ScriptEngineManager().getEngineByName("JavaScript") | |
val bindings: Bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE) | |
bindings.put("polyglot.js.allowHostAccess", true) | |
bindings.put("polyglot.js.allowHostClassLookup", { true }) | |
// Eval from string | |
val resultString = engine.eval( | |
""" | |
// JavaScript code inside java | |
var a = 10; | |
var b = 20; | |
// Result of the last line will be return value of the script | |
print("JS: " + (a + b)); | |
print("JS: " + a + b); | |
"JS" | |
""" | |
) | |
println("Java: return from script $resultString") | |
engine.put("myJavaVariable", "Hello From Java") | |
engine.put("myAsync", MyClass()) | |
// Eval from file in fs | |
// val resultFile = engine.eval(FileReader("myscript.js")) | |
// Eval from file in classpath/jar | |
val resultFile = engine.eval( | |
(object {})::class.java.getResourceAsStream("/myscript.js").bufferedReader() | |
) | |
println(resultFile) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dsl3 | |
import java.time.LocalDate | |
@DslMarker annotation class PersonDsl | |
data class Person( | |
val firstName: String? = null, | |
val lastName: String? = null, | |
val patronymic: String? = null, | |
val dateOfBirth: LocalDate? = null, | |
val gender: Gender? = null, | |
val addresses: List<Address>? = null | |
) | |
enum class Gender { | |
MALE, FEMALE, OTHER | |
} | |
data class Address( | |
val country: String? = null, | |
val region: String? = null, | |
val area: String? = null, | |
val city: String? = null, | |
val street: String? = null, | |
val house: String? = null, | |
val building: String? = null, | |
val room: String? = null | |
) | |
@PersonDsl | |
class AddressBuilder { | |
var country: String? = null | |
var region: String? = null | |
var area: String? = null | |
var city: String? = null | |
var street: String? = null | |
var house: String? = null | |
var building: String? = null | |
var room: String? = null | |
val countries = setOf("Russia") | |
fun country(country: String): AddressBuilder { | |
check(this.country == null) { "Country already declared" } | |
check(validateCountry(country)) { "Uknown country $country" } | |
this.country = country | |
return this | |
} | |
fun region(region: String): AddressBuilder { | |
check(this.region == null) { "Region already declared" } | |
check(this.country != null) { "Country not declared" } | |
check(validateRegion(region)) { "Unknown region $region" } | |
this.region = region | |
return this | |
} | |
fun area(area: String): AddressBuilder { | |
// TOOD checks | |
this.area = area | |
return this | |
} | |
fun city(city: String): AddressBuilder { | |
// TOOD checks | |
this.city = city | |
return this | |
} | |
fun street(street: String): AddressBuilder { | |
// TOOD checks | |
this.street = area | |
return this | |
} | |
fun house(house: String): AddressBuilder { | |
// TOOD checks | |
this.house = house | |
return this | |
} | |
fun building(building: String): AddressBuilder { | |
// TOOD checks | |
this.building = building | |
return this | |
} | |
fun room(room: String): AddressBuilder { | |
// TOOD checks | |
this.room = room | |
return this | |
} | |
private fun validateCountry(country: String): Boolean = country in countries | |
private fun validateRegion(region: String): Boolean = true | |
fun build() = Address( | |
country, | |
region, | |
area, | |
city, | |
street, | |
house, | |
building, | |
room | |
) | |
} | |
@PersonDsl | |
class PersonBuilder { | |
var firstName: String? = null | |
var lastName: String? = null | |
var patronymic: String? = null | |
var dateOfBirth: LocalDate? = null | |
var gender: Gender? = null | |
var addresses: MutableList<Address> = mutableListOf() | |
fun name(firstName: String, lastName: String): PersonBuilder { | |
this.firstName = firstName | |
this.lastName = lastName | |
return this | |
} | |
fun name(firstName: String, lastName: String, patronymic: String): PersonBuilder { | |
this.firstName = firstName | |
this.lastName = lastName | |
this.patronymic = patronymic | |
return this | |
} | |
fun dateOfBirth(year: Int, month: Int, day: Int): PersonBuilder { | |
this.dateOfBirth = LocalDate.of(year, month, day) | |
return this | |
} | |
fun gender(gender: Gender): PersonBuilder { | |
this.gender = gender | |
return this | |
} | |
fun address(address: Address): PersonBuilder { | |
this.addresses.add(address) | |
return this | |
} | |
fun build() = Person(firstName, lastName, patronymic, dateOfBirth, gender, addresses) | |
} | |
/** | |
* Lambda with receiver | |
*/ | |
fun person(body: PersonBuilder.() -> Unit) = PersonBuilder().apply(body).build() | |
/** | |
* Add method to person builder | |
*/ | |
fun PersonBuilder.address(body: AddressBuilder.() -> Unit) { | |
val ab = AddressBuilder() | |
ab.body() | |
addresses.add(ab.build()) | |
} | |
fun main() { | |
// Create via DSL version | |
val db3 = listOf( | |
person { | |
name("Linnick", "Constantine") | |
dateOfBirth(1988, 8, 17) | |
gender(Gender.MALE) | |
address { | |
country("Russia") | |
region("Kemerovskaya oblast") | |
city("Kemerovo") | |
street("Bakinsky pereulok") | |
house("18b") | |
room("112") | |
} | |
}, | |
person { | |
name("Vasilisa", "Pupkina", "Petrovna") | |
dateOfBirth(1996, 2, 29) | |
gender(Gender.FEMALE) | |
address { | |
// Parent lambda call forbidden | |
// gender(Gender.FEMALE) | |
// [email protected](Gender.FEMALE) | |
country("Russia") | |
region("Novosibirskaya oblast") | |
area("Bolotny rayon") | |
city("Demidovo") | |
street("Lenina") | |
house("1") | |
} | |
address { | |
country("Russia") | |
region("Kemerovskaya oblast") | |
city("Novokuznetsk") | |
street("Sovetskaya") | |
house("10") | |
building("2") | |
room("20") | |
} | |
} | |
) | |
// Pattern DSL | |
println(db3) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// JavaScript code inside java | |
var a = 10; | |
var b = 20; | |
function myJsFunction() { | |
print("JS: callback function") | |
} | |
print("JS: before Async"); | |
myAsync.doAfterDelay(2000, function () { | |
print("JS: anonymous function") | |
}); | |
print("JS: after Async"); | |
// Result of the last line will be return value of the script | |
print("JS: " + myJavaVariable + ": " + (a + b)); | |
var MyAnotherClassType = Java.type("dsl4.MyAnotherClass"); | |
var another = new MyAnotherClassType(); | |
print("JS: "+ another.sum(1, 2)); | |
"JS: return value"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment