1010import java .lang .reflect .Modifier ;
1111import java .util .ArrayDeque ;
1212import java .util .Collection ;
13+ import java .util .Collections ;
1314import java .util .Deque ;
1415import java .util .HashSet ;
1516import java .util .LinkedList ;
16- import java .util .List ;
1717import java .util .Map ;
1818import java .util .Set ;
1919import java .util .function .Function ;
@@ -32,95 +32,103 @@ public class DynamicRelationsPrintService {
3232
3333 private final EntityManager entityManager ;
3434 private final RelationService relationService ;
35-
3635 private Map <String , Class <RelationIdentity >> classBySimpleName ;
3736
3837 public String printRelations (RelationIdentity relationIdentity ) {
39- TreeNodeRelationIdentity root = new TreeNodeRelationIdentity (relationIdentity , new LinkedList <>());
40- createTree (root );
41- return printTree (root );
38+ TreeNodeRelationIdentity tree = createTree (relationIdentity );
39+ return printTree (tree );
40+ }
41+
42+ @ PostConstruct
43+ public void configure () {
44+ Set <Class <RelationIdentity >> classesImplementingInterface = findClassesImplementingInterface ();
45+ classBySimpleName = classesImplementingInterface .stream ()
46+ .collect (Collectors .toMap (clazz -> clazz .getSimpleName () + "Type" , Function .identity ()));
4247 }
4348
4449 private String printTree (TreeNodeRelationIdentity root ) {
4550 Deque <Map .Entry <TreeNodeRelationIdentity , Integer >> stack = new ArrayDeque <>();
4651 stack .push (Map .entry (root , 0 ));
47-
4852 StringBuilder result = new StringBuilder ();
4953 while (!stack .isEmpty ()) {
5054 var entry = stack .pop ();
5155 var node = entry .getKey ();
5256 int level = entry .getValue ();
53-
5457 result .append (" " .repeat (level ))
5558 .append (node .object ().getType ())
5659 .append ("\n " );
57-
5860 for (var child : node .childObjects ()) {
5961 stack .push (Map .entry (child , level + 1 ));
6062 }
6163 }
6264 return result .toString ();
6365 }
6466
65- private void createTree (TreeNodeRelationIdentity root ) {
66- Set < Relation > visited = new HashSet <>();
67+ private TreeNodeRelationIdentity createTree (RelationIdentity relationIdentity ) {
68+ TreeNodeRelationIdentity root = new TreeNodeRelationIdentity ( relationIdentity , new LinkedList <>() );
6769 Deque <TreeNodeRelationIdentity > stack = new ArrayDeque <>();
6870 stack .push (root );
71+ createTreeNodes (stack );
72+ return root ;
73+ }
74+
75+ private void createTreeNodes (Deque <TreeNodeRelationIdentity > stack ) {
76+ Set <Relation > visited = new HashSet <>();
6977 while (!stack .isEmpty ()) {
70- var parentObject = stack .poll ();
78+ TreeNodeRelationIdentity parentObject = stack .poll ();
7179 Collection <RelationLink > relations = tryGetSourceObjectRelations (parentObject );
72- TreeNodeRelationIdentity childObject ;
73- for (RelationLink relation : relations ) {
74- var entityClass = classBySimpleName .get (relation .getTargetType ());
75- var childRelationIdentity = entityManager .find (entityClass , relation .getTargetId ());
76- childObject = new TreeNodeRelationIdentity (childRelationIdentity , new LinkedList <>());
77- var r = new Relation (parentObject .object (), childObject .object ());
78- if (!visited .contains (r )) {
79- parentObject .childObjects ().add (childObject );
80- visited .add (r );
81- stack .add (childObject );
82- }
83- }
80+ relations .forEach (relation -> addNode (stack , relation , parentObject , visited ));
8481 }
8582 }
8683
87- @ PostConstruct
88- public void configure () {
89- Set <Class <RelationIdentity >> classesImplementingInterface = findClassesImplementingInterface ();
90- classBySimpleName = classesImplementingInterface .stream ()
91- .collect (Collectors .toMap (clazz -> clazz .getSimpleName () + "Type" , Function .identity ()));
84+ private void addNode (Deque <TreeNodeRelationIdentity > stack , RelationLink relation ,
85+ TreeNodeRelationIdentity parentObject , Set <Relation > visited ) {
86+ RelationIdentity childRelationIdentity = getChildRelationIdentity (relation );
87+ TreeNodeRelationIdentity childObject = new TreeNodeRelationIdentity (childRelationIdentity , new LinkedList <>());
88+ Relation parentRelation = new Relation (parentObject .object (), childObject .object ());
89+ if (!visited .contains (parentRelation )) {
90+ parentObject .childObjects ().add (childObject );
91+ visited .add (parentRelation );
92+ stack .add (childObject );
93+ }
9294 }
9395
96+ private RelationIdentity getChildRelationIdentity (RelationLink relation ) {
97+ Class <RelationIdentity > entityClass = classBySimpleName .get (relation .getTargetType ());
98+ return entityManager .find (entityClass , relation .getTargetId ());
99+ }
94100
95101 private <T > Set <Class <T >> findClassesImplementingInterface () {
96102 Set <Class <T >> classes = new HashSet <>();
97-
98103 ClassPathScanningCandidateComponentProvider scanner =
99104 new ClassPathScanningCandidateComponentProvider (false );
100-
101105 scanner .addIncludeFilter (new AssignableTypeFilter (RelationIdentity .class ));
102106 Set <BeanDefinition > candidates = scanner .findCandidateComponents ("*" );
103107 for (BeanDefinition candidate : candidates ) {
104- try {
105- Class <T > clazz = (Class <T >) Class .forName (candidate .getBeanClassName ());
106- if (!clazz .isInterface () && !Modifier .isAbstract (clazz .getModifiers ())) {
107- classes .add (clazz );
108- }
109- } catch (ClassNotFoundException e ) {
110- log .error ("Class not found: {}" , candidate .getBeanClassName ());
111- throw new RuntimeException ("Class is not found. Finding classes is ended" );
112- }
108+ findRelationIdentities (candidate , classes );
113109 }
114-
115110 return classes ;
116111 }
117112
113+ private <T > void findRelationIdentities (BeanDefinition candidate , Set <Class <T >> classes ) {
114+ try {
115+ Class <T > clazz = (Class <T >) Class .forName (candidate .getBeanClassName ());
116+ if (!clazz .isInterface () && !Modifier .isAbstract (clazz .getModifiers ())) {
117+ classes .add (clazz );
118+ }
119+ } catch (ClassNotFoundException e ) {
120+ log .error ("Class not found: {}" , candidate .getBeanClassName ());
121+ throw new RuntimeException ("Class is not found. Finding classes is ended" );
122+ }
123+ }
124+
118125 private Collection <RelationLink > tryGetSourceObjectRelations (TreeNodeRelationIdentity root ) {
119126 try {
120127 return relationService .findRelationBySourceObject (root .object ());
121128 } catch (NoRelationDaoFoundException e ) {
122- log .info ("No relations found for root with id {} and type {}" , root .object ().getId (), root .object ().getType ());
123- return List .of ();
129+ log .info ("No relations found for root with id {} and type {}" , root .object ().getId (),
130+ root .object ().getType ());
131+ return Collections .emptyList ();
124132 }
125133 }
126134
0 commit comments