support included configurations
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -9,7 +9,7 @@ class FlowActionResolverDelegate implements ActionResolver {
|
||||
private final NamedItemResolver<ActionItem> resolver;
|
||||
|
||||
FlowActionResolverDelegate(FlowRoot src) {
|
||||
resolver = new NamedItemResolver<>(src.getActions());
|
||||
resolver = new NamedItemResolver<>(Traversal.traverse(src, FlowRoot::getActions));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class FlowParser {
|
||||
|
||||
private final XmlMapper mapper = new XmlMapper();
|
||||
private String basePath = "";
|
||||
|
||||
public FlowRoot read(File file) throws IOException {
|
||||
return read(new FileInputStream(file));
|
||||
}
|
||||
|
||||
public FlowRoot read(@NonNull String fileName) {
|
||||
if (fileName.startsWith("classpath:")) {
|
||||
String fn = fileName.replaceFirst("^classpath:", "");
|
||||
basePath = "classpath:" + Paths.get(fileName).getParent().toString();
|
||||
return read(FlowParser.class.getResourceAsStream(fn));
|
||||
} else {
|
||||
basePath = Paths.get(fileName).getParent().toString();
|
||||
try {
|
||||
return read(new FileInputStream(fileName));
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException("Can't load file " + fileName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FlowRoot read(InputStream is) {
|
||||
FlowRoot flow = readFlow(is);
|
||||
includes(flow);
|
||||
return flow;
|
||||
}
|
||||
|
||||
private void includes(FlowRoot src) {
|
||||
final List<FlowRoot> flowRoots = src.getIncludes().stream()
|
||||
.map(IncludeItem::getFile)
|
||||
.map(fileName -> readFlow(basePath, fileName))
|
||||
.filter(Objects::nonNull)
|
||||
.peek(this::includes)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
src.getIncluded().addAll(flowRoots);
|
||||
}
|
||||
|
||||
private FlowRoot readFlow(InputStream is) {
|
||||
try {
|
||||
return mapper.readValue(is, FlowRoot.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Can't load resource", e);
|
||||
}
|
||||
}
|
||||
|
||||
private FlowRoot readFlow(String basePath, String file) {
|
||||
return readFlow(FlowParser.class.getResourceAsStream(file));
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class FlowScreenResolverDelegate implements ScreenResolver {
|
||||
|
||||
FlowScreenResolverDelegate(FlowRoot src, ActionResolver actionResolver) {
|
||||
this.actionResolver = actionResolver;
|
||||
resolver = new NamedItemResolver<>(src.getScreens());
|
||||
resolver = new NamedItemResolver<>(Traversal.traverse(src, FlowRoot::getScreens));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
@UtilityClass
|
||||
class Traversal {
|
||||
|
||||
public <T> Collection<T> traverse(FlowRoot flow, Function<FlowRoot, Collection<T>> getter) {
|
||||
final ArrayList<T> target = new ArrayList<>();
|
||||
traverse(flow, getter, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
private <T> void traverse(FlowRoot flow, Function<FlowRoot, Collection<T>> getter, Collection<T> target) {
|
||||
Collection<T> c = getter.apply(flow);
|
||||
target.addAll(c);
|
||||
|
||||
flow.getIncluded().forEach(f -> traverse(f, getter, target));
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,30 @@
|
||||
package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import ru.penkrat.stbf.api.Action;
|
||||
import ru.penkrat.stbf.api.Screen;
|
||||
import ru.penkrat.stbf.templates.TemplateRenderer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Slf4j
|
||||
public class XmlFlowResolver implements FlowResolver {
|
||||
|
||||
private final XmlMapper mapper = new XmlMapper();
|
||||
private final FlowParser reader = new FlowParser();
|
||||
|
||||
private final FlowActionResolverDelegate actionDelegate;
|
||||
private final FlowScreenResolverDelegate screenDelegate;
|
||||
|
||||
public XmlFlowResolver(InputStream is) throws IOException {
|
||||
FlowRoot flow = mapper.readValue(is, FlowRoot.class);
|
||||
public XmlFlowResolver(String filename) {
|
||||
FlowRoot flow = reader.read(filename);
|
||||
actionDelegate = new FlowActionResolverDelegate(flow);
|
||||
screenDelegate = new FlowScreenResolverDelegate(flow, this);
|
||||
}
|
||||
|
||||
public XmlFlowResolver(InputStream is) {
|
||||
FlowRoot flow = reader.read(is);
|
||||
actionDelegate = new FlowActionResolverDelegate(flow);
|
||||
screenDelegate = new FlowScreenResolverDelegate(flow, this);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,11 @@ import ru.penkrat.stbf.api.Screen;
|
||||
import ru.penkrat.stbf.templates.impl.MustacheRenderer;
|
||||
import ru.penkrat.stbf.templates.utils.ReflectionUtils;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -59,4 +63,50 @@ public class XmlFlowResolverTest {
|
||||
assertThat(screen2.getKeyboard()).isEqualTo(keyboard);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadWithInclude() throws Exception {
|
||||
InputStream xmlUnderTest = XmlFlowResolverTest.class.getResourceAsStream("flow.xml");
|
||||
|
||||
XmlFlowResolver resolver = new XmlFlowResolver(xmlUnderTest);
|
||||
|
||||
assertThat(resolver.getScreen("screen-1")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadWithIncludeWithInclude() throws Exception {
|
||||
InputStream xmlUnderTest = XmlFlowResolverTest.class.getResourceAsStream("flow.xml");
|
||||
|
||||
XmlFlowResolver resolver = new XmlFlowResolver(xmlUnderTest);
|
||||
|
||||
assertThat(resolver.getAction("4001")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadFile() throws Exception {
|
||||
Path tmp = Files.createTempFile("test-flow", ".xml");
|
||||
OutputStream fos = new FileOutputStream(tmp.toFile());
|
||||
|
||||
InputStream xmlUnderTest = XmlFlowResolverTest.class.getResourceAsStream("flow.xml");
|
||||
int b = xmlUnderTest.read();
|
||||
while (b >= 0) {
|
||||
fos.write(b);
|
||||
b = xmlUnderTest.read();
|
||||
}
|
||||
fos.close();
|
||||
|
||||
XmlFlowResolver resolver = new XmlFlowResolver(tmp.toFile().getAbsolutePath());
|
||||
|
||||
assertThat(resolver.getScreen("screen-1")).isNotNull();
|
||||
assertThat(resolver.getAction("3001")).isNotNull();
|
||||
|
||||
Files.deleteIfExists(tmp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadClasspath() throws Exception {
|
||||
XmlFlowResolver resolver = new XmlFlowResolver("classpath:/ru/penkrat/stbf/templates/xml/flow.xml");
|
||||
assertThat(resolver.getScreen("screen-1")).isNotNull();
|
||||
assertThat(resolver.getAction("3001")).isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<flow>
|
||||
|
||||
<include file="screens.xml"/>
|
||||
<include file="/test/a.xml"/>
|
||||
|
||||
<actions>
|
||||
<action id="2001" requestContact="true">Send phone</action>
|
||||
</actions>
|
||||
<screens>
|
||||
<screen id="5001" name="screen-5001">
|
||||
<text>Test text</text>
|
||||
<keyboard>
|
||||
<row>
|
||||
<button>Btn1</button>
|
||||
<button>Btn2</button>
|
||||
</row>
|
||||
</keyboard>
|
||||
</screen>
|
||||
</screens>
|
||||
</flow>
|
||||
6
stbf-templates/src/test/resources/test/a.xml
Normal file
6
stbf-templates/src/test/resources/test/a.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<flow>
|
||||
<include file="/test/b/b.xml"/>
|
||||
<actions>
|
||||
<action id="3001">A action</action>
|
||||
</actions>
|
||||
</flow>
|
||||
5
stbf-templates/src/test/resources/test/b/b.xml
Normal file
5
stbf-templates/src/test/resources/test/b/b.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<flow>
|
||||
<actions>
|
||||
<action id="4001">B action</action>
|
||||
</actions>
|
||||
</flow>
|
||||
Reference in New Issue
Block a user