First, I am using Spring MVC.
I have a "Skill"-modelclass, where I placed the #JsonIgnoreProperties
#JsonIgnoreProperties({"personSkills","berufsgruppes","skills"})
#JsonPropertyOrder({"idSkill", "name", "levelBezeichnung", "skill"})
I am using it because there are many-to-many or many-to-one or one-to-many relationships and without this property it causes an StackOverFlowException (Infinite Error). One skill can have many skills, so there is a kind of recursion.
I implemented an Sub-Class for "Skill" named "SkillBean", which has one more attribute "checked" thats just relevant for the application not for database.
public class Skill implements java.io.Serializable {
private Set<Skill> skills = new HashSet<Skill>(0);
...
#OneToMany(fetch = FetchType.LAZY, mappedBy = "skill")
public Set<Skill> getSkills() {
return this.skills;
}
public void setSkills(Set<Skill> skills) {
this.skills = skills;
}
public class SkillBean extends Skill implements Serializable{
public boolean checked;
public SkillBean() {
}
public SkillBean(Skill skill, boolean checked) {
this.checked = checked;
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
}
Im Using BeanUtils.copyProperties() to copy a Skill-Object into a SkillBean-Object. This works fine. I need to reorder the skills because currently I get the lowest Child-Skill first and not its parent. For this, I am trying to reorder objects and trying to build a tree in a list. Every skill has a Set of its children.
private ArrayList<SkillBean> formatSkillMap(HashMap<Integer, SkillBean> map) {
Map<Integer, SkillBean> tempSkills = (Map<Integer, SkillBean>) map.entrySet().stream().filter(p -> p.getValue().getSkill() == null)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
ArrayList<SkillBean> list = new ArrayList<SkillBean>(tempSkills.values());
for (int i = 0; i < list.size(); i++) {
SkillBean sb = list.get(i);
tempSkills = (Map<Integer, SkillBean>) map.entrySet().stream().filter(p -> p.getValue().getSkill() != null)
.filter(p -> p.getValue().getSkill().getIdSkill() == sb.getIdSkill()).collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Set<Skill> test = new HashSet<Skill>(tempSkills.values());
list.get(i).setSkills(test);
}
return list;
But the list doesnt return the Sub-skillset Could anyone tell me why the subskills are not serialized? When I return the subset of this parent-skill it their subskills are serialized.
0: {
"idSkill": 34
"name": "Methodik"
"levelBezeichnung": {
"#id": 1
"idLevelBezeichnung": 1
"bezeichnung": "Standard"
"handler": {}
"hibernateLazyInitializer": {}
}-
"checked": true
}
Without reordering it looks sth like this, but the problem is that the skill with id=34 is the parent skill and 9 is the subskill. I want it exactly the other way around. There could be three levels.
9: {
"idSkill": 9
"name": "Standards"
"levelBezeichnung": {
"#id": 1
"idLevelBezeichnung": 1
"bezeichnung": "Standard"
"handler": {}
"hibernateLazyInitializer": {}
}-
"skill": {
"idSkill": 34
"name": "Methodik"
"levelBezeichnung": 1
}-
"checked": true
}
Finally, I end up with this:
Ignore parent of a skill or ignore children of a skill to avoid infinite recursion. In some case you don't need to ignore one of them. If you have not that much data it could work. I'am talking about 150 nodes where each node knows its parent/children.
I am querying for the path from bottom to top of my lowest skill with a custom sql query.
I am putting all my skills on the highest level in a map. That means, I have access to all my skills, cause (as I said) every node knows his children.
I am searching in my map from top to bottom and delete all references that I don't need based on the path, which I already got.
The whole code is a bit complex and I'm using recursion to made it less complex. In the end I am not that pleased with this solution because there are many loops in it and so far I am having some trouble with performance-issues.
I need to discover whether it is a database-query problem or a problem caused by the loops.
Related
I have a simple hierarchy in neo4j directly derived from the business model.
#Node
public class Team {
#Id private String teamId;
private String name;
}
#Node
public class Driver {
#Id private String driverId;
private String name;
#Relationship(direction = Relationship.Direction.OUTGOING)
private Team team;
}
#Node
public class Car {
#Id private String carId;
private String name;
#Relationship(direction = Relationship.Direction.OUTGOING)
private Driver driver;
}
which results in the corresponding graph (Team)<--(Driver)<--(Car) usually all requests start at Car.
A new use case needs to create a tree structure starting at Team nodes. The Cypher query aggregates the data on neo and returns it to SDN.
public List<Projection> loadHierarchy() {
return neo4jClient.query("""
MATCH(t:Team)<--(d:Driver)<--(c:Car)
WITH t, d, collect(distinct c{.carId, .name}) AS carsEachDriver
WITH t, collect({driver: d{.driverId, .name}, cars: carsEachDriver }) AS driverEachTeam
WITH collect({team: t{.teamId, .name}, drivers: driverEachTeam }) as teams
RETURN teams
""")
.fetchAs(Projection.class)
.mappedBy((typeSystem, record) -> new Projection() {
#Override
public Team getTeam() {
return record.get... // how to access single object?
}
#Override
public List<Retailers> getRetailers() {
return record.get... // how to access nested list objects?
}
})
.all();
}
The result is a list of following objects:
{
"drivers": [
{
"driver": {
"name": "Mike",
"driverId": "15273c10"
},
"cars": [
{
"carId": "f4ca4581",
"name": "green car"
},
{
"carId": "11f3bcae",
"name": "red car"
}
]
}
],
"team": {
"teamId": "4586b33f",
"name": "Blue Racing Team"
}
}
The problem is now, how to map the response into an according Java model. I don't use the entity classes.
I tried multi-level projection with nested interfaces.
public interface Projection {
Team getTeam();
List<Drivers> getDrivers();
interface Drivers {
Driver getDriver();
List<Cars> getCars();
}
interface Driver {
String getDriverId();
String getName();
}
interface Car {
String getCarId();
String getName();
}
interface Team {
String getTeamId();
String getName();
}
}
I struggle to access the nested lists and objects, to put them into the model.
SDN is the Spring Boot Starter in version 2.6.3.
An example how to map a nested object in a list would be a good starting point.
Or may be my approach is totally wrong? Any help is appreciated.
Projection are not meant to be something like a view or wrapper of arbitrary data.
Within the context you can get a Neo4jMappingContext instance.
You can use this to obtain the mapping function for an already existing entity.
With this, you do not have to take care about mapping the Car and (partially because of the team relationship) the Drivers.
BiFunction<TypeSystem, MapAccessor, Car> mappingFunction = neo4jMappingContext.getRequiredMappingFunctionFor(Car.class);
The mapping function accepts an object of type MapAccessor.
This is a Neo4j Java driver type that is implemented besides others also by Node and MapValue.
You can use those values from your result e.g. drivers in a loop (should be possible to call asList on the record) and within this loop you would also assign the cars.
Of course using the mapping function would only make sense if you have a lot more properties to map because nothing in the return structure (as you already said between the lines) applies to the entity structure regarding the relationships.
Here is an example of using the mapping function and direct mapping.
You have to decide what matches best for your use case.
public Collection<Projection> loadHierarchy() {
var teamMappingFunction = mappingContext.getRequiredMappingFunctionFor(Team.class);
var driverMappingFunction = mappingContext.getRequiredMappingFunctionFor(Driver.class);
return neo4jClient.query("""
MATCH(t:Team)<--(d:Driver)<--(c:Car)
WITH t, d, collect(distinct c{.carId, .name}) AS carsEachDriver
WITH t, collect({driver: d{.driverId, .name}, cars: carsEachDriver }) AS driverEachTeam
WITH {team: t{.teamId, .name}, drivers: driverEachTeam } as team
RETURN team
""")
.fetchAs(Projection.class)
.mappedBy((typeSystem, record) -> {
Team team = teamMappingFunction.apply(typeSystem, record.get("team"));
List<DriverWithCars> drivers = record.get("team").get("drivers").asList(value -> {
var driver = driverMappingFunction.apply(typeSystem, value);
var cars = value.get("carsEachDriver").asList(carValue -> {
return new Car(value.get("name").asString());
});
return new DriverWithCars(driver, cars); // create wrapper object incl. cars
});
return new Projection(team, drivers);
})
.all();
}
(Disclaimer: I did not execute this on a data set, so there might be typos or wrong access to the record)
Please note that I changed the cypher statement a little bit to have get one Team per record instead of the whole list.
Maybe this is already what you have asked for.
I understand that the soft constraint in the tsp problem is to find the shortest total distance, but I see that the two drools constraints in the example seem to express the distance of each segment and the distance from the last visited city to the starting point? It seems that the distance is not calculated. And, can you explain these two constraints in detail? I'm a beginner, and I don't understand a little bit.
rule "distanceToPreviousStandstill"
when
$visit : Visit(previousStandstill != null, $distanceFromPreviousStandstill : distanceFromPreviousStandstill)
then
scoreHolder.addConstraintMatch(kcontext, - $distanceFromPreviousStandstill);
end
rule "distanceFromLastVisitToDomicile"
when
$visit : Visit(previousStandstill != null)
not Visit(previousStandstill == $visit)
$domicile : Domicile()
then
scoreHolder.addConstraintMatch(kcontext, - $visit.getDistanceTo($domicile));
end
In DRL (unlike in Java), calling Visit(..., $distanceFromPreviousStandstill : distanceFromPreviousStandstill) means its calling the getDistanceFromPreviousStandstill() getter:
public class Visit extends AbstractPersistable implements Standstill {
...
public long getDistanceFromPreviousStandstill() {
if (previousStandstill == null) {
return 0L;
}
return getDistanceFrom(previousStandstill);
}
}
If you prefer Java over DRL, take a look at the ConstraintProvider alternative implementation, which is written in Java, uses incremental score calculation too (= can scale), is equally fast (8.3.0+), easier to debug and has code highlighting and code completion in any Java IDE:
public final class TspConstraintProvider implements ConstraintProvider {
#Override
public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
return new Constraint[] {
distanceToPreviousStandstill(constraintFactory),
distanceFromLastVisitToDomicile(constraintFactory)
};
}
private Constraint distanceToPreviousStandstill(ConstraintFactory constraintFactory) {
return constraintFactory.from(Visit.class)
.penalizeLong("Distance to previous standstill",
SimpleLongScore.ONE,
Visit::getDistanceFromPreviousStandstill);
}
private Constraint distanceFromLastVisitToDomicile(ConstraintFactory constraintFactory) {
return constraintFactory.from(Visit.class)
.ifNotExists(Visit.class, Joiners.equal(visit -> visit, Visit::getPreviousStandstill))
.join(Domicile.class)
.penalizeLong("Distance from last visit to domicile",
SimpleLongScore.ONE,
Visit::getDistanceTo);
}
}
I want to use "pin" feature of optaplanner for immovable operations. However i get "Bailing out of neverEnding selector (Filtering(FromSolutionEntitySelector(PersonAssignment))) to avoid infinite loop." error. I've tried both with #PlanningPin and movableEntitySelectionFilter. Optaplanner version is 7.32.0 final, also i tried with version 7.44.0.Final. I've searched a lot and as can i see you've solved this problem in version 7.31.0.Final.
I've generated my domain and it is working well. Idea of my problem is there are more then one hotel. People come to hotel at different hours. Each hotel has different capacity and i want to asign people to a hotel if there is enough space. I've also many rules about assignment. My domain model consists of two #PlanningEntity,customShadowVariable and also TimeGrain. Structure is below:
#PlanningEntity(movableEntitySelectionFilter = PersonAssignmentSelectionFilter.class)
public class PersonAssignment extends AbstractPersistable {
private Person person;
private TimeGrain startingTimeGrain;
private TimeGrain endTime; // This added
private HotelDomain hotelDomain;
public TimeGrain getStartingTimeGrain() {
return startingTimeGrain;
}
public void setStartingTimeGrain(TimeGrain startingTimeGrain) {
this.startingTimeGrain = startingTimeGrain;
}
public TimeGrain getEndTime() {
return endTime;
}
public void setEndTime(TimeGrain endTime) {
this.endTime = endTime;
}
#PlanningVariable(valueRangeProviderRefs = { "hotelDomainRange" }, nullable = true)
public HotelDomain getHotelDomain() {
return hotelDomain;
}
public void setHotelDomain(HotelDomain hotelDomain) {
this.hotelDomain = hotelDomain;
}
......
}
#DeepPlanningClone
public class HotelDomain extends AbstractPersistable {
private String hotelName;
#CustomShadowVariable(variableListenerRef = #PlanningVariableReference(variableName = "tightOccupancy, personAssignment))
private Map<Integer, HotelOccupancyPerSlot> hotelOccupancyMap;
......
}
#PlanningEntity
public class HotelOccupancyPerSlot extends AbstractPersistable {
#CustomShadowVariable(variableListenerClass = HotelDomainVariableListener.class, sources = {
#PlanningVariableReference(entityClass = PersonAssignment.class, variableName = "hotelDomain") })
private Integer tightOccupancy; // days
#CustomShadowVariable(variableListenerRef = #PlanningVariableReference(variableName = "tightOccupancy"))
private List<PersonAssignment> personAssignments;
.......
}
public class HotelDomainVariableListener implements VariableListener<PersonAssignment> {
......
}
config.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<solver>
<moveThreadCount>3</moveThreadCount> <!-- To solve faster by saturating multiple CPU cores -->
<solutionClass>com.domain.HotelAccomodation</solutionClass>
<entityClass>com.domain.PersonAssignment</entityClass>
<entityClass>com.domain.HotelOccupancyPerSlot</entityClass>
<scoreDirectorFactory>
<scoreDrl>solver/solverScoreRules.drl</scoreDrl>
</scoreDirectorFactory>
<termination>
<minutesSpentLimit>15</minutesSpentLimit>
</termination>
</solver>
If i use #PlannigPin in HotelOccupancyPerSlot there is no problem but i want to use it(or filter) only in PersonAssignment class because it is my basic class. Is there any suggestion? Should i add something to config?
Thank You :)
The "Bailing out" warning happens when a move selection filter is filtering out every move (it never returns true). It's not an error, but a warning, because there if you see it only once, it could be a harmless fluke in theory in some cases.
Anyway, when does a filter return false for all selected moves? In these cases:
A) you configured a custom move filter in solverConfig.xml that never returns true
B) the solution value range has no values - OptaPlanner checks for that ins 7.44+ and does the right thing automatically. Not sure if it does the right thing if there are 2 planning variables and only 1 has no values...
C) the solution value range has a single value - that would mean the move isDoable() false. I don't recall this being a problem though.
D) the solution value range has no non-pinned value. See B)
E) the solution value range has only 1 non-pinned value. See C)
Take a look at your input data. Are you dealing with case B, C, D or E by any chance?
I am looking for a data structure to represent hierarchy class system in Java.
For example, I have three class, University,Major,Student, and their relationship looks like below.
Is there a efficient data structure that I can query with a path-like expression?
For example, if the expression is CMU/cs/jake,then I get a instance of student class whose name is jake. As far as I know, the Trie could do this, is there any other option?
If your data fits into memory then you can implement this by putting a Set of children in each node of the hierarchy and then walking the sets to determine if the path is valid, for example
class University {
private Set<Major> majors;
}
class Major {
private Set<Student> students;
}
class Main {
// true if the path is valid, else false
public boolean query(University university, Major major, Student student) {
return university.getMajors().contains(major) &&
major.getStudents().contains(student);
}
}
If you also need to walk the reverse path (i.e. if you need a bidirectional hierarchy) then you can put a Set of parents in each child.
This will run in average case O(d) where d is the depth of the hierarchy if you use HashSets, and in worst case O(d * lg(n)) where n is the size of the sets if you use TreeSets.
If your data doesn't fit into memory then you may want to consider using a graph database, e.g. Neo4j.
Edit: You can make the code more generic at the cost of type safety by using Map<String, E> at each level, assuming that each object has a unique name or some other string identifier.
abstract class Hierarchical<E extends Hierarchical> {
protected final Map<String, E> children;
public boolean query(Queue<String> query) {
String key = query.poll();
if(key != null) {
E value = map.get(key);
if(value != null) {
return query.isEmpty() || value.contains(query);
}
}
return false;
}
}
class University extends Hierarchical<Major> {}
class Major extends Hierarchical<Student> {}
// special case for the bottom of the hierarchy
class Student extends Hierarchical<Hierarchical> {
public Student() {
children = null;
}
#Override
public boolean query(Queue<String> query) {
throw new UnsupportedOperationException("query should never reach this depth");
}
}
class Main {
// true if the path is valid, else false
public boolean query(Hierarchial root, Queue<String> query) {
return root.contains(query);
}
}
This has the same runtime depending on whether you use a HashMap or TreeMap. The query only consists of a queue of strings; at each level of the hierarchy the first string is removed, the Map is queried and the child node is returned if found, and the query proceeds on to the child node until the queue is empty (return true) or a node isn't found (return false).
I need to create a structure that need to represent the following (For Category and Sub-Category).Its just one level deep. I am thinking of doing it using Java Enums and not sure how to represent this hierarchical structure.
My java objects (business objects) that represent a device will have both category and sub-category properties and I want to use an Enum instead of using integer codes like 100, 1 etc.. Some devices will have only category but not the sub-category (like 300 in the following example).
100 Switch
1 Interior
2 Exterior
200 Security Sensor
1 Door Sensor
2 Leak Sensor
3 Motion Sensor
300 Camera
Any help is appreciated.
Thanks
This java.dzone article showcases is a beautiful example of hierarchical enums:
public enum OsType {
OS(null),
Windows(OS),
WindowsNT(Windows),
WindowsNTWorkstation(WindowsNT),
WindowsNTServer(WindowsNT),
Windows2000(Windows),
Windows2000Server(Windows2000),
Windows2000Workstation(Windows2000),
WindowsXp(Windows),
WindowsVista(Windows),
Windows7(Windows),
Windows95(Windows),
Windows98(Windows),
Unix(OS) {
#Override
public boolean supportsXWindows() {
return true;
}
},
Linux(Unix),
AIX(Unix),
HpUx(Unix),
SunOs(Unix),
;
private OsType parent = null;
private OsType(OsType parent) {
this.parent = parent;
}
}
The article show cases lots of little tricks you can pull off with this set up.
I think this answer would be an excellent solution for you. With a type hierarchy like this:
public enum Component {
Interior(Part.Switch),
Exterior(Part.Switch),
DoorSensor(Part.SecuritySensor),
LeakSensor(Part.SecuritySensor),
MotionSensor(Part.SecuritySensor),
Camera(Part.Camera);
private final Part kindOf;
Component(Part kindOf) {
this.kindOf = kindOf;
}
enum Part {
Switch, SecuritySensor, Camera
}
}
More detail can be found in Chapter Enum from Effective Java 2nd Edition.
It seems unusual that you want to express this with an enumeration as opposed to inheritance. The thing with enumerations is that they're essentially compile-time constants, and if you wanted to generate more information in your hierarchy, you'd have to add more enumerations.
That can get messy, fast. It's also slightly contradictory to the real purpose of enumerations - as predefined constants instead of hierarchical entities.
What I propose is using an abstract class called CategoryBase in which to draw everything out of. Then, create your inheritance tree based off of that.
Here's a diagram:
The bulk of the work is really holding properties, and we don't ever expect those properties to be changed once created, so we can allow our abstract class to hold them. We've also set them as final, so they can't be modified, either.
public abstract class CategoryBase {
protected final int ranking;
protected final String name;
protected final SubCategory[] subCategories;
protected CategoryBase(int ranking, String name, SubCategory... subCategories) {
this.ranking = ranking;
this.name = name;
this.subCategories = subCategories;
}
public int getRanking() {
return ranking;
}
public String getName() {
return name;
}
public SubCategory[] getSubCategories() {
return subCategories;
}
}
From there, we can start basing our marker classes off of this - including SubCategory, since it's really just a holder of information that's represented in a different way.
This would also make writing the marker classes straightforward and simple. For example, here's Camera:
public class Camera extends CategoryBase {
protected Camera(int ranking, String name) {
super(ranking, name);
}
}
It's got a striking similarity to SubCategory - a SubCategory doesn't have any nested SubCategorys, so we don't pass in anything to the vararg portion of the constructor.
For something that does have SubCategorys, we need to instantiate them on construction. Here's SecuritySensor as an example.
public class SecuritySensor extends CategoryBase {
public SecuritySensor(int ranking, String name) {
super(ranking, name,
new SubCategory(1, "Door Sensor"),
new SubCategory(2, "Leak Sensor"),
new SubCategory(3, "Motion Sensor"));
}
}
This approach gives you some flexibility around ranking as well - if you wanted to be able to specify the exact ranking of the subcategories at runtime, you'd replace this constructor with one that supported the vararg signature.
you can do something like the code below. but that is probably not quite what you want. you could add the child enums to the constructor for the parent enum like here.
enum Stuff {
Swich,Sensor,Camera;
enum swich {
interior,exterior;
enum Where {
bathroom,kitchen
}
}
enum sensor {
door,leak,motion
}
}
Perhaps reconsider and do use integers here. However, instead of basing them on a decimal system (100, 200, 300,... for first level; 1, 2, 3,... for second level) base them on a binary representation.
// top-level
public static final int SWITCH = 1 << 16;
public static final int SECURITY_SENSOR = 2 << 16;
public static final int CAMERA = 4 << 16;
// sub-types of 'switch'
public static final int INTERIOR = SWITCH | 1;
public static final int EXTERIOR = SWITCH | 2;
// sub-types of 'security sensor'
public static final int DOOR_SENSOR = SECURITY_SENSOR | 1;
public static final int LEAK_SENSOR = SECURITY_SENSOR | 2;
public static final int MOTION_SENSOR = SECURITY_SENSOR | 4;
This allows you to do a weak form of inheritance testing:
if (value == SWITCH) {
// value is a switch, but not interior or exterior
} else if (value & SWITCH != 0) {
// value is interior or exterior
}
Does following code meet your request?
public enum Category {Switch, ...}
public enum SubCategory {Interior, ...}