Cucumber V5-V6 - passing complex object in feature file step - cucumber

So I have recently migrated to v6 and I will try to simplify my question
I have the following class
#AllArgsConstructor
public class Songs {
String title;
List<String> genres;
}
In my scenario I want to have something like:
Then The results are as follows:
|title |genre |
|happy song |romance, happy|
And the implementation should be something like:
#Then("Then The results are as follows:")
public void theResultsAreAsFollows(Songs song) {
//Some code here
}
I have the default transformer
#DefaultParameterTransformer
#DefaultDataTableEntryTransformer(replaceWithEmptyString = "[blank]")
#DefaultDataTableCellTransformer
public Object transformer(Object fromValue, Type toValueType) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.convertValue(fromValue, objectMapper.constructType(toValueType));
}
My current issue is that I get the following error: Cannot construct instance of java.util.ArrayList (although at least one Creator exists)
How can I tell cucumber to interpret specific cells as lists? but keeping all in the same step not splitting apart? Or better how can I send an object in a steps containing different variable types such as List, HashSet, etc.
If I do a change and replace the list with a String everything is working as expected

#M.P.Korstanje thank you for your idea. If anyone is trying to find a solution for this here is the way I did it as per suggestions received. Inspected to see the type fromValue has and and updated the transform method into something like:
if (fromValue instanceof LinkedHashMap) {
Map<String, Object> map = (LinkedHashMap<String, Object>) fromValue;
Set<String> keys = map.keySet();
for (String key : keys) {
if (key.equals("genres")) {
List<String> genres = Arrays.asList(map.get(key).toString().split(",", -1));
map.put("genres", genres);
}
return objectMapper.convertValue(map, objectMapper.constructType(toValueType));
}
}
It is somehow quite specific but could not find a better solution :)

Related

how effciently read soap web service response with nested objects using streams

I consider a very easy task parse a nested object asnwered by a soap webservice using Java 8 streams. Nevertheless, I am quite confused when I think about the correct or most appropriate approach to use. I know it will depend on circunstances and there will never be a simple recipe. I have been reading for the last two weeks where and how to use stream but I couldn't reach a final conclusion about few options. I put bellow four approaches I would appreciatte if someone could give technical opnion if I understood correctly the real application based on very common requirements when dealing with soap client.
I am not loking for a simple answer like "Here I do successfully this way so you can copy and paste similar idea". I am really interested to understand if I am applying properly what I have read so far.
Firstly, my nested objects answered by web service:
//first level
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "OndernemingAlgemeenType", propOrder = {
"adressen",
... others properties
})
#XmlSeeAlso({
Onderneming20Type.class
})
public class OndernemingAlgemeenType
{
#XmlElement(name = "Adressen")
protected AdresOndernemingLijstType adressen;
... others elements
}
//second level that returns a list
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "AdresOndernemingLijstType", propOrder = {
"adres"
})
public class AdresOndernemingLijstType {
#XmlElement(name = "Adres", required = true)
protected List<AdresOndernemingType> adres;
...
}
// third level used to filter the list and return just one AdresOndernemingType
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "AdresOndernemingType", propOrder = {
"type"
})
public class AdresOndernemingType
extends AdresOndernemingBasisType{
#XmlElement(name = "Type", required = true)
protected TypeAdresOndernemingType type;
}
// fourth level
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "AdresOndernemingBasisType", propOrder = {
... not relevant for this question
})
#XmlSeeAlso({
AdresOndernemingType.class
})
public class AdresOndernemingBasisType
extends AdresBasisType
{
... not relevant for this question
}
// fifth level and finally, the desired fields (street and city)
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "AdresBasisType", propOrder = {
"straat", //street
"gemeente" //city
})
#XmlSeeAlso({
AdresOndernemingDeelnemingInType.class,
AdresOndernemingBasisType.class
})
public class AdresBasisType {
#XmlElement(name = "Straat")
protected StraatRR20Type straat;
#XmlElement(name = "Gemeente")
protected GemeenteOptioneel20Type gemeente;
// Approaches with its understanding
Approach 1:
I understand that this is null exception safe.
I mean, in case either getAdressen or getAdres is null there will be no exception at all and no address printed.
private void printOptionalDidactic(){
Optional<AdresOndernemingLijstType> op = Optional.ofNullable(onderneming.getAdressen());
op.map(AdresOndernemingLijstType::getAdres).get().stream().filter(Objects::nonNull)
.filter(o -> "001".equals(o.getType().getCode().getValue().getValue()))
.map(x -> System.out.println("My street is: ".concat(x.getStraat())));
}
Approach 2:
Assuming that there will be never a null element (minOccurs="1" in xsd for all) so using Optional would be pointless
private void printNoOptionalDidactic(){
onderneming.getAdressen().getAdres().stream()
.filter(o -> "001".equals(o.getType().getCode().getValue().getValue()))
.map(x -> System.out.println("My street is: ".concat(x.getStraat())));
}
Approach 3:
Assuming I want to print all streets and I don't care about filtering, I understand there is no advantage at all to use flatMap before forEach
Replace nested loop with Java 8 flatmap
private void printForEachDidactic(){
onderneming.getAdressen().getAdres().stream()
.forEach(x -> System.out.println("My street is: ".concat(x.getStraat())));
}
Approach 4
Since no shared resource is used by the predicates and functions used in the process,
I understand I could use parallelism. Nevertheless, provided that it is little data so I have no real gain on it
Should I always use a parallel stream when possible?
private void printParallelDidactic(){
onderneming.getAdressen().getAdres().parallelStream()
.filter(o -> "001".equals(o.getType().getCode().getValue().getValue()))
.map(x -> System.out.println("My street is: ".concat(x.getStraat())));
}
I wouldn't use map stream method when you really do not map elements of the stream (e.g. in approach 1 .map(x -> System.out.println...). Better call forEach, it is dedicated to execute code for each element of the stream.
Regarding your first approach, I think there will be a NoSuchElementException thrown if onderneming.getAdressen() is null. See implementation of Optional.get:
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
Otherwise all approaches look valid from the code point of view. Of course I cannot say anything about your data model.
However, you do not need to apply Java 8 streams and lambdas just because Java 8 introduced them. For example, I wouldn't use streams in your approach 3. An old school for loop will do it, too (and is slightly more readable here IMO):
for (AdresOndernemingType x : onderneming.getAdressen().getAdres()) {
System.out.println("My street is: ".concat(x.getStraat())));
}
Regarding parallel streams, I wouldn't use parallel() except when I really need parallelism to gain performance on huge data sets or long running tasks.

