Eclipse Java AST parser: insert statement before if/for/while - java

I'm using the org.eclipse.jdt parser.
I want to rewrite this code:
public void foo(){
...
...
if(a>b)
...
...
}
into this:
public void foo(){
...
...
System.out.println("hello");
if(a>b)
...
...
}
Supposing that ifnode is an IF_STATEMENT node, I can do something similar to this:
Block block = ast.newBlock();
TextElement siso = ast.newTextElement();
siso.setText("System.out.println(\"hello\");");
ListRewrite listRewrite = rewriter.getListRewrite(block, Block.STATEMENTS_PROPERTY);
listRewrite.insertFirst(ifnode, null);
listRewrite.insertFirst(siso, null);
rewriter.replace(ifnode, block, null);
but this will insert the syso statement at the beginning of the method, while I want it right before the if.
Is there a way to achieve it?

You can use the below code to achieve this (this will add the sysout just before the first IfStatement) :
Block block = ast.newBlock();
TextElement siso = ast.newTextElement();
siso.setText("System.out.println(\"hello\");");
ListRewrite listRewrite = rewriter.getListRewrite(block, CompilationUnit.IF_STATEMENT);
listRewrite.insertFirst(siso, null);
TextEdit edits = rewriter.rewriteAST(document, null);
Also you can limit the scope of rewrite to the IfStatement:
ASTRewrite rewriter = ASTRewrite.create(ifNode.getAST());
Note: code not tested. Do let me know if you find any issues.

Related

adding inner label gives error on string variable

