27
27
import java .util .stream .Collectors ;
28
28
29
29
/**
30
- * Abstract service for constructing tree nodes from objects.
30
+ * Abstract base service for constructing tree structures from objects.
31
+ * Provides functionality for creating tree nodes and organizing them
32
+ * based on superior-subordinate relationships.
31
33
*
32
- * @param <T> the type of object representing a node
33
- * @author wq li
34
+ * @param <T> the type of object representing a node in the tree
34
35
* @since 0.1.3
35
36
*/
36
37
public abstract class AbstractTreeNodeService <T > {
@@ -42,76 +43,60 @@ public abstract class AbstractTreeNodeService<T> {
42
43
private static final Logger log = StatusLogger .getLogger ();
43
44
44
45
/**
45
- * Constructs a tree node from an object, optionally expanding additional properties.
46
+ * Creates a tree node from the given object, using the provided property names to expand additional data.
47
+ * This method extracts ID, name, and superior ID from the object and attaches any expanded properties.
46
48
*
47
- * @param t the object representing the node
48
- * @param expand a set of property names to expand on the node
49
- * @return a constructed TreeNode
50
- * @since 0.2.0
49
+ * @param t the object representing a node
50
+ * @param expand a set of property names to be expanded into the node's additional properties
51
+ * @return a fully constructed TreeNode instance
52
+ * @throws IllegalArgumentException if the ID property is null
53
+ * @since 0.3.0
51
54
*/
52
- protected TreeNode node (T t , Set <String > expand ) {
55
+ protected TreeNode createNode (T t , Set <String > expand ) {
53
56
Class <?> aClass = t .getClass ();
54
57
Object id = this .getId (t , aClass .getSuperclass ());
58
+ if (Objects .isNull (id )) {
59
+ throw new IllegalArgumentException ("ID cannot be null" );
60
+ }
55
61
Object name = this .getName (t , aClass );
56
62
Object superiorId = this .getSuperiorId (t , aClass );
57
63
58
- TreeNode treeNode = new TreeNode (Objects .nonNull (id ) ? (Long ) id : null ,
59
- Objects .nonNull (name ) ? String .valueOf (name ) : null );
60
- treeNode .setSuperior (Objects .nonNull (superiorId ) ? (Long ) superiorId : null );
61
-
62
- this .expand (treeNode , aClass , t , expand );
63
- return treeNode ;
64
+ return TreeNode .withId ((Long ) id )
65
+ .name (Objects .nonNull (name ) ? String .valueOf (name ) : null )
66
+ .superiorId (Objects .nonNull (superiorId ) ? (Long ) superiorId : null )
67
+ .meta (meta (aClass , t , expand )).build ();
64
68
}
65
69
66
70
/**
67
- * Sets the children for tree nodes based on their superior IDs.
71
+ * Organizes the tree nodes by assigning children to their respective parents based on the superior ID.
72
+ * Returns a list of root nodes (nodes that do not have a superior).
68
73
*
69
- * @param treeNodes the list of tree nodes
70
- * @return a list of root nodes (nodes without a superior)
74
+ * @param treeNodes the list of all nodes to organize
75
+ * @return a list of root nodes, each containing its child nodes
71
76
* @since 0.2.0
72
77
*/
73
78
protected List <TreeNode > children (List <TreeNode > treeNodes ) {
74
79
Map <Long , List <TreeNode >> nodesMap = treeNodes .stream ()
75
- .filter (node -> Objects .nonNull (node .getSuperior ()) && node .getSuperior () != 0 )
76
- .collect (Collectors .groupingBy (TreeNode ::getSuperior ));
77
-
78
- treeNodes .forEach (node -> node .setChildren (nodesMap .get (node .getId ())));
80
+ .filter (node -> Objects .nonNull (node .getSuperiorId ()) && node .getSuperiorId () != 0 )
81
+ .collect (Collectors .groupingBy (TreeNode ::getSuperiorId ));
79
82
80
83
return treeNodes .stream ()
81
- .filter (node -> Objects .isNull (node .getSuperior ()) || node .getSuperior () == 0 )
84
+ .map (treeNode -> TreeNode .withId (treeNode .getId ())
85
+ .name (treeNode .getName ())
86
+ .superiorId (treeNode .getSuperiorId ())
87
+ .children (nodesMap .get (treeNode .getId ()))
88
+ .meta (treeNode .getMeta ())
89
+ .build ())
90
+ .filter (node -> Objects .isNull (node .getSuperiorId ()))
82
91
.collect (Collectors .toList ());
83
92
}
84
93
85
94
/**
86
- * Expands additional properties for a TreeNode.
87
- *
88
- * @param treeNode the TreeNode to expand
89
- * @param clazz the class of the object
90
- * @param t the object representing the node
91
- * @param expand a set of property names to expand
92
- */
93
- private void expand (TreeNode treeNode , Class <?> clazz , T t , Set <String > expand ) {
94
- if (expand != null && !expand .isEmpty ()) {
95
- Map <String , Object > expandedData = new HashMap <>(expand .size ());
96
- try {
97
- for (String field : expand ) {
98
- PropertyDescriptor descriptor = new PropertyDescriptor (field , clazz );
99
- Object value = descriptor .getReadMethod ().invoke (t );
100
- expandedData .put (field , value );
101
- }
102
- } catch (IllegalAccessException | InvocationTargetException | IntrospectionException e ) {
103
- log .error ("Error expanding data for TreeNode." , e );
104
- }
105
- treeNode .setExpand (expandedData );
106
- }
107
- }
108
-
109
- /**
110
- * Retrieves the ID from the object.
95
+ * Retrieves the ID value from the given object using reflection.
111
96
*
112
97
* @param obj the object instance
113
- * @param clazz the class of the object
114
- * @return the ID value, or null if an error occurs
98
+ * @param clazz the class of the object or its superclass
99
+ * @return the ID value, or null if an error occurs during reflection
115
100
*/
116
101
private Object getId (Object obj , Class <?> clazz ) {
117
102
try {
@@ -124,11 +109,11 @@ private Object getId(Object obj, Class<?> clazz) {
124
109
}
125
110
126
111
/**
127
- * Retrieves the name from the object.
112
+ * Retrieves the name value from the given object using reflection .
128
113
*
129
114
* @param t the object instance
130
115
* @param clazz the class of the object
131
- * @return the name value, or null if an error occurs
116
+ * @return the name value, or null if an error occurs during reflection
132
117
*/
133
118
private Object getName (T t , Class <?> clazz ) {
134
119
try {
@@ -141,11 +126,11 @@ private Object getName(T t, Class<?> clazz) {
141
126
}
142
127
143
128
/**
144
- * Retrieves the superior ID from the object.
129
+ * Retrieves the superior ID value from the given object using reflection .
145
130
*
146
131
* @param t the object instance
147
132
* @param clazz the class of the object
148
- * @return the superior ID value, or null if an error occurs
133
+ * @return the superior ID value, or null if an error occurs during reflection
149
134
*/
150
135
private Object getSuperiorId (T t , Class <?> clazz ) {
151
136
try {
@@ -156,5 +141,32 @@ private Object getSuperiorId(T t, Class<?> clazz) {
156
141
return null ;
157
142
}
158
143
}
144
+
145
+ /**
146
+ * Expands additional properties for the TreeNode by reflecting on the object's class and property names.
147
+ *
148
+ * @param clazz the class of the object
149
+ * @param t the object representing the node
150
+ * @param expand a set of property names to expand as additional data
151
+ * @return a map containing the expanded properties
152
+ * @since 0.3.0
153
+ */
154
+ private Map <String , Object > meta (Class <?> clazz , T t , Set <String > expand ) {
155
+ Map <String , Object > expandedData = Collections .emptyMap ();
156
+ if (expand != null && !expand .isEmpty ()) {
157
+ expandedData = new HashMap <>(expand .size ());
158
+ try {
159
+ for (String field : expand ) {
160
+ PropertyDescriptor descriptor = new PropertyDescriptor (field , clazz );
161
+ Object value = descriptor .getReadMethod ().invoke (t );
162
+ expandedData .put (field , value );
163
+ }
164
+ } catch (IllegalAccessException | InvocationTargetException | IntrospectionException e ) {
165
+ log .error ("Error expanding data for TreeNode." , e );
166
+ }
167
+ }
168
+ return expandedData ;
169
+ }
159
170
}
160
171
172
+
0 commit comments