Interface Element<T>
- Type Parameters:
T- the class type of the wrapped object node that will be encapsulated in thisElement
Element represents a node within a tree. It consists of the
elementary unit of the HappyTree API, and it is directly handled through the
TreeManager interface. An element can move from one tree to another,
be removed, copied, and even encapsulate any object (node) within it, making
this encapsulated object hierarchically available within a tree structure.
This interface is only responsible for handling the element itself and its
children. Here, there is no direct relationship with the other available
interfaces, except its respective session (TreeSession) which this
element belongs to. Considering that an element corresponds to an elementary
unit, it can only relate to itself and its children.
An element is always associated with a session. Even after its creation, the element already belongs to a session, but that does not mean that this element is already in the tree. It depends on its lifecycle state.
To be handled, an element must be in an appropriate state in its lifecycle, depending on the operation that is desired to perform. Its lifecycle consists of 3 states:
| State | Description |
|---|---|
| NOT_EXISTED | When the element is created. At this time, the element has not been persisted inside any tree session yet. |
| ATTACHED | When the element is created and after that, it is persisted within the tree session. |
| DETACHED | When the element is already inside of the tree as ATTACHED but it has been changed since the API client gained access to it. |
Considering that an element is previously attached to some session,
each subsequent manipulation from the perspective of the element itself will
turn its state to DETACHED, thus requiring an update by invoking
TreeManager.updateElement(Element).
The API client has access to the following attributes:
| Attributes | Description |
|---|---|
ID | The element identifier within the tree (must be unique within the tree). |
Parent | The parent element identifier within the
tree (if the parent element is not found or null then this
element will be moved to the tree root level). |
Children | The children list and all descendants of the element. |
Wrapped Node | The encapsulated object node (the original object). |
Session | The session to which this element belongs. |
Lifecycle | The current state in the lifecycle. |
The relationship between @Id and @Parent in the
tree composition represents the main part of the HappyTree API. The tree is
assembled strictly by this relation, in which the @Parent of an
element references the @Id of the parent element. Therefore, the
@Id of an element can never be null, and if the
@Parent of an element is null or not found, that
element is moved to the root level (first level) of the tree.
- Author:
- Diego Madson de Andrade Nóbrega
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionvoidAdds a new child element into the current element.voidaddChildren(Collection<Element<T>> children) Adds a list of child elements to be concatenated to the current children list.voidApplies a function to be performed on this element and all its children recursively within the tree structure.voidApplies a function to be performed within this element that satisfies the specified condition.Returns theTreeSessioninstance to which this element belongs.Obtains all child elements of the current element.getElementById(Object id) Searches within the current element for an element according to theidparameter.getId()Obtains the element identifier.Obtains the parent identifier of this element.Returns the current lifecycle state of this element.voidremoveChild(Element<T> child) Removes the specifiedchildelement from the children list of the current element.voidremoveChild(Object id) Removes the element from the children list of the current element by theidparameter.voidremoveChildren(Collection<Element<T>> children) Removes a subset of elements within this one.Searches for elements that satisfy a specific condition within this element and its children recursively.voidSets the element identifier.voidSets the parent identifier reference of this element.toJSON()Converts the whole element structure into a JSON format.Converts the whole element structure into a well formatted JSONString.Converts the whole element structure into a well formatted XMLString.toXML()Converts the whole element structure into an XMLString.unwrap()Returns a copy of the object node wrapped in this element.voidEncapsulates any object node within the element, as long as this object has the same class type as other objects that were encapsulated within the same tree session.
-
Method Details
-
getId
Object getId()Obtains the element identifier.This identifier is unique within the tree session when this is attached to the tree.
- Returns:
- the element identifier
-
setId
Sets the element identifier.By invoking this method, the element will not change its
@Idimmediately. It is necessary to update the element for the change to take effect.The
@Idmust be unique. If it isnull, nothing happens because this method is used for updates, so the element keeps the old@Id.When the element is a root element, the
@Idis not set.- Parameters:
id- the element identifier to be updated
-
getParent
Object getParent()Obtains the parent identifier of this element.- Returns:
- the parent element identifier
-
setParent
Sets the parent identifier reference of this element.If the
@Parentreference isnullor references a nonexistent element, then it is certain that this element will be in the root level of the tree when it is going to be persisted or updated.When the element is a root element, the
@Parentis not set.- Parameters:
parent- the parent element identifier
-
getChildren
Collection<Element<T>> getChildren()Obtains all child elements of the current element. This includes all descendants recursively.- Returns:
- all children of the current element
-
addChild
-
addChildren
Adds a list of child elements to be concatenated to the current children list.If each element within the
childrenlist contains more children within it recursively, they will also be added.- Parameters:
children- the list of child elements to be concatenated to the current children list
-
getElementById
Searches within the current element for an element according to theidparameter.The search is performed recursively within the children of this element starting by the current element itself. If the element is not found, then
nullis returned.- Parameters:
id- the element identifier to be searched for- Returns:
- the found element within this one
-
removeChildren
Removes a subset of elements within this one.The element references are removed whether they are found in children list. When an element is removed, all of its children as well as the elements below the hierarchy are also removed, recursively.
- Parameters:
children- the list of child elements to be removed
-
removeChild
Removes the specifiedchildelement from the children list of the current element.The
childelement reference is removed if it is found in the children list. When an element is removed, all of its children as well as the elements below in the hierarchy are also removed, recursively.- Parameters:
child- the element to be removed
-
removeChild
Removes the element from the children list of the current element by theidparameter.If it exists, then the element and all of its children are removed as well.
- Parameters:
id- the element identifier to be removed
-
wrap
Encapsulates any object node within the element, as long as this object has the same class type as other objects that were encapsulated within the same tree session.As an element conceptually represents a node within a tree, the wrapped object node would be simulating precisely its position within the tree in question.
The object node itself can be wrapped at two different times:
- Initializing a new empty tree session;
- Initializing a tree session from the API Transformation Process.
To be effectively wrapped within this element in the tree session, the invocation of
TreeManager.persistElement(Element)(for new elements) orTreeManager.updateElement(Element)(for changing object nodes) is required, depending on the context.The first one would be to create an empty tree. In this way, the wrapped node is determined after the tree is ready by invoking this method. This includes the choice of not determining it, leaving it with a
nullvalue.The latter happens in the API Transformation Process, that is, at the moment of initialization, before the tree is created, when a call to
TreeTransaction.initializeSession(String, Collection)transforms a previous linear structure into a real hierarchical tree structure. Then, eachElementobject will wrap its respective node automatically.Therefore, each object node of this linear structure would be represented precisely by this encapsulated object within its respective
Elementobject in its respective hierarchy within the tree. In this case, during the API Transformation Process lifecycle, the object node will be transformed, managed, and wrapped within its own element automatically.There are some requirements for this object node to be wrapped when initializing a session by the API Transformation Process:
- The class of this node must be annotated by
@Tree; - The parent attribute of this node must be annotated by
@Parent; - The ID attribute of this node must be annotated by
@Id; - The class of this node must implement
Serializable; - The
@Idvalue cannot benull; - The
@Idand@Parentmust be of the same class type.
These requirements apply only when the session is initialized by the API Transformation Process.
When the element is a root element, it is not possible to wrap the object in it. So, the wrapped object node is always
null.- Parameters:
object- the object to be wrapped within this element
-
unwrap
T unwrap()Returns a copy of the object node wrapped in this element.The object node itself cannot be changed. This method provides a way to access this object. To modify its state, consider using the
wrap(Object)method and save the changes by invoking theTreeManager.updateElement(Element)method.- Returns:
- a copy of the wrapped object node inside this element
-
attachedTo
TreeSession attachedTo()Returns theTreeSessioninstance to which this element belongs. It represents the tree to which this element belongs.When an element is created, either through the API Transformation Process or normally through invoking
TreeManager.createElement(Object, Object, Object), the current session of the transaction is always associated with the created element.Therefore, an element is always associated with a session.
- Returns:
- the session (tree) to which this element belongs
-
lifecycle
String lifecycle()Returns the current lifecycle state of this element.The lifecycle is important to indicate which operations are allowed for this element through the
TreeManagerinterface.Allowed Operations by Element Lifecycle State TreeManager Operation Allowed Lifecycle cut() ATTACHED copy() ATTACHED removeElement() ATTACHED containsElement() ATTACHED persistElement() NOT_EXISTED updateElement() ATTACHED; DETACHED
For all operations where the lifecycle does not correspond, aTreeExceptionwill be thrown, except forTreeManager.containsElement(Element, Element)which just returnsfalsewhen the elements are not ATTACHED.All operations provided by
TreeManagerchange the element's state to ATTACHED, exceptTreeManager.createElement(Object, Object, Object)(NOT_EXISTED).- Returns:
Stringcorresponding to the lifecycle state name of this element
-
toJSON
String toJSON()Converts the whole element structure into a JSON format. This includes all children recursively.It is mandatory that the element as well as all its children have non-null wrapped object nodes. If there is at least one wrapped object node that is
null, then an empty JSON object is returned "{}".The above restriction is not applied to the root element, as it is a special element created by the HappyTree API itself with no wrapped object node. Therefore, calling
TreeManager.root()orTreeSession.tree()is allowed to print the tree structure in a JSON format, but the root element will not contain the@Id,@Parent, or the wrapped object node.The JSON representation consists of the attributes of the wrapped object node plus an attribute called children, which holds all the children of the node and so on recursively:
- Object Node Attributes: all getters attributes from the class
annotated with the
@Treeannotation; - Children Attribute: the same structure but placed as child in a recursive way.
For example, considering an element that wraps an object of type
Directory, the JSON representation would look like (pretty print):{ "identifier": 1, "parentIdentifier": null, "name": "Music" "children": [ { "identifier": 2, "parentIdentifier": 1, "name": "Country" "children": [ { "identifier": 3, "parentIdentifier": 2, "name": "Bruce Springsteen", "children": [] }, { "identifier": 4, "parentIdentifier": 2, "name": "George Strait", "children": [] } ] } ] }To convert the wrapped object into a JSON format, it is not necessary that the element be attached to any session. However, the element as well as all its children need to have their original objects nodes not
null(except for the root element).For conversion, the Jackson library is used internally, so the wrapped object can be annotated with Jackson annotations to customize the conversion if necessary.
- Returns:
- the JSON representation of this element (minified)
- Object Node Attributes: all getters attributes from the class
annotated with the
-
toPrettyJSON
String toPrettyJSON()Converts the whole element structure into a well formatted JSONString. This includes all children recursively.It is mandatory that the element as well as all its children have non-null wrapped object nodes. If there is at least one wrapped object node that is
null, then an empty JSON object is returned "{}".The above restriction is not applied to the root element, as it is a special element created by the HappyTree API itself with no wrapped object node. Therefore, calling
TreeManager.root()orTreeSession.tree()is allowed to print the tree structure in a JSON format, but the root element will not contain the@Id,@Parent, or the wrapped object node.- Returns:
- a well-formatted JSON of this element
- See Also:
-
toXML
String toXML()Converts the whole element structure into an XMLString. This includes all children recursively.It is mandatory that the element as well as all its children have non-null wrapped object nodes. If there is at least one wrapped object node that is
null, then an empty XML is returned.The above restriction is not applied to the root element, as it is a special element created by the HappyTree API itself with no wrapped object node. Therefore, calling
TreeManager.root()orTreeSession.tree()is allowed to print the tree structure as an XMLString, but the root element will not contain the@Id,@Parent, or the wrapped object node.The XML content consists of the attributes of the wrapped object node plus a tag called children, which holds all other elements that contain all other children of the node and so on recursively. The root tag of this XML is always element.
For example, considering an element that wraps an object of type
Directory, the XML content would look like (pretty print):<element> <identifier>1</identifier> <parentIdentifier>null</parentIdentifier> <name>Music</name> <children> <element> <identifier>2</identifier> <parentIdentifier>1</parentIdentifier> <name>Country</name> <children> <element> <identifier>3</identifier> <parentIdentifier>2</parentIdentifier> <name>Bruce Springsteen</name> <children/> </element> <element> <identifier>4</identifier> <parentIdentifier>2</parentIdentifier> <name>George Strait</name> <children/> </element> </children> </element> </children> </element>To convert the wrapped object into an XML format, it is not necessary that the element be attached to any session. However, the element as well as all its children need to have their original objects nodes not
null(except for the root element).For conversion, the Jackson library is used internally, so the wrapped object can be annotated with Jackson annotations to customize the conversion if necessary.
- Returns:
- the XML content of this element (minified)
-
toPrettyXML
String toPrettyXML()Converts the whole element structure into a well formatted XMLString. This includes all children recursively.It is mandatory that the element as well as all its children have non-null wrapped object nodes. If there is at least one wrapped object node that is
null, then an empty XML is returned.The above restriction is not applied to the root element, as it is a special element created by the HappyTree API itself with no wrapped object node. Therefore, calling
TreeManager.root()orTreeSession.tree()is allowed to print the tree structure as an XMLString, but the root element will not contain the@Id,@Parent, or the wrapped object node.- Returns:
- a well formatted XML of this element
- See Also:
-
search
Searches for elements that satisfy a specific condition within this element and its children recursively. The method returns a list of elements that match the provided condition.This method traverses the subtree starting from this element (including the element itself) and evaluates each element against the specified condition. If an element satisfies the condition, it is included in the resulting list.
The resulting list consists of all elements that match the specified condition, including their children. Therefore, the list will include the elements that satisfy the condition, while preserving each element's hierarchical structure.
When this method is invoked by the root element, the search is performed on all elements in the tree, except for the root element itself, as it is a special element created by the HappyTree API itself, not having the
@Id,@Parentneither a wrapped object node.Example usage:
//Find all elements within this subtree which the object node has its //name starting with "A" List<Element<MyNodeType>> results = element.search( e -> e.unwrap().getName().startsWith("A") );- Parameters:
condition- the predicate function defining the search criteria- Returns:
- a list of elements that satisfy the specified condition within this element's subtree
-
apply
Applies a function to be performed on this element and all its children recursively within the tree structure. The action applied to the elements is not automatically reflected on the tree session, thus requiring to invokeTreeManager.persistElement(Element)for new elements orTreeManager.updateElement(Element)to save the changes for already existing elements.This method traverses the entire subtree starting from this element (including the element itself) and applies the given action to all elements in the tree.
The action function receives each
Elementas a parameter and can perform any operation on it, such as modifying the wrapped object, changing element properties, or performing calculations/verifications.When this method is invoked by the root element, the action is applied to all elements in the tree, except for the root element itself, as it is a special element created by the HappyTree API itself, not having the
@Id,@Parentnor a wrapped object node.Example usage:
//Transform all directory names to uppercase element.apply(e -> e.unwrap().transformNameToUpperCase()); //Log all element IDs in the subtree element.apply(e -> System.out.println("Element ID: " + e.getId()));Note: The function is applied to all elements in the subtree (except for the root element itself). If you need conditional execution based on specific criteria, consider using
apply(Consumer, Predicate)instead.- Parameters:
action- the function to apply to each element in the subtree- See Also:
-
apply
Applies a function to be performed within this element that satisfies the specified condition. The action applied to the elements is not automatically reflected on the tree session, thus requiring to invoke theTreeManager.persistElement(Element)for new elements orTreeManager.updateElement(Element)to save the changes for already existing elements.This method traverses the entire subtree starting from this element (including the element itself) and applies the given action only to those elements that match the specified predicate condition.
The condition predicate is evaluated for each element in the subtree, and the action is only performed on elements where the predicate returns
true. This allows for fine-grained control over which elements are affected by the function.When this method is invoked by the root element, the action is applied to all elements that match the condition in the tree, except for the root element itself, as it is a special element created by the HappyTree API itself, not having the
@Id,@Parentnor a wrapped object node.Example usage:
//Transform only elements containing "photo" in their name element.apply( e -> e.unwrap().transformNameToUpperCase(), e -> e.unwrap().getName().toLowerCase().contains("photo") ); //Apply action only to leaf elements (elements with no children) element.apply( e -> processLeafElement(e), e -> e.getChildren().isEmpty() );Note: Unlike
apply(Consumer), the function is applied only for elements that satisfy the condition passed as parameter. Elements that don't match the condition remain unchanged, providing selective capabilities.- Parameters:
action- the function to apply to matching elementscondition- the predicate that determines which elements should receive the action- See Also:
-