initial commands support
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2021-09-05 08:33:26 +03:00
parent d47e43edb1
commit e5a9c82ff3
9 changed files with 175 additions and 7 deletions

View File

@@ -0,0 +1,11 @@
package ru.penkrat.stbf.templates;
import ru.penkrat.stbf.api.Command;
import java.util.Collection;
public interface CommandResolver {
Collection<Command> getCommands();
}

View File

@@ -0,0 +1,24 @@
package ru.penkrat.stbf.templates.xml;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@JacksonXmlRootElement(localName = "command")
public class CommandItem extends NamedItem {
@JacksonXmlProperty(isAttribute = true)
private String actionRef;
@JacksonXmlProperty(isAttribute = true)
private String screenRef;
@JacksonXmlProperty(isAttribute = true, localName = "class")
private String clazz;
}

View File

@@ -0,0 +1,92 @@
package ru.penkrat.stbf.templates.xml;
import lombok.RequiredArgsConstructor;
import ru.penkrat.stbf.api.Action;
import ru.penkrat.stbf.api.BotRequest;
import ru.penkrat.stbf.api.BotResponse;
import ru.penkrat.stbf.api.Command;
import ru.penkrat.stbf.api.CommandChain;
import ru.penkrat.stbf.api.RequestMatcher;
import ru.penkrat.stbf.api.Screen;
import ru.penkrat.stbf.templates.ActionResolver;
import ru.penkrat.stbf.templates.CommandResolver;
import ru.penkrat.stbf.templates.ScreenResolver;
import ru.penkrat.stbf.templates.utils.StringUtils;
import ru.penkrat.stbf.tools.RequestMatchers;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public class FlowCommandResolverDelegate implements CommandResolver {
private final FlowRoot root;
private final ActionResolver actionResolver;
private final ScreenResolver screenResolver;
private boolean resolved;
private Collection<Command> commands;
@Override
public Collection<Command> getCommands() {
resolve();
return commands;
}
private void resolve() {
if (!resolved) {
Collection<Command> parsedCommands = Traversal.traverse(root, FlowRoot::getCommands)
.stream()
.map(this::createCommand)
.filter(Objects::nonNull)
.collect(Collectors.toList());
commands = Collections.unmodifiableCollection(parsedCommands);
resolved = true;
}
}
private Command createCommand(CommandItem commandItem) {
Action action = null;
Screen screen = null;
Function<Object, Screen> screenFactory;
if (StringUtils.isNotEmpty(commandItem.getActionRef())) {
action = actionResolver.getAction(commandItem.getActionRef());
}
if (StringUtils.isNotEmpty(commandItem.getScreenRef())) {
screen = screenResolver.getScreen(commandItem.getScreenRef());
screenFactory = screenResolver.getScreenFactory(commandItem.getScreenRef());
}
if (action != null && screen != null) {
return simpleCommand(action, screen, commandItem.getId(), commandItem.getName());
}
return null;
}
private Command simpleCommand(Action action, Screen screen, String id, String name) {
return new Command() {
RequestMatcher matcher = RequestMatchers.action(action);
@Override
public void process(BotRequest botRequest, BotResponse botResponse, CommandChain chain) {
if (matcher.match(botRequest)) {
botResponse.send(screen);
}
chain.processCommand(botRequest, botResponse);
}
@Override
public String toString() {
return "Command {" +
"id=" + id +
", name=" + name +
'}';
}
};
}
}

View File

@@ -1,7 +1,8 @@
package ru.penkrat.stbf.templates.xml; package ru.penkrat.stbf.templates.xml;
import ru.penkrat.stbf.templates.ActionResolver; import ru.penkrat.stbf.templates.ActionResolver;
import ru.penkrat.stbf.templates.CommandResolver;
import ru.penkrat.stbf.templates.ScreenResolver; import ru.penkrat.stbf.templates.ScreenResolver;
public interface FlowResolver extends ScreenResolver, ActionResolver { public interface FlowResolver extends ScreenResolver, ActionResolver, CommandResolver {
} }

View File

@@ -26,6 +26,11 @@ class FlowRoot {
@JsonProperty("include") @JsonProperty("include")
private List<IncludeItem> includes = new ArrayList<>(); private List<IncludeItem> includes = new ArrayList<>();
@Getter
@JacksonXmlElementWrapper(localName = "commands")
@JsonProperty("command")
private List<CommandItem> commands = new ArrayList<>();
@Getter @Getter
private transient List<FlowRoot> included = new ArrayList<>(); private transient List<FlowRoot> included = new ArrayList<>();
} }

View File

