Gradle - using a function from within Ant - function

I have a Gradle script with few invocations of XJC to generate JAXB classes from XSD.
I thought I could parametrize these invocations and reuse the common code.
So I created a function:
ext.generateJaxbClasses = { HashMap params ->
project.ant {
...
And then I wanted to use it:
task genJaxb {
ext.generic = [
schema: "..."
]
doLast() {
ext.generateJaxbClasses(jaxbSetA)
ext.generateJaxbClasses(jaxbSetB)
}
But I get this error:
> No signature of method: org.gradle.internal.extensibility.DefaultExtraPropertiesExtension.generateJaxbClasses() is applicable for argument types: (LinkedHashMap) values: [[...]]
How can I use the function within a task definition?

Use project.ext.generateJaxbClasses(jaxbSetA)
Using ext inside the task resolves to searching for the property inside the task's extension container.
See ExtensionAware.
I would suggest using an actual free function inside the project rather than using extensions as it can lead to this kind of frustration.
def generateJaxbClasses(HashMap params) {
project.ant {...}
}

Related

Build gradle kotlin dsl task extension method

I want to modify my build.gradle.kts by implementing some tasks. Specially, I want to obtain the output of the first task in my second task, where the first task runs a shell command. There are some basic examples here and here, which are implemented in groovy dsl. Now, I need this functionality in kotlin dsl.
A working example is:
task<Exec>("avdIsRunning") {
commandLine("adb", "devices")
standardOutput = ByteArrayOutputStream()
}
task("task2") {
dependsOn("avdIsRunning")
doLast {
val standardOutput = (tasks.getByName("avdIsRunning") as Exec).standardOutput.toString()
println("Foo's output: $standardOutput")
}
}
What I want is, to call a extension method avdIsRunning.output() that provides the standradOutput of avdIsRunning-task, compare to the examples I linked above.

How can I test/access companion object extension functions in Kotlin?

I have an Base64Util class with amongst others an extension function decodeBase64ToByteArray :
class Base64Util {
companion object {
fun String.decodeBase64ToByteArray(): ByteArray {
return Base64.getUrlDecoder().decode(this)
}
}
}
Now I would like to test my Base64Util via Base64IUtilTest. I can access non extension functions of course, but how can I access/test the String.decodeBase64ToByteArray() from Base64UtilTest ?
You cannot simply access member extension functions such as decodeBase64ToByteArray from outside. This is only possible if you get into the scope of the object it is defined in:
with(Base64Util.Companion){ //.Companion could be removed
"123fsad123".decodeBase64ToByteArray()
}
It could make sense to define your util functions as top-level functions in a file base64Utils.kt for example. This way, they can be called in a static way without any issue.

TypeScript: how to JSON stringify a class definition?

Say we have:
class MyClass {
myProperty: string
}
Is there any built in function or easy way to get JSON like this?:
{
"myProperty": "string"
}
EDIT: My end goal is I want to dynamically print typed class definitions to a web view, in some kind of structured object syntax like JSON. I'm trying to make a server API that will return the schema for various custom classes - for example http://myserver.com/MyClass should return MyClass's properties and their types as a JSON string or other structured representation.
Evert is correct, however a workaround can look like this
class MyClass {
myProperty: string = 'string'
}
JSON.stringify(new MyClass) // shows what you want
In other words, setting a default property value lets TS compile properties to JS
If the above solution is not acceptable, then I would suggest you parsing TS files with your classes with https://dsherret.github.io/ts-simple-ast/.
Typescript class properties exist at build-time only. They are removed from your source after compiling to .js. As such, there is no run-time way to get to the class properties.
Your code snippet compiles to:
var MyClass = /** #class */ (function () {
function MyClass() {
}
return MyClass;
}());
As you can see, the property disappeared.
Based on your update, I had this exact problem. This is how I solved it.
My JSON-based API uses json-schema across the board for type validation, and also exposes these schemas for clients to re-use.
I used an npm package to automatically convert json-schema to Typescript.
This works brilliantly.

Sitecore Configuration Factory - Call method with more than one argument

I have read John West's article on the Site Configuration Factory (http://www.sitecore.net/unitedkingdom/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2011/02/The-Sitecore-ASPNET-CMS-Configuration-Factory.aspx)
I'm trying implement it in a custom link provider.
I want the Configuration Factory to call the following method in the link provider:
public void AddSitePath(String site, String path)
{
// do stuff
}
Here's the config (although I've tried several similar variations).
<add name="sitecore" type="MyProject.Providers.CustomLinkProvider, MyProject" addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="never" languageLocation="filePath" shortenUrls="true" useDisplayName="false">
<sitePaths hint="list:AddSitePath">
<sitePath>
<site>SiteOneName</site>
<path>/product-range/</path>
</sitePath>
<sitePath >
<site>SiteTwoName</site>
<path>/items-for-sale/</path>
</sitePath>
</sitePaths>
</add >
I'm getting the following error message:
Could not find add method: AddSitePath (type: MyProject.Providers.CustomLinkProvider)
I suspected that the problem was that I was trying to pass 2 parameters into the method, and sure enough, when I tested it with a single parameter version it worked.
What do I need to change in either the config or the class code to achieve what I need?
So it looks like you can't supply 2 arguments. Instead, you pass in a single XmlNode object, which contains everything you you need. You have to extract the information from the XmlNode within the method.
Something along the lines of:
public void AddSitePath(XmlNode arg)
{
// pick apart the XmlNode and do stuff
}
<sitePaths hint="raw:AddSitePath">
<sitePath site="SiteNameOne" path="/product-range/">
<sitePath site="SiteNameTwo" path="/items-for-sale/">
</sitePaths>
Note that you have to use the 'raw' prefix instead of 'list'

Why is this groovy code throwing a MultipleCompilationErrorsException?

I have the following groovy code :
class FileWalker {
private String dir
public static void onEachFile(String dir,IAction ia) {
new File(dir).eachFileRecurse {
ia.perform(it)
}
}
}
walker = new FileWalker()
walker.onEachFile(args[0],new PrintAction())
I noticed that if I place a def in front of walker , the script works. Shouldn't this work the way it is now ?
You don't need a def in groovyConsole or in a groovy script. I consider it good programming practice to have it, but the language will work without it and add those types of variables to the scripts binding.
I'm not sure about the rest of your code (as it won't compile as you've posted it). But you either have a really old version of groovy or something else is wrong with your config or the rest of your code.
With the addition of a stub for the missing IAction interface and PrintAction class, I'm able to get it to run without modification:
interface IAction {
def perform(obj)
}
class PrintAction implements IAction{
def perform(obj) {
println obj
}
}
class FileWalker {
private String dir
public static void onEachFile(String dir,IAction ia) {
new File(dir).eachFileRecurse {
ia.perform(it)
}
}
}
walker = new FileWalker()
walker.onEachFile(args[0],new PrintAction())
I created a dummy directory with "foo/bar" and "foo/baz" files.
If I save it to "walkFiles.groovy" and call it from the command line with
groovy walkFiles.groovy foo
It prints:
foo/bar
foo/baz
This is with the latest version of groovy:
groovy -v
Groovy Version: 1.6-RC-3 JVM: 1.5.0_16
In scripting mode (or via "groovyConsole"), you need a declaration of walker with "def" before using it. A Groovy script file is translated into a derivative class of class Script before it get compiled. So, every declaration needs to be done properly.
On the other hand, when you're running a script in "groovysh" (or using an instance of class GroovyShell), its mechanism automatically binds every referencing object without the need of declaration.
updated:
My above answer would be wrong as I decompiled a .class of Groovy and found that it's using a binding object inside the script as well. Thus my first paragraph was indeed wrong.