Java 8 Copy Map with Filter of Another Map - java-8

I am trying to filter an original map by comparing with a condition map which has only the key sets with id. Based on the condition map, I want to filter from the original map.
The original map which I have is,
Map<Integer, AppFeatureDTO> appFeatureMap = new TreeMap<>();
which will result like,
{
"101": {
"id": 101,
"subFeature": {
"1": {
"id": 1,
"title": "Title Value",
"desc": "Description Value"
}
}
},
"102": {
"id": 102,
"subFeature": {
"1": {
"id": 1,
"title": "Title Value",
"desc": "Description Value"
}
}
},
"103": {
"id": 103,
"subFeature": {
"1": {
"id": 1,
"title": "Title Value",
"desc": "Description Value"
},
"2": {
"id": 2,
"title": "Title Value",
"desc": "Description Value"
},
"3": {
"id": 3,
"title": "Title Value",
"desc": "Description Value"
},
"4": {
"id": 4,
"title": "Title Value",
"desc": "Description Value"
}
}
}
}
and the corresponding classes are:
class AppFeatureDTO {
private int id;
private Map<Integer, AppSubFeatureDTO> subFeature;
}
class AppSubFeatureDTO{
private int id;
private String title;
private String description;
}
then I have a filter map,
Map<Integer, FeatureDTO> conditionFilterMap = new TreeMap<>();
which is resulting like,
{
"101": {
"id": 101,
"subFeature": {
"1": {
"id": 1,
}
}
},
"103": {
"id": 103,
"subFeature": {
"2": {
"id": 2
},
"4": {
"id": 4
}
}
}
}
the corresponding classes for the filter map are,
class FeatureDTO {
private int id;
private Map<Integer, SubFeatureDTO> subFeature;
}
class SubFeatureDTO{
private int id;
}
I want to filter the result map using conditionFilterMap like,
{
"101": {
"id": 101,
"subFeature": {
"1": {
"id": 1,
"title": "Title Value",
"desc": "Description Value"
}
}
},
"103": {
"id": 103,
"subFeature": {
"2": {
"id": 2,
"title": "Title Value",
"desc": "Description Value"
},
"4": {
"id": 4,
"title": "Title Value",
"desc": "Description Value"
}
}
}
}
I'm using spring modelMapper to copy AppFeatureDTO to FeatureDTO. But, filtering the map, I didn't get clue.
Could you please suggest how to get the resultMap using Java 8?
Even I couldn't imagine a simple solution using Java 7 or 6 also.

Assuming that the map key is the same as the id field:
Map<Integer, AppFeatureDTO> resultMap = conditionFilterMap.values().stream()
.map(FeatureDTO::getId)
.map(appFeatureMap::get)
.collect(Collectors.toMap(AppFeatureDTO::getId, a -> new AppFeatureDTO(a.getId(),
conditionFilterMap.get(a.getId()).getSubFeature().values().stream()
.map(SubFeatureDTO::getId)
.map(a.getSubFeature()::get)
.collect(Collectors.toMap(AppSubFeatureDTO::getId, x -> x)))));
If you need TreeMap, add the arguments (a, b) -> a, TreeMap::new to the Collectors.toMap calls.
The non-stream version doesn't really look any worse:
Map<Integer, AppFeatureDTO> resultMap = new TreeMap<>();
for (FeatureDTO f : conditionFilterMap.values()) {
AppFeatureDTO a = appFeatureMap.get(f.getId());
Map<Integer, AppSubFeatureDTO> resultSub = new TreeMap<>();
for (SubFeatureDTO s : f.getSubFeature().values()) {
resultSub.put(s.getId(), a.getSubFeature().get(s.getId()));
}
resultMap.put(a.getId(), new AppFeatureDTO(a.getId(), resultSub));
}

Related

Get GraphQL output without second curly bracket