I have a special case in my code where a label would fix possible issues
start:
String zipCodes1 = "90019,90036,90016,90005,90010,90018,90020,90004,90048,90035,90211,90006,90038,90008,90089,90062,90007,90028,90034,90212,90232,90231,90233,90057,90209,90213,90070,90029,90069,90015,90056,90037,90017,90067,90043,90046,90026,90071,90014,90230,90064,90099,90302,90189,90011,90030,90050,90051,90052,90053,90054,90055,90060,90072,90074,90075,90076,90078,90080,90081,90082,90083,90086,90087,90088,90093,90024,90009,90013,90068,90090,90079,90012,90210,90021,90025,90306,90307,90308,90309,90310,90312,90311,90095,90305,91608,90027,90084,90066,90301,90073,90094,90047,91522,91604,90039,90003,90044,91602,90031,91204,91523,90033,90295,90001,90045,90077,91521,90065,90096,90404,90292,90405,90303,90058,90294,90304,90291,91209,91221,91222,91224,91225,91226,91210,91205,90023,91203,91601,91393,91506,91423,90063,90002,90403,90255,91607,91603,91609,91610,91611,91612,91614,91615,91616,91617,91618,90406,90407,90408,90409,90410,90411,90049,91201,91505,91502,90401,90251,90296,90293,91503,91507,91508,91510,91526,90402,91202,90250,91413,90032,90042,90061,90270,90041,91495,90245,91403,91606,90059,90249,91401,91501,91207,91206,91504,90261,90022,90247,91754,90201,90222,90091,90260,91208,91411,91803,90040,91030,91404,91407,91408,91409,91410,91470,91482,91496,91499,90506,90280,91605,90267,90266,90262,91436,91353,91031,91105,90248,91416,91426,91801,90272,91804,90504,90278,90202,91405,91123,91756,90223,90224,91802,91896,91899,91046,91714,91715,91352,91103,91716,91021,91316,91020,91755,90254,91102,91109,91110,91114,91115,91116,91117,91118,91121,91124,91125,91126,91129,91182,91184,91185,91188,91189,90220,91101,91406,91106,90640,91012,90747,91412,91214,91108,90746,91778,91402,91356,90239,90221,90240,91776,90723,90242,91043,90241,90503,90661,90662,90507,90508,90509,90510,91770,91775,91357,91104,90502,91331,91199,90660,90501,91334,91041,90277,91343,90749,91337,91003,91771,91772,91001,91385,91335,91333,90290,90805,90895,90745,91346,91395,90671,91107,91325,90706,90610,91040,90606,91733,91364,91371,91327,91328,91329,91345,90505,91780,91731,90264,91042,91341,91330,90707,90810,91365,91340,91007,91396,90710,91306,90807,90717,90712,90711,90714,90651,90652,91734,91735,91324,90650,91367,91305,91308,91309,91303,90601,91025,91394,90607,90608,90609,90670,91006,91066,91077,90602,91372,91024,91011,91732,90806,91392,90713,90748,90274,90744,91302,90702,90701,91344,90755,91746,90605,91023,90703";
String[] zipArray1 = zipCodes1.trim().split(",");
Random zipIndex1 = new Random();
int randomIndex1 = zipIndex1.nextInt(395);
System.out.println("Zip bad! New zip = "+zipArray1[randomIndex1]+"");
driver.findElement(By.xpath("//android.widget.EditText[#index='0']")).sendKeys(zipArray1[randomIndex1]);
Thread.sleep(750);
driver.pressKey(new KeyEvent(AndroidKey.BACK));
Thread.sleep(1000);
driver.findElement(saveLoc).click();
Thread.sleep(5750);
if (driver.findElements(By.xpath("//*[#text='Check your zip and try again']")).isEmpty()) {
System.out.println("Zip code change successful");
} else {
continue start;
}
}
but right after start on String zipCodes1 it gives me an error saying that:
String cannot be resolved to a variable
and
zipCodes1 cannot be resolved to a variable
why is this happening? is there a way to fix this?
Try doing this
while(true){
String zipCodes1 = "90019,90036,90016,90005,90010,90018,90020,90004,90048,90035,90211,90006,90038,90008,90089,90062,90007,90028,90034,90212,90232,90231,90233,90057,90209,90213,90070,90029,90069,90015,90056,90037,90017,90067,90043,90046,90026,90071,90014,90230,90064,90099,90302,90189,90011,90030,90050,90051,90052,90053,90054,90055,90060,90072,90074,90075,90076,90078,90080,90081,90082,90083,90086,90087,90088,90093,90024,90009,90013,90068,90090,90079,90012,90210,90021,90025,90306,90307,90308,90309,90310,90312,90311,90095,90305,91608,90027,90084,90066,90301,90073,90094,90047,91522,91604,90039,90003,90044,91602,90031,91204,91523,90033,90295,90001,90045,90077,91521,90065,90096,90404,90292,90405,90303,90058,90294,90304,90291,91209,91221,91222,91224,91225,91226,91210,91205,90023,91203,91601,91393,91506,91423,90063,90002,90403,90255,91607,91603,91609,91610,91611,91612,91614,91615,91616,91617,91618,90406,90407,90408,90409,90410,90411,90049,91201,91505,91502,90401,90251,90296,90293,91503,91507,91508,91510,91526,90402,91202,90250,91413,90032,90042,90061,90270,90041,91495,90245,91403,91606,90059,90249,91401,91501,91207,91206,91504,90261,90022,90247,91754,90201,90222,90091,90260,91208,91411,91803,90040,91030,91404,91407,91408,91409,91410,91470,91482,91496,91499,90506,90280,91605,90267,90266,90262,91436,91353,91031,91105,90248,91416,91426,91801,90272,91804,90504,90278,90202,91405,91123,91756,90223,90224,91802,91896,91899,91046,91714,91715,91352,91103,91716,91021,91316,91020,91755,90254,91102,91109,91110,91114,91115,91116,91117,91118,91121,91124,91125,91126,91129,91182,91184,91185,91188,91189,90220,91101,91406,91106,90640,91012,90747,91412,91214,91108,90746,91778,91402,91356,90239,90221,90240,91776,90723,90242,91043,90241,90503,90661,90662,90507,90508,90509,90510,91770,91775,91357,91104,90502,91331,91199,90660,90501,91334,91041,90277,91343,90749,91337,91003,91771,91772,91001,91385,91335,91333,90290,90805,90895,90745,91346,91395,90671,91107,91325,90706,90610,91040,90606,91733,91364,91371,91327,91328,91329,91345,90505,91780,91731,90264,91042,91341,91330,90707,90810,91365,91340,91007,91396,90710,91306,90807,90717,90712,90711,90714,90651,90652,91734,91735,91324,90650,91367,91305,91308,91309,91303,90601,91025,91394,90607,90608,90609,90670,91006,91066,91077,90602,91372,91024,91011,91732,90806,91392,90713,90748,90274,90744,91302,90702,90701,91344,90755,91746,90605,91023,90703";
String[] zipArray1 = zipCodes1.trim().split(",");
Random zipIndex1 = new Random();
int randomIndex1 = zipIndex1.nextInt(395);
System.out.println("Zip bad! New zip = "+zipArray1[randomIndex1]+"");
driver.findElement(By.xpath("//android.widget.EditText[#index='0']")).sendKeys(zipArray1[randomIndex1]);
Thread.sleep(750);
driver.pressKey(new KeyEvent(AndroidKey.BACK));
Thread.sleep(1000);
driver.findElement(saveLoc).click();
Thread.sleep(5750);
if (driver.findElements(By.xpath("//*[#text='Check your zip and try again']")).isEmpty()) {
System.out.println("Zip code change successful");
break;
}
}
From JLS 14.7. Labeled Statements
LabeledStatement:
Identifier : Statement
LabeledStatementNoShortIf:
Identifier : StatementNoShortIf
The Identifier is declared to be the label of the immediately contained Statement.
Unlike C and C++, the Java programming language has no goto statement; identifier statement labels are used with break or continue statements (§14.15, §14.16) appearing anywhere within the labeled statement.
The scope of a label of a labeled statement is the immediately contained Statement.
So you can't use like below:
start:
String zipCodes1 = "..."
One example you can use this with loops like answer by #Shrey Garg

