Replace only part of a string with velocity - java

I found no way to replace only parts of a string with velocity.
Assume the following velocity template:
$test
something$test
$test.something
I want to replace all occurrences of $test with the string TEST.
I therefore use the following code:
VelocityContext context = new VelocityContext();
context.put("test", "TEST");
This is the result, I expect:
TEST
somethingTEST
TEST.something
But what I really get is:
TEST
somethingTEST
$test.something
So obviously Velocity doesn't replace a variable if there is some text after the variables name.
What can I do to replace a variable even if it is only a part of a string?

The $test.something is causing the problem.
It is expecting a variable something inside the object test.
Use ${test}.something instead...
--Cheers, Jay

The problem you face here is not 'obviously Velocity doesn't replace a variable if there is some text after the variables name'.
The symbol '$' is used to represent beginning of any line. So you have to find a way to escape that symbol in the input string so that the literal meaning of '$' is not considered

Related

Is there any way to find out an argument passed to a jar was quoted?

I'm trying to pass a number of arguments to my Java application, but I would like to parse them by myself using an intelligent parser that doesn't just rely on whitespace to separate the arguments. An example:
/update source=foo func=(bar, foo ,foo,bar)
This all works nicely by converting everything to tokens and then parse those. However, a problem occurs when I add:
path="./foo/bar/foo bar.txt"
(note the double space between foo and bar).
When I use double quotes, the argument is passed as a single string, preserving the double space. The quotation marks are removed though like this:
path=./foo/bar/foo bar.txt
which makes my parser fail. But when I try to use some other character to use as quotes, like ', the parser works fine but then the shell passes the string as two separate strings, separated at the double space, therefore I lose the information that there were two spaces there.
What can I do to pass an argument using double quotes to keep the literal string representation, but also keep the information that the string was quoted, without the user having to type weird constructions like "'string'"? I'm using Java, maybe there is a way to get the entire line of arguments unparsed by the shell? Or just without the quotes being removed?
Btw, I ran this from microsoft command line, haven't tried a unix shell yet, which might even fail on the single quotes from what I read on the interwebs
On the Windows command line (using cmd.exe), you can escape double quotes with \". For example,
java MyApp path=\"./foo/bar/foo bar.txt\"
will result in
args[0] = path="./foo/bar/foo
args[1] = bar.txt"
while
java MyApp path="\"./foo/bar/foo bar.txt\""
will give you
args[0] = path="./foo/bar/foo bar.txt"
Thanks for the help I got, but I already figured it out:
I know the thing that could be quoted doesn't contain brackets, comma's or equals signs, the things that my parser recognizes.
I know that IF something was quoted and it contained spaces, those spaces would still exist within the split argument.
I know that the original string of arguments is split at every region of whitespace, so the final split arguments don't contain spaces, only those in the quoted parts.
Therefore I can assume that if I parse a split argument, that any space in there does not imply a new token has to be generated, therefore it is retained in the final string-token.
I just have to rewrite my tokenizer now to accept an array of arguments instead of the concatenated string I now create from the args array I get passed in my main() method. That way I can differentiate between skipping real whitespace (going into the next element of the array) and quoted whitespace (any other whitespace).

Elegant way to do variable substitution in a java string

