Replace variables in text: Suggestions? - java

I'm looking for a nice template engine or short piece of code to expand Ant-like variables in a string in Java. Example:
String result = expand ("${firstName} ${familyName}", map);
It should at least support java.util.Map but something that can handle beans or recursive lookups or lookups in a list of maps/objects would be welcome, too.
Suggestions?
[EDIT] In reply to TofuBeer: No nesting, only valid Java identifiers within the {}. Anything outside of ${} should be copied verbatim. $$ should become $``. If that's not possible ${dollar} should expand to a single $ (so you can express 15.00 $).

StrSubstitutor from Commons Lang does pretty much what you're asking for

use StringTemplate in order to implement expand:
void expand(String template, Map<String,String> map) {
StringTemplate st = new StringTemplate(template);
for (Map.Entry<String, String> attribute : map) {
st.setAttribute(attribute.getKey(), attribute.getValue());
}
return st.toString();
}

Have a look at Freemarker och Velocity, both of them are template engines

Related

Is there anyway to convert emoji to text in Java?

๐Ÿ˜ how can I convert emojis like this to text? I mean to convert a happy face to the words "happy" and so on. Using Java, how can I achieve this?
You may use emoji4j library.
String text = "A ๐Ÿฑ, ๐Ÿถ and a ๐Ÿญ became friendsโค๏ธ. For ๐Ÿถ's birthday party, they all had ๐Ÿ”s, ๐ŸŸs, ๐Ÿชs and ๐Ÿฐ.";
EmojiUtils.shortCodify(text); //returns A :cat:, :dog: and a :mouse: became friends:heart:. For :dog:'s birthday party, they all had :hamburger:s, :fries:s, :cookie:s and :cake:.
Since that emoji is simply a standard Unicode code point (U+1F601, see here), probably the best way is to set up a map which translates them into strings.
By way of example, here's a piece of code that creates a string-to-string map to allow you to look up and translate that exact code point:
import java.util.HashMap;
import java.util.Map;
class Xyzzy {
public static Map<String,String> xlat = new HashMap<String, String>();
public static void main (String[] args) {
xlat.put("\uD83D\uDE01", "happy");
System.out.println(xlat.get("\uD83D\uDE01"));
}
}
You can add as many code points to the map as you wish, and use Map.get() to extract the equivalent text for any of them.

Use fields in one tuplestream as part of regex in RegexParser on second tuplestream

I'm trying to read in a csv in the hdfs, parse it with cascading, and then use the resulting tuple stream to form the basis of regex expressions in another tuple stream using RegexParser. As far as I can tell, the only way to do this would be to write a custom Function of my own, and I was wondering if anybody knew how to use the Java API to do this instead.
Pointers on how to write my own function to do this inside the cascading framework would be welcome, too.
I'm running Cascading 2.5.1
The best resource for this question is the Palo Alto cascading example tutorial. It's in java and provides examples of a lot of use cases, including writing custom functions.
https://github.com/Cascading/CoPA/wiki
And yes, writing a function that allows an input regex that references other argument inputs is your best option.
public class SampleFunction extends BaseOperation implements Function
{
public void operate( FlowProcess flowProcess, FunctionCall functionCall )
{
TupleEntry argument = functionCall.getArguments();
String regex = argument.getString( 0 );
String argument = argument.getString( 1 );
String parsed = someRegexOperation();
Tuple result = new Tuple();
result.add( parsed );
functionCall.getOutputCollector().add( result );
}
}

Parsing text in parens using JParsec

I'm writing a parser for a DSL that uses the syntax (nodeHead: nodeBody). The problem is that nodeBody may contain parens, at some cases.
The between operator of JParsec should have been a good solution, yet the following code fails:
public void testSample() {
Parser<Pair<String,String>> sut = Parsers.tuple(Scanners.IDENTIFIER.followedBy(Scanners.among(":")),
Scanners.ANY_CHAR.many().source()
).between(Scanners.among("("), Scanners.among(")"));
sut.parse("(hello:world)");
}
It does not fail when I change ANY_CHAR to IDENTIFIER, so I assume the issue here is that the second parser in the tuple is too greedy. Alternatively, can I make JParsec apply the between parsers before it applies the body?
Any ideas are very much appriciated.
At the time I was asking, seems like there was no way to do that. However, a github fork-and-pull later, there is: reluctantBetween().
Big thanks to #abailly on the fast response.
If the syntax rule is that the last character will always be ")", you could probably do:
static <T> Parser<T> reluctantBetween(
Parser<?> begin, Parser<T> parser, Parser<?> end) {
Parser<?> terminator = end.followedBy(eof());
return between(begin, terminator.not().next(parser).many(), terminator);
}

Not able to create SimpleName for '.class' string pattern

Having a problem with the ast.newSimpleName() method.
I am not able to create a SimpleName of the sort 'SomeJava.class'. But the method works fine for names like 'SWT.None' or 'SomeJava.None'.
Here is the code :
MethodInvocation loggerInstance = ast.newMethodInvocation();
loggerInstance.setExpression(ast.newSimpleName("Logger"));
loggerInstance.setName(ast.newSimpleName("getLogger"));
String[] name1 = {className.replace(".java", ""),"None"};
String[] name2 = {className.replace(".java", ""), "class"};
loggerInstance.arguments().add(ast.newName(name1)); // This works
loggerInstance.arguments().add(ast.newName(name2)); // This doesn't
Should i use any thing else other than SimpleName for this. Thanks in advance.
Edit : This is the statement i want to construct:
Logger.getLogger(ClientTest.class);
During my analysis, i found out that the problem arises when using the "class" literal. Not sure how to overcome this.
ast.newName("class");
ast.newSimpleName("class");
Use ASTView plugin (http://www.eclipse.org/jdt/ui/astview/index.php) to see what is the type of node for 'ClientTest.class' and then construct that type of node.
Got it from ASTView. Finally downloaded and installed it. :)
It should be a generated as a TypeLiteral, not as a SimpleName/Name.
TypeLiteral typeLiteral = ast.newTypeLiteral();
typeLiteral.setType(ast.newSimpleType(ast.newSimpleName(className)));

How to pull variables out of a string

I'm looking for a Java class that for a given string "the ${animal} jumped over the ${target}." is able to pull out the variable names, ie 'animal' and 'target'.
I had hoped StrSubstitutor in Commons Lang had a method
getVariables(String str) : List<String>
... but no such luck.
Yes I could write this myself, but I'm certain there must be a 3rd party library that exists out there that does this.
You could just do a simple regex match if you really just want to pull out those values and avoid the dependency of an entire library:
public List<String> getVariableNames(String source) {
List<String> vs = new ArrayList<String>();
Pattern p = Pattern.compile("\\$\\{(\\w+)\\}");
Matcher m = p.matcher(source);
while (m.find()) {
vs.add(m.group(1));
}
return vs;
}
Storing the pattern as a member variable will improve performance.
Actually I was also looking for a similar library while developing DSL Adapter for my GenericFixture.
After looking at some libraries and template based framework I eventually decided to write code by myself. Feel free to check the code I used for this purpose in DSLAdapter class from GenericFixture available on sourceforge.

Categories