Skip to content

Commit

Permalink
[#163] docs and minor renames
Browse files Browse the repository at this point in the history
  • Loading branch information
susanw1 committed Sep 12, 2024
1 parent 2742d43 commit c1cef27
Show file tree
Hide file tree
Showing 22 changed files with 223 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import net.zscript.util.ByteString.ByteAppendable;
import net.zscript.util.ByteString.ByteStringBuilder;

/**
* Represents a fixed command-sequence, augmented by the addresses of nodes it passes through to get to the target..
*/
public class AddressedCommand implements ByteAppendable {
private final Queue<ZscriptAddress> addressSections;
private final CommandSequence content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

/**
* Representation of a single address, as per <code>@1.5.192</code>, where each element is a uint16.
*
* <p/>
* Aggregation to create a full multi-hop address is managed by {@link AddressedCommand} and {@link CompleteAddressedResponse}
*/
public class ZscriptAddress implements ByteAppendable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import net.zscript.util.ByteString;
import net.zscript.util.ByteString.ByteAppendable;

/**
* Represents a single command within a command-sequence, with its fields; it keeps track of the commands that follow it onSuccess
*/
public class Command implements ByteAppendable {
private final ZscriptFieldSet fieldSet;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,48 @@

public class CommandExecutionPath implements Iterable<Command>, ByteAppendable {

static class CommandBuilder {
ReadToken start = null;
public static CommandExecutionPath parse(ReadToken start) {
return parse(ZscriptModel.standardModel(), start);
}

CommandBuilder onSuccess = null;
int successBracketCount = 0;
CommandBuilder onFail = null;
int failBracketCount = 0;
public static CommandExecutionPath parse(ZscriptModel model, ReadToken start) {
List<CommandBuilder> builders = createLinkedPaths(start);

public void setOnSuccess(CommandBuilder onSuccess) {
this.onSuccess = onSuccess;
Map<CommandBuilder, Command> commands = new HashMap<>();
for (ListIterator<CommandBuilder> iter = builders.listIterator(builders.size()); iter.hasPrevious(); ) {
CommandBuilder b = iter.previous();
if (b.start != null) {
commands.put(b, b.generateCommand(commands));
}
}
return new CommandExecutionPath(model, commands.get(builders.get(0)));
}

public void setOnFail(CommandBuilder onFail) {
this.onFail = onFail;
}
public static CommandExecutionPath from(ZscriptModel model, Command success) {
return new CommandExecutionPath(model, success);
}

public ReadToken getStart() {
return start;
}
public static CommandExecutionPath blank() {
return blank(ZscriptModel.standardModel());
}

public void setStart(ReadToken token) {
this.start = token;
}
public static CommandExecutionPath blank(ZscriptModel model) {
return new CommandExecutionPath(model, null);
}

public Command generateCommand(Map<CommandBuilder, Command> commands) {
return new Command(commands.get(onSuccess), commands.get(onFail), ZscriptFieldSet.fromTokens(start));
}
private final ZscriptModel model;
private final Command firstCommand;

private CommandExecutionPath(ZscriptModel model, Command firstCommand) {
this.model = model;
this.firstCommand = firstCommand;
}

private static List<CommandBuilder> createLinkedPaths(ReadToken start) {
List<CommandBuilder> builders = new ArrayList<>();

List<CommandBuilder> needSuccessPath = new ArrayList<>();
List<CommandBuilder> needFailPath = new ArrayList<>();
List<CommandBuilder> builders = new ArrayList<>();

CommandBuilder last = new CommandBuilder();
builders.add(last);
Expand Down Expand Up @@ -124,43 +133,6 @@ private static List<CommandBuilder> createLinkedPaths(ReadToken start) {
return builders;
}

public static CommandExecutionPath parse(ReadToken start) {
return parse(ZscriptModel.standardModel(), start);
}

public static CommandExecutionPath parse(ZscriptModel model, ReadToken start) {
List<CommandBuilder> builders = createLinkedPaths(start);

Map<CommandBuilder, Command> commands = new HashMap<>();
for (ListIterator<CommandBuilder> iter = builders.listIterator(builders.size()); iter.hasPrevious(); ) {
CommandBuilder b = iter.previous();
if (b.start != null) {
commands.put(b, b.generateCommand(commands));
}
}
return new CommandExecutionPath(model, commands.get(builders.get(0)));
}

public static CommandExecutionPath from(ZscriptModel model, Command success) {
return new CommandExecutionPath(model, success);
}

public static CommandExecutionPath blank() {
return blank(ZscriptModel.standardModel());
}

public static CommandExecutionPath blank(ZscriptModel model) {
return new CommandExecutionPath(model, null);
}

private final ZscriptModel model;
private final Command firstCommand;

private CommandExecutionPath(ZscriptModel model, Command firstCommand) {
this.model = model;
this.firstCommand = firstCommand;
}

@Override
public void appendTo(ByteStringBuilder builder) {
Deque<Command> openedTrees = new ArrayDeque<>();
Expand Down Expand Up @@ -246,38 +218,40 @@ public List<MatchedCommandResponse> compareResponses(ResponseExecutionPath resps
parenStarts.add(tmp1);
tmp1 = tmp1.getOnFail();
}

boolean lastEndedOpen = false;
boolean lastEndedClose = false;
boolean lastSucceeded = true;
int lastParenCount = 0;

List<MatchedCommandResponse> cmds = new ArrayList<>();
Command current = firstCommand;
Command currentCmd = firstCommand;
Response currentResp = resps.getFirstResponse();
Command lastFail = null;

while (currentResp != null) {
if (current == null) {
if (currentCmd == null) {
throw new IllegalArgumentException("Command sequence ended before response - cannot match");
}
cmds.add(new MatchedCommandResponse(current, currentResp));
cmds.add(new MatchedCommandResponse(currentCmd, currentResp));

if (lastSucceeded) {
if (lastEndedClose) {
if (parenStarts.peek().getOnFail() == current.getOnFail()) {
if (parenStarts.peek().getOnFail() == currentCmd.getOnFail()) {
throw new IllegalArgumentException("Response has ')' without valid opening '('");
}
Command tmp2 = parenStarts.pop().getOnFail();
while (tmp2 != null && tmp2 != current) {
while (tmp2 != null && tmp2 != currentCmd) {
tmp2 = tmp2.getOnSuccess();
}
if (tmp2 != current) {
if (tmp2 != currentCmd) {
throw new IllegalArgumentException("Response has ')' without command sequence merging");
}
lastEndedClose = false;
} else if (lastEndedOpen) {
parenStarts.push(current);
parenStarts.push(currentCmd);
lastEndedOpen = false;
} else if (lastFail != null && current.getOnFail() != lastFail) {
} else if (lastFail != null && currentCmd.getOnFail() != lastFail) {
throw new IllegalArgumentException("Fail conditions don't match up around '&'");
}
} else {
Expand All @@ -286,22 +260,22 @@ public List<MatchedCommandResponse> compareResponses(ResponseExecutionPath resps
throw new IllegalArgumentException("Command sequence ran out of parens before response sequence");
}
Command tmp3 = parenStarts.peek().getOnFail();
while (tmp3 != null && tmp3.getOnFail() != current) {
while (tmp3 != null && tmp3.getOnFail() != currentCmd) {
tmp3 = tmp3.getOnSuccess();
}
if (tmp3 == null) {
throw new IllegalArgumentException("Response has ')' without command sequence merging");
}
tmp3 = parenStarts.peek().getOnFail();
while (tmp3 != null && tmp3 != current) {
while (tmp3 != null && tmp3 != currentCmd) {
tmp3 = tmp3.getOnFail();
}
if (tmp3 != current) {
if (tmp3 != currentCmd) {
throw new IllegalArgumentException("Response has ')' without command sequence merging");
}
parenStarts.pop();
}
if (parenStarts.isEmpty() || parenStarts.peek().getOnFail() != current) {
if (parenStarts.isEmpty() || parenStarts.peek().getOnFail() != currentCmd) {
throw new IllegalArgumentException("Response has failure divergence without parenthesis");
}
}
Expand All @@ -311,14 +285,14 @@ public List<MatchedCommandResponse> compareResponses(ResponseExecutionPath resps
} else if (currentResp.hasOpenParen()) {
lastEndedOpen = true;
}
lastFail = current.getOnFail();
lastFail = currentCmd.getOnFail();
lastSucceeded = true;
current = current.getOnSuccess();
currentCmd = currentCmd.getOnSuccess();
} else {
lastFail = null;
lastParenCount = currentResp.getParenCount();
lastSucceeded = false;
current = current.getOnFail();
currentCmd = currentCmd.getOnFail();
}
currentResp = currentResp.getNext();
}
Expand Down Expand Up @@ -377,4 +351,33 @@ public Command getFirstCommand() {
public ZscriptModel getModel() {
return model;
}

private static class CommandBuilder {
ReadToken start = null;

CommandBuilder onSuccess = null;
int successBracketCount = 0;
CommandBuilder onFail = null;
int failBracketCount = 0;

public void setOnSuccess(CommandBuilder onSuccess) {
this.onSuccess = onSuccess;
}

public void setOnFail(CommandBuilder onFail) {
this.onFail = onFail;
}

public ReadToken getStart() {
return start;
}

public void setStart(ReadToken token) {
this.start = token;
}

public Command generateCommand(Map<CommandBuilder, Command> commands) {
return new Command(commands.get(onSuccess), commands.get(onFail), ZscriptFieldSet.fromTokens(start));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import net.zscript.util.ByteString.ByteStringBuilder;

public class NumberField implements ZscriptField, ByteString.ByteAppendable {
private byte key;
private int value;
private final byte key;
private final int value;

public static NumberField fieldOf(byte key, int value) {
return new NumberField(key, value);
Expand Down Expand Up @@ -42,4 +42,9 @@ public BlockIterator iterator() {
public void appendTo(ByteStringBuilder builder) {
builder.appendByte(key).appendNumeric16(value);
}

@Override
public String toString() {
return "NumberField[" + ByteString.from(this) + "]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,42 @@
import net.zscript.javaclient.addressing.ZscriptAddress;
import net.zscript.javaclient.threading.ZscriptWorkerThread;

/**
* Maintains the mapping of addresses to connections for a node in the device tree. The device node must be known at create-time, and the addresses are attached (or detached)
* thereafter.
*/
class AddressingSystem {
private final Map<ZscriptAddress, AddressingConnection> connections = new HashMap<>();

private final ZscriptBasicNode node;

AddressingSystem(ZscriptBasicNode node) {
this.node = node;
}

private void sendAddressed(AddressedCommand cmd) {
node.getParentConnection().send(cmd);
}

public boolean response(AddressedResponse addrResp) {
AddressingConnection connection = connections.get(addrResp.getAddressSection());
if (connection == null) {
return false;
}
connection.response(addrResp.getChild());
return true;
}

public Connection attach(ZscriptAddress address) {
AddressingConnection connection = new AddressingConnection(address);
connections.put(address, connection);
return connection;
}

public Connection detach(ZscriptAddress address) {
return connections.remove(address);
}

class AddressingConnection implements Connection {
private final ZscriptAddress address;
private Consumer<AddressedResponse> respConsumer = null;
Expand Down Expand Up @@ -45,35 +80,4 @@ public ZscriptWorkerThread getAssociatedThread() {
return node.getParentConnection().getAssociatedThread();
}
}

private final Map<ZscriptAddress, AddressingConnection> connections = new HashMap<>();

private final ZscriptBasicNode node;

AddressingSystem(ZscriptBasicNode node) {
this.node = node;
}

private void sendAddressed(AddressedCommand cmd) {
node.getParentConnection().send(cmd);
}

public boolean response(AddressedResponse addrResp) {
AddressingConnection connection = connections.get(addrResp.getAddressSection());
if (connection == null) {
return false;
}
connection.response(addrResp.getChild());
return true;
}

public Connection attach(ZscriptAddress address) {
AddressingConnection connection = new AddressingConnection(address);
connections.put(address, connection);
return connection;
}

public Connection detach(ZscriptAddress address) {
return connections.remove(address);
}
}
Loading

0 comments on commit c1cef27

Please sign in to comment.