@@ -2,12 +2,12 @@ package ru.penkrat.stbf.templates.xml;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import ru.penkrat.stbf.api.Action; import ru.penkrat.stbf.api.Action;
import ru.penkrat.stbf.api.Command;
import ru.penkrat.stbf.api.Screen; import ru.penkrat.stbf.api.Screen;
import ru.penkrat.stbf.templates.TemplateRenderer; import ru.penkrat.stbf.templates.TemplateRenderer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Collection;
@Slf4j @Slf4j
public class XmlFlowResolver implements FlowResolver { public class XmlFlowResolver implements FlowResolver {
@@ -16,17 +16,20 @@ public class XmlFlowResolver implements FlowResolver {
private final FlowActionResolverDelegate actionDelegate; private final FlowActionResolverDelegate actionDelegate;
private final FlowScreenResolverDelegate screenDelegate; private final FlowScreenResolverDelegate screenDelegate;
private final FlowCommandResolverDelegate commandResolver;
public XmlFlowResolver(String filename) { public XmlFlowResolver(String filename) {
FlowRoot flow = reader.read(filename); FlowRoot flow = reader.read(filename);
actionDelegate = new FlowActionResolverDelegate(flow); actionDelegate = new FlowActionResolverDelegate(flow);
screenDelegate = new FlowScreenResolverDelegate(flow, this); screenDelegate = new FlowScreenResolverDelegate(flow, this);
commandResolver = new FlowCommandResolverDelegate(flow, actionDelegate, screenDelegate);
} }
public XmlFlowResolver(InputStream is) { public XmlFlowResolver(InputStream is) {
FlowRoot flow = reader.read(is); FlowRoot flow = reader.read(is);
actionDelegate = new FlowActionResolverDelegate(flow); actionDelegate = new FlowActionResolverDelegate(flow);
screenDelegate = new FlowScreenResolverDelegate(flow, this); screenDelegate = new FlowScreenResolverDelegate(flow, this);
commandResolver = new FlowCommandResolverDelegate(flow, actionDelegate, screenDelegate);
} }
@Override @Override
@@ -47,4 +50,9 @@ public class XmlFlowResolver implements FlowResolver {
public void setTemplateRenderer(TemplateRenderer templateRenderer) { public void setTemplateRenderer(TemplateRenderer templateRenderer) {
screenDelegate.setTemplateRenderer(templateRenderer); screenDelegate.setTemplateRenderer(templateRenderer);
} }
@Override
public Collection<Command> getCommands() {
return commandResolver.getCommands();
}
} }

View File

@@ -0,0 +1,18 @@
package ru.penkrat.stbf.templates.xml;
import org.junit.Test;
import ru.penkrat.stbf.api.Command;
import static org.assertj.core.api.Assertions.assertThat;
public class FlowCommandsTest {
@Test
public void testReadCommands() {
XmlFlowResolver resolver = new XmlFlowResolver("classpath:/ru/penkrat/stbf/templates/xml/flow.xml");
assertThat(resolver.getCommands()).hasSize(1);
final Command command = resolver.getCommands().iterator().next();
assertThat(command.toString()).contains("startCommand");
}
}

View File

@@ -1,10 +1,10 @@
package ru.penkrat.stbf.templates.xml; package ru.penkrat.stbf.templates.xml;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.junit.Before;
import org.junit.Test;
import ru.penkrat.stbf.api.Command;
public class XmlWriterTest { public class XmlWriterTest {
@@ -52,6 +52,12 @@ public class XmlWriterTest {
root.getIncludes().add(new IncludeItem()); root.getIncludes().add(new IncludeItem());
final CommandItem commandItem = new CommandItem();
commandItem.setActionRef("action-1");
commandItem.setScreenRef("screen-1");
commandItem.setClazz(Command.class.getCanonicalName());
root.getCommands().add(commandItem);
String xml = mapper.writeValueAsString(root); String xml = mapper.writeValueAsString(root);
System.out.println(xml); System.out.println(xml);

View File

@@ -4,7 +4,7 @@
<include file="/test/a.xml"/> <include file="/test/a.xml"/>
<actions> <actions>
<action id="2001" requestContact="true">Send phone</action> <action id="2001" name="start" command="/start">Start</action>
</actions> </actions>
<screens> <screens>
<screen id="5001" name="screen-5001"> <screen id="5001" name="screen-5001">
@@ -17,4 +17,7 @@
</keyboard> </keyboard>
</screen> </screen>
</screens> </screens>
<commands>
<command actionRef="2001" screenRef="5001" id="5002" name="startCommand"/>
</commands>
</flow> </flow>