Android - Getting identifier for view using string variable - java

I have a string variable which is the same as the identifier for a view.
I would like to use the R.id.xxx, but obviously I can't just replace the xxx with my string as the xxx is actually an int. What can I do to get around this?
Thanks!

Nonsense. The framework obviously discourages that approach but it is possible: just use Java reflection, e.g.,
java.lang.reflect.Field f = R.id.class.getField(name);
int id = f == null ? -1 : (Integer)f.get(null);
// now just use findViewById(id);

String s=getString(R.string.xxx);

Related

Java string set default value if null

Is there a proficient way to set a string to some default value if assignment gives nullPointerException?
Say im initializing a string like this:
String myString= jsonElement.getAsJsonObject().get("myString").getAsString();
If it gives nullPointer i need to give it a default value, i know i can do it with an "if" check after but is that the only way? It would mean alot of checks as i am initiating around 20 strings.
Is there any way to do it like:
String myString = jsonElement.getAsJsonObject().get("myString")
.getAsString() || "defaultValue";
You can use Optional for that, as in:
Optional.of(jsonElement).map(element -> element.getAsJsonObject()).map(o -> o.get("myString")).map(e -> e.getAsString()).orElse("defaultValue");
How about make a method to do that.
String getOrDefault(JsonElement jsonElement, String key)
JsonObject obj = jsoneElement.getAsJsonObject().get(key);
return obj==null?"default":obj.getAsString();
}

Handling null values in protobuffers

I am working on something which fetches data from database and constructs protobuff message. Given the possibility that null values can be fetched from the database for certain fields , I will get Null-pointer exception while trying to construct the protobuff message. Getting to know that null is not supported in protobuffs from the thread http://code.google.com/p/protobuf/issues/detail?id=57, I am wondering whether the only other way to handle NPE getting thrown is to insert manual checks into the java file corresponding to the proto like below!
message ProtoPerson{
optional string firstName = 1;
optional string lastName = 2;
optional string address1 = 3;
}
ProtoPerson.Builder builder = ProtoPerson.Builder.newBuilder();
if (p.getFirstName() != null) builder.setFirstName(p.getFirstName());
if (p.getLastName() != null) builder.setLastName(p.getLastName());
if (p.getAddress1() != null) builder.setAddress1(p.getAddress1());
...
So can someone please clarify whether there is any other possible efficient way to handle the null values during protobuff construction??
Disclaimer: Answer from a Googler using protobufs on a daily basis. I'm by no means representing Google in any way.
Name your proto Person instead of PersonProto or ProtoPerson. Compiled protobufs are just class definitions specified by the language you are using, with some improvements. Adding "Proto" is extra verbosity.
Use YourMessage.hasYourField() instead of YourMessage.getYourField() != null. Default value for protobuf string is an empty string, which does NOT equal to null. Whereas, no matter whether your field is unset or cleared or empty string, .hasYourField() always returns false. See default values for common protobuf field types.
You've probably known, but I wanna say explicitly: Don't programmatically set a protobuf field to null. Even for outside of protobuf, null causes all sorts of problems. Use .clearYourField() instead.
Person.Builder class does NOT have a .newBuilder() method. Person class does. Understand the Builder Pattern like this: You create a new builder only if you do not have it yet.
A rewrite of your protobuf:
message Person {
optional string first_name = 1;
optional string last_name = 2;
optional string address_1 = 3;
}
A rewrite of your logic:
Person thatPerson = Person.newBuilder()
.setFirstName("Aaa")
.setLastName("Bbb")
.setAddress1("Ccc")
.build();
Person.Builder thisPersonBuilder = Person.newBuilder()
if (thatPerson.hasFirstName()) {
thisPersonBuilder.setFirstName(thatPerson.getFirstName());
}
if (thatPerson.hasLastName()) {
thisPersonBuilder.setLastName(thatPerson.getLastName());
}
if (thatPerson.hasAddress1()) {
thisPersonBuilder.setAddress1(thatPerson.getAddress1());
}
Person thisPerson = thisPersonBuilder.build();
And if thatPerson is a person object that you created that has attribute values that could be an empty string, empty spaces or null, then I'd recommend using Guava's Strings library:
import static com.google.common.base.Strings.nullToEmpty;
Person.Builder thisPersonBuilder = Person.newBuilder()
if (!nullToEmpty(thatPerson.getFirstName()).trim().isEmpty()) {
thisPersonBuilder.setFirstName(thatPerson.getFirstName());
}
if (!nullToEmpty(thatPerson.hasLastName()).trim().isEmpty()) {
thisPersonBuilder.setLastName(thatPerson.getLastName());
}
if (!nullToEmpty(thatPerson.hasAddress1()).trim().isEmpty()) {
thisPersonBuilder.setAddress1(thatPerson.getAddress1());
}
Person thisPerson = thisPersonBuilder.build();
Proto 3
wrappers.proto supports nullable values:
string(StringValue),
int(Int32Value),
bool(BoolValue)
and etc
Example
syntax = "proto3";
import "google/protobuf/wrappers.proto";
message ProtoPerson {
google.protobuf.StringValue firstName = 1;
google.protobuf.StringValue lastName = 2;
google.protobuf.StringValue address1 = 3;
google.protobuf.Int32Value age = 4;
}
There's no easy solution to this. I'd recommend just dealing with the null checks. But if you really want to get rid of them, here are a couple ideas:
You could write a code generator plugin which adds setOrClearFoo() methods to each Java class. The Java code generator provides insertion points for this (see the end of that page).
You could use Java reflection to iterate over the get*() methods of p, call each one, check for null, and then call the set*() method of builder if non-null. This will have the added advantage that you won't have to update your copy code every time you add a new field, but it will be much slower than writing code that copies each field explicitly.