Java Util SQL Parser throws an exception for a correct statement

My statement is
new_call.cdctype=goal.cdctype
When I call the method CCJSqlParser.SQLCondition() on this, I get an exception saying
Encountered " "=" "= "" at line 1, column 17.
Was expecting one of:
"NOT" ...
"LIKE" ...
"ILIKE" ...
"NOT" ...
"NOT" ...
Any insight on why this happens?
I am checking join conditions and I think that this is an appropriate expression for join condition.
Code:
String sql = "new_call.cdctype=goal.cdctype";
CCJSqlParser parser = new CCJSqlParser(new StringReader(sql));
String errorMsg=null;
try {
parser.SQLCondition();
} catch (ParseException e) {
errorMsg=e.getMessage();
}
return errorMsg;
If you dig a bit deeper into JSqlParsers grammer you will find, that a SQLCondition is only one of:
in
between
isnull
exists
like
expression.
You specified a so called RegularCondition.
Here are two methods to parse your condition:
//Shortcut
Expression parseCondExpression = CCJSqlParserUtil.parseCondExpression("new_call.cdctype=goal.cdctype");
System.out.println(parseCondExpression);
//from issue
String sql = "new_call.cdctype=goal.cdctype";
CCJSqlParser parser = new CCJSqlParser(new StringProvider(sql));
try {
parser.RegularCondition();
} catch (ParseException e) {
e.printStackTrace();
}
By the way I am using JSqlParser V1.2. Your version seems a bit older, because the constructor parameter of the parser is now a Provider.

if-else statements are not working properly for Appium Java code

