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;
|
private final NamedItemResolver<ActionItem> resolver;
|
||||||
|
|
||||||
FlowActionResolverDelegate(FlowRoot src) {
|
FlowActionResolverDelegate(FlowRoot src) {
|
||||||
resolver = new NamedItemResolver<>(src.getActions());
|
resolver = new NamedItemResolver<>(Traversal.traverse(src, FlowRoot::getActions));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
FlowScreenResolverDelegate(FlowRoot src, ActionResolver actionResolver) {
|
||||||
this.actionResolver = actionResolver;
|
this.actionResolver = actionResolver;
|
||||||
resolver = new NamedItemResolver<>(src.getScreens());
|
resolver = new NamedItemResolver<>(Traversal.traverse(src, FlowRoot::getScreens));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
package ru.penkrat.stbf.templates.xml;
|
||||||
|
|
||||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
|
||||||
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.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.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class XmlFlowResolver implements FlowResolver {
|
public class XmlFlowResolver implements FlowResolver {
|
||||||
|
|
||||||
private final XmlMapper mapper = new XmlMapper();
|
private final FlowParser reader = new FlowParser();
|
||||||
|
|
||||||
private final FlowActionResolverDelegate actionDelegate;
|
private final FlowActionResolverDelegate actionDelegate;
|
||||||
private final FlowScreenResolverDelegate screenDelegate;
|
private final FlowScreenResolverDelegate screenDelegate;
|
||||||
|
|
||||||
public XmlFlowResolver(InputStream is) throws IOException {
|
public XmlFlowResolver(String filename) {
|
||||||
FlowRoot flow = mapper.readValue(is, FlowRoot.class);
|
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);
|
actionDelegate = new FlowActionResolverDelegate(flow);
|
||||||
screenDelegate = new FlowScreenResolverDelegate(flow, this);
|
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.impl.MustacheRenderer;
|
||||||
import ru.penkrat.stbf.templates.utils.ReflectionUtils;
|
import ru.penkrat.stbf.templates.utils.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
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;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@@ -59,4 +63,50 @@ public class XmlFlowResolverTest {
|
|||||||
assertThat(screen2.getKeyboard()).isEqualTo(keyboard);
|
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