Using String.format with RPGLE - java

I would like to interface RPGLE with String.format which takes variable length arguments or an array, I also want to pass numbers as well as strings, so I will be using format like "hello %s, you are %d years old". Can someone give me some advide on how to prototype this in RPGLE?
UPDATE
It seems that some people were confused with the quesion. To make things clear, I want to prototype the following in RPGLE. Note that the second argument to the method is a varargs parameter, so any number of arguments can be supplied! RPGLE definitely does not support this, but it does support *nopass so this my be helpful in achieving the result I need.
String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
System.out.format(format, "FirstName", "Init.", "LastName");
or
String.format(format, "FirstName", "Init.", "LastName");
I am not interested in how I can format strings in RPGLE, I want to prototype a java method.

How about using message's to do the formatting ... they are quite powerful and the text is externalized (and CCSID aware).
You can use the QMHRTVM API to retrieve the formatted message.
When you're in RPG code, it's always faster to invoke native functionality than Java.

Is there a particular reason you want to use Java? The overhead of starting up a JVM can be killer on many applications. RPG itself can do that easily using concatenation.
/free
resultString = 'hello ' + %trim(name) + ', you are ' +
%trim(%char(years)) + ' years old';
/end-free

Related

Are there other ways to concatenate inofrmation when I am going to print other than +, like System.out.println("hello" + etc + variable))

Before I learnt the basics in python and there are several ways to concatenate information like:
name = "Eduardo"
surname = "Garcia"
print("Hello " + name + " " + surname)
print("Hello {} {}".format(name, surname))
I like this one
print(f"Hello {name} {surname}")
But I am making a course in java and the teacher says that the only way to do it is with +
But that sounds strange to me. Are there other ways to do it like in python with .format or f.
Thank you.
I am learning the basics in java. I just want to understand how it works.
Java has System.out.printf, which is more-or-less (not exactly) like every other printf that's out there (see documentation).
The String class has String.format (see documentation).
With respect to what your teacher tells you - literally, they are correct. Formatting is not concatenation; however, to achieve a particular result, you can often choose between formatting and concatenation.

String with EX, EEX, EXP or EE scientific notation to double

In my code I am receiving numeric values as strings from different sources. One of the source is sending me this kind of value:
-6.535402781EX-05
After few tests I know that EX format is not handled by Double.valueOf() method. NumberFormatException is thrown.
I figured out easy workaround:
String val = "-6.535402781EX-05".replace("X", "");
Actually it is working, but I am not sure if that's best solution. I saw also EEX, EE and EXP. Question: How to protect my code for this kind of edge cases?
You may want to use replaceAll witha regex instead of replace if those are the only possible values:
String[] val = {"-6.535402781EX-05","-6.535402781EEX-05","-6.535402781EE-05","-6.535402781EXP-05"};
for(String v :val){
System.out.println(v.replaceAll("[EXP]{2,}", "E"));
}
Would a simple regular expression do the trick for you? You could first convert the different input formats to your known input format that can be handled by Double.valueOf().
String pattern = "(\\D?)(\\d+)(\\.?)(\\d+)(\\D+)(\\d+)";
List<String> inputs = Arrays.asList("-6.535402781EX-05",
"-6.535402781EXP-05",
"-6.535402781EE-05",
"-6.535402781E-05",
"6.535402781E-05",
"6.535402781",
"-6.535402781",
"6.5",
"6");
inputs.forEach((String in) -> System.out.println(in.replaceAll(pattern, "$1$2$3$4E-$6")));
The inputs in my example should be converted to the following and parsing them should be possible with Double.valueOf().
-6.535402781E-05
-6.535402781E-05
-6.535402781E-05
-6.535402781E-05
6.535402781E-05
6.535402781
-6.535402781
6.5
6
You should be careful to add enough unit test cases for all input formats you want to support.

How to store mathematical formula in MS SQL Server DB and interpret it using JAVA?

