intellij mass refactoring using macros - java

I am working on a project in intellij using java and spring.
I want to change in multiple files my api's in a similar way like this:
instead of:
public void someApi(HttpServletRequest request, HttpServletResponse response) throws Exception {
someThrift thriftRequest = getThrift(...);
someOtherThrift thriftResponse = …
setThriftResponse(...);
}
use this:
#ThriftResponse
public someThrift getReports(#ThriftRequestBody someThrift thriftRequest) throws Exception {
someOtherThrift thriftResponse = …
return thriftResponse;
}
is there a way to achieve this using some sort of a macro?
this kind of code spans on multiple files that all have the same suffix in their name as well
thank you

As said in the comments, you can use Structural search and replace. It allows you to search and replace fragment of codes using a template defined with variables constraint by count numbers, regular expressions, and even Groovy scripts.
The easiest way to create a template is to browse the list of existing ones, find one similar to what you want to achieve and modify it.

Related

How to generate Code in pre existing code files in Java?

I just found out how to generate code using annotation processing
But as I understand these are just additional code files.
What i want to achieve is something like this (In a already existing file):
#basicMethod
public void executeStuff(String help, int me) {
mySystem.executor(help, me); // <- This should be generated by this annotation
}
Is there any way to achieve something like this?
Also, I am not sticking to Annotations. Any other way would also be helpful.

Insert v1 into #Path annotation (java 1.6)

Our current path annotation omitted the 'v1' and we'd like to insert it. Since we cannot have more than one Path annotation, is there a way to add the v1 using a regular expression? I have seen this used for parameters, but not for constants in the endpoint.
So if my path annotation currently looks like this:
#Path("/rest/noun")
Can it be replaced with something like this?
#Path("/rest/noun|/rest/v1/noun")
Since some users are using the original path of /rest/noun, I want to offer the corrected one and the old one, not to break their current functionality. I want to offer both of these:
/rest/noun
/rest/v1/noun
If you want more than one path for same code of execution, you can create wrapper function calling the current function internally like below:
#Path("/rest/noun")
void currentfunction(){
//all functionality code here
}
#Path("/rest/v1/noun")
void newfunction(){
currentfunction();
}
Or you can also use:
#Path("/rest/{parameter: v1\\/noun|noun}")
void currentfunction(){
//all functionality code here
}

Is it possible to create a Freemarker macro programmatically?

Freemarker is used as the default template engine in the ninja web framework. The framework assigns some default values to a template which are globaly available when using the ninja web framework. I have created an extension for the template which does enbales CSRF-Protection. The extension offers a function which can be used in a template, e.g.
${foo(bar)}
At the moment the function needs to be called with specific parameters, which is not very intuitiv. Using a macro I could simplify this call to
#{foo}
and the user doesn't need to worry about passing the correct (e.g. "bar") parameter. But to make this available in the ninja web framework I have to define a macro programmatically. Is that possible?
UPDATE
Sorry for the confusion. Meant <#foo/> instead of #{foo} ...
Looking at the Freemarker documentation I maybe can make more clear what I want to achieve: http://freemarker.org/docs/ref_directive_macro.html
Like I explained above I am passing a custom function to the template, enabling me to call
${foo("bar")}
What I want to do, is call this via a macro like
#<myMacro/>
But the defined macro like
<#macro myMacro>
${foo("bar")}
</#macro>
should not be defined in the template but programmatically. Hope that makes it more clear.
UPDATE2 / SOLUTION
I ended up using the recommended TemplateDirectiveModel.
public class TemplateEngineFreemarkerAuthenticityTokenDirective implements TemplateDirectiveModel {
private String authenticityToken;
public TemplateEngineFreemarkerAuthenticityTokenDirective(Context context) {
this.authenticityToken = context.getSession().getAuthenticityToken();
}
#Override
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
if (!params.isEmpty()) {
throw new TemplateException("This directive doesn't allow parameters.", env);
}
if (loopVars.length != 0) {
throw new TemplateException("This directive doesn't allow loop variables.", env);
}
Writer out = env.getOut();
out.append(this.authenticityToken);
}
}
FreeMarker macro invocations doesn't look like #{...}. Is that some kind of Ninja-specific extension?
Anyway, if you know that there's a bar in the data-model, then your method can get it like Environment.getCurrentEnvironment().getDataModel().get("bar"), so it need not be passed in.
Also, it's maybe useful to know that FTL has two kind of "subroutines", the function-like ones, and the directive-like ones. Both can be implement both in FTL (#function, #macro) and in Java (plain Java methods, TemplateMethodModelEx, TemplateDirectiveModel). The real difference is that the function-like ones are for calculating values, and the directive-like ones are for printing values directly to the output (hence bypassing auto-escaping) and for side-effects. But all of these can reach the Environment, so there's no difference there.
You can call a macro "dynamically". Let's say you had a macro:
<#macro myMacro>
${foo("bar")}
</#macro>
You can call it like this:
<#myMacro />
OR
<#.vars["myMacro"] />
So then you can do...
<#assign someVar = "myMacro" />
<#.vars[someVar] />