eliminating embedded actions from antlr4 grammar

I have an antlr grammar in which embedded actions are used to collect data bottom up and build aggregated data structures. A short version is given below, where the aggregated data structures are only printed (ie no classes are created for them in this short sample code).
grammar Sample;
top returns [ArrayList l]
#init { $l = new ArrayList<String>(); }
: (mid { $l.add($mid.s); } )* ;
mid returns [String s]
: i1=identifier 'hello' i2=identifier
{ $s = $i1.s + " bye " + $i2.s; }
;
identifier returns [String s]
: ID { $s = $ID.getText(); } ;
ID : [a-z]+ ;
WS : [ \t\r\n]+ -> skip ;
Its corresponding Main program is:
public class Main {
public static void main( String[] args) throws Exception
{
SampleLexer lexer = new SampleLexer( new ANTLRFileStream(args[0]));
CommonTokenStream tokens = new CommonTokenStream( lexer );
SampleParser parser = new SampleParser( tokens );
ArrayList<String> top = parser.top().l;
System.out.println(top);
}
}
And a sample test is:
aaa hello bbb
xyz hello pqr
Since one of the objectives of antlr is to keep the grammar file reusable and action-independent, I am trying to delete the actions from this file and move it to a tree walker. I took a first stab at it with the following code:
public class Main {
public static void main( String[] args) throws Exception
{
SampleLexer lexer = new SampleLexer( new ANTLRFileStream(args[0]));
CommonTokenStream tokens = new CommonTokenStream( lexer );
SampleParser parser = new SampleParser( tokens );
ParseTree tree = parser.top();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk( new Walker(), tree );
}
}
public class Walker extends SampleBaseListener {
public void exitTop(SampleParser.TopContext ctx ) {
System.out.println( "Exit Top : " + ctx.mid() );
}
public String exitMid(SampleParser.MidContext ctx ) {
return ctx.identifier() + " bye "; // ignoring the 2nd instance here
}
public String exitIdentifier(SampleParser.IdentifierContext ctx ) {
return ctx.ID().getText() ;
}
}
But obviously this is wrong, because at the least, the return types of the Walker methods should be void, so they dont have a way to return aggregated values upstream. Secondly, I dont see a way how to access the "i1" and "i2" from the walker code, so I am not able to differentiate between the two instances of "identifier" in that rule.
Any suggestions on how to separate the actions from the grammar for this purpose?
Should I use a visitor instead of a listener here, since the visitor has the capability of returning values? If I use a visitor, how do I solve the problem of differentiating between "i1" and "i2" (as mentioned above)?
Does a visitor perform its action only at the exit of a rule (unlike the listeners, which exist for both entry and exit)? For example, if I have to initialize the list at the entry of rule "top", how can I do it with a visitor, which executes only at the conclusion of a rule? Do I need a enterTop listener for that purpose?
EDIT: After the initial post, I have modified the rule "top" to create and return a list, and pass this list back to the main program for printing. This is to illustrate why I need an initialization mechanism for the code.
Based on what you are trying to do I think you may benefit from using ANTLR's BaseVisitor Class rather than the BaseListener Class.
Assuming your grammar is this (I generalized it and I'll explain the changes below):
grammar Sample;
top : mid* ;
mid : i1=identifier 'hello' i2=identifier ;
identifier : ID ;
ID : [a-z]+ ;
WS : [ \t\r\n]+ -> skip ;
Then your Walker would look like this:
public class Walker extends SampleBaseVisitor<Object> {
public ArrayList<String> visitTop(SampleParser.TopContext ctx) {
ArrayList<String> arrayList = new ArrayList<>();
for (SampleParser.MidContext midCtx : ctx.mid()) {
arrayList.add(visitMid(midCtx));
}
return arrayList;
}
public String visitMid(SampleParser.MidContext ctx) {
return visitIdentifier(ctx.i1) + " bye " + visitIdentifier(ctx.i2);
}
public String visitIdentifier(SampleParser.IdentifierContext ctx) {
return ctx.getText();
}
}
This allows you to visit and get the result of any rule you want.
You are able to access i1 and i2, as you labeled them through the visitor methods. Note that you don't really need the identifier rule since it contains only one token and you can access a token's text directly in the visitMid, but really it's personal preference.
You should also note that SampleBaseVisitor is a generic class, where the generic parameter determines the return type of the visit methods. For your example I set the generic parameter Object, but you could even make your own class which contains the information you want to preserve and use that for your generic parameter.
Here are some more useful methods which BaseVisitor inherits which may help you out.
Lastly, your main method would end up looking something like this:
public static void main( String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream(args[0]);
SampleLexer lexer = new SampleLexer(CharStreams.fromStream(fileInputStream));
CommonTokenStream tokens = new CommonTokenStream(lexer);
SampleParser parser = new SampleParser(tokens);
for (String string : new Walker().visitTop(parser.top())) {
System.out.println(string);
}
}
As a side note, the ANTLRFileStream class is deprecated in ANTLR4.
It is recommend to use CharStreams instead.
As Terence Parr points out in the Definitive Reference, one main difference between Visitor and Listener is that the Visitor can return values. And that can be convenient. But Listener has a place too! What I do for listener is exemplified in this answer. Granted, there are simpler ways of parsing a list of numbers, but I made that answer to show a complete and working example of how to aggregate return values from a listener into a public data structure that can be consumed later.
public class ValuesListener : ValuesBaseListener
{
public List<double> doubles = new List<double>(); // <<=== SEE HERE
public override void ExitNumber(ValuesParser.NumberContext context)
{
doubles.Add(Convert.ToDouble(context.GetChild(0).GetText()));
}
}
Looking closely at the Listener class, I include a public data collection -- a List<double> in this case -- to collect values parsed or calculated in the listener events. You can use any data structure you like: another custom class, a list, a queue, a stack (great for calculations and expression evaluation), whatever you like.
So while the Visitor is arguably more flexible, the Listener is a strong contender too, depending on how you want to aggregate your results.

Find MethodInvocation method bindings in JDT ASTVisitor

I have a java file which uses java.sql.Statement.execute as below.
public class Dummy
{
public void execute(String q) throws SQLException
{
...
Statement stmt = conn.createStatement();
...
stmt.execute(q);
...
}
}
My use case is I want to identify what are all the classes and their method names which use "Statement.execute(String)" using JDT ASTVisitor. Is this possible?
I found below entry using eclipse ASTView plugin.
method binding: Statement.execute(String)
How can I get this method binding value in my ASTVisitor.
I tried this.
#Override
public boolean visit(MethodInvocation node)
{
IMethodBinding iMethod = (IMethodBinding) node.resolveMethodBinding();
if(iMethod != null)
System.out.println("Binding "+iMethod.getName());
return super.visit(node);
}
but node.resolveMethodBinding() always returns null.
... i want to identify what are all the classes and its method names which using "Statement.execute(String)"
This sounds like a job for the org.eclipse.jdt.core.search.SearchEngine, which will produce the results much faster than traversing all your source files using a visitor.
... node.resolveMethodBinding() always returns null
This depends on how you obtained the AST. See, e.g., org.eclipse.jdt.core.dom.ASTParser.setResolveBindings(boolean)

Store sessionScope java.util.TreeMap variable in a document in xPage

I am working on an application where I am creating a java.util.TreeMap containing data fetched from various other documents of the application and then assigning that treemap to a sessionsScope variable. This is working fine.
Now I want to provide a functionality wherein I need to store this map inside a NotesDocument.
But when I try doing this, I am getting an error.
var doc:NotesDocument = database.createDocument();
doc.replaceItemValue("Form","testForm");
print("json = "+sessionScope.get("Chart_Map"));
doc.replaceItemValue("Calender_Map",sessionScope.get("Chart_Map"));
doc.save();
Exception:
Error while executing JavaScript action expression
Script interpreter error, line=4, col=13: [TypeError] Exception occurred calling method NotesDocument.replaceItemValue(string, java.util.TreeMap) null**
Is it possible to store a java.util.TreeMap in a notesdocument field?
If yes then how to implement that?
If no then why not? has that something to do with serializability?
You can't store Java objects inside Document fields unless you use the MimeDomino Document data source
http://www.openntf.org/main.nsf/blog.xsp?permaLink=NHEF-8XLA83
Or even better the new openntf Domino API that has this functionallity built in
http://www.openntf.org/main.nsf/project.xsp?r=project/OpenNTF%20Domino%20API
using MimeStorage
Fredrik is right, the MimeDomino makes most sense. If you are not ready and your field isn't too big for a normal Notes item, you could use CustomDataBytes as Sven suggested - or you use JSON by subclassing TreeMap. It could look like this:
import java.util.TreeMap;
import java.util.Vector;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import lotus.domino.Item;
import lotus.domino.NotesException;
public class TreeMapItem extends TreeMap<String, String> {
private static final long serialVersionUID = 1L;
public static TreeMapItem load(Item source) throws JsonSyntaxException, NotesException {
Gson g = new Gson();
TreeMapItem result = g.fromJson(source.getText(), TreeMapItem.class);
return result;
}
public void save(Item target) throws NotesException {
Gson g = new Gson();
target.setValueString(g.toJson(this));
}
}
I used Google's Gson, it is quite easy, but you might need to deploy it as plug-in for the Java security to work. There is build in JSON in XPages too - a little more work. An alternate approach would be to use 2 fields in Domino, one to load the keys from and one for the values - it would be in line with Domino practises from classic.
A third approach would be be to store the values separated using a pipe character:
#SuppressWarnings({ "unchecked", "rawtypes" })
public void saveCompact(Item target) throws NotesException {
Vector v = new Vector();
for (Map.Entry<String, String> me : this.entrySet()) {
v.add(me.getKey()+"|"+me.getValue());
}
target.setValues(v);
}
#SuppressWarnings("rawtypes")
public static TreeMapItem loadCompact(Item source) throws NotesException {
TreeMapItem result = new TreeMapItem();
Vector v = source.getValues();
for (Object o : v) {
String[] candidate = o.toString().split("|");
if (candidate.length > 1) {
result.put(candidate[0], candidate[1]);
}
}
return result;
}
Let us know how it works for you

Declarative hyperlinking with Jersey and JAXB

I am trying to use Jersey declarative hyperlinking and JAXB to achieve something that seems fairly simple to me, but despite reading all the docs and examples I could find I can't get things to work.
I have a bookstore with books, each of which has just a title.
I would like GET /bookstore to return just an array of hyperlinks to books,
while GET /bookstore/some-title would return the actual serialized book attributes.
I am getting completely confused with resources and "representations", and with the way #Ref is supposed to work. What would be the cleanest way to design this?
The icing on the cake would be the ability to get either versions of the bookstore collection (shallow with just book URIs or deep with actual book attributes) based on a query parameter...
I have tried to add this method to bookstore:
#XmlElement
public BookRef[] getBookReferences()
{
BookRef[] refs = new BookRef[_books.size()];
for (int i = 0; i < refs.length; i++) {
refs[i] = new BookRef(_books.get(i).getTitle());
}
return refs;
}
with this BookRef class:
#XmlRootElement(name="book")
public class BookRef
{
private String _title;
public BookRef()
{
}
public BookRef(#PathParam("title") String title)
{
_title= title;
}
#Ref(resource=Book.class,
style = Ref.Style.ABSOLUTE,
bindings=#Binding(title="title", value="${instance.title}")
)
private URI _self;
#XmlElement
public URI getURI()
{
return _self;
}
}
... but that just yields (in JSON): {"bookReferences":null}

Resources