public Collection<OwnerDetail> getAllOwners() {
final MorphiaCursor<Listing> listings = datastore.find(Listing.class)
.iterator(new FindOptions()
.projection().include("ownerDetail"));
Map<String, OwnerDetail> map = new HashMap<>();
while (listings.hasNext()) {
final Listing next = listings.next();
if (next.getOwnerDetail() != null) {
map.put(next.getOwnerDetail().getEmail(), next.getOwnerDetail());
}
}
return map.values();
}
I want to remove java code that distinct values by email and handle it by mongodb morphia. How can I do that?
Related
I have Request by status = PENDING_PAYMENT,DONE, I want to split by comma with java spring to search
data by find to repository.
how can I resolved this?
#Override
public Map<String, Object> getAllOrderDetails(String status, String productName, String page, String limit) {
Map<String, Object> result = new HashMap<>();
String[] statusSplit = status.split(",");
OrderStatus os = OrderStatus.valueOf(status.toUpperCase());
List<Order> orders = orderRepo.findByStatus(os);
if(orders == null){
throw new NonexistentEntityException(ErrCode.ERR_UNKNOWN, "Order not listed");
}
List<OrderResult> order = new ArrayList<>();
// order = serviceDataList.getOrderDetails(o);
result.put("order", order);
return result;
}
This is the sql script that I have used to create the necessary classes :
CREATE CLASS ProductSummary;
CREATE PROPERTY ProductSummary.name STRING (NOTNULL, MANDATORY TRUE);
CREATE PROPERTY ProductSummary.modelNumber LONG (NOTNULL, MANDATORY TRUE);
ALTER CLASS ProductSummary STRICTMODE TRUE;
CREATE CLASS PricingSummary;
CREATE PROPERTY PricingSummary.price LONG (NOTNULL, MANDATORY TRUE);
CREATE PROPERTY PricingSummary.discount LONG (NOTNULL, MANDATORY TRUE);
ALTER CLASS PricingSummary STRICTMODE TRUE;
CREATE CLASS TotalSummary EXTENDS V;
CREATE PROPERTY TotalSummary.projectLink LINK Project (NOTNULL, MANDATORY TRUE);
CREATE PROPERTY TotalSummary.productSummaries EMBEDDEDLIST ProductSummary;
CREATE PROPERTY TotalSummary.pricingSummaries EMBEDDEDLIST PricingSummary;
ALTER CLASS TotalSummary STRICTMODE TRUE;
CREATE INDEX TotalSummary_projectLink_idx ON TotalSummary (projectLink) UNIQUE;
I am trying to insert some values into my TotalSummary class, where I also need to insert some values into the EmbeddedList for pricingSummaries and productSummaries.
public TotalSummary create(final TotalSummary totalSummary) {
final Long projectId = 1;
final StatementBuilder builder = new StatementBuilder();
final StringBuilder query = new StringBuilder();
final List<Map<?, ?>> productSummaries = totalSummary.getProductSummaries().stream()
.map(ProductSummary::toMap)
.collect(Collectors.toList());
final List<Map<?, ?>> pricingSummaries = totalSummary.getPricingSummaries().stream()
.map(PricingSummary::toMap)
.collect(Collectors.toList());
builder.addAttribute("projectLink = (SELECT FROM project WHERE id = ?)", projectId);
if ( ! productSummaries.isEmpty()) {
builder.addAttribute("productSummaries = ?", productSummaries);
}
if ( ! pricingSummaries.isEmpty()) {
builder.addAttribute("pricingSummaries = ?", pricingSummaries);
}
try {
insert(TotalSummary.class.getSimpleName(), builder.attributes(), statement -> {
builder.init(statement);
return statement;
});
} catch (final UncategorizedSQLException e) {
throw new ConstraintViolationException(totalSummary, ExceptionUtils.getRootCauseMessage(e), e);
}
return assertNotNull(findById(projectId));
}
This is the utility method that I am using to build the insert query :
protected String insert(final String vertex, final String fieldValuePairs, final PreparedStatementInitializer initializer) {
final String sql = "INSERT INTO " + vertex + " SET " + fieldValuePairs + " RETURN #rid";
return executeStatement(sql, initializer);
}
The toMap methods to convert the List<ProductSummary> to List<Map<?,?>>
**ProductSummary**
public Map<String, Object> toMap() {
final Map<String, Object> ret = new HashMap<>();
ret.put("name", name);
ret.put("model number", Long.valueOf(modelNumber));
return ret;
}
The toMap methods to convert the List<PricingSummary> to List<Map<?,?>>
**PricingSummary**
public Map<String, Object> toMap() {
final Map<String, Object> ret = new HashMap<>();
ret.put("price", Long.valueOf(price));
ret.put("discount", Long.valueOf(discount));
return ret;
}
I am getting the following exception when I execute the code
Constraint violation for: TotalSummary#58f79eeb[recordId=<null>,customProperties=[]]. Reason: OValidationException: The field 'TotalSummary.productSummaries' has been declared as EMBEDDEDLIST but an incompatible type is used.
Things that I have already tried :
I have tried to covert to list to json format before adding it to
the builder like so new Gson().toJson(pricingSummaries);
Converted the pricingSummaries and productSummaries toArray().
You defined the summaries as EMBEDDEDLIST ProductSummary but you are passing lists of maps as values.
Try to create real ProductSummary objects instead eg.
OElement ret = db.newEmbeddedElement("ProductSummary");
ret.setProperty("price", Long.valueOf(price));
ret.setProperty("discount", Long.valueOf(discount));
I have ProductInfo object which looks like this
ProductInfo.java
public class ProductInfo
{
private List<String> servicetagInfo;
}
I have Order object like this which has list of Products info
OrderDetail.java
public class OrderDetail
{
private String orderNum;
private List<ProductInfo> productInfo;
}
And then I have a Response object which basically has List of Order objects
Response.java
public class Response
{
private List<OrderDetail> orderInfo;
}
I am getting response as expected.But right now in this format
orderInfo:
0: {orderNum: "162293591",...}
productInfo:
0: {servicetag_info: ["7LSMW33", "49SMW33"]}
1: {servicetag_info: ["JF6XN33", "CQ5XN33"]}
2: {servicetag_info: ["5VRR523", "13LR523"]}
Here I am trying to merge productInfo List to be like this
productInfo:
0: {servicetag_info: ["7LSMW33", "49SMW33","JF6XN33", "CQ5XN33","5VRR523", "13LR523"]}
Just add all strings into one main property.
Here is my code
List<String> serviceTagList = new ArrayList<>();
for (OrderDetail orderDetail : arInvoiceOrderResponseBody.getOrders()) { //Here i am getting orders from external service
if (orderDetail != null) {
if (orderDetail.getProductInfo() != null && orderDetail.getProductInfo().size() > 0) {
for (ProductInfo productInfoDetail : orderDetail.getProductInfo()) {
if (productInfoDetail != null) {
if (productInfoDetail.getServicetagInfo() != null) {
for (String serviceTag : productInfoDetail.getServicetagInfo()) {
serviceTagList.add(serviceTag);
}
}
}
}
}
}
ProductInfo productInfo = new ProductInfo();
productInfo.setServicetagInfo(serviceTagList);
orderDetail.setProductInfo(Arrays.asList(productInfo));
}
Can anyone suggest how can i achieve same using streams in java so that it will be readable.
Try this:
Set<String> tags = order.stream()
.flatMap(order -> order.getProductInfo().stream())
.map(ProductInfo::getServicetagInfo)
.collect(Collectors.toSet());
Full implementation:
for (OrderDetail orderDetail : arInvoiceOrderResponseBody.getOrders()) {
if (orderDetail != null && orderDetail.getProductInfo() != null) {
orderDetail.getProductInfo().removeAll(null); // Remove any null elems
Set<String> tags = orderDetail.getProductInfo().stream()
.flatMap(product -> (product.getServicetagInfo() == null) ? null : product.getServicetagInfo().stream())
.collect(Collectors.toSet());
tags.remove(null); // Remove null if exists
}
ProductInfo productInfo = new ProductInfo();
productInfo.setServicetagInfo(tags);
orderDetail.setProductInfo(Arrays.asList(productInfo));
}
With streams your code could be like this:
arInvoiceOrderResponseBody.getOrders().stream()
.filter(Objects::nonNull)
.forEach(YourClassName::mergeProductInfo);
The method mergeProductInfo would be:
private static void mergeProductInfo(OrderDetail orderDetail) {
List<String> serviceTagList = new ArrayList<>();
if (orderDetail.getProductInfo() != null) {
serviceTagList = orderDetail.getProductInfo().stream()
.filter(Objects::nonNull)
.map(ProductInfo::getServicetagInfo)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
ProductInfo productInfo = new ProductInfo();
productInfo.setServicetagInfo(serviceTagList);
orderDetail.setProductInfo(Arrays.asList(productInfo));
}
It could be simplified if you could be sure that you are not going to receive null lists or elements.
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 render a key,value Map to a template and then show there in this way:
#(twittsIfollow: Map[String, String])
.....
#if(twittsIfollow != null) {
#for((key, value) <- twittsIfollow) {
#key
#value
}
}
it says, it is wrong. is there a scala tag for Map keys values?
here is my method:
public static Map<String, String> alltwitts(List<Long> otherIDs) {
Map<String, String> results=new HashMap<String, String>();
for (Long id: otherIDs) {
Query selected_twitt = JPA.em().createQuery("select u.twitt from Twitt u where " + " u.whose = ?").setParameter(1, id);
String twOwner = User.getOneUser(id);
String twitt = (String) selected_twitt.getSingleResult();
results.put(twOwner, twitt);
}
return results;
}
then i render to template in this place:
Map<String, String> twittsIfollow = Twitt.alltwitts(IDusersIamFollowing);
return ok(microblog.render(twittsIfollow));
now it is saying: [NonUniqueResultException: result returns more than one elements]
thanks
Simply
#for((key, value) <- twittsIfollow) {
#key
#value
}
BTW, if you are using Scala, twittsIfollow should never be null. Prefer using Option.
how i solved:
public static Map<String, List<String>> alltwitts(List<Long> otherIDs) {
Map<String, List<String>> results=new HashMap<String, List<String>>();
for (Long id: otherIDs) {
Query selected_twitt = JPA.em().createQuery("select twitt from Twitt where " + " whose = ? order by id").setParameter(1, id);
String twOwner = User.getOneUser(id);
List<String> twitt = selected_twitt.getResultList();
results.put(twOwner, twitt);
}
System.out.println(results);
return results;
}
then in my Application:
Map<String, List<String>> twittsIfollow = Twitt.alltwitts(IDusersIamFollowing);
return ok(microblog.render(twittsIfollow));
then in my template:
#(twittsIfollow: Map[String, List[String]])
and
#if(twittsIfollow != null) {
#for((key, value) <- twittsIfollow) {
#for(innervalue <- value){
Username: #key
Twitt: #innervalue
}
}
}
just for those who are dumb like me :D and looking for solution like this..
thanks for help,guys..
#doniyor, I'm surpriesed as I showed you the way in other question not so long ago.
By the way I think it will be better to build, pass and iterate twittsIfollow as a List of Maps
then you can use
#if(twittsIfollow != null) {
#for(twitts <- twittsIfollow) {
the value is: #twitts.get("key")
}
}