toad-java/src/main/java/dev.toad/msg/build/Message.java
2023-04-20 13:42:28 -05:00

180 lines
4.8 KiB
Java

package dev.toad.msg.build;
import dev.toad.msg.Code;
import dev.toad.msg.Id;
import dev.toad.msg.Payload;
import dev.toad.msg.Token;
import dev.toad.msg.Type;
import dev.toad.msg.option.Host;
import dev.toad.msg.option.Path;
import dev.toad.msg.option.Query;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
public final class Message
implements MessageNeeds.Code, MessageNeeds.Destination, MessageNeeds.Type {
HashMap<Long, ArrayList<dev.toad.msg.owned.OptionValue>> options =
new HashMap<>();
Optional<Id> id = Optional.empty();
Optional<Token> token = Optional.empty();
Optional<InetSocketAddress> addr = Optional.empty();
Optional<Code> code = Optional.empty();
Optional<Type> type = Optional.empty();
Optional<Payload> payload = Optional.empty();
Message() {}
public static Message from(dev.toad.msg.Message other) {
var builder = new Message();
Function<dev.toad.msg.Option, Long> key = o -> o.number();
Function<dev.toad.msg.Option, ArrayList<dev.toad.msg.owned.OptionValue>> value =
o ->
o
.values()
.stream()
.map(v -> v.toOwned())
.collect(Collectors.toCollection(ArrayList::new));
BinaryOperator<ArrayList<dev.toad.msg.owned.OptionValue>> merge = (
a,
b
) -> {
a.addAll(b);
return a;
};
builder.options =
other
.options()
.stream()
.collect(Collectors.toMap(key, value, merge, () -> new HashMap<>()));
builder.id = Optional.of(other.id());
builder.code = Optional.of(other.code());
builder.token = Optional.of(other.token());
builder.type = Optional.of(other.type());
builder.payload = Optional.of(other.payload());
builder.addr = other.addr();
return builder;
}
public static MessageNeeds.Destination builder() {
return new Message();
}
public MessageNeeds.Type uri(String uriStr)
throws URISyntaxException, UnknownHostException {
var uri = new URI(uriStr);
var addr = InetAddress.getByName(uri.getHost());
var port = uri.getPort() > 0
? uri.getPort()
: uri.getScheme().equals("coaps") ? 5684 : 5683;
this.addr = Optional.of(new InetSocketAddress(addr, port));
return this.option(new Host(uri.getHost()))
.option(new Query(uri.getQuery()))
.option(new Path(uri.getPath()));
}
public MessageNeeds.Type addr(InetSocketAddress addr) {
this.addr = Optional.of(addr);
return this;
}
public MessageNeeds.Code type(Type type) {
this.type = Optional.of(type);
return this;
}
public Message code(Code code) {
this.code = Optional.of(code);
return this;
}
public Message id(Id id) {
this.id = Optional.of(id);
return this;
}
public Message unsetId() {
this.id = Optional.empty();
return this;
}
public Message token(Token token) {
this.token = Optional.of(token);
return this;
}
public Message unsetToken() {
this.token = Optional.empty();
return this;
}
public Message unsetOption(long num) {
this.options.remove(num);
return this;
}
public Message payload(Payload payload) {
this.payload = Optional.of(payload);
return this.option(payload.contentFormat().get());
}
public Message option(
Function<OptionNeeds.Number, dev.toad.msg.owned.Option> fun
) {
var opt = fun.apply(Option.builder());
return this.option(opt);
}
public Message option(dev.toad.msg.Option opt) {
return this.putOption(opt.number(), opt.values());
}
public Message putOption(long number, List<dev.toad.msg.OptionValue> values) {
this.options.put(
number,
values
.stream()
.map(v -> v.toOwned())
.collect(Collectors.toCollection(ArrayList::new))
);
return this;
}
public Message option(long number, List<dev.toad.msg.OptionValue> values) {
var vals = Optional
.ofNullable(this.options.get(number))
.orElse(new ArrayList<>());
vals.addAll(values.stream().map(v -> v.toOwned()).toList());
return this.putOption(number, List.copyOf(vals));
}
public dev.toad.msg.Message build() {
return new dev.toad.msg.owned.Message(
this.addr,
this.type.get(),
this.code.get(),
this.id.orElse(Id.defaultId()),
this.token.orElse(Token.defaultToken()),
this.payload.orElse(new Payload()),
this.options.entrySet()
.stream()
.map(ent -> new dev.toad.msg.owned.Option(ent.getKey(), ent.getValue()))
.collect(Collectors.toCollection(() -> new ArrayList<>()))
);
}
}