Can someone explain why this does not work ?
StringTemplate query = new StringTemplate("hello " +
"$if(param==\"val1\")$" +
" it works! " +
"$endif$ " +
"world");
query.setAttribute("param", "val1");
System.out.println("result: "+query.toString());
It throws
eval tree parse error
:0:0: unexpected end of subtree
at org.antlr.stringtemplate.language.ActionEvaluator.ifCondition(ActionEvaluator.java:815)
at org.antlr.stringtemplate.language.ConditionalExpr.write(ConditionalExpr.java:99)
ST doesn't allow computation in the templates. That would make it part of the model.
You can't compare strings inside stringtemplate, unfortunately, but you can send a result of such a comparison into template as a parameter:
StringTemplate query = new StringTemplate("hello " +
"$if(paramEquals)$" +
" it works! " +
"$endif$ " +
"world");
query.setAttribute("paramEquals", param.equals("val1"));
System.out.println("result: "+query.toString());
It might not be what you're looking for, since every time you need to add a comparison you have to pass an extra parameter, and for loops it's even worse. But this is one workaround that may work for simple cases.
Related
I need to remove all types of comments from my string without affecting the URL defined in that string. When i tried removing comments from string using regular expression some part of the URL also removed from the string.
I tried the following regex but the same issue happening.
String sourceCode= "/*\n"
+ " * Multi-line comment\n"
+ " * Creates a new Object.\n"
+ " */\n"
+ "public Object someFunction() {\n"
+ " // single line comment\n"
+ " Object obj = new Object();\n"
+ " return obj; /* single-line comment */\n"
+ "}"
+ "\n"
+ "https://stackoverflow.com/questions/18040431/remove-comments-in-a-string";
sourceCode=sourceCode.replaceAll("//.*|/\\*((.|\\n)(?!=*/))+\\*/", "");
System.out.println(sourceCode);
but anyway the comments are removed but the out put is showing like this
public Object someFunction() {
Object obj = new Object();
return obj;
}
https:
please help me to find out a solution for this.
[^:]//.*|/\\*((.|\\n)(?!=*/))+\\*/
Changes are in first few characters - [^:]. This means that symbol before // must be not :.
I usually use regex101.com to work with regular expressions. Select python language for your case (since languages use a little bit different escaping).
This is quite complex regexp to be read by human, so another solultion may be in using several simple expressions and process incoming text in multiple passes. Like
Remove one-line comments
Remove multiline comments
Process some special cases
Note: Processing regexp costs pretty much time. So if performance is required, you should check for another solution - your own processor or third-party libraries.
EDITED
As suggested #Wiktor expression [^:]//.*|/\\*((?!=*/)(?s:.))+\\*/ is faster solution. At least 2-3 times faster.
You can split your String by "\n" and check each line. Here is the tested code:
String sourceCode= "/*\n"
+ " * Multi-line comment\n"
+ " * Creates a new Object.\n"
+ " */\n"
+ "public Object someFunction() {\n"
+ " // single line comment\n"
+ " Object obj = new Object();\n"
+ " return obj; /* single-line comment */\n"
+ "}"
+ "\n"
+ "https://stackoverflow.com/questions/18040431/remove-comments-in-a-string";
String [] parts = sourceCode.split("\n");
System.out.println(getUrlFromText(parts));
Here is the fetching method:
private static String getUrlFromText(String []parts) {
for (String part : parts) {
if(part.startsWith("http")) {
return part;
}
}
return null;
}
For more specific this EXP should be use
.*[^:]//.*|/\\*((.|\\n)(?!=*/))*\\*/
Your provided pattern was not able to remove /**/ portion of code if it is there.(If it is special requirement then its fine)
So Your EXP is like :
And it should be:
For more understanding visit and use your EXP .*[^:]\/\/.*|\/\*((.|\n)(?!=*\/))*\*\/ it will show you graph for that.
I am trying to implement a functionality in android app where as user keys in the numbers, I want to incrementally search those numbers in Phone book (the generic phone book search) and display result.
For this, I am using
Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(aNumber));
This seems to work for most of the cases and is handling search for ' ' etc.
There are 2 issues that I am not able to resolve :
It does not ignore the country code.
So as an e.g. if I have a number : +9199776xx123
When my search string is +9199, the result comes up. While if my search string is 9977, it does not come up.
It does not search from between.
When my search string is 776, then also result does not come up.
So the behavior of CONTENT_FILTER_URI of Phone is not exactly clear to me.
P.S. : I have tried PhoneLookup but for some reason, it does not throw any result. My belief is that it might not be capable to searching partial numbers.
After quite a lot or research, I was able to find the answer. Now, I search on both the columns, Number and normalized number. This takes care of both the cases since normalized number contains country code in the number.
My selection string looks like :
String selection = ContactsContract.CommonDataKinds.Phone.NUMBER + " LIKE ? OR "
+ ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER + " LIKE ?";
Phone.CONTENT_FILTER_URI is built for speed, but it's not perfect, as you've noticed.
You can use the plain Phone.CONTENT_URI to process any kind of request you want.
e.g.:
String partialPhone = "9977";
String[] projection = new String[] {Phone.DISPLAY_NAME, Phone.NUMBER, Phone. NORMALIZED_NUMBER};
String selection = "(" + Phone.NUMBER + " LIKE %" + partialPhone + "%) OR (" + Phone.NORMALIZED_NUMBER + " LIKE %" + partialPhone + "%)";
Cursor c = cr.query(Data.CONTENT_URI, projection, selection, null, null);
I created this Java method:
public String isInTheList(List<String> listOfStrings)
{
/*
* Iterates through the list, and if the list contains the input of the user,
* it will be returned.
*/
for(String string : listOfStrings)
{
if(this.answer.matches("(?i).*" + string + ".*"))
{
return string;
}
}
return null;
}
I use this method in a while block in order to validate user input. I want to check if that input matches the concatenation of two different predefined ArrayLists of Strings.
The format of the input must be like this:
(elementOfThefirstList + " " + elementOfTheSecondList)
where the Strings elementOfThefirstList and elementOfTheSecondList are both elements from their respective list.
for(int i = 0; i < firstListOfString.size(); i++)
{
if(userInput.contains(firstListOfString.get(i) + " " + userInput.isInTheList(secondListOfString)))
{
isValid = true;//condition for exit from the while block
}
}
It work if the user input is like this:
elementOfThefirstList + " " + elementOfTheSecondList
However, it will also work if the user input is like this:
elementOfThefirstList + " " + elementOfTheSecondList + " " + anotherElementOfTheFirstList
How can I modify my regular expression, as well as my method, in order to have exactly one repetition of elements in both lists concatenated with a space between them?
I tried with another regular expression and I think that I will use this: "{1}". However, I am not able to do that with a variable.
With the information you provide as to how you are getting this issue, there is little that can be said about how to fix it. I strongly encourage you to look at this quantifiers tutorial before moving forward.
Let's look at some solutions.
For example, lets look at the line:if(this.answer.matches("(?i).*" + string + ".*"))What you are trying to do is to see if this.answer contains string, ignoring case (I doubt you need the last .*). But you are using a Greedy Quantifier to compare them. If the issue is arising due to an input error in this comparison, I would consider looking at the linked tutorial for Reluctant Quantifiers.
Okay, so it wasn't a quantifier issue. The other possible fix may be this block of code:
for(int i = 0; i < firstListOfString.size(); i++)
{
if(userInput.contains(firstListOfString.get(i) + " " + userInput.isInTheList(secondListOfString)))
{
isValid = true;//condition for exit from the while block
}
}
I don't know you you got userInput to have the containsmethod, but I assume that you used containment to call the String method. If this is the case, there could be a solution to the issue. You would only have to state that it is valid if and only if it is equal to an element from the first list and a matching element from the second string.
The final solution I have for you is simple. If there are no other spaces present within the list elements, you could split the concatenated String on a space and check how many elements the resulting array contains. If it is greater than two, then you have an invalid concatenation.
Hopefully this helps!
See the below code snippet:
int count = 0;
String query = "getQuery";
String query1 = "getQuery";
final String PARAMETER = "param";
query += "&" + PARAMETER + "=" + String.valueOf(count);
query1 += "&" + PARAMETER + "=" + count;
System.out.println("Cast to String=>"+query);
System.out.println("Without casting=>"+query1);
Got the both output exactly same. So I am wondering why this has been used when we can get the same result by using only count.
I got some link but did not found exactly same confusion.
This is well explained in the JLS - 15.18.1. String Concatenation Operator +:
If only one operand expression is of type String, then string conversion (ยง5.1.11) is performed on the other operand to produce a string at run time.
You should note the following:
The + operator is syntactically left-associative, no matter whether it
is determined by type analysis to represent string concatenation or
numeric addition. In some cases care is required to get the desired
result.
If you write 1 + 2 + " fiddlers" the result will be
3 fiddlers
However, writing "fiddlers " + 1 + 2 yields:
fiddlers 12
Java compiler plays a little trick when it sees operator + applied to a String and a non-string: it null-checks the object, calls toString() on it, and then performs string concatenation.
That is what's happening when you write this:
query1 += "&" + PARAMETER + "=" + count;
// ^^^ ^^^^^^^^^ ^^^
You can certainly do this when the default conversion to String is what you want.
However, if you do this
String s = count; // <<== Error
the compiler is not going to compile this, because there is no concatenation. In this situation you would want to use valueOf:
String s = String.valueOf(count); // <<== Compiles fine
String.valueOf(int) actually calls Integer.toString().
So, it is used to convert an int to a String elegantly. As, doing i+"" is IMNSHO, not quite elegant.
Moreover, when you print any number directly, it actually calls the toString() method of its Wrapper class, and the prints the string.
I need to compare two strings.
The input value is like
SELECT * FROM ds WHERE ds.age='24';
The text against which it needs to be compared being
SELECT * FROM ds WHERE ds.status='VALID' AND ds.age='24';
Since "ds.status='VALID' AND" is a static string, I thought of inserting it into the input and then compare it with the original string.
So I created a StringBuilder object and
query.insert(query.indexOf("WHERE"), "ds.status='VALID' AND");
but the output was
SELECT * FROM ds ds.status='VALID' AND WHERE ds.age='24';
Also, indexOf() cannot be inputted with a static position since it can vary with the input.
Is there any way to find the index of the last letter of the word "WHERE"?
The work-around I found is
String query = query.replace("WHERE", "WHERE ds.status='VALID' AND");
Is this the best possible method?
query.insert(query.indexOf("WHERE") + "WHERE".length(), " ds.status='VALID' AND");
I think the replace is a lot cleaner and easier to read - like Peter Lawrey's comment:
query.replace(" WHERE ", " WHERE ds.status='VALID' AND ");
No having to worry about fencepost errors or magic numbers and so much clearer in intent!
EDIT
That would be:
query.toString().replace(" WHERE ", " WHERE ds.status='VALID' AND ");
(Replace on StringBuilder takes indexes)
You can do something like this -
StringBuffer str = new StringBuffer("SELECT * FROM ds WHERE ds.age='24'");
str.insert(str.lastIndexOf("WHERE") + 6, "ds.status='VALID' AND ");