Stax parse doesn't return proper response - jaxb

Hi ,
I am facing very strange issue while parsing SOAP Response with Jaxb. I am not able to get complete list of tags while parsing .Stax parser is able to parse only one tag ,its not giving any error or exception.However if I try to format the xml response(which is stored in string) Everything works perfectly fine. Here is what I am doing to parse it :-
public void parseResponse(){
String response="<SOAP:Body><response><result><myTag></myTag><myTag></myTag>/result</response</SOAP:Body>";
getUnmarshalledObject(response,myTag,MyTag.class,"com.mylearning.parseXml");
}
public <T> List<T> getUnmarshalledObject( String response ,String TAG_TO_SEARCH ,Class<T> clazz , String basePkg)
throws XMLStreamException, JAXBException{
Reader reader = new StringReader(response);
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(reader);
List<T> listOfUnmarshalledObjects = new ArrayList<T>();
while (xsr.hasNext()) {
if (xsr.getEventType() == XMLStreamReader.START_ELEMENT && TAG_TO_SEARCH.equals(xsr.getLocalName())) {
T unmarshalledObj = unmarshalXml( clazz ,xsr, basePkg);
listOfUnmarshalledObjects .add(unmarshalledObj);
}
xsr.next();
}
return listOfUnmarshalledObjects;
}
Here are different use cases of the problem:-
Case 1:- Input String response is unformatted.
Result :- listOfUnmarshalledObjects is 1.
Case 2:- Format response with response.replaceAll("><",">\n<");
Result:- listOfUnmarshalledObjects is 2.
Case 3 : Input String unformatted , just give space b/w </myTag><myTag>
Result: listOfUnmarshalledObjects is 2.
I tried my best to explain the question, please help me.
> Blockquote

I turns out that main culprit was missing else condition.
Parsing cursor was able to find the first block of ..tag but once it’s done with it , xsr.next is also getting executed in each iteration.
So in case where xml is not formatted :-
1. Parser finds the first complete block of and store it in list , now cursor is at next tag but before control goes to the next iteration xsr.next gets executed and moves cursor to the next immediate tag.
In case of formatted xml :-
1. There will be \n character between two continuous block \n so even if xsr.next gets executed at each iteration
it will just eat \n character and cursor will be right on track to parse next block of tag.
Here is the updated code with else condition :-
while (xsr.hasNext()) {
if (xsr.getEventType() == XMLStreamReader.START_ELEMENT && TAG_TO_SEARCH.equals(xsr.getLocalName())) {
T unmarshalledObj = unmarshalXml( clazz ,xsr, basePkg);
listOfUnmarshalledObjects .add(unmarshalledObj);
}else{
xsr.next();
}
}

Related

How to get first String based on whitespace out of a full String using java8?

Let's Example I have String s = "Rahul Kumar" I need to have Rahul as a output using java8
Actual Requirement, I do have a list of Trip Object, I want to set driverName property as only first name to each Trip Object and return that list?
System.out.println( someStringValue.subSequence(0, someStringValue.indexOf(' ')));
I'm getting trouble to incorporate this code into the listOfTrip. If I'm doing like this,
List<CharSequence> list = listOfTrips.stream().map(e -> e.getDriverName().subSequence(0, someStringValue.indexOf(' '))).collect(Collectors.toList()); System.out.println(list);
Here, With this, The return type is wrong and it is not fetching only first name out of full name.
Below will give you the proper result:
List<CharSequence> list2 = listOfTrips.stream()
.map(m->m.getDriverName().substring(0,m.getDriverName().indexOf(' ')))
.collect(Collectors.toList());
Please try this also once:
String s = "Rahul Kumar";
Optional<String> beforeWhiteSpace = Pattern.compile(" ").splitAsStream(s).collect(Collectors.toList()).stream().findFirst();

How to know how much of the same structure i have to parse

I am trying to parse this using ANTLR4 :
FSM
name type String
state type State
Relation
name type String
Mathieu
name type String
Someone helped me, corrected my grammar and i got this thanks to him
grammar Generator;
parse
: classToGenerate+ EOF;
classToGenerate
: name=Name attributes+;
attributes
: attribute=Name 'type' type=Name;
Name : [a-zA-Z]+;
Spaces : [ \t\r\n] -> skip;
I am using the parser generated by ANTLR4 this way :
GeneratorLexer l = new GeneratorLexer(new ANTLRInputStream(GeneratorFactory.class.getResourceAsStream("/example.generator")));
GeneratorParser p = new GeneratorParser(new CommonTokenStream(l));
p.addParseListener(new GeneratorBaseListener() {
#Override public void exitClassToGenerate(GeneratorParser.ClassToGenerateContext ctx) {
System.out.println(ctx.name.getText());
}
#Override
public void exitAttributes(GeneratorParser.AttributesContext ctx) {
System.out.println(ctx.type.getText());
System.out.println(ctx.attribute.getText());
}
});
Here is the result after executing
String
name
State
state
FSM
Where is the rest ?
It didn't print Relation name String // Mathieu name String
Any idea ?
EDIT : Okay it seems i was able to print the rest of the files but i've still have something to figure out.
When i do :
p.classToGenerate();
It parses the first structure which results in the print i had.
If i want to find another structure i need to do another
p.classToGenerate();
The thing is, how should i know how much structure i have to parse?
Imagine i have 5 or 20 same structures, how can i know it ?
Thanks !
In your grammar you've called your main rule parse. The rule classToGenerate only matches a single class. So in order to match all classes in the file, you should call p.parse();, not p.classToGenerate();.

