string interpolation java 1.3 and below(if possible)? - java

I have a simple string, where I need to insert a few numbers and strings.
Say String a = "My name is %s. I am %d years old".
I also need to insert same number or string at several of these holes.
I need a solution which works for ancient versions of java atleast upto 1.3
I know about String.format (JDK 5+). I read about formatter, my head hurts!!
please help.

Your only option is to use MessageFormat here.
You'd type:
String s = "My name is {0}. I am {1} years old";
and use the appropriate method to render this to a string. For instance:
String ret = MessageFormat.format(s, "John", 32);
I'd like to put a link to the javadoc, but... I don't know how much has changed since 1.3! (well, link added, it can't hurt)
(it should be noted that even in 2013, Java's ResourceBundles still use MessageFormat and read property files in ISO-8859-1, not UTF-8)

What about this one
String text = "The user {0} has email address {1}."
String msg = MessageFormat.format(text, params);
And this other
String text = "The user {name} has email address {email}.";
Object[] params = { "nameRobert", "rhume55#gmail.com" };
Map map = new HashMap();
map.put("name", "Robert");
map.put("email", "rhume55#gmail.com");
System.out.println("1st : " + MapFormat.format(text, map));

Related

URLEncoder - what character set to use for empty space instead of %20 or +

I am trying to open new email from my Java app:
String str=String.valueOf(email);
String body="This is body";
String subject="Hello worlds";
String newStr="mailto:"+str.trim()+"?subject="+URLEncoder.encode(subject,"UTF-8")+"&body="+URLEncoder.encode(body, "UTF-8")+"";
Desktop.getDesktop().mail(new URI(newStr));
Here it is my URLEncoding. As I cannot use body or subject string in URL without encoding them, my output here is with "+" instead of whitespace. Which is normal, I understand that. I was thinking if there is a way to visualize subject and body normally in my message? I tried with .replace("+"," ") but it is not working as it is giving an error. This is how it is now:
I think there might be different character set but I am not sure.
That's the way URLEncoder works.
One possible approach would be to replace all + with %20 after URLEncoder.enocde(...)
Or you could rely on URI constructor to encode your parameters correctly:
String scheme = "mailto";
String recipient = "recipient#snakeoil.com";
String subject = "The Meaning of Life";
String content = "..., the universe and all the rest is 42.\n Rly? Just kidding. Special characters: äöü";
String path = "";
String query = "subject=" + subject + "&body=" + content;
Desktop.getDesktop().mail(new URI(scheme, recipient, path, query, null));
Both solutions have issues:
In the first approach, you might replace actual + signs, with the second, you'll have issues with & character.

Java regex for google maps url?

I want to parse all google map links inside a String. The format is as follows :
1st example
https://www.google.com/maps/place/white+house/#38.8976763,-77.0387185,17z/data=!3m1!4b1!4m5!3m4!1s0x89b7b7bcdecbb1df:0x715969d86d0b76bf!8m2!3d38.8976763!4d-77.0365298
https://www.google.com/maps/place/white+house/#38.8976763,-77.0387185,17z
https://www.google.com/maps/place//#38.8976763,-77.0387185,17z
https://maps.google.com/maps/place//#38.8976763,-77.0387185,17z
https://www.google.com/maps/place/#38.8976763,-77.0387185,17z
https://google.com/maps/place/#38.8976763,-77.0387185,17z
http://google.com/maps/place/#38.8976763,-77.0387185,17z
https://www.google.com.tw/maps/place/#38.8976763,-77.0387185,17z
These are all valid google map URLs (linking to White House)
Here is what I tried
String gmapLinkRegex = "(http|https)://(www\\.)?google\\.com(\\.\\w*)?/maps/(place/.*)?#(.*z)[^ ]*";
Pattern patternGmapLink = Pattern.compile(gmapLinkRegex , Pattern.CASE_INSENSITIVE);
Matcher m = patternGmapLink.matcher(s);
while (m.find()) {
logger.info("group0 = {}" , m.group(0));
String place = m.group(4);
place = StringUtils.stripEnd(place , "/"); // remove tailing '/'
place = StringUtils.stripStart(place , "place/"); // remove header 'place/'
logger.info("place = '{}'" , place);
String latLngZ = m.group(5);
logger.info("latLngZ = '{}'" , latLngZ);
}
It works in simple situation , but still buggy ...
for example
It need post-process to grab optional place information
And it cannot extract one line with two urls such as :
s = "https://www.google.com/maps/place//#38.8976763,-77.0387185,17z " +
" and http://google.com/maps/place/#38.8976763,-77.0387185,17z";
It should be two urls , but the regex matches the whole line ...
The points :
The whole URL should be matched in group(0) (including the tailing data part in 1st example),
in the 1st example , if the zoom level : 17z is removed , it is still a valid gmap URL , but my regex cannot match it.
Easier to extract optional place info
Lat / Lng extraction is must , zoom level is optional.
Able to parse multiple urls in one line
Able to process maps.google.com(.xx)/maps , I tried (www|maps\.)? but seems still buggy
Any suggestion to improve this regex ? Thanks a lot !
The dot-asterisk
.*
will always allow anything to the end of the last url.
You need "tighter" regexes, which match a single URL but not several with anything in between.
The "[^ ]*" might include the next URL if it is separated by something other than " ", which includes line break, tab, shift-space...
I propose (sorry, not tested on java), to use "anything but #" and "digit, minus, comma or dot" and "optional special string followed by tailored charset, many times".
"(http|https)://(www\.)?google\.com(\.\w*)?/maps/(place/[^#]*)?#([0123456789\.,-]*z)(\/data=[\!:\.\-0123456789abcdefmsx]+)?"
I tested the one above on a perl-regex compatible engine (np++).
Please adapt yourself, if I guessed anything wrong. The explicit list of digits can probably be replaced by "\d", I tried to minimise assumptions on regex flavor.
In order to match "URL" or "URL and URL", please use a variable storing the regex, then do "(URL and )*URL", replacing "URL" with regex var. (Asuming this is possible in java.) If the question is how to then retrieve the multiple matches: That is java, I cannot help. Let me know and I delete this answer, not to provoke deserved downvotes ;-)
(Edited to catch the data part in, previously not seen, first example, first line; and the multi URLs in one line.)
I wrote this regex to validate google maps links:
"(http:|https:)?\\/\\/(www\\.)?(maps.)?google\\.[a-z.]+\\/maps/?([\\?]|place/*[^#]*)?/*#?(ll=)?(q=)?(([\\?=]?[a-zA-Z]*[+]?)*/?#{0,1})?([0-9]{1,3}\\.[0-9]+(,|&[a-zA-Z]+=)-?[0-9]{1,3}\\.[0-9]+(,?[0-9]+(z|m))?)?(\\/?data=[\\!:\\.\\-0123456789abcdefmsx]+)?"
I tested with the following list of google maps links:
String location1 = "http://www.google.com/maps/place/21.01196755,105.86306012";
String location2 = "https://www.google.com.tw/maps/place/#38.8976763,-77.0387185,17z";
String location3 = "http://www.google.com/maps/place/21.01196755,105.86306012";
String location4 = "https://www.google.com/maps/place/white+house/#38.8976763,-77.0387185,17z/data=!3m1!4b1!4m5!3m4!1s0x89b7b7bcdecbb1df:0x715969d86d0b76bf!8m2!3d38.8976763!4d-77.0365298";
String location5 = "https://www.google.com/maps/place/white+house/#38.8976763,-77.0387185,17z";
String location6 = "https://www.google.com/maps/place//#38.8976763,-77.0387185,17z";
String location7 = "https://maps.google.com/maps/place//#38.8976763,-77.0387185,17z";
String location8 = "https://www.google.com/maps/place/#38.8976763,-77.0387185,17z";
String location9 = "https://google.com/maps/place/#38.8976763,-77.0387185,17z";
String location10 = "http://google.com/maps/place/#38.8976763,-77.0387185,17z";
String location11 = "https://www.google.com/maps/place/#/data=!4m2!3m1!1s0x3135abf74b040853:0x6ff9dfeb960ec979";
String location12 = "https://maps.google.com/maps?q=New+York,+NY,+USA&hl=no&sll=19.808054,-63.720703&sspn=54.337928,93.076172&oq=n&hnear=New+York&t=m&z=10";
String location13 = "https://www.google.com/maps";
String location14 = "https://www.google.fr/maps";
String location15 = "https://google.fr/maps";
String location16 = "http://google.fr/maps";
String location17 = "https://www.google.de/maps";
String location18 = "https://www.google.com/maps?ll=37.0625,-95.677068&spn=45.197878,93.076172&t=h&z=4";
String location19 = "https://www.google.de/maps?ll=37.0625,-95.677068&spn=45.197878,93.076172&t=h&z=4";
String location20 = "https://www.google.com/maps?ll=37.0625,-95.677068&spn=45.197878,93.076172&t=h&z=4&layer=t&lci=com.panoramio.all,com.google.webcams,weather";
String location21 = "https://www.google.com/maps?ll=37.370157,0.615234&spn=45.047033,93.076172&t=m&z=4&layer=t";
String location22 = "https://www.google.com/maps?ll=37.0625,-95.677068&spn=45.197878,93.076172&t=h&z=4";
String location23 = "https://www.google.de/maps?ll=37.0625,-95.677068&spn=45.197878,93.076172&t=h&z=4";
String location24 = "https://www.google.com/maps?ll=37.0625,-95.677068&spn=45.197878,93.076172&t=h&z=4&layer=t&lci=com.panoramio.all,com.google.webcams,weather";
String location25 = "https://www.google.com/maps?ll=37.370157,0.615234&spn=45.047033,93.076172&t=m&z=4&layer=t";
String location26 = "http://www.google.com/maps/place/21.01196755,105.86306012";
String location27 = "http://google.com/maps/bylatlng?lat=21.01196022&lng=105.86298748";
String location28 = "https://www.google.com/maps/place/C%C3%B4ng+vi%C3%AAn+Th%E1%BB%91ng+Nh%E1%BA%A5t,+354A+%C4%90%C6%B0%E1%BB%9Dng+L%C3%AA+Du%E1%BA%A9n,+L%C3%AA+%C4%90%E1%BA%A1i+H%C3%A0nh,+%C4%90%E1%BB%91ng+%C4%90a,+H%C3%A0+N%E1%BB%99i+100000,+Vi%E1%BB%87t+Nam/#21.0121535,105.8443773,13z/data=!4m2!3m1!1s0x3135ab8ee6df247f:0xe6183d662696d2e9";

How to handle foreign addresses in Java application that calls Nominatim Webservice

The following code produces a string that has question marks as the display name when I insert an Iranian address(?????, ???????). However if I put the same url into my browser, it returns Tehran, Iran instead of question marks. I know that it has something to do with encoding but how do I get the English text as the browser returns in my java application?
String rawAddress = "Tehran";
String address = URLEncoder.encode(rawAddress, "utf-8");
String geocodeURL = "http://nominatim.openstreetmap.org/search?format=json&limit=1&polygon=0&addressdetails=0&email=myemail#gmail.com&languagecodes=en&q=";
String formattedUrl = geocodeURL + address;
URL theGeocodeUrl = new URL(formattedUrl);
System.out.println("HERE " +theGeocodeUrl.toString());
InputStream is = theGeocodeUrl.openStream();
final ObjectMapper mapper = new ObjectMapper();
final List<Object> dealData = mapper.readValue(is, List.class);
System.out.println(dealData.get(0).toString());
I tried the following code but it produced this: تهران, �ايران‎ for the display name which should be Tehran, Iran.
System.out.println(new String(dealData.get(0).toString().getBytes("UTF-8")));
Use "accept-language" in the URL parameter for Nominatim to specify the preferred language of Nominatim's results, overriding whatever default the HTTP header may set. From the documentation:
accept-language= <browser language string>
Preferred language order for showing search results, overrides the
value specified in the "Accept-Language" HTTP header. Either uses
standard rfc2616 accept-language string or a simple comma separated
list of language codes.

Simple way templating multiline strings in java code

I'm often run in to the following situation: I have long multiline strings where properties must be injected - e.g. something like templating. But I don't want to inlcude a complete templating engine (like velocity or freemarker) in my projects.
How can this be done in a simple way:
String title = "Princess";
String name = "Luna";
String community = "Stackoverflow";
String text =
"Dear " + title + " " + name + "!\n" +
"This is a question to " + community + "-Community\n" +
"for simple approach how to code with Java multiline Strings?\n" +
"Like this one.\n" +
"But it must be simple approach without using of Template-Engine-Frameworks!\n" +
"\n" +
"Thx for ...";
You can create your own small & simply template engine with few lines of code:
public static void main(String[] args) throws IOException {
String title = "Princes";
String name = "Luna";
String community = "Stackoverflow";
InputStream stream = DemoMailCreater.class.getResourceAsStream("demo.mail");
byte[] buffer = new byte[stream.available()];
stream.read(buffer);
String text = new String(buffer);
text = text.replaceAll("§TITLE§", title);
text = text.replaceAll("§NAME§", name);
text = text.replaceAll("§COMMUNITY§", community);
System.out.println(text);
}
and small text file e.g. in the same folder (package) demo.mail:
Dear §TITLE§ §NAME§!
This is a question to §COMMUNITY§-Community
for simple approach how to code with Java multiline Strings?
Like this one.
But it must be simple approach without using of Template-Engine-Frameworks!
Thx for ...
With Java 15+:
String title = "Princess";
String name = "Luna";
String community = "Stackoverflow";
String text = """
Dear %s %s!
This is a question to %s-Community
for simple approach how to code with Java multiline Strings?
""".formatted(title, name, community);
One basic way of doing it would be to use String.format(...)
Example:
String title = "Princess";
String name = "Celestia";
String community = "Stackoverflow";
String text = String.format(
"Dear %s %s!%n" +
"This is a question to %s-Community%n" +
"for simple approach how to code with Java multiline Strings?%n" +
"Like this one.%n" +
"But it must be simple approach without using of Template-Engine-Frameworks!%n" +
"%n" +
"Thx for ...", title, name, community);
More info
You can use Java Resources in order to achieve it HERE
Or you can keep the current method you're using with different approach like HERE
You can use String#format():
String title = "Princess";
String name = "Luna";
String community = "Stackoverflow";
String text = String.format("Dear %s %s!\n" +
"This is a question to %s-Community\n" +
"for simple approach how to code with Java multiline Strings?\n" +
"Like this one.\n" +
"But it must be simple approach without using of Template-Engine-Frameworks!\n" +
"\n" +
"Thx for ...", title, name, community);
Java has no built-in support for templating. Your choices are:
use an existing templating framework / engine,
build your own templating framework / engine (or similar), or
write a lot of "string bashing" code ... like in your question.
You may be able to write the above code a bit more concisely using String.format(...), MessageFormat and similar, but they don't get you very far ... unless your templating is very simple.
By contrast, some languages have built-in support for string interpolation, "here" documents, or a concise structure building syntax that can be adapted to templating.
You can use java.text.MessageFormat for this:
String[] args = {"Princess", "Luna", "Stackoverflow"};
String text = MessageFormat.format("Bla bla, {1}, and {2} and {3}", args);

dynamically read/add value to the parameter of conf file with Properties

I have a message like below in my conf file.
text.message = Richard has to go to School in 01/06/2012 / 1days.
All highlighted field will be variable.
I want to read this text.me string and insert the value from my java using Properties.
I know how to read the whole string using Prop, but don't know how to read like above String which will be like.
text.message = #name# has to go to #place# in #date# / #days#.
how can I read the above string from the conf using Properties and insert data dynamically?
It can be either date or days in the string. How I can turn on and off between those parameters?
Thanks ahead.
You can use the MessageFormat API for this.
Kickoff example:
text.message = {0} has to go to {1} in {2,date,dd/MM/yyyy} / {3}
with
String message = properties.getProperty("text.message");
String formattedMessage = MessageFormat.format(message, "Richard", "School", new Date(), "1days");
System.out.println(formattedMessage); // Richard has to go to School in 31/05/2012 / 1days
You can use the MessageFormat class, which replaces dynamic placeholders in a string with the desired values.
For example, the following code...
String pattern = "{0} has to go to {1} in {2,date} / {3,number,integer} days.";
String result = MessageFormat.format(pattern, "Richard", "school", new Date(), 5);
System.out.println(result);
...will produce the following output:
Richard has to go to school in 31-May-2012 / 5 days.
You can simply get the pattern from your Properties object, then apply the MessageFormat translation.

Categories