I have to give the user the option to enter in a text field a mathematical formula and then save it in the DB as a String. That is easy enough, but I also need to retrieve it and use it to do calculations.
For example, assume I allow someone to specify the formula of employee salary calculation which I must save in String format in the DB.
GROSS_PAY = BASIC_SALARY - NO_PAY + TOTAL_OT + ALLOWANCE_TOTAL
Assume that terms such as GROSS_PAY, BASIC_SALARY are known to us and we can make out what they evaluate to. The real issue is we can't predict which combinations of such terms (e.g. GROSS_PAY etc.) and other mathematical operators the user may choose to enter (not just the +, -, ×, / but also the radical sigh - indicating roots - and powers etc. etc.). So how do we interpret this formula in string format once where have retrieved it from DB, so we can do calculations based on the composition of the formula.
Building an expression evaluator is actually fairly easy.
See my SO answer on how to write a parser. With a BNF for the range of expression operators and operands you exactly want, you can follow this process to build a parser for exactly those expressions, directly in Java.
The answer links to a second answer that discusses how to evaluate the expression as you parse it.
So, you read the string from the database, collect the set of possible variables that can occur in the expression, and then parse/evaluate the string. If you don't know the variables in advance (seems like you must), you can parse the expression twice, the first time just to get the variable names.
as of Evaluating a math expression given in string form there is a JavaScript Engine in Java which can execute a String functionality with operators.
Hope this helps.
You could build a string representation of a class that effectively wraps your expression and compile it using the system JavaCompiler — it requires a file system. You can evaluate strings directly using javaScript or groovy. In each case, you need to figure out a way to bind variables. One approach would be to use regex to find and replace known variable names with a call to a binding function:
getValue("BASIC_SALARY") - getValue("NO_PAY") + getValue("TOTAL_OT") + getValue("ALLOWANCE_TOTAL")
or
getBASIC_SALARY() - getNO_PAY() + getTOTAL_OT() + getALLOWANCE_TOTAL()
This approach, however, exposes you to all kinds of injection type security bugs; so, it would not be appropriate if security was required. The approach is also weak when it comes to error diagnostics. How will you tell the user why their expression is broken?
An alternative is to use something like ANTLR to generate a parser in java. It's not too hard and there are a lot of examples. This approach will provide both security (users can't inject malicious code because it won't parse) and diagnostics.

Java concatenate to build string or format

I'm writing a MUD (text based game) at the moment using java. One of the major aspects of a MUD is formatting strings and sending it back to the user. How would this best be accomplished?
Say I wanted to send the following string:
You say to Someone "Hello!" - where "Someone", "say" and "Hello!" are all variables. Which would be best performance wise?
"You " + verb + " to " + user + " \"" + text + "\""
or
String.format("You %1$s to %2$s \"%3$s\"", verb, user, text)
or some other option?
I'm not sure which is going to be easier to use in the end (which is important because it'll be everywhere), but I'm thinking about it at this point because concatenating with +'s is getting a bit confusing with some of the bigger lines. I feel that using StringBuilder in this case will simply make it even less readable.
Any suggestion here?
If the strings are built using a single concatenation expression; e.g.
String s = "You " + verb + " to " + user + " \"" + text + "\"";
then this is more or less equivalent to the more long winded:
StringBuilder sb = new StringBuilder();
sb.append("You");
sb.append(verb);
sb.append(" to ");
sb.append(user);
sb.append(" \"");
sb.append(text );
sb.append('"');
String s = sb.toString();
In fact, a classic Java compiler will compile the former into the latter ... almost. In Java 9, they implemented JEP 280 which replaces the sequence of constructor and method calls in the bytecodes with a single invokedynamic bytecode. The runtime system then optimizes this1.
The efficiency issues arise when you start creating intermediate strings, or building strings using += and so on. At that point, StringBuilder becomes more efficient because you reduce the number of intermediate strings that get created and then thrown away.
Now when you use String.format(), it should be using a StringBuilder under the hood. However, format also has to parse the format String each time you make the call, and that is an overhead you don't have if you do the string building optimally.
Having said this, My Advice would be to write the code in the way that is most readable. Only worry about the most efficient way to build strings if profiling tells you that this is a real performance concern. (Right now, you are spending time thinking about ways to address a performance issue that may turn out to be insignificant or irrelevant.)
Another answer mentions that using a format string may simplify support for multiple languages. This is true, though there are limits as to what you can do with respect to such things as plurals, genders, and so on.
1 - As a consequence, hand optimization as per the example above might actually have negative consequences, for Java 9 or later. But this is a risk you take whenever you micro-optimize.
I think that concatenation with + is more readable than using String.format.
String.format is good when you need to format number and dates.
Concateneting with plus, the compilet can transforms the code in performatic way. With string format i don t know.
I prefer cocatenation with plus, i think that is easer to undersand.
The key to keeping it simple is to never look at it. Here is what I mean:
Joiner join = Joiner.on(" ");
public void constructMessage(StringBuilder sb, Iterable<String> words) {
join.appendTo(sb, words);
}
I'm using the Guava Joiner class to make readability a non-issue. What could be clearer than "join"? All the nasty bits regarding concatenation are nicely hidden away. By using Iterable, I can use this method with all sorts of data structures, Lists being the most obvious.
Here is an example of a call using a Guava ImmutableList (which is more efficient than a regular list, since any methods that modify the list just throw exceptions, and correctly represents the fact that constructMessage() cannot change the list of words, just consume it):
StringBuilder outputMessage = new StringBuilder();
constructMessage(outputMessage,
new ImmutableList.Builder<String>()
.add("You", verb, "to", user, "\"", text, "\"")
.build());
I will be honest and suggest that you take the first one if you want less typing, or the latter one if you are looking for a more C-style way of doing it.
I sat here for a minute or two pondering the idea of what could be a problem, but I think it comes down to how much you want to type.
Anyone else have an idea?
Assuming you are going to reuse base strings often Store your templates like
String mystring = "You $1 to $2 \"$3\""
Then just get a copy and do a replace $X with what you want.
This would work really well for a resource file too.
I think String.format looks cleaner.
However you can use StringBuilder and use append function to create the string you want
The best, performance-wise, would probably be to use a StringBuffer.

