Apache Velocity access String array created in Java code? - java

I am trying to access a String array which i have created in my Java class.
The string array is stored in a Map with the name 'notSelected' using the same key.
I also have a single String object called 'testString' stored in the same Map which i can easily access and display using:
$testString
However how do i go about accessing the String array object (notSelected) from the Map inside the velocity template object?
I have tried:
$notSelected.get(0)
$notSelected[0]
$notSelected.[0]
${notSelected}.get(0)
The last three seem to return the reference value of the memory location of the String array object but i still can't access the values inside the array.
Any help is gladly appreciated. Thanks
Here is the java code:
public Map<String, Object> getVelocityParameters
(final Issue issue, final CustomField field, final FieldLayoutItem fieldLayoutItem) {
final Map<String, Object> map = super.getVelocityParameters(issue, field, fieldLayoutItem);
String[] notSelected = {"foo", "bar", "baz"};
map.put("notSelected", notSelected);
String[] selected = {"foo", "bar", "baz"};
map.put("selected", selected);
//this code works and i can access $testString in the velocity template
String testString = "Test Worked";
map.put("testString", testString);
return map;
}

JIRA uses an older version of Velocity that does not support array index notation for accessing arrays. Instead, use a List and .get(n) notation:
List foo = new ArrayList() {{ add("hi"); add("there"); }};
$foo.get(0)
$foo.get(1)
And remember, little tidbits of info like the environment you're operating in can make a huge difference (and when someone asks a question, there may be a reason for asking it ;)

Related

How to get an Array from an EnumMap?

In Java EnumMaps have constant access time, because they can be implemented with an array using the ordinal value of the enum as an index.
If I have an EnumMap how can I get the Array?
Example:
enum Abc { A, B, C };
EnumMap<Abc, String> abc = new EnumMap<Abc, String>(Abc.class);
abc.put(Abc.A, "α");
abc.put(Abc.B, "β");
abc.put(Abc.C, "γ");
String[] abcarray = ?;
The variable abcarray should contain the same as if initialized in this way:
String[] abcarray = new String[] { "α", "β", "γ" };
I can not find a method in the documentation. Why is such a function missing?
You can go via the Map.values() method (remember that an EnumMap is just a specialized Map):
String[] abcarray = abc.values().toArray(new String[abc.size()]);
For the reason why no such method exists we can only speculate.
But there are two common themes in the collections framework, that come into play here:
allow complexer operations by chaining simpler operations (which reduces the total number of operations/methods that need to be implemented, while keeping the options available)
get rid of arrays: they have no real use once you're in "collection area"
It is a little abstracted... try :
String[] abcarray = abc.values().toArray(new String[abc.size()]);

Is the given initialization of an associative array wrong?

Suppose I define the following statement, will an array of dictionaries (key-value pairs) be created, with all keys initialized to "stringvalue1" and values to stringvalue2?
String exampledatastruct[] = { "stringvalue1", stringvlaue2 };
Is the above statement a bad way of using?
The above Collection type is unsuitable for keyed access. Use a Map:
Map<String, String> map = new HashMap<>();
map.put("stringvalue1", stringvlaue2);
That would simply give you an array with two String elements in it. The first would be the string "stringvalue1", the second would be whatever String the variable stringvalue2 references. There'd be no relation between the two, other than the fact they're in the same array.
What you wrote is an array, not a dictionary. A usual representation of java dictionary is java.util.Map. For example:
Map<String, String> dictionary= new HashMap<String, String>();
you would put values in the dictionary in this way:
dictionary.put("key", "value");
and would get values from the dictionary in this way:
String value= dictionary.get("key");
You are creating a String array, not an associative array. You should use the java Map interface. Also, you can only have 1 key "stringvalue1".

Can you reference a java variable from a string?

Hi I have a strange question about java. I will leave out the background info so as not to complicate it. If you have a variable named fname. And say you have a function returning a String that is "fname". Is there a way to say reference the identifier fname via the String "fname". The idea would be something like "fname".toIdentifier() = value but obviously toIdentifier isn't a real method.
I suppose a bit of background mite help. Basically I have a string "fname" mapped to another string "the value of fname". And I want a way to quickly say the variable fname = the value of the key "fname" from the map. I'm getting the key value pair from iterating over a map of cookies in the form . And I don't want to do "if key = "fname" set fname to "value of fname" because I have a ton of variables that need to be set that way. I'd rather do something like currentkey.toIdentifer = thevalue. Weird question maybe I'm overlooking a much easier way to approach this.
Why don't you just use a simple hashmap for this?
Map<String, String> mapping = new HashMap<String, String>();
mapping.put("fname", "someValue");
...
String value = mapping.get(key); //key could be "fname"
In a way you're describing what reflection is used for:
You refer to an object's fields and methods by name.
Java Reflection
However, most of the time when people ask a question like this, they're better off solving their problem by re-working their design and taking advantage of data structures like Maps.
Here's some code that shows how to create a Map from two arrays:
String[] keyArray = { "one", "two", "three" };
String[] valArray = { "foo", "bar", "bazzz" };
// create a new HashMap that maps Strings to Strings
Map<String, String> exampleMap = new HashMap<String, String>();
// create a map from the two arrays above
for (int i = 0; i < keyArray.length; i++) {
String theKey = keyArray[i];
String theVal = valArray[i];
exampleMap.put(theKey, theVal);
}
// print the contents of our new map
for (String loopKey : exampleMap.keySet()) {
String loopVal = exampleMap.get(loopKey);
System.out.println(loopKey + ": " + loopVal);
}
Here's a link to the JavaDoc for Map.