I have written a Java code with if-else statements and user would move from 'Screen1' to 'Screen2' through any of 4 alternate routes and I have attached an image for all possible application flows which are decided on the go by of course code written by developer. Just to add tool used is Appium.
driver.findElement(By.id("----")).click(); //this click will take from 'screen1' to next screen.
if(driver.findElement(By.id("com.abc.rbanking:id/WhatsNew")).isDisplayed())
{ //case if screen A is displayed just after screen 1
MobileElement cross = driver.findElement(By.xpath("//*[#class = 'android.widget.ImageView']"));
cross.click();
Thread.sleep(3000);
}
if(driver.findElement(By.xpath("//android.widget.TextView[#resource-id='com.abc.rbanking:id/text_logo'][text()='Security Question']")).isDisplayed())
{ //case when screen B is displayed Just after screen 1
MobileElement mfaQ = driver.findElement(By.id("com.abc.rbanking:id/MfaQuestionText"));
String question = mfaQ.getText();
String lastword = question.replaceAll("^.*?(\\w+)\\W*$", "$1");
System.out.println(lastword);
MobileElement answer = driver.findElement(By.id("com.abc.rbanking:id/MfaAnswerTextBox"));
answer.sendKeys(lastword);
MobileElement checkbox = driver.findElement(By.id("com.abc.rbanking:id/ShowChallengeAnswerCheckbox"));
checkbox.click();
Thread.sleep(3000);
MobileElement nextb = driver.findElement(By.id("com.abc.rbanking:id/PrimaryButton"));
nextb.click();
Thread.sleep(8000);
}
if(driver.findElement(By.id("com.abc.rbanking:id/WhatsNew")).isDisplayed())
{ //case when screen A is displayed after screen B
MobileElement cross = driver.findElement(By.xpath("//*[#class = 'android.widget.ImageView']"));
cross.click();
Thread.sleep(3000);
}
driver.findElement(By.id("----")); //this is code for 'Screen 2'
What happens is during execution of script, first 'If' is checked and rest all code skipped. I am not able to figure out the issue. Please help.
It sounds here as if (no pun intended) you actually don't want an if else construct. So try just using separate if statements:
// see if element on 'screen A' is displayed
if (driver.findElement(By.id("abc")).isDisplayed()) {
//execute a few statements
}
// see if element on 'Screen B' is displayed
if (driver.findElement(By.id("xyz")).isDisplayed()) {
// execute a few statements
}
// see if element on 'screen A' is displayed
if (driver.findElement(By.id("abc")).isDisplayed()) {
}
driver.findElement(By.id("----")); //this is code for 'Screen 2'
The behavior your describe, namely with the first if being hit and nothing else executing, is precisely how your code should behave. If you intend to allow for each block of code to possibly execute, then what I gave above is one option.
Finally I am able to find a solution for the problem and it is working fine. I put if statement in try-catch block like in below code and it works perfectly fine for every alternative posed by application to the end user.
try {
if (driver.findElement(By.xpath("//android.widget.TextView[#resource-id='com.abc.rbanking:id/text_logo'][text()='Security Question']")).isDisplayed()) { //case when screen B is displayed Just after screen 1
MobileElement mfaQ = driver.findElement(By.id("com.abc.rbanking:id/MfaQuestionText"));
String question = mfaQ.getText();
String lastword = question.replaceAll("^.*?(\\w+)\\W*$", "$1");
System.out.println(lastword);
MobileElement answer = driver.findElement(By.id("com.abc.rbanking:id/MfaAnswerTextBox"));
answer.sendKeys(lastword);
MobileElement checkbox = driver.findElement(By.id("com.abc.rbanking:id/ShowChallengeAnswerCheckbox"));
checkbox.click();
Thread.sleep(3000);
MobileElement nextb = driver.findElement(By.id("com.abc.rbanking:id/PrimaryButton"));
nextb.click();
Thread.sleep(8000);
}
} catch (
Exception e) {
e.printStackTrace();
}
try
{
if (driver.findElement(By.id("com.abc.rbanking:id/WhatsNew")).isDisplayed()) { //case when screen A is displayed after screen B
MobileElement cross = driver.findElement(By.xpath("//*[#class = 'android.widget.ImageView']"));
cross.click();
Thread.sleep(3000);
}
} catch (
Exception e)
{
e.printStackTrace();
}
}

OpenOffice xSentenceCursor stuck at end of paragraph

I am using this routine to iterate over sentences in an OpenOffice document:
while (moreParagraphsOO) {
while (moreSentencesOO) {
xSentenceCursor.gotoEndOfSentence(true);
textSentence = xSentenceCursor.getString();
xTextViewCursor.gotoRange(xSentenceCursor.getStart(), false);
xTextViewCursor.gotoRange(xSentenceCursor.getEnd(), true);
if (!textSentence.equals("")) {
return textSentence;
}
moreSentencesOO = xSentenceCursor.gotoNextSentence(false);
}
moreParagraphsOO = xParagraphCursor.gotoNextParagraph(false);
moreSentencesOO = xSentenceCursor.gotoStartOfSentence(false);
}
It works fine unless it finds a paragraph which ends with ". ", this is, a period and one or several whitespaces after it. In that case it enters and infinite loop executing the
while (moreSentencesOO)
...
moreSentencesOO = xSentenceCursor.gotoNextSentence(false);
endlessly. I am not so proeficient with OpenOffice API, and I am quite stuck here. Any ideas?
Thanks.
EDIT: I have come with a somewhat awkward patch consisting in checking the current position of the cursor, and if it does not advance between two iterations, jump to next paragraph:
while (moreParagraphsOO) {
while (moreSentencesOO) {
/**********************************/
int previousPosX = xTextViewCursor.getPosition().X;
int previousPosY = xTextViewCursor.getPosition().Y;
/*********************************/
xSentenceCursor.gotoEndOfSentence(true);
textSentence = xSentenceCursor.getString();
xTextViewCursor.gotoRange(xSentenceCursor.getStart(), false);
xTextViewCursor.gotoRange(xSentenceCursor.getEnd(), true);
if (!textSentence.equals("")) {
return textSentence;
}
moreSentencesOO = xSentenceCursor.gotoNextSentence(false);
/**********************************/
if (previousPosX == xTextViewCursor.getPosition().X &&
previousPosY == xTextViewCursor.getPosition().Y){
xParagraphCursor.gotoNextParagraph(false);
}
/**********************************/
}
moreParagraphsOO = xParagraphCursor.gotoNextParagraph(false);
moreSentencesOO = xSentenceCursor.gotoStartOfSentence(false);
}
It seems to work, but I am unsure about whether it could introduce future problems. I would rather prefer an "elegant" solution.
According to gotoNextSentence(), it should only return true if the cursor was moved, so this is a bug. Consider filing a report.
The problem seems to occur when isEndOfSentence() but not isStartOfSentence(). So test for that instead of getPosition().
Here is Andrew Pitonyak's Basic macro that I modified to include this fix.
Sub CountSentences
oCursor = ThisComponent.Text.createTextCursor()
oCursor.gotoStart(False)
Do
nSentences = nSentences + 1
If oCursor.isEndOfSentence() And Not oCursor.isStartOfSentence() Then
oCursor.goRight(1, False)
End If
Loop While oCursor.gotoNextSentence(False)
MsgBox nSentences & " sentences."
End Sub

