it.auties.whatsapp.model.request.Node Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of whatsappweb4j Show documentation
Show all versions of whatsappweb4j Show documentation
Standalone fully-featured Whatsapp Web API for Java and Kotlin
package it.auties.whatsapp.model.request;
import it.auties.whatsapp.util.Json;
import lombok.NonNull;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* An immutable model class that represents the primary unit used by WhatsappWeb's WebSocket to
* communicate with the client
*
* @param description a non-null String that describes the content of this node
* @param attributes a non-null Map that describes the metadata of this object
* @param content a nullable object: a List of {@link Node}, a {@link String} or a
* {@link Number}
*/
public record Node(@NonNull String description, @NonNull Attributes attributes,
Object content) {
/**
* Constructs a Node that only provides a non-null tag
*
* @param description a non-null String that describes the data that this object holds
* @return a new node with the above characteristics
*/
public static Node of(@NonNull String description) {
return new Node(description, Attributes.of(), null);
}
/**
* Constructs a Node that provides a non-null tag and a nullable content
*
* @param description a non-null String that describes the data that this object holds
* @param content a nullable object, usually a List of {@link Node}, a {@link String} or a
* {@link Number}
* @return a new node with the above characteristics
*/
public static Node of(@NonNull String description, Object content) {
return new Node(description, Attributes.of(), content);
}
/**
* Constructs a Node that provides a non-null tag, a non-null map of attributes and a nullable
* content
*
* @param description a non-null String that describes the data that this object holds
* @param attributes a non-null Map that describes the metadata of this object
* @param content a nullable object, usually a List of {@link Node}, a {@link String} or a
* {@link Number}
* @return a new node with the above characteristics
*/
public static Node of(@NonNull String description, @NonNull Map attributes, Object content) {
return new Node(description, Attributes.ofNullable(attributes), content);
}
/**
* Constructs a Node that provides a non-null tag and a non-null map of attributes
*
* @param description a non-null String that describes the data that this object holds
* @param attributes a non-null Map that describes the metadata of this object
* @return a new node with the above characteristics
*/
public static Node ofAttributes(@NonNull String description, @NonNull Map attributes) {
return new Node(description, Attributes.ofNullable(attributes), null);
}
/**
* Constructs a Node that provides a non-null tag and a nullable var-args of children
*
* @param description a non-null String that describes the data that this object holds
* @param children the nullable children of this node
* @return a new node with the above characteristics
*/
public static Node ofChildren(@NonNull String description, Node... children) {
return ofChildren(description, Arrays.asList(children));
}
/**
* Constructs a Node that provides a non-null tag and a nullable var-args of children
*
* @param description a non-null String that describes the data that this object holds
* @param children the nullable children of this node
* @return a new node with the above characteristics
*/
public static Node ofChildren(@NonNull String description, Collection children) {
return new Node(description, Attributes.of(), requireNonNullNodes(children));
}
private static List requireNonNullNodes(Collection nodes) {
if (nodes == null) {
return null;
}
var results = nodes.stream().filter(Objects::nonNull).toList();
return results.isEmpty() ? null : results;
}
/**
* Constructs a Node that provides a non-null tag, a non-null map of attributes and a nullable
* var-args of children
*
* @param description a non-null String that describes the data that this object holds
* @param attributes a non-null Map that describes the metadata of this object
* @param children the nullable children of this node
* @return a new node with the above characteristics
*/
public static Node ofChildren(@NonNull String description, @NonNull Map attributes, Node... children) {
return ofChildren(description, attributes, Arrays.asList(children));
}
/**
* Constructs a Node that provides a non-null tag, a non-null map of attributes and a nullable
* var-args of children
*
* @param description a non-null String that describes the data that this object holds
* @param attributes a non-null Map that describes the metadata of this object
* @param children the nullable children of this node
* @return a new node with the above characteristics
*/
public static Node ofChildren(@NonNull String description, @NonNull Map attributes, Collection children) {
return new Node(description, Attributes.ofNullable(attributes), requireNonNullNodes(children));
}
/**
* Returns the content of this object as string
*
* @return an optional
*/
public Optional contentAsString() {
if (content instanceof String string) {
return Optional.of(string);
} else if (content instanceof byte[] bytes) {
return Optional.of(new String(bytes, StandardCharsets.UTF_8));
} else {
return Optional.empty();
}
}
/**
* Returns the content of this object as bytes
*
* @return an optional
*/
public Optional contentAsBytes() {
return content instanceof byte[] bytes ? Optional.of(bytes) : Optional.empty();
}
/**
* Returns the content of this object as a long
*
* @return an optional
*/
@SuppressWarnings("unused")
public OptionalLong contentAsLong() {
return content instanceof Number number ? OptionalLong.of(number.longValue()) : OptionalLong.empty();
}
/**
* Returns the content of this object as a double
*
* @return an optional
*/
@SuppressWarnings("unused")
public OptionalDouble contentAsDouble() {
return content instanceof Number number ? OptionalDouble.of(number.doubleValue()) : OptionalDouble.empty();
}
/**
* Returns the content of this object as a double
*
* @return an optional
*/
@SuppressWarnings("unused")
public Optional contentAsBoolean() {
if (content instanceof String string) {
return Optional.of(Boolean.parseBoolean(string.toLowerCase(Locale.ROOT)));
} else if (content instanceof byte[] bytes) {
return Optional.of(Boolean.parseBoolean(new String(bytes, StandardCharsets.UTF_8).toLowerCase(Locale.ROOT)));
} else {
return Optional.empty();
}
}
/**
* Checks whether the child node with the given description exists
*
* @return true if a child node with the given description exists
*/
public boolean hasNode(String description) {
return children().stream().anyMatch(node -> Objects.equals(node.description(), description));
}
/**
* Returns a non-null list of children of this node
*
* @return a non-null list
*/
public LinkedList children() {
if (content == null) {
return new LinkedList<>();
}
if (!(content instanceof Collection> collection)) {
return new LinkedList<>();
}
return collection.stream()
.filter(entry -> entry instanceof Node)
.map(entry -> (Node) entry)
.collect(Collectors.toCollection(LinkedList::new));
}
/**
* Checks whether this node's description is equal to the one provided
*
* @param description the non-null description to check against
* @return a boolean
*/
public boolean hasDescription(@NonNull String description) {
return Objects.equals(description(), description);
}
/**
* Finds the first child node
*
* @return an optional
*/
public Optional findNode() {
return children().stream().findFirst();
}
/**
* Returns the first node that matches the description provided
*
* @return an optional
*/
public Optional findNode(String description) {
return children().stream().filter(node -> Objects.equals(node.description(), description)).findFirst();
}
/**
* Returns all the nodes that match the description provided
*
* @return an optional body, present if a result was found
*/
public List findNodes(String description) {
return children().stream().filter(node -> Objects.equals(node.description(), description)).toList();
}
/**
* Returns the size of this object
*
* @return an unsigned int
*/
public int size() {
var descriptionSize = 1;
var attributesSize = 2 * attributes.toMap().size();
var contentSize = hasContent() ? 1 : 0;
return descriptionSize + attributesSize + contentSize;
}
/**
* Returns whether this object's content is non-null
*
* @return true if this object has a content
*/
public boolean hasContent() {
return Objects.nonNull(content);
}
/**
* Constructs a new request from this node
*
* @return a non null request
* @throws NullPointerException if no valid jid can be found
*/
public Request toRequest(Function filter) {
if (id() == null) {
attributes.put("id", UUID.randomUUID().toString());
}
return Request.of(this, filter);
}
/**
* Returns the nullable id of this node
*
* @return a nullable String
*/
public String id() {
return attributes.getString("id", null);
}
/**
* Checks if this object is equal to another
*
* @param other the reference object with which to compare
* @return whether {@code other} is equal to this object
*/
@Override
public boolean equals(Object other) {
return other instanceof Node that && Objects.equals(this.description(), that.description()) && Objects.equals(this.attributes(), that.attributes()) && (Objects.equals(this.content(), that.content()) || this.content() instanceof byte[] theseBytes && that.content() instanceof byte[] thoseBytes && Arrays.equals(theseBytes, thoseBytes));
}
/**
* Converts this node into a String
*
* @return a non null String
*/
@Override
public String toString() {
var description = this.description.isBlank() || this.description.isEmpty() ? "" : "description=%s".formatted(this.description);
var attributes = this.attributes.toMap().isEmpty() ? "" : ", attributes=%s".formatted(this.attributes.toMap());
var content = this.content == null ? "" : ", content=%s".formatted(this.content instanceof byte[] bytes ? Arrays.toString(bytes) : this.content);
return "Node[%s%s%s]".formatted(description, attributes, content);
}
/**
* Converts this node into a JSON String
*
* @return a non null String
*/
public String toJson() {
return Json.writeValueAsString(this, true);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy