Gradle 2 - CopySpec properties for custom plugin - groovy

I am writing a custom plugin for Gradle 2.0 which extends AbstractArchiveTask. I wish to add some properties to the CopySpec closure, e.g.
task myCopy(type: CustomCopy) {
propertyA = 'cheese'
into 'destDir'
from('srcDir')
from('otherSrcDir') {
into 'otherDestDir'
propertyA = 'Beef'
}
}
What would be the best way to add these properties to both the task and the inner closure?
How would I then get these properties in my CopyAction and CopyActionProcessingStreamAction implementations?
Thanks in advance
Mike

Last time I checked, there wasn't a way to achieve this with public APIs. Perhaps have a look at the Rpm task implementation of https://github.com/nebula-plugins/gradle-ospackage-plugin. As you can see in its docs, that task adds new properties in both the locations you mentioned.

Related

How to retain some of the interface methods' default implementations in the implementing class in C# 8.0?

One would think that in C# 8.0 you should be able to do the following (according to this (1st snippet)):
public interface IRestApiClient : IRestClient
{
...
Task<T> PostPrivateAsync<T>(string action, OrderedDictionary<string, object> parameters = null, DeserializeCustom<T> deserializer = null)
{
return QueryPrivateAsync(Method.POST, action, parameters, deserializer);
}
...
}
public class SpecificClient : ExchangeClient, IRestApiClient, IRestHtmlClient, ISeleniumClient, IWebSocketClient
{
}
The example above won't compile because the interface members need to be explicitly and wholly implemented (including the methods supplying the default logic)
So one would think that the following should work:
public interface IRestApiClient : IRestClient
{
...
Task<T> PostPrivateAsync<T>(string action, OrderedDictionary<string, object> parameters = null, DeserializeCustom<T> deserializer = null)
{
return QueryPrivateAsync(Method.POST, action, parameters, deserializer);
}
...
}
public class SpecificClient : ExchangeClient, IRestApiClient, IRestHtmlClient, ISeleniumClient, IWebSocketClient
{
...
public async Task<T> PostPrivateAsync<T>(string action, OrderedDictionary<string, object> parameters = null, DeserializeCustom<T> deserializer = null)
=> await ((IRestApiClient) this).PostPrivateAsync(action, parameters, deserializer);
...
}
Nope, it looks like this method is recursive (despite the upcast) and will cause our favorite Stack Overflow exception.
So my question is (abstracting from the fact that I could change the design in my example), is there a way of keeping the implementation for a specific method default, preferably without the necessity of resorting to hacky or Static Helper Extension methods? I could call static extension method in both interface and the class but it kind of defeats the purpose of this feature.
// EDIT
I must admit it confuses me and it appears I am missing something critical that is obvious to other people. I didn't provide additional info because I didn't consider my issue to be code specific. Lets look at this simple example (taken from the website I linked on the beginning of my post):
According to #Panagiotis Kanavos comment: No, default members don't need to be implemented (...) what I screenshoted should not be true. Can sb please enlighten me?
// EDIT 2
As you can see I am properly targeting .NET CORE 3.0 with C# 8.0.
ERRORS:
Interface method cannot declare a body
Interface member 'void CryptoBotCoreMVC.IDefaultInterfaceMethod.DefaultMethod()' is not implemented
To answer the question in the comments: I didn't specify LangVersion explicitly in the .csproj file.
// EDIT 3
The issue was ReSharper, see:
https://stackoverflow.com/a/58614702/3783852
My comment have been deleted, presumably by the owner of the answer so I'll write it here: the clue was the fact that there was actually no error numbers, but the compilation was blocked. It turned out that there is an option to block compilation when these errors occur in ReSharper.
It seems that in the end this is a possible duplicate, but getting to this conclusion was quite a journey :).
The issue is caused by ReSharper, reference:
https://youtrack.jetbrains.com/issue/RSRP-474628
It appears that the problem will be resolved in version v2019.3 and we currently have v2019.2.3. You can setup ReSharper to block compilation depending on issue severity, the workaround is to disable this feature for the time being.

Optaplanner multithreading attempt yielded "missing rebase" on custom move

I updated from 7.5 to 7.9 Optaplanner libraries for use with a variant of the nurserostering code, and used the release notes (for example, some method names changed) to successfully rebuild and re-run. Then, I added the "moveThreadCount" xml line (for multithreading) to my solver config xml.
<moveThreadCount>AUTO</moveThreadCount>
Running then immediately threw an error:
Caused by: java.lang.UnsupportedOperationException: The custom move class (class westgranite.staffrostering.solver.move.EmployeeChangeMove) doesn't implement the rebase() method, so multithreaded solving is impossible.
I do have a number of custom moves. I did not see any reference to the need to add a rebase() method in the release notes, nor do I see a reference to rebase() in the current (newer) documentation section on building custom moves.
https://docs.optaplanner.org/7.12.0.Final/optaplanner-docs/html_single/index.html#customMoves
Would someone please point me the right way? Thanks!
I would suggest reading this excellent blog post: http://www.optaplanner.org/blog/2018/07/03/AGiantLeapForwardWithMultithreadedIncrementalSolving.html as it gives a more in depth explanation of how multithreaded solving works.
I also suggest to read the javadoc on the rebase method, it should point you in the right direction: https://docs.optaplanner.org/7.12.0.Final/optaplanner-javadoc/org/optaplanner/core/impl/heuristic/move/Move.html#rebase-org.optaplanner.core.impl.score.director.ScoreDirector-
Here's an example:
public class CloudComputerChangeMove extends AbstractMove<CloudBalance> {
private CloudProcess cloudProcess;
private CloudComputer toCloudComputer;
...
#Override
public CloudComputerChangeMove rebase(ScoreDirector<CloudBalance> destinationScoreDirector) {
return new CloudComputerChangeMove(
destinationScoreDirector.lookUpWorkingObject(cloudProcess),
destinationScoreDirector.lookUpWorkingObject(toCloudComputer));
}
}