Inserting a Java string in another string without concatenation? [duplicate]

This question already has answers here:
How to format strings in Java
(10 answers)
Closed 5 years ago.
Is there a more elegant way of doing this in Java?
String value1 = "Testing";
String test = "text goes here " + value1 + " more text";
Is it possible to put the variable directly in the string and have its value evaluated?
String test = String.format("test goes here %s more text", "Testing");
is the closest thing that you could write in Java
A more elegant way might be:
String value = "Testing";
String template = "text goes here %s more text";
String result = String.format(template, value);
Or alternatively using MessageFormat:
String template = "text goes here {0} more text";
String result = MessageFormat.format(template, value);
Note, if you're doing this for logging, then you can avoid the cost of performing this when the log line would be below the threshold. For example with SLFJ:
The following two lines will yield the exact same output. However, the second form will outperform the first form by a factor of at least 30, in case of a disabled logging statement.
logger.debug("The new entry is "+entry+".");
logger.debug("The new entry is {}.", entry);
Rythm a java template engine now released with an new feature called String interpolation mode which allows you do something like:
String result = Rythm.render("Hello #who!", "world");
The above case shows you can pass argument to template by position. Rythm also allows you to pass arguments by name:
Map<String, Object> args = new HashMap<String, Object>();
args.put("title", "Mr.");
args.put("name", "John");
String result = Rythm.render("Hello #title #name", args);
Links:
Check the full featured demonstration
read a brief introduction to Rythm
download the latest package or
fork it
It may be done by some template-libaries. But beware, Strings are immutable in Java. So in every case at some low level the concatenation will be done.
You'll always have to use some form of concatenation for this (assuming value1 isn't a constant like you show here).
The way you've written it will implicitly construct a StringBuilder and use it to concatenate the strings. Another method is String.format(String, Object...)1, which is analogous to sprintf from C. But even with format(), you can't avoid concatenation.
1 Yes, I know the anchor link is broken.
What you want is called String interpolation. It is not possible in Java, although JRuby, Groovy and probably other JVM languages do that.
Edit: as for elegance, you can use a StringBuffer or check the other poster's solution. But at the low level, this will always be concatenation, as the other posters said.
You can use this free library. It gives you sprintf like functionality. Or use String.format static method provided you use Java 5 or newer.
Why do you think string concatenation isn't elegant?
If all you are doing is simple concatenation, I'd argue that code readability is more important and I'd leave it like you have it. It's more readable than using a StringBuilder.
Performance won't be the problem that most people think it is.
Read this from CodingHorror
I would use a StringBuffer.. it's a common practise when you are dealing with strings. It may seem a bit when you see it for the first time, but you'll get quickly used to it..
String test = new StringBuffer("text goes here ").append(value1).append(" more text").toString();
Strings are immutable thus a new instance is created after every concatenation. This can cause performance issues when used in loops.
StringBuffer is mutable version of String - that means you can create one, modify it as you want and you have still only one instance. When desired you can get a String representation of the StringBuffer by calling it's toString() method.
The problem is not if this is an elegant way or not. The idea behind using a template system may be that you put your template in a normal text file and don't have to change java code if you change your message (or think about i18ln).

Categories