{"ok":true,"service":"equality-lab-evaluate","method":"POST","backendConfigured":false,"objectTypes":[{"id":"Party","label":"Party","parentId":null,"defaultRole":"party","description":"Root domain object. Useful for explaining broad business identity."},{"id":"IndividualParty","label":"IndividualParty","parentId":"Party","defaultRole":"individual","description":"A natural person under the party hierarchy."},{"id":"EmployeeParty","label":"EmployeeParty","parentId":"IndividualParty","defaultRole":"employee","description":"A person who also has an employee number."},{"id":"TraderParty","label":"TraderParty","parentId":"EmployeeParty","defaultRole":"trader","description":"Employee role used by trading workflows."},{"id":"ManagerParty","label":"ManagerParty","parentId":"EmployeeParty","defaultRole":"manager","description":"Employee role used by approval and risk workflows."},{"id":"EmployeePartyHibernateProxy","label":"EmployeePartyHibernateProxy","parentId":"EmployeeParty","defaultRole":"employee","proxyTargetType":"EmployeeParty","description":"A proxy-like runtime type that stands in for an EmployeeParty row."},{"id":"InstitutionParty","label":"InstitutionParty","parentId":"Party","defaultRole":"institution","description":"A legal entity with registration and BIC style identifiers."}],"strategies":[{"id":"java-reference","label":"Java default reference","shortLabel":"Reference","intent":"Only the exact same object instance is equal.","useWhen":"You did not override equals/hashCode or you intentionally need object identity.","risk":"Two separately loaded objects with the same business meaning stay different.","trap":false},{"id":"party-business-key","label":"Party business key","shortLabel":"Party key","intent":"Same tenant and normalized party number means same party.","useWhen":"The business says every subtype is just a view of one party identity.","risk":"Can be too broad when employee roles or legal entity records need separation.","trap":false},{"id":"employee-broad","label":"Broad employee key","shortLabel":"Employee","intent":"Same tenant and employee number means same employee.","useWhen":"Trader, manager, and employee views should collapse into one person record.","risk":"Can merge role records that should remain separate in approval or audit flows.","trap":false},{"id":"role-strict","label":"Role-strict employee key","shortLabel":"Role strict","intent":"Same tenant, employee number, and role means same Java value.","useWhen":"A person can have multiple role-specific records that must not merge.","risk":"Needs clear domain wording because the same human can produce multiple values.","trap":false},{"id":"jpa-id","label":"JPA id, strict runtime class","shortLabel":"JPA id","intent":"Same concrete runtime type and non-null database id means same entity.","useWhen":"Entities are persisted and proxy classes are not involved in comparison.","risk":"Hibernate proxies can look different from their target class.","trap":false},{"id":"proxy-safe-jpa","label":"Proxy-safe JPA id","shortLabel":"Proxy safe","intent":"Unwrap proxy-like runtime type, then compare persistent class and non-null id.","useWhen":"Spring Data JPA or Hibernate can hand you lazy proxy objects.","risk":"Transient entities with null ids must still be treated as different.","trap":false},{"id":"institution-legal-key","label":"Institution legal key","shortLabel":"Legal key","intent":"Same tenant, country, and legal registration or BIC means same institution.","useWhen":"The object is a legal entity, not a person or employee role.","risk":"Requires normalization and should not apply to employee subtypes.","trap":false},{"id":"broken-inheritance","label":"Trap: parent/child instanceof","shortLabel":"Symmetry trap","intent":"Base Party compares broadly, child Employee compares narrowly.","useWhen":"Only as a teaching example. It can reproduce p.equals(e) != e.equals(p).","risk":"Breaks the equals symmetry contract and makes collection behavior hard to trust.","trap":true},{"id":"broken-hashcode","label":"Trap: equals without hashCode","shortLabel":"Hash trap","intent":"equals says business keys match, but hashCode still behaves like identity.","useWhen":"Only as a teaching example for HashMap and HashSet misses.","risk":"Equal objects can land in different hash buckets, so lookups and dedup fail.","trap":true}],"modules":[{"id":"pair-matrix","label":"Pair matrix","description":"Anchor versus selected targets equality, hash, and verdict checks."},{"id":"collection-matrix","label":"Collections","description":"List, HashSet, HashMap, and Stream.distinct consequences."},{"id":"contract-review","label":"Contract review","description":"Symmetry, hashCode, null safety, and mutation warnings."},{"id":"implementation-guide","label":"Spring/Java guide","description":"The implementation direction this rule implies."}],"samplePayload":{"objects":[{"id":"party-a","label":"A","name":"A: Trader role for employee E-42","type":"TraderParty","tenantId":"eu","partyNo":"P-100","employeeNo":"E-42","role":"trader","dbId":"501","country":"DE","legalRegistrationNo":"","bic":"","note":"Same employee/person line as B and C. The open question is whether role records should be equal or only related."},{"id":"party-b","label":"B","name":"B: Manager role for employee E-42","type":"ManagerParty","tenantId":"eu","partyNo":"P-100","employeeNo":"E-42","role":"manager","dbId":"502","country":"DE","legalRegistrationNo":"","bic":"","note":"Same employee number and party number as A, but a different role leaf under EmployeeParty."},{"id":"party-c","label":"C","name":"C: Hibernate proxy for employee row","type":"EmployeePartyHibernateProxy","targetType":"EmployeeParty","tenantId":"eu","partyNo":"P-100","employeeNo":"E-42","role":"employee","dbId":"501","country":"DE","legalRegistrationNo":"","bic":"","note":"Proxy-like runtime class. Same database id as A, so proxy-safe JPA can treat it as the same persisted row."},{"id":"party-d","label":"D","name":"D: Institution counterparty","type":"InstitutionParty","tenantId":"eu","partyNo":"ORG-900","employeeNo":"","role":"institution","dbId":"900","country":"DE","legalRegistrationNo":"HRB-900","bic":"BARCDEFF","note":"Different branch under Party. It is a legal entity, not a person or employee role."}],"primaryId":"party-a","comparedIds":["party-b","party-c"],"strategyId":"role-strict"}}