I use this great Java library for converting a text to speech using Google Translate Unofficial API.
Using this code it is able to "read" the text in English (see Language.ENLGISH):
Audio audio = Audio.getInstance();
InputStream sound = audio.getAudio("I am a bus", Language.ENGLISH);
audio.play(sound);
I have a list (a combobox) with all languages.
How can I convert a string that is "ENGLISH" into the field Language.ENGLISH?
I don't want to use a lot of ifs in the code (if (mySelectedLanguage.equals("ENGLISH") // ...Language.English).
I already tried with:
Language["ENGLISH"] inspired from Javascript, but it doesn't work
Language.class.getField("ENGLISH").toString() (toString because their types are String: public static final String ENGLISH)
Which is the correct way that will really work?
Edit: I already asked here how to get the languages. Maybe it helps us to find the answer.
If you want to get value of public static field
then instead of
Language.class.getField("ENGLISH").toString();
use
(String)Language.class.getField("ENGLISH").get(null);
null indicates that you don't want to get field from some object, but rather from entire class (which in case of static variable is desired behavior)
But if it is possible I would recommend rewriting your Language class to enum and using Language.valueOf("ENGLISH")
Create your own enum to store these values. This is good practice regardless of your particular difficulties - by creating a façade for this third-party class, you de-couple one part of your code.
If you implement toString() as shown below, you can store these enum values directly in your combo box.
public enum Languages {
ENGLISH(Language.ENGLISH, "English"),
// etc..
;
private final String languageName;
private final String displayName;
private Languages(String languageName, String displayName) {
this.languageName = languageName;
this.displayName = displayName;
}
public String getLanguageString() {
return languageName;
}
public String getDisplayString() {
return displayName;
}
public static Languages fromString(String languageString) {
for (Language l : values()) {
if (l.getLanguageString().equals(languageString)) {
return l;
}
}
return null;
}
// optional
#Override
public String toString() {
return displayName;
}
}
Maybe choose a better name than Languages - I'm not feeling very inspired.
Related
Building up on this question, the example provided seems to lock the text in the feature file too much to Java programming style (notice that the text is written in all uppercase, and is only one word.
Is it possible to pass enums when the feature file has more "human readable" text? E.g.:
Simple Example
Feature: Setup Enum and Print value
In order to manage my Enum
As a System Admin
I want to get the Enum
Scenario Outline: Verify Enum Print
When I supply a more human readable text to be converted to <Enum>
Examples: Text can have multiple formats
|Enum |
|Christmas |
|New Year Eve |
|independence-day|
I reckon the enum could be something like:
public enum Holiday {
CHRISTMAS("Christmas"),NEW_YEAR("New Year"),INDEPENDENCE_DAY("independence-day");
private String extendedName;
private Holidays(String extendedName) {
this.extendedName = extendedName;
}
}
How could we convert one from the other?
More complex example
In a more complex example, we would pass this onto a ScenarioObject
Scenario: Enum within a Scenario Object
When I supply a more human readable text to be converted in the objects:
|Holiday |Character|
|Christmas |Santa |
|New Year Eve |Harry|
|independence-day|John Adams|
public class ScenarioObject{
private String character;
private Holiday holiday;
(...getters and setters)
}
Update:
If the only solution is to apply a Transformer, as described here, an example of how this would be a applied to the ScenarioObject would be appreciated, since simply tagging the enum with a #XStreamConverter(HolidayTransformer.class) is not sufficient for the transformer to work within the ScenarioObject.
The best solution I found for this so far was with a transformer.
In the case of the complex example with ScenarioObject,this involves:
Mark enum with converter
#XStreamConverter(HolidayTransformer.class)
public enum Holiday {
CHRISTMAS("Christmas"),NEW_YEAR("New Year"),INDEPENDENCE_DAY("independence-day");
private String extendedName;
private Holidays(String extendedName) {
this.extendedName = extendedName;
}
public static Holiday fromString(String type) throws Exception {...}
}
Create the transformer
public class HolidayTransformer extends Transformer<Holiday> {
#Override
public Holiday transform(String value) {
try {
return Holiday.fromString(value);
} catch (Exception e) {
fail("Could not convert from value");
return null;
}
}
}
Mark the ScenarioObject with the transformer as well
public class ScenarioObject{
private String character;
#XStreamConverter(HolidayTransformer.class)
private Holiday holiday;
(...getters and setters)
}
Recently i faced one interview question.
Question :Suppose you have many values (lets say more then 20) which
you need to set in object. now setting these values using setters or
using constructor is tedious task.
What java design pattern will you use to solve this problem
Help me know the solution guys.
Well, in the end the attributes somehow, but some patterns might help you making it less chatty. A quick wikipedia search for creational patterns reveals some possible fits depending on the exact situation:
Factory and Factory Method can take the attributes as parameters at once, for example.
Builder generally makes it easier to construct an object fitted to your current needs.
Prototype might help when you want to repeatedly create similar instances of a type.
To really decide, you need toknow the exact circumstances and needs.
Standard builder:
public class Account {
private final String userId;
private final String token;
public Account(String userId, String token) {
this.userId = userId;
this.token = token;
}
public String getUserId() {
return userId;
}
public String getToken() {
return token;
}
public static class Builder {
private String userId;
private String token;
public Builder setUserId(String userId) {
this.userId = userId;
return this;
}
public Builder setToken(String token) {
this.token = token;
return this;
}
public Account build() {
return new Account(userId, token);
}
}
}
If the values are heavily dynamic, what about having a Map<String, Object> (and maybe a List<Object> for index-based access) and methods like public Double getDoubleByName(String nameKey) (and the corresponding for index, like public String getStringAt(int index))?
Edit:
If you are interesetd in a Map implementation that provides also an efficient (i.e.: O(log2(n)) way to access elements by their index like a List, then you could try to use my own MapTreeAVL available at my repo with code like
MapTreeAVL<String, Object> m = MapTreeAVL.newMap(MapTreeAVL.Optimizations.ToQueueFIFOIterating, String::compareTo);
....
Object o = m.getAt(7);
I have an enum class, but I want to display string based on user system language. For example, If the system is English , it should display 1 , 2 ,3
. But if the System is Chinese, the display should totally be different like "一", “二”, “三”. (一 means 1 in Chinese, 二 means 2 in Chinese).
Here is my code
public enum OrderType {
ONE("1"), TWO("2"), THREE("3")
private String name;
private OrderType(String name) {
this.name = name;
}
public String toString() {
return name;
}
public static String getEnumByString(String code) {
for (OrderType e : OrderType.values()) {
if (code.equals(e.name)) {
return e.name();
}
}
return null;
}
}
The enum works fine in android, Can I define the String in the value folder,
Like values-iw, values-ru... And how can I use that?
UPDATE:
I also want to use constructor to initialize the enum string. Just like
private OrderType(String name) {
String temp = getResources().getString(R.string.name);
this.name = temp ;
}
But I do not know how to pass parameter of R.string.parameter..
Second, how Can I use getResources() function in enum class
Just provide the String resource ID as a parameter to your Enum:
public enum OrderType {
ONE(R.string.order_type_one),
TWO(R.string.order_type_two)
private final int mTextResourceId;
OrderType(int resourceId) {
mTextResourceId = resourceId;
}
public int getTextResourceId() {
return mTextResourceId;
}
}
Provide these strings in each desired resource folder, e.g.:
res/values/strings.xml
res/values-es/strings.xml
res/values-fr/string.xml
Then, when you want to consume this in a TextView somewhere:
myTextView.setText(myOrderType.getTextResourceId());
No Context passing required, and it is determined at runtime based on the current locale.
You must know that enums are initialized statically. Each of ONE, TWO, THREE is static.
In android to use resources, such as strings, you need a context.
Generally, you can not access Android context in static methods or initializes, therefore you can't use them with enums.
Even if you could use a hack to make android context statically available you would still have issues :
you'd need to ensure none of your OrderType enums accessed before Application#onCreate
strings in your enums won't reflect runtime language changes
Edit
I hope it is clear that you can not reliably initialize your enums with string resources.
You could, however, associate static id of a string (R.string.string_name) with your enum and obtain needed resource string later using a context, as proposed in kcoppock's answer.
You should keep the strings in your string xml resource. That way you can get it from there into your code. For example like this:
String one = getResources().getString(R.string.num_one);
Then you just put a strings.xml file with overloading values in the language folders you want (values-ru, values-sv etc.)
For tasks of that kind use localizations.
"google on i18n java"
and
"android app localization"
public enum OrderType {
One(mActivity.getString(R.string.One)), Two(mActivity.getString(R.string.Two));
private String name;
private OrderType(String name) {
this.name = name;
}
public String toString() {
return name;
}
public static String getEnumByString(String code) {
for (OrderType e : OrderType.values()) {
if (code.equals(e.name)) {
return e.name();
}
}
return null;
}
}
also Here is the link, which I think is best way solve the porblem. This developing for API level 11 currently, however this code should run on higher versions. After a quick review in API 16 I did not see an existing core Android solution to this problem, if you know of one please post below and share.
I know that it isn't possible to extend enum in Java, but I am trying to find an elegant solution for the below
I am trying to model enums (or classes) which will contain http end points of various web services across regions, say I have service A and B, each will have 4 region specific end points in US, EU, JP or CN. (This is basically for some seperate debug code that I am writing, in production the end points will be picked from configuration)
I was hoping to do something like this (not compliant java code).
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum ServiceAEndPoint extends IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
I could do this using interfaces where I have a method for each region, but in my opinion the enum way is more expressive, is there any better way I could model this ? What I am looking for is if there is any better way to model the inheritence relation and also having the expressive power of enumerations.
ServiceAEndPoint.NA_END_POINT
vs
serviceAEndPoint.getNAEndPoint()
I'm assuming that you will also want a ServiceBEndPoint enum (and similar). In which case I don't think your model really makes that much sense.
IEndPoint is really an enumeration of the kind of environments/regions where a service might be running. It is not an enumeration of the services themselves. Each individual service (A, B or whatever) will have different addresses for each of the regions.
Therefore I would stick with just the IEndPoint enum, and then in some service-specific code have a lookup map that will give you the address for a given end-point. Something like this:
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public class ServiceABroker {
private static final Map<IEndPoint, String> addressesByEndPoint;
static {
addressesByEndPoint = new EnumMap<>();
addressesByEndPoint.put(NA_END_POINT, "http://A.com/");
addressesByEndPoint.put(EU_END_POINT, "http://A-eu.com/");
addressesByEndPoint.put(JP_END_POINT, "http://A-jp.com/");
addressesByEndPoint.put(CN_END_POINT, "http://A-cn.com/");
}
public String getAddressForEndPoint(IEndPoint ep) {
return addressesByEndPoint.get(ep);
}
}
If these are static final constants, then just put them in an interface. Name the interface something like IServiceAEndPointKeys, where the keys part is a convention.
Here's where I consider enums to be more appropriate and useful:
Example 1: File type. An enum containing jpg, pdf etc.
Example 2: Column definitions. If I have a table with 3 columns, I would write an enum declaring ID, Name, Description (for example), each one having parameters like column header name, column width and column ID.
Im not sure I understand you question, but you can add methods to an enum for example you could do something like the following:
public enum ServiceAEndPoint{
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
private final String url;
private EndPoint(String url){
this.url=url;
}
public String getURL(){
return url;
}
}
Enums cannot be extended in such a manner, mostly because enums cannot be sub-classed or the constraints they must adhere to will not be possible to impose.
Instead leverage interfaces, like so
public interface IEndPoint;
public enum DefaultEndPoints implements IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum DefaultServiceEndPoints implements IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
public void doSomething(IEndPoint endpoint) {
...
}
The reason why one can't subclass in the manner you wish is related to the contract that enums will be both equal via .equals(object) and via ==. If you could subclass, would this make sense?
if ( (DefaultEndPoints)JP_END_POINT == (DefaultServiceEndPoints)JP_END_POINT) {
}
if you say "yes" then I would expect to be able to do this
DefaultEndPoint someEndpoint = DefaultServiceEndPoints.JP_END_POINT;
which would leave a door open for error, as there is no guarantee that a enum entry in one enum declaration is in the other enum declaration.
Could it be different? Perhaps, but it isn't, and changing it would definately introduce a lot of complications that would have to be thoroughly thought out (or it would open avenues to work around Java's strong static-type checking).
You may want to consider something like this:
public abstract class EndpointFactory {
public abstract String getNAEndPoint();
public abstract String getEUEndPoint();
}
public class ServiceAEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://A.com/";
public static final String EU_END_POINT = "http://A-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
public class ServiceBEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://B.com/";
public static final String EU_END_POINT = "http://B-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
Then you can refer to your strings directly like this:
ServiceAEndpointFactory.NA_END_POINT;
Or, you can use the base object if the type of service is not known until execution:
EndpointFactory ef1 = new ServiceAEndpointFactory();
String ep = ef1.getNAEndPoint();
The drawback of this is the redefinition of the get*Endpoint() functions in each sub-class. You could eliminate that by moving the static final variables to be not static in the base class and putting the getter/setter in the base class only one time. However, the drawback of that is you are not able to reference the values without instantiating an object (which essentially emulates what I find valuable with ENUMs).
How does a pattern like this appeal to you? I let the enum implement an interface and implement the interface in a Debug set and a Release set. The release set can then derive the property name from the enum name - which is neat.
public interface HasURL {
public String getURL();
}
public enum DebugEndPoints implements HasURL {
NA,
EU,
JP,
CN;
#Override
public String getURL() {
// Force debug to go to the same one always.
return "http://Debug.com/";
}
}
public enum NormalEndPoints implements HasURL {
NA,
EU,
JP,
CN;
final String url;
NormalEndPoints () {
// Grab the configured property connected to my name.
this.url = getProperty(this.name());
}
#Override
public String getURL() {
return url;
}
}
I have the following Java enum:
public enum CertificateType {
EMAIL("Email"),
NATURAL_QUALIFIED("Qualified"),
PSEUDONYMOUS_QUALIFIED("Qualified");
public final String NAME;
private CertificateType( final String name ) {
this.NAME = name;
}
}
What I would like to do is turn that enum into a Map[enum as String, enum.NAME] to use in a Play Framework #select function. By enum as String, I mean "EMAIL", or "NATURAL_QUALIFIED"
For a list of objects, I'd use the .map function, like so:
Organization.all.map(org => (org.id.toString, org.name))(collection.breakOut)
But I don't think I can modify that to work with an enum.
How can I accomplish this?
EDIT: The annotations are nothing to do with Scala, but are ORM annotations for Play. The code above is a Java enum. By enum value, I mean each enum, as in EMAIL, NATURAL_QUALIFIED, etc.
An example key=>value pair would be "EMAIL"=>"Email"
EDIT 2: I have removed the annotations on the enums for clarity.
CertificateType.values.map(e => (e.name -> e.NAME) ).toMap
Stripping out the scala part that I'm not familiar with, could you not do something like this?
public enum CertificateType {
EMAIL("Email"),
NATURAL_QUALIFIED("Qualified"),
PSEUDONYMOUS_QUALIFIED("Qualified");
public final String NAME;
private static Map<CertificateType, String> map = new HashMap<CertificateType, String>();
private CertificateType( final String name ) {
this.NAME = name;
map.put(this, this.NAME);
}
public Map<CertificateType, String> getMap()
{ //Return a copy so that any modifications a
//user might make won't propagate back to the stored map
return new HashMap<CertificateType, String>(map);
}
}