Pretty simple question and my brain is frozen today so I can't think of an elegant solution where I know one exists.
I have a formula which is passed to me in the form "A+B"
I also have a mapping of the formula variables to their "readable names".
Finally, I have a formula parser which will calculate the value of the formula, but only if its passed with the readable names for the variables.
For example, as an input I get
String formula = "A+B"
String readableA = "foovar1"
String readableB = "foovar2"
and I want my output to be "foovar1+foovar2"
The problem with a simple find and replace is that it can be easily be broken because we have no guarantees on what the 'readable' names are. Lets say I take my example again with different parameters
String formula = "A+B"
String readableA = "foovarBad1"
String readableB = "foovarAngry2"
If I do a simple find and replace in a loop, I'll end up replacing the capital A's and B's in the readable names I have already replaced.
This looks like an approximate solution but I don't have brackets around my variables
How to replace a set of tokens in a Java String?
That link you provided is an excellent source since matching using patterns is the way to go. The basic idea here is first get the tokens using a matcher. After this you will have Operators and Operands
Then, do the replacement individually on each Operand.
Finally, put them back together using the Operators.
A somewhat tedious solution would be to scan for all occurences of A and B and note their indexes in the string, and then use StringBuilder.replace(int start, int end, String str) method. (in naive form this would not be very efficient though, approaching smth like square complexity, or more precisely "number of variables" * "number of possible replacements")
If you know all of your operators, you could do split on them (like on "+") and then replace individual "A" and "B" (you'd have to do trimming whitespace chars first of course) in an array or ArrayList.
A simple way to do it is
String foumula = "A+B".replaceAll("\\bA\\b", readableA)
.replaceAll("\\bB\\b", readableB);
Your approach does not work fine that way
Formulas (mathematic Expressions) should be parsed into an expression structure (eg. expression tree).
Such that you have later Operand Nodes and Operator nodes.
Later this expression will be evaluated traversing the tree and considering the mathematical priority rules.
I recommend reading more on Expression parsing.
Matching Only
If you don't have to evaluate the expression after doing the substitution, you might be able to use a regex. Something like (\b\p{Alpha}\p{Alnum}*\b)
or the java string "(\\b\\p{Alpha}\\p{Alnum}*\\b)"
Then use find() over and over to find all the variables and store their locations.
Finally, go through the locations and build up a new string from the old one with the variable bits replaced.
Not that It will not do much checking that the supplied expression is reasonable. For example, it wouldn't mind at all if you gave it )A 2 B( and would just replace the A and B (like )XXX 2 XXX(). I don't know if that matters.
This is similar to the link you supplied in your question except you need a different regular expression than they used. You can go to http://www.regexplanet.com/advanced/java/index.html to play with regular expressions and figure out one that will work. I used it with the one I suggested and it finds what it needs in A+B and A + (C* D ) just fine.
Parsing
You parse the expression using one of the available parser generators (Antlr or Sable or ...) or find an algebraic expression parser available as open source and use it. (You would have to search the web to find those, I haven't used one but suspect they exist.)
Then you use the parser to generate a parsed form of the expression, replace the variables and reconstitute the string form with the new variables.
This one might work better but the amount of effort depends on whether you can find existing code to use.
It also depends on whether you need to validate the expression is valid according to the normal rules. This method will not accept invalid expressions, most likely.

Java Code Conventions: must match pattern '^[a-z][a-zA-Z0-9]*$'

i would like to use the following constant:
final String ADD = "Add text";
But my CheckStyle tool tells me that 'ADD' does not match the pattern '^[a-z][a-zA-Z0-9]*$'.
Could anyone please tell me what is wrong with 'ADD'?
Means '^[a-z][a-zA-Z0-9]*$' that every name has to start with a low character?
Is there no other possibility?
Thanks for answers.
^[a-z][a-zA-Z0-9]*$
This regex describes something which starts with lowercase and the remainder is composed of uppercase, lowercase, and numbers. (Examples: aVariable, variable, aNewVariable, variable7, aNewVariable7.)
If you want your field to be constant and static, use:
static final String ADD = "Add text";
Otherwise, use:
final String add = "Add text";
If it is a constant you want, it should also be static
static final String ADD = "Add text";
Constants normally use uppercase letters, but since your variable was not static, it was not interpreted as a constant.
This Regex indicate the need for camelCase with the first letter being small and then every next word having the first letter in it as capital letter.
I just ran into the same problem, turns out it was because it is expected for the Java codebase I was working on to use camel case for all variables as the naming convention. So be sure to check if your variables are named according to the regex pattern ^[a-z]([a-z0-9][a-zA-Z0-9]*)?$. In my case, I got stuck in the Python mode and had my variable named version_regex instead of versionRegex. Once I have made the needed correction the error is no longer thrown.

Need a little help on this regular expression

I have a Java string which looks like this, it is actually an XML tag:
"article-idref="527710" group="no" height="267" href="pc011018.pct" id="pc011018" idref="169419" print-rights="yes" product="wborc" rights="licensed" type="photo" width="322" "
Now I want to remove the article-idref="52770" segment by using regular expression, I came up with the following one:
trimedString.replaceAll("\\article-idref=.*?\"","");
but it doesn't seem to work, could anybody give me an idea on where I got wrong in my regular expression? I need this to be represented as a String in my Java class, so probably HTMLParser won't help me a lot here.
Thanks in advance!
Try this:
trimedString.replaceAll("article-idref=\"[^\"]*\" *","");
I corrected the regular expression by adding quotes and a word boundary (to prevent false matches). Also, in case you didn't, remember to reassign to your string after the replacement:
trimmedString = trimmedString.replaceAll("\\barticle-idref=\".*?\"", "");
See it working at ideone.
Also since this is from an XML document it might be better to use an XML parser to extract the correct attributes instead of a regular expression. This is because XML is quite a complex data format to parse correctly. The example in your question is simple enough. However a regular expression could break on a more complex case, such as a document that includes XML comments. This could be an issue if you are reading data from an untrusted source.
if you are sure the article-idref is allways at the beginning try this:
// removes everything from the beginning to the first whitespace
trimedString = trimedString.replaceFirst("^\\s","");
Be sure to assign the result to trimedString again, since replace does not midify the string itself but returns another string.

Java Inner Text (getTextContents()) Problem

I'm trying to do some parsing in Java and I'm using Cobra HTML Parser to get the HTML into a DOM then I'm using XPath to get the nodes I want. When I get down to the desired level I call node.getTextContents(), but this gives me a string like
"\n\n\nValue\n-\nValue\n\n\n"
Is there a built in way to get rid of the line breaks? I would like to do a RegEx like
(?:\s*([^-]+)\s*-\s*([^-]+)\s*)
on the inner text and would really prefer not to have to deal with the possible different white space symbols in between the text.
Example Input:
Value
-
Value
Thanks
You can use String.replaceAll().
String trimmed = original_string.replaceAll("\n", "");
The first argument is a regular expression: you could replace all contiguous blocks of whitespace in the original string with replaceAll("\\s+", "") for instance.
I'm not totally sure I understood the question correctly, but the simplest way to remove all the whitespace would be:
String s = node.getTextContents().replaceAll("\\s","");
If you just want to get rid of the leading/trailing whitespace, use trim().

Categories