I have a problem. I do not want a "break" down in my GraphQL output. I have a GraphQL schema with a person. That person can have one or more interests. But unfortunately I only get a breakdown
What I mean by breakdown is the second curly brackets.
{
...
{
...
}
}
Is there an option to get the id of the person plus the id of the interests and the status without the second curly bracket?
GraphQL schema
Person
└── Interest
Query
query {
model {
allPersons{
id
name
interest {
id
status
}
}
}
}
[OUT]
{
"data": {
"model": {
"allPersons": [
{
"id": "01",
"name": "Max",
"interest ": {
"id": 4488448
"status": "active"
}
},
{
"id": "02",
"name": "Sophie",
"interest ": {
"id": 15445
"status": "deactivated"
}
},
What I want
{
{
"id": "01",
"id-interest": 4488448
"status": "active"
},
{
"id": "02",
"name": "Sophie",
"id-interest": 15445
"status": "deactivated"
},
}
What I tried but that deliver me the same result
fragment InterestTask on Interest {
id
status
}
query {
model {
allPersons{
id
interest {
...InterestTask
}
}
}
}

How to mutate a list of objects in an array as an argument in GraphQL completely

I cannot mutate a list of objects completely, because only the last element of the array will be mutated.
What already works perfectly is, if I put each element ({play_positions_id: ...}) in the array manually like here:
mutation CreateProfile {
__typename
create_profiles_item(data: {status: "draft", play_positions: [{play_positions_id: {id: "1"}}, {play_positions_id: {id: "2"}}]}) {
id
status
play_positions {
play_positions_id {
abbreviation
name
}
}
}
}
Output:
{
"data": {
"__typename": "Mutation",
"create_profiles_item": {
"id": "1337",
"status": "draft",
"play_positions": [
{
"play_positions_id": {
"id": "1",
"abbreviation": "RWB",
"name": "Right Wingback"
}
},
{
"play_positions_id": {
"id": "2",
"abbreviation": "CAM",
"name": "Central Attacking Midfielder"
}
}
],
}
}
}
Since you can add many of those elements, I defined a variable/argument like here
mutation CreateProfile2($cpppi: [create_profiles_play_positions_input]) {
__typename
create_profiles_item(data: {status: "draft", play_positions: $cpppi}) {
id
status
play_positions {
play_positions_id {
id
abbreviation
name
}
}
}
}
Variable object for above:
"cpppi": {
"play_positions_id": {
"id": "1"
},
"play_positions_id": {
"id": "2
}
}
Output:
{
"data": {
"__typename": "Mutation",
"create_profiles_item": {
"id": "1338",
"play_positions": [
{
"play_positions_id": {
"id": "2",
"abbreviation": "CAM",
"name": "Central Attacking Midfielder"
}
}
],
}
}
}
Schema:
input create_profiles_input {
id: ID
status: String!
play_positions: [create_profiles_play_positions_input]
}
input create_profiles_play_positions_input {
id: ID
play_positions_id: create_play_positions_input
}
input create_play_positions_input {
id: ID
abbreviation: String
name: String
}
At the last both snippets, only the last object with the id "2" will be mutated. I need these to use the defined input type from my backend.
I figured it out. I got it wrong with the brackets in the variable. Here the solution:
"cpppi": [
{
"play_positions_id": {
"id": "1"
}
},
{
"play_positions_id": {
"id": "2"
}
}
]

WebAPI convert nested JSON to string

I have a somewhat complex JSON coming into a WEBAPI -
{
"TypeInq": "ResidentialStart",
"DataInq": {
"Account_ID": "2491054657",
"Premise_ID": "5394660000",
"DogWarning": "N",
"ServiceStartDate": "2020-01-10",
"PrimaryPerson": {
"PersonId": "0357801000",
"POS_ID_Required": "Y",
"LastName": "HOGAN",
"FirstName": "BARRY L",
"Username": "garmin789#gmail.com",
"EmailList": [
{
"Email": "garmin789#gmail.com",
"EmailType": "PERSONAL EMAIL",
"PrimaryEmailFlag": "Y",
"ActionFlag": "ADD",
"ActiveInactiveFlag": "C1AC"
}
],
"DateOfBirth": "1977-11-04",
"CurrentAddress": {
"AddressLine1": "1923 Chestnut Dr",
"City": "Pleasant hill ",
"State": "MO",
"Zip": "64080"
},
"MailingAddress": {
"PremiseID": "5394660000"
}
},
"AdditionalPersons": [
{
"PersonId": "0357801000",
"POS_ID_Required": "Y",
"LastName": "HOGAN",
"FirstName": "BARRY L",
"Username": "garmin789#gmail.com",
"EmailList": [
{
"Email": "garmin789#gmail.com",
"EmailType": "PERSONAL EMAIL",
"PrimaryEmailFlag": "Y",
"ActionFlag": "ADD",
"ActiveInactiveFlag": "C1AC"
}
],
"DateOfBirth": "1977-11-04",
"CurrentAddress": {
"AddressLine1": "1923 Chestnut Dr",
"City": "Pleasant hill ",
"State": "MO",
"Zip": "64080"
},
"MailingAddress": {
"PremiseID": "5394660000"
}
}
]
}
}
So the part 'TypeInq' seems to be fine
The Part 'DataInq' i need to convert all that into a string before I process it. Not 100% sure how to approach this in C# but was trying this where the 'Base' object just has strings in it for 'TypeInq' and 'DataInq'
[HttpPost]
[Route("CreateInquiry")]
public IHttpActionResult CreateNewInquiry(Base inqBasic)
{
string retval = "";
try
{
//return Ok();
InquiryService svc = new InquiryService();
retval = svc.CreateInquiry(inqBasic);
}
catch (Exception ex)
{
Logger.LogEx(ex);
return WebApiConfig.ExceptionResponse(this);
}
return Ok(retval);
}
You can directly deserialize the incoming json object. Then just reference the appropriate property you want the value of.
object somenewobject = new JavaScriptSerializer().Deserialize(response.Data.ToString());

How to convert hierarchical list to flat list?

Usually we convert flat list to hierarchical list but in my case I want to convert hierarchical list to flat list.
I have a hierarchical list<T> and I want convert this hierarchical list into flat list<T> class.
Let's say I have a below hierarchical list
Parent1
--- Child1 ,F1
----Child2, F2
----Child2, F3
Parent2
----Child2,F2
----Child4,F6
Parent3
--- Child1 ,F1
I need output like below:
Parent1, Child1,F1
Parent1, Child2,F2
Parent1, Child2,F3
Parent2,Child2,F2
Parent2,Child4, F6
Parent3, Child1,F1
It may not be the most optimized solution (it could be further minimized I think, and I have a more concise version - but this form is something I'm using the most)
It's what I've been using
public static IEnumerable<T> FlattenHierarchy<T>(this T node,
Func<T, IEnumerable<T>> getChildEnumerator)
{
yield return node;
if (getChildEnumerator(node) != null)
{
foreach (var child in getChildEnumerator(node))
{
foreach (var childOrDescendant
in child.FlattenHierarchy(getChildEnumerator))
{
yield return childOrDescendant;
}
}
}
}
and you can use it like
folder.FlattenHierarchy(x => x.SubFolders)
Finally i got the solution:
public class RNode
{
public string Id;
public long ID;
public string name;
public string subTitle;
public IList<RNode> children;
}
public class FlatObj //For Data format
{
public long Id;
public long ParentId;
public long Position;
public string name;
public string subTitle;
}
List<FlatObj> GlobalFlatObj = new List<FlatObj>();
List<long> ParentIdList = new List<long>();
long CurrentParentId=0;
long CurrentPosition = 0;
public List<FlatObj> FlatData(IList<RNode> HData) //Converting Heirarchical to Flat
{
foreach (RNode node in HData)
{
FlatObj ObjFlatObj = new FlatObj();
ObjFlatObj.Id = node.ID;
ObjFlatObj.name = node.name;
ObjFlatObj.ParentId = CurrentParentId;
ObjFlatObj.Position = CurrentPosition;
GlobalFlatObj.Add(ObjFlatObj);
if (node.children.Count > 0)
{
CurrentParentId = node.ID;
ParentIdList.Add(node.ID);
FlatData(node.children);
}
CurrentPosition++;
}
if (ParentIdList.Count > 0)
{
ParentIdList.RemoveAt(ParentIdList.Count - 1);
if (ParentIdList.Count > 0)
CurrentParentId = ParentIdList[ParentIdList.Count - 1];
CurrentPosition = 0;
}
return GlobalFlatObj;
}
public dynamic Test(List<RNode> EmployeeHierarchy)
{
var HierarchyResult = FlatData(EmployeeHierarchy); //Calling
return Ok(HierarchyResult);
}
Input:
[
{
"$id": "1",
"ID": 1,
"name": "root",
"subTitle": "root",
"children": [
{
"$id": "2",
"ID": 2,
"name": "child 1",
"subTitle": "child 1",
"children": [
{
"$id": "3",
"ID": 5,
"name": "grandchild",
"subTitle": "grandchild",
"children": []
}]
},
{
"$id": "4",
"ID": 3,
"name": "child 2",
"subTitle": "child 2",
"children": []
},
{
"$id": "5",
"ID": 4,
"name": "child 3",
"subTitle": "child 3",
"children": []
}
]
}
]
Output:
[
{
"$id": "1",
"Id": 1,
"ParentId": 0,
"Position": 0,
"name": "root",
"subTitle": null
},
{
"$id": "2",
"Id": 2,
"ParentId": 1,
"Position": 0,
"name": "child 1",
"subTitle": null
},
{
"$id": "3",
"Id": 5,
"ParentId": 2,
"Position": 0,
"name": "grandchild",
"subTitle": null
},
{
"$id": "4",
"Id": 3,
"ParentId": 1,
"Position": 1,
"name": "child 2",
"subTitle": null
},
{
"$id": "5",
"Id": 4,
"ParentId": 1,
"Position": 2,
"name": "child 3",
"subTitle": null
}
]

WebAPI 2 Odata Filter not working

I have a problem with using multiple filters on my WebAPI 2 Odata project.
We only want JSON output and only have one object type to query so we set the url to "/" without the possibility to use a different controller.
I have an object I want to query with the following properties:
public class Content
{
public int Id { get; set; }
public string Title { get; set; }
public string Excerpt { get; set; }
public string Link { get; set; }
public IList<Tag> Tags { get; set; }
}
public class Tag
{
public string Id { get; set; }
public string Name { get; set; }
}
And the controller code looks like this:
public class ContentController : ApiController
{
private readonly IContentRepository _repository;
// constructor
public ContentController(IContentRepository repository)
{
_repository = repository;
}
[Queryable]
public IQueryable<Content> Index()
{
// IContentRepository.GetAll returns an IEnumerable List of Content
return _repository.GetAll().AsQueryable();
}
}
Now, I've mocked some testdata with adding multiple objects to the repository that have multiple tags with values set to either (test1, test2 or test3). Now when i Query
http://localhost:xxx?$filter=Tags/any(o: o/Id eq 'test1')
I get all objects with Tag/Id set to 'test1'. But if I query
http://localhost:xxx?$filter=Tags/any(o: o/Id eq 'test1' and o/Id eq 'test2')
I get no result (JSON return = []). But it should return objects that have both tags.
What am I doing wrong?
EDIT:
My sample data JSON looks like this:
[
{
"Id": 1,
"Title": "TESTOBJECT 1",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test1",
"Name": "Test Tag 1",
}
],
},
{
"Id": 2,
"Title": "TESTOBJECT 2",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test2",
"Name": "Test Tag 2",
}
],
},
{
"Id": 3,
"Title": "TESTOBJECT 3",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test3",
"Name": "Test Tag 3",
}
],
},
{
"Id": 4,
"Title": "TESTOBJECT 4",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test1",
"Name": "Test Tag 1",
},
{
"Id": "test2",
"Name": "Test Tag 2",
}
],
},
{
"Id": 5,
"Title": "TESTOBJECT 5",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test1",
"Name": "Test Tag 1",
}
],
}
]
Now query one gives me object 1,4,5 and I would expect query two to give me object 4. How can I accomplish this with odata?
Did you want this?
http://localhost:xxx?$filter=Tags/any(o: o/Id eq 'test1') and Tags/any(o: o/Id eq 'test2')
((X == "test1") AND (X == "test2")) will always return false!
If you want to identify Tags whose property Id is test1 or test2, use the or operator.

Resources