Not all that sure how I would describe this question, so I'll jump right into the example code.
I have a Constants.java
package com.t3hh4xx0r.poc;
public class Constants {
//RootzWiki Device Forum Constants
public static final String RWFORUM = "http://rootzwiki.com/forum/";
public static final String TORO = "362-cdma-galaxy-nexus-developer-forum";
public static String DEVICE;
}
In trying to determine the device type, I use this method.
public void getDevice() {
Constants.DEVICE = android.os.Build.DEVICE.toUpperCase();
String thread = Constants.(Constants.DEVICE);
}
Thats not correct though, but thats how I would think it would have worked.
Im setting the Constants.DEVICE to TORO in my case on the Galaxy Nexus. I want to then set the thread String to Constants.TORO.
I dont think I'm explaining this well, but you shoudl be able to understand what I'm trying to do fromt he example code. I want
Constants.(VALUE OF WHAT CONSTANTS.DEVICE IS) set for the String thread.
Another way to put it,
I want to get Constants.(//value of android.os.Build.DEVICE.toUpperCase())
I apologies for the poorly worded question, i dont know of any better way to explain what Im trying to achieve.
Im trying to determine the thread based on the device type. I could go in and do an
if (Constants.DEVICE.equals("TORO"){
String thread = Constants.TORO;
}
But I plan on adding a lot more device options in the future and would like to make it as easy as adding a string to the Constants.java rather than having to add another if clause.
I would suggest using an enum instead of just strings - then you can use:
String name = android.os.Build.DEVICE.toUpperCase();
// DeviceType is the new enum
DeviceType type = Enum.valueOf(DeviceType.class, name);
You can put the value of the string in a field for the enum, and expose it via a property:
public enum DeviceType {
RWFORUM("http://rootzwiki.com/forum/"),
TORO("362-cdma-galaxy-nexus-developer-forum");
private final String forumUrl;
private DeviceType(String forumUrl) {
this.forumUrl = forumUrl;
}
public String getForumUrl() {
return forumUrl;
}
}
(I'm guessing at the meaning of the string value - not a great guess, but hopefully it gives the right idea so you can make your actual code more meaningful.)
EDIT: Or to use a map:
Map<String, String> deviceToForumMap = new HashMap<String, String>();
deviceToForumMap.put("RWFORUM", "http://rootzwiki.com/forum/");
deviceToForumMap.put("TORO", "362-cdma-galaxy-nexus-developer-forum");
...
String forum = deviceToForumMap.get(android.os.Build.DEVICE.toUpperCase());
You can use reflection:
Constants.DEVICE = android.os.Build.DEVICE.toUpperCase();
String thread = (String) Constants.class.getField(Constants.DEVICE).get(null);
Not sure I've understood the question properly, but I feel that it's a right place to use a Map. The outcome will be something like this:
HashMap<String, String> map;
map.put(TORO, DEVICE);
Constants.DEVICE = android.os.Build.DEVICE.toUpperCase();
String thread = map.get(Constants.DEVICE);
Sorry for a possible misunderstanding or your question, but I hope you've got the idea.
P.S. You can find more info about Maps in the Java documentation: Map, HashMap.
Related
My software is a Java EE application which talks to another service via SOAP. I want to create a layer that is better testable and use an ideal solution for that. I am not sure which pattern is the right one for this issue.
I have an internal data class which is called InputData. It uses locically correct data types. The SOAP interface on the other hand needs most of the data in strings, like dates in "dd.MM.yyyy", boolean as "0" and "1" and some other weird rules. I cannot change that.
So I need a layer between that. First I thought the best way was to use pure functions because they are easier to test without any side effects. My idea was to create a class with static methods of which one is public. I should return a ValueObject which holds all the data in the correct format.
I had trouble finding a name, so I started with "Adapter". But having something like this:
public class SoapDataAdapter {
public static SoapData getSoapData(InputData input) {
SoapData data = new SoapData();
data.setDate = getDate(input.getDate());
data.isCustomer = isCustomer(input.isCustomer());
// and many more
return data;
}
private static String getDate(LocalDate date) {
return DateHelper.toSoapDate(date);
}
private static String isCustomer(boolean isCustomer) {
return isCustomer ? "0" : "1";
}
}
But this is not an Adapter according to the known patterns. But it is not a Factory -- if I go with the definition of the Gang of Four -- either.
Then I was not sure how to call it or if a "real" Adapter would be a better option. So I tried this:
public class SoapDataAdapter {
private InputData input;
public SoapData getSoapData(InputData input) {
this.input = input;
}
public String getDate() {
return DateHelper.toSoapDate(input.getDate());
}
public String isCustomer() {
return input.isCustomer ? "0" : "1";
}
}
The GoF design patterns gather around OOP which is probably not always the best solution. Having just those pure functions makes a lot of sense to me instead of having the overhead of creating an instance and holding the state. Also, my goal is to make it easier to understand and much easier to test.
What do you think is the best solution for the problem? The first, the second or even another solution? (Adapter seems to be the pattern that fits for exactly that problem, if I understood it correctly.)
What would you call the first one? Is Factory here acceptable?
I have a weird problem that I am trying to solve,
I have a enum with a string something like this
public enum Enumm{
Item1("i1"),
Item2("i2");
private String itemText;
private Enumm(String inText){
this.setitemText(inText);
}
// getter and setter for itemText not typing
}
now in the other class I want to check if a string inputString contains either "i1" or "i2" but the problem is I cannot use a loop.
I know I can do this
for(Enumm item: Enumm.values()){
if (inputString.contains(item.getItemText)) {
// do something
}
}
but the constraints of my problem do not allow me to do it this way
I am looking for something like
if(inputString.contains(Enumm.Item1.getItemText||Enumm.Item2.getItemText)){
//do something
}
but is also dynamic such that it finds all the items in the enum
could anyone help me find a solution ?? Thanks in advance.
You could add a static method to your enum called something like findInString(String s) that does the loops over the values() for you and returns a boolean if it finds it. But it depends on why you are trying to avoid the loop. Obviously, this does nothing except squirrels the loop away where you can't see it.
You can make an Item list/array and then parse through the array to check for i1 or i2.
Item[] string = {"i1","i2"}
if(string.contains("i1")||string.contains("i2"))
{
}
Maybe this could help?
List<String> list = Collections.list(enumeration);
boolean b = list.contains("Searchstring");
I have query string like that:
ObjectGUId=1abcde&ObjectType=2&ObjectTitle=maximumoflife&Content=racroi&TimeStamp=2012-11-05T17:20:06.056
And I have Java Object:
LogObject{
private String ObjectGUId;
private String ObjectType;
private String ObjectTitle;
private String Content;
private String TimeStamp;
}
So i want to parse this query string to this java Object.
I've searched and read many question but not gotten correct answer yet.
Show me what can solve this problem.
Inspired by #bruno.braga, here's a way using Apache http-components. You leverage all the parsing corner cases:
List<NameValuePair> params =
URLEncodedUtils.parse("http://example.com/?" + queryString, Charset.forName("UTF-8"));
That'll give you a List of NameValuePair objects that should be easy to work with.
If you do not really need to push the querystring into your own class (you might want that though), instead of parsing it manually, you could use the URLDecoder, as #Sonrobby has commented:
String qString = "ObjectGUId=1abcde&ObjectType=2&ObjectTitle=maximumoflife";
Uri uri = Uri.parse(URLDecoder.decode("http://dummy/?" + qString, "UTF-8"));
if (uri != null) {
for(String key: uri.getQueryParameterNames()) {
System.out.println("key=[" + key + "], value=[" + uri.getQueryParameter(key) + "]");
}
}
The "dummy" looks dirty but it is required if what you only have is the querystring values (qString). If you have the complete URL, just pass it directly to the URLDecoder, and you are done.
Etiquette
You really should be much more specific about what you have tried and why it didn't work.
A proper code sample of your LogObject would really be very helpful here.
Ideally, you would provide a SSCCE so others could easily test your problem themselves.
Answer
You can extract the name:value pairs like this:
String toParse = "ObjectGUId=1abcde&ObjectType=2&ObjectTitle=maximumoflife&Content=racroi&TimeStamp=2012-11-05T17:20:06.056";
String[] fields = toParse.split("&");
String[] kv;
HashMap<String, String> things = new HashMap<String, String>();
for (int i = 0; i < fields.length; ++i)
{
t = fields[i].split("=");
if (2 == kv.length)
{
things.put(kv[0], kv[1]);
}
}
I have chosen to put them into a HashMap, but you could just as easily look at the name part (kv[0]) and choose to do something with it. For example:
if kv[0].equals("ObjectGUId")
{
logObject.setGUId(kv[1]); // example mutator/setter method
}
else if //...
However, all your fields in LogObject are private and you haven't shown us any methods, so I hope you have some way of setting them from outside... bear in mind you will need to store the pairs in a data structure of some kind (as I have done with a HashMap) if you intend to intialise a LogObject with all the fields rather than setting the fields after a constructor call.
Speaking of SSCCEs, I made one for this answer.
So I'm trying to take the source of the gv4me app, and modify it. I have this filter I have to get around, and the way to get past it is to put a certain keyword(lets say it's "foobar") in whatever URL you're trying to access. So I've got the source compiled and such, but I can't figure out how to add this word in properly. So far, adding it to the post doesn't work. These are the URLs that gv4me uses:
private static final String rnrURL = "https://www.google.com/voice/m/i/voicemail?p=1000";
private static final String clientLoginURL = "https://www.google.com/accounts/ClientLogin";
private final String callURL = "https://www.google.com/voice/call/connect";
private static final String markReadURL = "https://www.google.com/voice/m/mark?p=1&label=unread&id=";
private static final String getMsgsURL = "https://www.google.com/voice/inbox/recent/unread";
private static final String textURL = "https://www.google.com/voice/sms/send";
private static final String replyURL = "https://www.google.com/voice/m/sendsms";
I need to modify each of these URLs so they have "foobar" in them, but still link to the same page. Is this possible?
EDIT: Also, if you search for HandlerUI on google, you'll find a plethora of applications(closed and open source) modified to include a user interface for automatically modifying all connection attempts of said applications. However, the creator is fairly difficult to locate, so I was wondering if anyone knew how to do this?
EDIT2: It seems that adding a query string variable doesn't seem to work. What I think would most likely work, is to somehow replace www.google.com with foobar.freednsredirectservice.com. Does anyone know of anything similar to this? Something that would allow foobar.freednsredirectservice.com/voice to still work?
Try adding a query string parameter. This may not, but usually will work.
For example:
http://www.example.com/ -> http://www.example.com/?foobar
http://www.example.com/page?existing=value -> http://www.example.com/page?foobar&existing=value
Your question is unclear as to where the foobar should go, but let's assume it's after the host name, ie
"https://www.google.com/voice/sms/send" --> "https://www.google.com/foobar/voice/sms/send"
Use this:
String url = "https://www.google.com/voice/sms/send";
url = url.replaceFirst("(?<=[^:/]/)", "foobar/");
System.out.println(url); // https://www.google.com/foobar/voice/sms/send
If the foobar replaces the hostname, ie
"https://www.google.com/voice/sms/send" --> "https://foobar/voice/sms/send" use this:
Use this:
String url = "https://www.google.com/voice/sms/send";
url = url.replaceAll("//.*?/", "//foobar/");
System.out.println(url); // https://foobar/voice/sms/send
I would say no because then it would be a link is an adress and a different adress leads to a different place. What you could do is something like this:
String[] url = new String[2];
url[0] = "http://www.yoururl.com/";// Accual url
url[1] = url[0].replaceFirst("(?<=[^:/]/)", "foobar/");// For other purpose such as diplay
Here's the situation :
I have 3 objects all named **List and I have a method with a String parameter;
gameList = new StringBuffer();
appsList = new StringBuffer();
movieList = new StringBuffer();
public void fetchData(String category) {
URL url = null;
BufferedReader input;
gameList.delete(0, gameList.length());
Is there a way to do something like the following :
public void fetchData(String category) {
URL url = null;
BufferedReader input;
"category"List.delete(0, gameList.length());
, so I can choose which of the lists to be used based on the String parameter?
I suggest you create a HashMap<String, StringBuffer> and use that:
map = new HashMap<String, StringBuffer>();
map.put("game", new StringBuffer());
map.put("apps", new StringBuffer());
map.put("movie", new StringBuffer());
...
public void fetchData(String category) {
StringBuffer buffer = map.get(category);
if (buffer == null) {
// No such category. Throw an exception?
} else {
// Do whatever you need to
}
}
If the lists are fields of your object - yes, using reflection:
Field field = getClass().getDeclaredField(category + "List");
List result = field.get();
But generally you should avoid reflection. And if your objects are fixed - i.e. they don't change, simply use an if-clause.
The logically simplest way taking your question as given would just be:
StringBuffer which;
if (category.equals("game"))
which=gameList;
else if (category.equals("apps"))
which=appList;
else if (category.equals("movie"))
which=movieList;
else
... some kind of error handling ...
which.delete();
As Jon Skeet noted, if the list is big or dynamic you probably want to use a map rather than an if/else/if.
That said, I'd encourage you to use integer constant or an enum rather than a String. Like:
enum ListType {GAME, APP, MOVIE};
void deleteList(ListType category)
{
if (category==GAME)
... etc ...
In this simple example, if this is all you'd ever do with it, it wouldn't matter much. But I'm working on a system now that uses String tokens for this sort of thing all over the place, and it creates a lot of problems.
Suppose you call the function and by mistake you pass in "app" instead of "apps", or "Game" instead of "game". Or maybe you're thinking you added handling for "song" yesterday but in fact you went to lunch instead. This will successfully compile, and you won't have any clue that there's a problem until run-time. If the program does not throw an error on an invalid value but instead takes some default action, you could have a bug that's difficult to track down. But with an enum, if you mis-spell the name or try to use one that isn't defined, the compiler will immediately alert you to the error.
Suppose that some functions take special action for some of these options but not others. Like you find yourself writing
if (category.equals("app"))
getSpaceRequirements();
and that sort of thing. Then someone reading the program sees a reference to "app" here, a reference to "game" 20 lines later, etc. It could be difficult to determine what all the possible values are. Any given function might not explicitly reference them all. But with an enum, they're all neatly in one place.
You could use a switch statement
StringBuffer buffer = null;
switch (category) {
case "game": buffer = gameList;
case "apps": buffer = appsList;
case "movie": buffer = movieList;
default: return;
}