Xtend/Xpand find and replace (rule)

Is it possible set a rule that will allow an Xpand method to output a specified string of text depending on the input. For example:
«FOR a:e.attributes»
Type = «a.eClass.name»
Value = «a.name.toFirstUpper»
«ENDFOR»
The above code may output:
Type = StringAttribute
Value = String1
Type = IntegerAttribute
Value = 123
How would I make this output:
Type = String
Value = String1
Type = int
Value = 123
I know this can be done with if statements but I would like to be able it to be more or less automatic. It would be a waste to have to specify such rules every time I need to output these details in the same file. Could someone show me what kind of code I could use to achieve this? Thank you.
I suggest that you create a reusable Xtend helper
toSimpleName(String inp):
switch (inp) {
case "StringAttribute" : "String"
case "IntegerAttribute" : "int"
// ...more cases here...
default : inp
}
;
and then call it from your Xpand template like this:
«FOR a:e.attributes»
Type = «a.eClass.name.toSimpleName()»
Value = «a.name.toFirstUpper»
«ENDFOR»

how to read a value from properties file of an enum type?

I have an enum as below:
public enum EnvironmentType {PRODUCTION, TEST, DEVELOPMENT}
in properties file the key value is like :
app.environmentType = TEST
we know that when i read the value from properties file using key, it returns as String like
String envType = properties.getProperty("app.environmentType");
My requirement is,
EnvironmentType envType = EnvironmentType.TEST;
Now i want to know that is there a way to get the value as enum type? how can i parse or cast it ?
EnvironmentType envType = EnvironmentType.valueOf(envTypeString);
You may use valueOf method as follows:
String envTypeStr = properties.getProperty("app.environmentType");
EnvironmentType envType = EnvironmentType.valueOf(envTypeStr);
The static methods valueOf() and values() are created at compile time and do not appear in source code. But they appear in documentation of some enumaration in java library. For example, see SortOrder and Normalizer.Form

How to get Locale from its String representation in Java?