Gradle, overload extension setter

Given an extension registered in gradle as foo:
class Foo {
Project proj
void setProject( Project project) {
this.proj = project
}
void setProject( String project) {
// do stuff
}
}
How do I get:
foo {
project = ':random-project'
}
to call the string setter and not fail in setProperty of the decorated extension object due to GroovyCastException?
The reason for this question arose from this issue: https://github.com/Centril/gradle-plugin-robospock/issues/5
Since I don't see any better answer yet, I am trying to suggest a possible alternative.
If you can keep type of proj as a String in Foo and where you actually use the instance of Foo class, lookup the project using the findProject method on the project object available to your plugin.
class FooPlugin implements Plugin<Project> {
// ...
void apply(Project project) {
// ...
project.findProject(fooInstance.proj)
}
}
You may find more on findProject or project methods to locate a project by path at API Documentation
There might be a way to access current Project instance in your Foo class then you may use the overloaded setter.
This works in Gradle versions 2.0 and later which is likely due to the move from Groovy 1.x to 2.x. I'd suggest using a later version of Gradle if that is possible.
Luke Daley from Gradleware informed me that this is a limitation of the Groovy language: https://issues.apache.org/jira/browse/GROOVY-2500

gradle object in a gradle build script

Consider the following method invokation containing in the gradle build script:
gradle.taskGraph.whenReady{taskGraph ->
println gradle.toString()
println "Ready"
}
It prints
build 'task_graph'
Ready
I thought we work in the scope of Project object, since gradle should be a property of that Project object. But there is neither property nor even method with such name. Why can we use it in the build script?
I may be wrong but I think your confusion is that there exists a getGradle() method on the Project interface but no such public field named gradle. This is a Groovy feature. In Groovy, getter and setter methods can by referenced as properties. For example:
println project.description // same as project.getDescription()
project.description = 'My java project' // same as project.setDescription('My java project')
I'd highly suggest familiarizing yourself with Groovy by checking out their documentation. You'll see a lot of differing syntax in Gradle examples simply because there are many different ways to accomplish the same thing in Groovy.

JBehave - all steps marked pending?

I'm trying to create and run a simple JUnitStory to run a .story file.
I have this:
class Scenario1 extends JUnitStory {
#Delegate MySteps steps = new MySteps()
#Override
public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(new LoadFromRelativeFile(new File('src/test/groovy').toURL()))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withDefaultFormats()
.withFormats(Format.HTML, Format.CONSOLE, Format.TXT)
);
}
#Override
public List candidateSteps() {
final candidateSteps = new InstanceStepsFactory(configuration(), this).createCandidateSteps()
return candidateSteps;
}
}
With or without the delegate (copying and pasting in all the annotated methods of MySteps), whenever I run JBehave, I get the following output:
somePattern(){
// PENDING
}
It's like the individual stories don't pick up the steps.
When I create a "Stories" class and pull all the story files in with storyPaths, the individual steps are defined. Using a debugger, I see that candidateSteps is being hit, but it's not pulling in the data it needs to.
What could possibly be going on here?
You don't need to delegate to the Steps. And also you should not override candidateSteps, but rather stepsFactory. In later versions of JBehave, candidateSteps is deprecated, to make that preference for the factory method more prominent ( http://jbehave.org/reference/stable/javadoc/core/org/jbehave/core/ConfigurableEmbedder.html#candidateSteps() )
See this blog, where I explained how the basic JBehave configuration works in more detail:
http://blog.codecentric.de/en/2012/06/jbehave-configuration-tutorial/
Andreas
Here is your answer buddy:
The package of format has Changed.
This is the deprecated
import static org.jbehave.core.reporters.StoryReporterBuilder.Format.HTML;
This is the new one :)
import static org.jbehave.core.reporters.Format.HTML;
Took a while to find the answer, but was hidden on the jbehave documentation
Hope it helps!
Cheers!
You shouldn't need to use the #Delegate - your JUnitStory is not your Steps class. Can you try passing in steps where you have this?
When you pass in a class that has been bytecode manipulated for Steps classes, JBehave may not see the jbehave annotations anymore.
JBehave is old, underdeveloped technology. Don't use it.

Resources