Passing an Int and String argument to an arrayList index and String element

import java.util.ArrayList;
public class DataBase {
public ArrayList<String> nameList = new ArrayList<>();
public void nameAdd(String s, int i) {
if (i < nameList.size()){
nameList.add(i, s);
//string not adding to arrayList, ive probably done it wrong.
}
System.out.println(s);
System.out.println("nameList.size = " + nameList.size());
System.out.println("arrayList number = " + i);
}
}
I've been coding for about a month now so please excuse my noobieness but i'm trying to basically take a string from a GUI i've built, cut it up to get a name, and add that name to a "database" when the user clicks another button to add it to it. Ive already been able to increment the i which is supposed to set an index for the string within the arrayList but the arrayList isnt increasing in size and I get a whole bunch of errors thus the if statement ive added to stop it from trying to add to an index that isnt yet in the arrayList.
In your code I see your array nameList always empty.
Because you have this line:
public ArrayList<String> nameList = new ArrayList<>();
In this moment you create your array (empty), but in your nameAdd method if you pass this at the first time:
nameAdd('ADDFIRSTELEMENT', 0)
Your if statemnt is always false
if (i < nameList.size()){
nameList.add(i, s);
//string not adding to arrayList, ive probably done it wrong.
}
You must to change your check as follow:
if (i <= nameList.size())
Because if your index is the same of the size, you can add your element in the array.
If you want you can use the contains method of your nameList ArrayList object so you can see if your string is present in your array

TextField's text does not update, but the other properties do

I have a class with a TextField as a property. This text field is added to the stage and has a digit as a value of the text property. I also have a method, that must change this digit:
public function decrementCooldown()
{
cdText.text = (--cd.value != 0)? cd.value : "";
}
However, it changes nothing. I've modified the code that way:
public function decrementCooldown()
{
cdText.text = (--cd.value != 0)? cd.value : "";
cdText.x -= 100;
}
This caused my text field to move to the left, but its text remained the same.
Then, I've tried to trace the text before and after modifying it. The second line of the output contained the digit that I wanted to appear on screen, it was 1 less than the digit on the first line.
I wonder how to solve my problem.
Ok, this seems really strange to me, but the problem was with DropShadowFilter I had on the TextField.
I've fixed this problem by adding two lines that clear the filters array before modifying the text, then adding a DropShadowFilter again after that:
public function decrementCooldown()
{
cdText.filters = [];
cdText.text = (--cd.value != 0)? cd.value : "";
cdText.filters = [new DropShadowFilter()];
}
Seems like a bug though.

How to get groovy to evaluate ${sth} when stored in string?

I'm getting a text which contains ${somethingElse} inside, but it's just a normal String.
I've got a class:
class Whatever {
def somethingElse = 5
void action(String sth) {
def test = []
test.testing = sth
assert test.testing == 5
}
}
Is it possible with groovy?
EDIT:
my scenario is: load xml file, which contains nodes with values pointing to some other values in my application. So let's say I've got shell.setVariable("current", myClass). And now, in my xml I want to be able to put ${current.someField} as a value.
The trouble is, that the value from xml is a string and I can't evaluate it easily.
I can't predict how these "values" will be created by user, I just give them ability to use few classes.
I cannot convert it when the xml file is loaded, it has to be "on demand", since I use it in specific cases and I want them to be able to use values at that moment in time, and not when xml file is loaded.
Any tips?
One thing you could do is:
class Whatever {
def somethingElse = 5
void action( String sth ) {
def result = new groovy.text.GStringTemplateEngine().with {
createTemplate( sth ).make( this.properties ).toString()
}
assert result == "Number 5"
}
}
// Pass it a String
new Whatever().action( 'Number ${somethingElse}' )
At first, what we did, was used this format in xml:
normalText#codeToExecuteOrEvaluate#normalText
and used replace closure to regexp and groovyShell.evaluate() the code.
Insane. It took a lot of time and a lot of memory.
In the end we changed the format to the original one and crated scripts for each string we wanted to be able to evaluate:
Script script = shell.parse("\""+stringToParse+"\"")
where
stringToParse = "Hello world # ${System.currentTimeMillis()}!!"
Then we were able to call script.run() as many times as we wanted and everything performed well.
It actually still does.

Resources