Is there a neat way of getting a Locale instance from its "programmatic name" as returned by Locale's toString() method? An obvious and ugly solution would be parsing the String and then constructing a new Locale instance according to that, but maybe there's a better way / ready solution for that?
The need is that I want to store some locale specific settings in a SQL database, including Locales themselves, but it would be ugly to put serialized Locale objects there. I would rather store their String representations, which seem to be quite adequate in detail.
Method that returns locale from string exists in commons-lang library:
LocaleUtils.toLocale(localeAsString)
Since Java 7 there is factory method Locale.forLanguageTag and instance method Locale.toLanguageTag using IETF language tags.
Java provides lot of things with proper implementation lot of complexity can be avoided. This returns ms_MY.
String key = "ms-MY";
Locale locale = new Locale.Builder().setLanguageTag(key).build();
Apache Commons has LocaleUtils to help parse a string representation. This will return en_US
String str = "en-US";
Locale locale = LocaleUtils.toLocale(str);
System.out.println(locale.toString());
You can also use locale constructors.
// Construct a locale from a language code.(eg: en)
new Locale(String language)
// Construct a locale from language and country.(eg: en and US)
new Locale(String language, String country)
// Construct a locale from language, country and variant.
new Locale(String language, String country, String variant)
Please check this LocaleUtils and this Locale to explore more methods.
See the Locale.getLanguage(), Locale.getCountry()... Store this combination in the database instead of the "programatic name"...
When you want to build the Locale back, use public Locale(String language, String country)
Here is a sample code :)
// May contain simple syntax error, I don't have java right now to test..
// but this is a bigger picture for your algo...
public String localeToString(Locale l) {
return l.getLanguage() + "," + l.getCountry();
}
public Locale stringToLocale(String s) {
StringTokenizer tempStringTokenizer = new StringTokenizer(s,",");
if(tempStringTokenizer.hasMoreTokens())
String l = tempStringTokenizer.nextElement();
if(tempStringTokenizer.hasMoreTokens())
String c = tempStringTokenizer.nextElement();
return new Locale(l,c);
}
Option 1 :
org.apache.commons.lang3.LocaleUtils.toLocale("en_US")
Option 2 :
Locale.forLanguageTag("en-US")
Please note Option 1 is "underscore" between language and country , and Option 2 is "dash".
If you are using Spring framework in your project you can also use:
org.springframework.util.StringUtils.parseLocaleString("en_US");
Documentation:
Parse the given String representation into a Locale
This answer may be a little late, but it turns out that parsing out the string is not as ugly as the OP assumed. I found it quite simple and concise:
public static Locale fromString(String locale) {
String parts[] = locale.split("_", -1);
if (parts.length == 1) return new Locale(parts[0]);
else if (parts.length == 2
|| (parts.length == 3 && parts[2].startsWith("#")))
return new Locale(parts[0], parts[1]);
else return new Locale(parts[0], parts[1], parts[2]);
}
I tested this (on Java 7) with all the examples given in the Locale.toString() documentation: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "zh_CN_#Hans", "zh_TW_#Hant-x-java", and "th_TH_TH_#u-nu-thai".
IMPORTANT UPDATE: This is not recommended for use in Java 7+ according to the documentation:
In particular, clients who parse the output of toString into language, country, and variant fields can continue to do so (although this is strongly discouraged), although the variant field will have additional information in it if script or extensions are present.
Use Locale.forLanguageTag and Locale.toLanguageTag instead, or if you must, Locale.Builder.
Old question with plenty of answers, but here's more solutions:
Get Locale From String
Converts a String to a Locale
There doesn't seem to be a static valueOf method for this, which is a bit surprising.
One rather ugly, but simple, way, would be to iterate over Locale.getAvailableLocales(), comparing their toString values with your value.
Not very nice, but no string parsing required. You could pre-populate a Map of Strings to Locales, and look up your database string in that Map.
Might be late but if someone looking for simple solution:
Instead of toString() set Locale string by using: String langTag = localeObj.toLanguageTag();
Store langTag in DB or wherever you want
At the consumer side get String lanTag = fromDB(); // or wherever
Get the Locale by: Locale locale = Locale.forLanguageTag(langTag);
No additional dependency needed!
You can use this on Android. Works fine for me.
private static final Pattern localeMatcher = Pattern.compile
("^([^_]*)(_([^_]*)(_#(.*))?)?$");
public static Locale parseLocale(String value) {
Matcher matcher = localeMatcher.matcher(value.replace('-', '_'));
return matcher.find()
? TextUtils.isEmpty(matcher.group(5))
? TextUtils.isEmpty(matcher.group(3))
? TextUtils.isEmpty(matcher.group(1))
? null
: new Locale(matcher.group(1))
: new Locale(matcher.group(1), matcher.group(3))
: new Locale(matcher.group(1), matcher.group(3),
matcher.group(5))
: null;
}
Well, I would store instead a string concatenation of Locale.getISO3Language(), getISO3Country() and getVariant() as key, which would allow me to latter call Locale(String language, String country, String variant) constructor.
indeed, relying of displayLanguage implies using the langage of locale to display it, which make it locale dependant, contrary to iso language code.
As an example, en locale key would be storable as
en_EN
en_US
and so on ...
Because I have just implemented it:
In Groovy/Grails it would be:
def locale = Locale.getAvailableLocales().find { availableLocale ->
return availableLocale.toString().equals(searchedLocale)
}

Categories

Resources