Using one variable as an another variable of different data type but the same name

I am using a class where I am taking input as the file name and the file location. I have a pre defined file names, so I will match the predefined file names with the file name that I received and then store the values accordingly. Please look at the code below
//Set of storage maps and tables
public class storage
{
//Storage set
public static Set<Integer> tiger = new HashSet<Integer>();
//Storage set
public static Set<Integer> lion = new HashSet<Integer>();
//This is the table used for storing the browser customer count
public static Table<String,String,Integer> elephant = HashBasedTable.create();
//Storage map
public static Map<String, String> monkey = new HashMap<String, String>();
public static void storeDataDirector(String fileLocation,String fileName) throws Exception
{
if (fileName = monkey)
**update the "monkey map"**
}
This is my problem, also I have lot of maps and tables to be used so I wouldn't be able to use multiple if conditions and then check and update the same.
What I would like to know is the below
As I have said earlier, The file name that I am sending to the program which is "String filename" has the same name of the "Map monkey" but the former is a String and the latter is the map. I would like to know if I will be able to use the string variable as a reference to the map instance as both of them have the same name . This will highly avoid the if conditions that I am using in the program and thus I would like to possible solution for this ... Anything related to type caseting ort
You need to have another Map - whose key is a String and value is a Map. Something like Map<String,Map> allMaps = new HashMap<String,Map>()
Once you have this map , populate it with all your filenames and the corresponding maps monkey.
allMaps .put("monkey", monkey)
If a string filename corresponds to not a map but to a set , then you need to declare something more general Map<String,Object> allMaps = new HashMap<String,Object>(). Ofcourse this means you need to cast the value to its particular type before you can do any meaningful thing with it.
Then , to use this map , use your filename argument
Map monkeyAgain = allMaps.get(filename)
You can use reflection:
Storage.class.getField(fileName).get(null)
You will still have to cast the returned object. I do not think this the right approach.
The idea is to relate them in a Map, and use the file name as a key for example
Map<String, Map<String, String>>
// file store structure
If you need a generic solution, you could solve this by implementing an abstraction of your store structure, by implementing an interface similar to this one:
// T is the store type and U is the original type (String from file for instance...)
public interface StoreUnit<T, U> {
void update(U record);
List<T> list();
}
so you will have an implementation for each case (Set, Map, Table ...) and will relate it in a map using the file name as key.
monkeyFileName => MapStoreUnit<Entry<String,String>,String>
tigerFileName => SetStoreUnit<Integer, String>
elephantFileName => TableStoreUnit<Entry<Entry<String,String>,String>,String> // not sure if for Table there is something better than Entry ;)
When you wanna update some store you perform a get over the map using the file name as key, and invoking update method implemented with the record (that could be an String, complex Object) and so on. When you need to read something from there you could use the list method.

convert fetched data into string , string array map

i am fetching a data from sqlite in android which is as follows
URL PHONE
---------------------------------
/test/img1.png 98989898
/test/img1.png 61216121
/test/img2.png 75757575
/test/img2.png 40404040
/test/img3.png 36363636
now i want to create such a map which stores the data as follows
/test/img1.png [98989898 , 61216121 ]
/test/img2.png [75757575 , 40404040 ]
/test/img3.png [36363636]
so that i can pass the whole map to the function which function eventually in background pick up the image url and send the data to the arrays listed to the phone number. so how can i transform the data that i have fetched into the key to string array style ?
I'd create a Map<String, List<String>> (aka "multi-map"). You don't have to know how many phone numbers for a given URL before you start if you use List<String>. That's not so if you choose the array route.
Map<String, List<String>> results = new HashMap<String, List<String>>();
while (rs.next()) {
String url = rs.getString(1);
String phone = rs.getString(2);
List<String> phones = (results.contains(url) ? results.get(url) : new ArrayList<String>());
phones.add(phone);
results.put(url, phones);
}
Google Collections has a multi-map that you can use out of the box, but I think you'll agree that this is sufficient.
If you want to store more items (e.g. name) you should start thinking about an object that encapsulates all of them together into one coherent thing. Java's an object-oriented language. You sound like you're guilty of thinking at too low a level. Strings, primitives, and data structures are building blocks for objects. Perhaps you need a Person here:
package model;
public class Person {
private String name;
private Map<String, List<String>> contacts;
// need constructors and other methods. This one is key
public void addPhone(String url, String phone) {
List<String> phones = (this.contacts.contains(url) ? this.contacts.get(url) : new ArrayList<String>());
phones.add(phone);
this.contacts.put(url, phones);
}
}
I'll leave the rest for you.
If you go this way, you'll need to map a result set into a Person. But you should see the idea from the code I've posted.

Categories