Java JEditorPane - Trying to edit an html tag value and getting Exception

I have a JEditorPane and I'm trying to edit one fo the html element attributes, basically changing the the src x value in to a custom value
The code I have is:
// Get <img src="..."> tag
RunElement imageTagElement = getImageTagElement(htmlDocument);
// Print src attribute value
System.out.println("src : " + runElement.getAttribute(HTML.Attribute.SRC));
// Replace existing src value
runElement.removeAttribute(HTML.Attribute.SRC);
runElement.addAttribute(HTML.Attribute.SRC, "customValue");
I get the following exception in the before last line when I try to remove the existing attribute (because you can't replace):
javax.swing.text.StateInvariantError: Illegal cast to MutableAttributeSet
I read a few places that you can use writeLock, but that's a protected method, which means I can't call it from this code...
So basically my question is that if you've found the element you want, how do you edit it's attributes?
The problem is that HtmlDocument requires you perform a writeLock before trying to change any attributes and a writeUnlock after. So to solve this I had to:
First extend the EditorKit for my JEditorPane to use a custom HtmlDocument. Then I extended the HTMLDocument to make the writeLock and writeUnlock publicly accesible:
public class ExtendedHTMLDocument extends HTMLDocument
{
public void hackWriteLock()
{
writeLock();
}
public void hackWriteUnlock()
{
writeUnlock();
}
}
Then I did:
public class ExtendedEditorKit extends HTMLEditorKit
{
#Override
public Document createDefaultDocument()
{
// For the left out code copy what's in the super method
..
HTMLDocument doc = new ExtendedHTMLDocument(ss);
..
}
}
Now I could in code above, all I have to do is call the lock before trying to edit the attributes, and unlock when I'm done:
// lock
htmlDocument.hackWriteLock()
// Get <img src="..."> tag
RunElement imageTagElement = getImageTagElement(htmlDocument);
// Print src attribute value
System.out.println("src : " + runElement.getAttribute(HTML.Attribute.SRC));
// Replace existing src value
runElement.removeAttribute(HTML.Attribute.SRC);
runElement.addAttribute(HTML.Attribute.SRC, "customValue");
// unlock
htmlDocument.hackWriteUnlock()
And everything works as expected. I'm able to modify and edit the attributes in the document.
I guess what I now don't fully understand or appreciate is why you can't access the writeLock and writeUnlock publicly? Why have they been setup as protected? What where the programmers trying to prevent you from doing and why?
## Use the htmlDoc.setCharacterAttributes (...);##
ElementIterator it = new ElementIterator(htmlDoc);
Element elem;
while ((elem = it.next()) != null) {
if (elem.getName().equals("img")) {
AttributeSet atts = elem.getAttributes();
// Modifiable
SimpleAttributeSet simple = new SimpleAttributeSet(atts);
String s = (String) simple.getAttribute(HTML.Attribute.SRC);
if (s != null) {
System.out.println(s); // testing
int len = elem.getEndOffset() - elem.getStartOffset();
//simple.removeAttribute(HTML.Attribute.SRC);
simple.addAttribute( HTML.Attribute.SRC, **newSRC_URL_String** );
//
// The doc takes care of the locks
//
htmlDoc.setCharacterAttributes(
elem.getStartOffset(),len,simple,true);
}
}
}

Categories

Resources