How to get a reference of cucumber RuntimeOptions when using cucumber-java and junit?

I am using cucumber-java in groovy code. I prefer cucumber-java to cucumber-groovy because I can run the tests like plain old good JUnit tests. However, the step definition templates spitted out by cucumber are in java style. Instead, I would like to have a groovy style. For example, in java style, you will get something like
#When("^an HTTP GET request is sent to obtain config.xml of \"([^\"]*)\"$")
public void an_HTTP_GET_request_is_sent_to_obtain_config_xml_of(String arg1) throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}
Since I am using groovy, I would like to get something like
#When(/^an HTTP GET request is sent to obtain config.xml of "([^"]*)"$/)
void 'an HTTP GET request is sent to obtain config.xml of'(String arg1) {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}
I am thinking to implement such a feature. Basically, my idea is to add a new field, maybe called templateLanguage, in cucumber.api.CucumberOptions. When this new field is equal to groovy, then the groovy-style templates will be spitted. This will probably involve an if statement in cucumber.runtime.java.JavaSnippet.template(), such as
if( runtimeOptions.getTemplateLanguage().toLowerCase().equals('groovy') ) {...}
However, my question is: how can I get a reference of the runtimeOptions that is passed in like
#CucumberOptions(
format = ["pretty", "html:build/cucumber"],
features="src/test/resources/cucumber_features/api/job_view.feature",
glue=['com.yahoo.adcd.jenkins.tests.smoke.api.cucumber.job.view'],
strict = true
)
Thank you very much!
In a case like this, you would need to write your own boot class since there is no dependency injection for RuntimeOptions. A good starting location is to look at cucumber.api.cli.Main. You would need to create your own class that extends RuntimeOptions, then add in your logic there.
This solution, however, will not allow you run the app using the CucumberOptions annotation anymore. If you do prefer using the annotation though, you would need to also implement your own custom annotation and override the RuntimeOptionsFactory to use your annotation, and then use that factory in your new main class to create the runtime dynamically.

How to key off a parameter to a stubbed method using Mockito

Greetings.
I am mocking a search engine for testing in my web app. This search engine returns xml documents with different schemas. The schema depends on a parameter known as a collection set. Returning different schemas based on collection sets is the part that's difficult to mock, because specifying the collection set is basically a setup method, and a void one at that. This search engine is an external jar file so I can't modify the API. I have to work with what's been provided. Here's an example:
Engine engine = factory.getEngine();
Search search = engine.getSearch();
search.addCollectionSet(someCollectionSet);
SearchResult result = search.getSearchResult();
Document[] documents = result.getAllDocuments();
Then for each document, I can get the xml by calling:
document.getDocumentText();
When I'm using my mock objects, getDocumentText() returns an xml string, created by a generator, that conforms to the schema. What I want to do is use a different type of generator depending on which collection set was provided in step 3 in the first code snippet above. I've been trying to do something like this:
doAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
if (args == "foo") {
SearchResult result = getMockSearchResult();
when(search.getSearchResult()).thenReturn(result);
}
}
}).when(search.addCollectionSet(anyString()));
But this results in lots of red highlighting :)
Basically, my goal is to key off of addCollectionSet(someCollectionSet) so that when it's called, I can do some kind of switch off of the parameter and ensure that a different generator is used. Does anyone know how I can accomplish something like this? Or is there maybe some form of Dependency Injection that could be used to conditionally wire up my generator?
Thanks!
Update
I've changed my factory object so that it never returns the engine, but rather, the Search and Find objects from that engine, so now I can do something like this:
Search search = factory.getSearch(collectionSet);
So what I'd like to do is something like this:
when(factory.getSearch(anyString()).thenAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
switch(args[0]) {
case fooSet: return fooSearch; break;
case barSet: return barSearch; break;
In other words, I still want to key off the string that was passed in to getSearch in a switch statement. Admittedly, I could do something more like felix has suggested below, but I'd rather have all my cases wrapped in a switch. Can someone provide an example of how this could be done? Thanks!
Update
I've seen that you can capture the arguments that are passed into mocked calls, but these captured arguments are used for later assertions. I haven't seen a way that I can key off these arguments so that a call to my mock will return different values depending on the arguments. It seems like there has to be a way to do this, I just don't have enough experience with Mockito to figure it out. But surely someone does!
I would recommend wrapping the call to the legacy code into your own object.
So you end up with your own method along these lines:
class SearchEngineWrapper {
public String getSearchResult(String collection){
Engine engine = factory.getEngine();
Search search = engine.getSearch();
search.addCollectionSet(someCollectionSet);
SearchResult result = search.getSearchResult();
...
return document.getDocumentText();
}
}
Now you can mock out this method. The method also nicely documents your intent. Also you could test the actual implementation in an integration test.
when(searchEngineWrapper.getSearchResult("abc").thenReturn("foo");
when(searchEngineWrapper.getSearchResult("xyz").thenReturn("bar");

Categories