Magnolia JCR get LinkedList Property Items - java

I am trying to retrieve the node 0's property - tag values, which is a linkedList object property I believe. as you can see it is [****,****]
I wish to retrieve the object value and store into a List<String> object
So I can get the each value out for late use, e.g
String idA = "542f74fd-bfaf-4377-854a-8e62082edc6c";
string idB = "39aab11f-243f-464c-ae6d-c1f069f17d6c";
My attampt is something like below:
List<String> tagList = new ArrayList<String>();
tagList = componentNode.getProperties(node, "tags");
also tried this:
List<String> tagList = new ArrayList<String>();
tagList = PropertyUtil.getProperty(node, "tags");
but none of them works.
Please suggest me with code sample.
Thanks

I believe they are called multi value properties in JCR and is supported via Arrays instead of Lists.
I haven't tested the code myself but I believe it'll work.
This should do the trick:
Property property = node.getProperty("tags");
Value[] tags = property.getValues();
and then you can convert/wrap it to List if you really want to.
Hope that helps,
Cheers,

Related

Convert list to hashmap

Title of the question may give you the impression that it is duplicate question, but according to me it is not.
I am just a few months old in Java and a month old in MongoDB, SpringBoot and REST.
I have a Mongo Collection with 3 fields in a document, _id (default field), appName and appKey. I am using list to iterate through all the documents and find one document whose appName and appKey matches with the one that is passed. This collection right now has only 4 entries, and thus it is running smoothly. But I was reading a bit about collections and found that if there will be a higher number of documents in a collection then the result with list will be much slower than hashMap.
But as I have already said that I am quite new to Java, I am having a bit of trouble converting my code to hashMap, so I was hoping if someone can guide me through this.
I am also attaching my code for reference.
public List<Document> fetchData() {
// Collection that stores appName and appKey
MongoCollection<Document> collection = db.getCollection("info");
List<Document> nameAndKeyList = new ArrayList<Document>();
// Getting the list of appName and appKey from info DB
AggregateIterable<Document> output = collection
.aggregate(Arrays.asList(new BasicDBObject("$group", new BasicDBObject("_id",
new BasicDBObject("_id", "$id").append("appName", "$appName").append("appKey", "$appKey"))
)));
for (Document doc : output) {
nameAndKeyList.add((Document) doc.get("_id"));
}
return nameAndKeyList;
}// End of Method
And then I am calling it in another method of the same class:
List<Document> nameAndKeyList = new ArrayList<>();
//InfoController is the name of the class
InfoController obj1 = new InfoController();
nameAndKeyList = obj1.fetchData();
// Fetching and checking if the appName & appKey pair
// is present in the DB one by one.
// If appName & appKey mismatches, it increments the value
// of 'i' and check them with the other values in DB
for (int i = 0; i < nameAndKeyList.size(); i++) {
"followed by my code"
And if I am not wrong then there will be no need for the above loop also.
Thanks in advance.
You just need a simple find query to get the record you need directly from Mongo DB.
Document document = collection
.find(new Document("appName", someappname).append("appKey", someappkey)).first();
First of all a list is not much slower or faster than an HashMap. A Hasmap is commonly used to save key-pair values such as "ID", "Name" or something like that. In your case I see you are using ArrayList without a specified size for the list. better use a linked list when you do not know the size because an arraylist is holding a array behind and extending this by copying. If you want to generate a Hasmap out of the List or use a Hasmap you need to map an ID and the value to the records.
HashMap<String /*type of the identifier*/, String /*type of value*/> map = new HashMap<String,String>();
for (Document doc : output) {
map.put(doc.get("_id"), doc.get("_value"));
}
First, avoid premature optimization (lookup the expression if you don’t know what it is). Put a realistic number of thousands of items containing near-realistic data in your list. Try to retrieve an item that isn’t there. This will force your for loop to traverse the entire list. See how long it takes. Try a number of times to get an impression of whether you get impatient. If you don’t, you’re done.
If you find out that you need a speed-up, I agree that HashMap is one of the obvious solutions to try. One of the first things to consider with this is a key type for you HashMap. As I understand, what you need to search for is an item where appName and appKey are both right. The good solution is to write a simple class with these two fields and equals and hashCode methods (I’ll call it DocumentHashMapKey for now, think of a better name). For hashCode(), try Objects.hash(appName, appKey). If it doesn’t give satisfactory performance with the data you have, consider alternatives. Now you are ready to build your HashMap< DocumentHashMapKey, Document>.
If you’re lazy or just want a first impression of how a HashMap performs, you may also build your keys by concatenating appName + "$##" + appKey (where the string in the middle is something that is unlikely to be part of a name or key) and use HashMap<String, Document>.
Everything I said can be refined depending on your needs. This was just to get you started.
Thanks everyone for your help, without which I would not have got to a solution.
public HashMap<String, String> fetchData() {
// Collection that stores appName and apiKey
MongoCollection<Document> collection = db.getCollection("info");
HashMap<String, String> appKeys = new HashMap<String, String>();
// Getting the list of appName and appKey from info DB
AggregateIterable<Document> output = collection
.aggregate(Arrays.asList(new BasicDBObject("$group", new BasicDBObject("_id",
new BasicDBObject("_id", "$id").append("appName", "$appName").append("appKey", "$appKey"))
)));
String appName = null;
String appKey = null;
for (Document doc : output) {
Document temp = (Document) doc.get("_id");
appName = (String) temp.get("appName");
appKey = (String) temp.get("appKey");
appKeys.put(appName, appKey);
}
return appKeys;
Calling the above method into another method of the same class.
InfoController obj = new InfoController();
//Fetching the values of 'appName' & 'appKey' sent from 'info' DB
HashMap<String, String> appKeys = obj.fetchData();
storedAppkey = appKeys.get(appName);
//Handling the case of mismatch
if (storedAppkey == null || storedApikey.compareTo(appKey)!=0)
{//Then the response and further processing that I need to do.
Now what HashMap has done is that it has made my code more readable and the 'for' loop that I was using for iterating is gone, although it might not make much difference in the performance as of now.
Thanks once again to everyone for your help and support.

Sling - AEM sling:members from a new collection

I've recently entered the world of AEM and sling (api). What I'm trying to do is write Java code to get the sling:members and its properties sling:resources for a new collection I created in the touch. I'm able to reference the collection properties with a ResourceResolver.resolve(path). The sling:members show up as { ....}. Do I have to do a separate ResourceResolver?
String path="/content/dam/collections/m/fafdsfdaf/my_collection";
Resource resourceMember = resourceResolver.resolve(path+"/sling:members");
ValueMap metaData = resourceMember.adaptTo(ValueMap.class);
String[] slingResources = metaData.get("sling:resources", new String[0]);
Am I totally off the mark? Any help would be greatly appreciated.
The correct way to get the members of the collection is to use the ResourceCollection API. To do this you obtain the resource which points to the collection then adapt it to a ResourceCollection. From there you call getResources() which returns you an iterator over the members.
Resource r = resourceResolver.getResource("/content/dam/collections/m/fafdsfdaf/my_collection");
ResourceCollection collection = r.adaptTo(ResourceCollection.class);
Iterator<Resource> it = collection.getResources();
while(it.hasNext()) {
Resource p = it.next();
%><%= p.getPath() %><%
}
Turns out this is the correct way to do this and is working.

HashSet contains substring

I have a HashSet of Strings in the format: something_something_name="value"
Set<String> name= new HashSet<String>();
Farther down in my code I want to check if a String "name" is included in the HashSet. In this little example, if I'm checking to see if "name" is a substring of any of the values in the HashSet, I'd like it to return true.
I know that .contains() won't work since that works using .equals(). Any suggestions on the best way to handle this would be great.
With your existing data structure, the only way is to iterate over all entries checking each one in turn.
If that's not good enough, you'll need a different data structure.
You can build a map (name -> strings) as follows:
Map<String, List<String>> name_2_keys = new HashMap<>();
for (String name : names) {
String[] parts = key.split("_");
List<String> keys = name_2_keys.get(parts[2]);
if (keys == null) {
keys = new ArrayList<>();
}
keys.add(name);
name_2_keys.put(parts[2], keys);
}
Then retrieve all the strings containing the name name:
List<String> keys = name_2_keys.get(name)
You can keep another map where name is the key and something_something_name is the value.
Thus, you would be able to move from name -> something_something_name -> value. If you want a single interface, you can write a wrapper class around these two maps, exposing the functionality you want.
I posted a MapFilter class here a while ago.
You could use it like:
MapFilter<String> something = new MapFilter<String>(yourMap, "something_");
MapFilter<String> something_something = new MapFilter<String>(something, "something_");
You will need to make your container into a Map first.
This would only be worthwhile doing if you look for the substrings many times.

How to pass a list of values into a crystal report

I have a list of integer values(employee IDs) which i need to pass to a Crystal Report.
I am using a Action class to pass these values.
So far i have succeeded with passing a single value but i couldn't find a way to pass a list of values.
Fields fields = new Fields();
Values vals1 = new Values();
ParameterFieldDiscreteValue pfieldDV1 = new ParameterFieldDiscreteValue();
pfield1.setName("fromDate");
pfieldDV1.setValue(start_Date);
vals1.add(pfieldDV1);
pfield1.setCurrentValues(vals1);
fields.add(pfield1);
CrystalReportViewer viewer = new CrystalReportViewer();
//some code to set CrystalReportViewer settings
viewer.setParameterFields(fields);
By this way i was able to get the fromDate value into the Crystal Report.
Does any one know how to get a this kind of list
int employeeList[]
Or a
String[] empListOptions
Thanks in advance.
foreach (string in string_array)
{
param.Value = string;
report.ParameterFields[parameter].CurrentValues.Add(param);
}
Found here: http://www.logicaltrinkets.com/wordpress/?p=227

Apache Velocity access String array created in Java code?

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 ;)

Categories