How can I create an programatically Event for UnitTests in AEM 6.4 after EventPropertiesMap has been removed?
List<EventPropertiesMap> fakeModifications = new ArrayList<>();
fakeModifications.add(PageModification.deleted(pagePath,
StringUtils.EMPTY).getEventProperties());
Map eventProps = new HashMap();
eventProps.put("modifications", fakeModifications);
return new Event("com/day/cq/wcm/core/page", eventProps);
I came up with this solution hoping to share the pain of an upgrade with others :-)
If you got a better solution I'm more than welcome!
List<Map<String, ?>> fakesList = new ArrayList<Map<String, ?>>();
Map<String, ?> fakeModifications = PageModification.deleted(pagePath, StringUtils.EMPTY).getEventProperties();
fakesList.add(fakeModifications);
Map<String, List<Map<String, ?>>> eventProps = new HashMap<String, List<Map<String, ?>>>();
eventProps.put("modifications", fakesList);
return new Event("com/day/cq/wcm/core/page", eventProps);
Related
I'm using guava to compare two JSON files together and have done the following:
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String, Object>> type =
new TypeReference<HashMap<String, Object>>() {};
Map<String, Object> leftMap = mapper.readValue(leftJson, type);
Map<String, Object> rightMap = mapper.readValue(rightJson, type);
MapDifference<String, Object> difference = Maps.difference(leftMap, rightMap);
System.out.println(difference.entriesDiffering());
Output
package=([{Name=Sarah}], [{Name=Conor}])
Expected output
package=([{Name=Conor}])
Does anyone know how to manipulate the output to just show one side?
I assume that you want to end up with another Map<String,Object>, but taking the value of keys with differing values from the right (or maybe the left, you don't say).
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Map<String, Object> left = Map.of("name", "sarah");
Map<String, Object> right = Map.of("name", "connor");
MapDifference<String, Object> result = Maps.difference(left, right);
Map<String,Object> f = result.entriesDiffering().entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().rightValue()));
System.out.println(f);
}
}
MapDifference#entriesDiffering() returns Map<K,​MapDifference.ValueDifference<V>>, so please read ValueDifference and make use of its API.
Here's a sample MRE:
#Test
public void shouldShowDifferences() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String, Object>> type =
new TypeReference<HashMap<String, Object>>() {};
String leftJson = "{\"package\": [{\"Name\": \"Sarah\"}]}";
String rightJson = "{\"package\": [{\"Name\": \"Connor\"}]}";
Map<String, Object> leftMap = mapper.readValue(leftJson, type);
Map<String, Object> rightMap = mapper.readValue(rightJson, type);
MapDifference<String, Object> difference = Maps.difference(leftMap, rightMap);
System.out.println(difference.entriesDiffering());
// {package=([{Name=Sarah}], [{Name=Connor}])}
difference.entriesDiffering().forEach(
(key, valueDifference) -> System.out.printf(
"key: '%s'; values: left: '%s', right: '%s'",
key, valueDifference.leftValue(), valueDifference.rightValue()));
// key: 'package'; values: left: '[{Name=Sarah}]', right: '[{Name=Connor}]'
}
I want to create the following object for the response but I don't want to create the class for this. Is there any way I can achieve this using map or other util classes?
"conferenceData": {
"createRequest": {
"conferenceSolutionKey": {
"type": "hangoutsMeet"
},
"requestId": "RANDOM_STRING2"
}
}
I think below is the solution you are looking for...
Map<String, Object> conferenceData = new HashMap<>();
Map<String, Object> createRequest = new HashMap<>();
Map<String, Object> keyAndRequestId= new HashMap<>();
Map<String, String> type = new HashMap<>();
type.put("type", "hangoutsMeet");
keyAndRequestId.put("conferenceSolutionKey", type);
keyAndRequestId.put("requestId", "RANDOM_STRING2");
createRequest.put("createRequest", keyAndRequestId);
conferenceData.put("conferenceData", createRequest);
Try to use :
Map<String,Object> result = new ObjectMapper().readValue(JSON_SOURCE, HashMap.class);
Or if you are using org.json, JSONObject has a method toMap(). You can easily do :
Map<String, Object> myMap = myJsonObject.toMap();
how to merge the list of values to the same Key in hashmap?
if I use the above logic I'm getting below result as an output
{Adam=[[Subject, ComputerScience], [Subject, ComputerScience]]}
But I have to merge like the below result, is it possible to append the list of values to the same key?
{Adam=[Subject, ComputerScience,Subject, ComputerScience]}
public class DemoMap {
public static void main(String[] args) {
HashMap<String, ArrayList<String>> tmeMap = new HashMap<>();
HashMap<String, ArrayList<Object>> mngrMap = new HashMap<>();
ArrayList<Object> emailcontent = new ArrayList<>();
ArrayList<String> mngrList1 = new ArrayList<>();
mngrList1.add("Jay");
mngrList1.add("Aaron");
tmeMap.put("Adam", mngrList1);
//Adam is Senior Manager who has the list of managers under him
emailcontent.add("Subject");
emailcontent.add("ComputerScience");
mngrMap.put("Jay", emailcontent);
mngrMap.put("Aaron", emailcontent);
//Each manager will have the email content
ArrayList<Object> collectionOfManagerContent = new ArrayList<>();
for (Map.Entry<String,ArrayList<Object>> emailEntry : mngrMap.entrySet()) {
collectionOfManagerContent.add(emailEntry.getValue());
}
//our Target is to show the manager's content to Senior Project manager
HashMap<String, ArrayList<Object>> tmeEmailMap1 = new HashMap<>();
for (Map.Entry<String,ArrayList<String>> emailEntry : tmeMap.entrySet()) {
emailEntry.getValue();
tmeEmailMap1.put(emailEntry.getKey(), collectionOfManagerContent);
}
System.out.println(tmeEmailMap1.toString());
}
}
Use addAll() to add all elements of ArrayList into another ArrayList
for (Map.Entry<String,ArrayList<Object>> emailEntry : mngrMap.entrySet()) {
collectionOfManagerContent.addAll(emailEntry.getValue());
}
I'm trying to migrate an old project to Retrofit library and this project has quite tricky API. So I have a query template like this:
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch();
And I have to add some parameters here of following template:
filter[attributeId]=attributeValueId
For example:
products/search?filter[1]=10&filter[1]=11&filter[2]=20&filter[2]=21
That's how API works and I can't change it. I know that we can pass a list as a parameter, like this:
#Query("filter") List<Integer> attributeValueIds
But how can I also set parameter's name dynamically?
You can use an arrayList! Something like the code below.
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch(
#Query("status") List<Integer> status
);
ArrayList<Integer> queryStatus = new ArrayList<>();
queryStatus.add(0);
queryStatus.add(1);
queryStatus.add(2);
productService.productSearch(queryStatus);
Your url will be like that -> {url}?status=0&status=1&status=2
Thanks to the link, posted by #ILLIA DEREVIANKO (https://github.com/square/retrofit/issues/1324), I've managed to solve the problem with this class:
public class ProxyRetrofitQueryMap extends HashMap<String, Object> {
public ProxyRetrofitQueryMap(Map<String, Object> m) {
super(m);
}
#Override
public Set<Entry<String, Object>> entrySet() {
Set<Entry<String, Object>> originSet = super.entrySet();
Set<Entry<String, Object>> newSet = new HashSet<>();
for (Entry<String, Object> entry : originSet) {
String entryKey = entry.getKey();
if (entryKey == null) {
throw new IllegalArgumentException("Query map contained null key.");
}
Object entryValue = entry.getValue();
if (entryValue == null) {
throw new IllegalArgumentException(
"Query map contained null value for key '" + entryKey + "'.");
}
else if(entryValue instanceof List) {
for(Object arrayValue:(List)entryValue) {
if (arrayValue != null) { // Skip null values
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, arrayValue);
newSet.add(newEntry);
}
}
}
else {
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, entryValue);
newSet.add(newEntry);
}
}
return newSet;
}
}
With this we can just use a map, where key is a unique parameter name and value is a List of Strings, that are values for this parameter. Something like this:
ProxyRetrofitQueryMap map = new ProxyRetrofitQueryMap();
List<String> values1 = new ArrayList<>();
values1.add("10");
values1.add("11");
map.put("filter[1]", values1);
List<String> values2 = new ArrayList<>();
values1.add("20");
values1.add("21");
map.put("filter[2]", values2);
You can use #QueryMap annotation like this:
public interface NewsService() {
#GET("/news")
Call<List<News>> getNews(
#QueryMap Map<String, String> options
);
}
Map<String, String> data = new HashMap<>();
data.put("author", "Marcus");
data.put("page", String.valueOf(2));
...
newsService.getNews(data);
More details: https://futurestud.io/tutorials/retrofit-2-add-multiple-query-parameter-with-querymap
I am trying to call the Ejabberd command create_room_with_opts via XMLRPC using the apache XMLRPC api. The following is the code I am using.
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL(<EJABBERD_HOST_URL>));
XmlRpcClient client = new XmlRpcClient();
client.setConfig(config);
// Command string
String command = "create_room_with_opts";
Map<String, Object> struct1 = new HashMap<String, Object>();
struct1.put("user", <ADMIN_USERNAME>);
struct1.put("server", <HOST>);
struct1.put("password", <ADMIN_PASSWORD>);
struct1.put("admin", Boolean.TRUE);
Map<String, Object> struct = new HashMap<String, Object>();
struct.put("name", "testroom");
struct.put("service", <NAME_OF_SERVICE>);
struct.put("host", <HOST>);
struct.put("options", getOpts());
HashMap result = (HashMap) client.execute(command, params);
static Object[] getOpts() {
Object opt[] = new Object[1];
HashMap<String, Object> option = new HashMap<String, Object>();
HashMap<String, Object> optionTuple = new HashMap<String, Object>();
option.put("name", "public");
option.put("value", Boolean.TRUE);
optionTuple.put("option", option);
return opt;
}
However, when I run this code I get the following exception.
org.apache.xmlrpc.XmlRpcException: Error -122
Parameter '{struct,[{name,<<"public">>},{value,<<"true">>}]}' can't be coerced to type '{tuple,[{name,binary},{value,binary}]}'
at org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse(XmlRpcStreamTransport.java:181)
at org.apache.xmlrpc.client.XmlRpcStreamTransport.sendRequest(XmlRpcStreamTransport.java:149)
at org.apache.xmlrpc.client.XmlRpcHttpTransport.sendRequest(XmlRpcHttpTransport.java:95)
at org.apache.xmlrpc.client.XmlRpcSunHttpTransport.sendRequest(XmlRpcSunHttpTransport.java:39)
at org.apache.xmlrpc.client.XmlRpcClientWorker.execute(XmlRpcClientWorker.java:53)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:166)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:136)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:125)
I am unable to identify the problem in this code.
I have tried the example given in the ejabberd documentation at the API-Documentation,
but it seems that there is a syntax error in that example.
I am able to call the other commands(for example create_room, register, etc) for the same Ejabberd server successfully, so I know that the configuration is correct.
I am using JDK1.7 and apache XMLRPC api 3.1.3
Is there any other example(for create_room_with_opts command) which I can check.