#1 initial sending media files support
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:
28
stbf-api/src/main/java/ru/penkrat/stbf/api/Media.java
Normal file
28
stbf-api/src/main/java/ru/penkrat/stbf/api/Media.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package ru.penkrat.stbf.api;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@ToString(of = {"mediaType", "url"})
|
||||
public class Media {
|
||||
|
||||
private MediaType mediaType;
|
||||
|
||||
private String url;
|
||||
|
||||
private String fileId;
|
||||
|
||||
private Supplier<byte[]> data;
|
||||
|
||||
private Integer duration;
|
||||
|
||||
private Integer width;
|
||||
|
||||
private Integer height;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package ru.penkrat.stbf.api;
|
||||
|
||||
public enum MediaType {
|
||||
ANIMATION,
|
||||
AUDIO,
|
||||
PHOTO,
|
||||
VIDEO,
|
||||
VOICE
|
||||
}
|
||||
@@ -2,13 +2,17 @@ package ru.penkrat.stbf.api;
|
||||
|
||||
public interface Screen {
|
||||
|
||||
String getText();
|
||||
String getText();
|
||||
|
||||
default Keyboard getKeyboard() {
|
||||
return null;
|
||||
}
|
||||
default Media getMedia() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default ScreenProperties getScreenProperties() {
|
||||
return ScreenProperties.DEFAULT;
|
||||
}
|
||||
default Keyboard getKeyboard() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default ScreenProperties getScreenProperties() {
|
||||
return ScreenProperties.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package ru.penkrat.stbf.common.screen;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import ru.penkrat.stbf.api.Keyboard;
|
||||
import ru.penkrat.stbf.api.Media;
|
||||
import ru.penkrat.stbf.api.Screen;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class MediaScreen implements Screen {
|
||||
|
||||
private final String text;
|
||||
|
||||
private final Media media;
|
||||
|
||||
private final Keyboard keyboard;
|
||||
|
||||
public MediaScreen(String text, Media media) {
|
||||
this(text, media, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
<flow>
|
||||
<media>
|
||||
<video id="40001" url="http://techslides.com/demos/sample-videos/small.mp4"/>
|
||||
<photo id="40002" url="https://telegram.org/img/t_logo.png"/>
|
||||
</media>
|
||||
<actions>
|
||||
<action id="10001" name="start-action" command="/start">Start</action>
|
||||
<action id="10002" name="help-action" command="/help">Help</action>
|
||||
<action id="10003" name="to-inline-action" command="/inline">Inline</action>
|
||||
<action id="10004" name="inline1-action" callbackData="cmd:inline1">Inline button #1</action>
|
||||
<action id="10005" name="inline2-action" callbackData="cmd:inline2">Inline button #2</action>
|
||||
<action id="10006" name="url-action" url="https://git.penkrat.ru/ruslan/stbf">Git repo</action>
|
||||
<action id="10004" name="inline1-action" callbackData="cmd:inline1">🔞 Inline button #1</action>
|
||||
<action id="10005" name="inline2-action" callbackData="cmd:inline2">🐱 Inline button #2</action>
|
||||
<action id="10006" name="url-action" url="https://git.penkrat.ru/ruslan/stbf">💻 Git repo</action>
|
||||
<action id="10007" name="photo-action" callbackData="cmd:sendPhoto">🖼 My photo</action>
|
||||
<action id="10008" name="video-action" callbackData="cmd:sendVideo">🎞 My video</action>
|
||||
<action id="10009" name="to-inline-back-action" callbackData="cmd:inline">🔙 Back</action>
|
||||
</actions>
|
||||
<screens>
|
||||
<screen id="20001" name="on-start-screen">
|
||||
@@ -35,6 +42,10 @@
|
||||
<button actionRef="inline1-action"></button>
|
||||
<button actionRef="inline2-action"></button>
|
||||
</row>
|
||||
<row>
|
||||
<button actionRef="photo-action"></button>
|
||||
<button actionRef="video-action"></button>
|
||||
</row>
|
||||
<row>
|
||||
<button actionRef="url-action"></button>
|
||||
</row>
|
||||
@@ -47,6 +58,10 @@
|
||||
<button actionRef="inline1-action"></button>
|
||||
<button actionRef="inline2-action"></button>
|
||||
</row>
|
||||
<row>
|
||||
<button actionRef="photo-action"></button>
|
||||
<button actionRef="video-action"></button>
|
||||
</row>
|
||||
<row>
|
||||
<button actionRef="url-action"></button>
|
||||
</row>
|
||||
@@ -59,17 +74,40 @@
|
||||
<button actionRef="inline1-action"></button>
|
||||
<button actionRef="inline2-action"></button>
|
||||
</row>
|
||||
<row>
|
||||
<button actionRef="photo-action"></button>
|
||||
<button actionRef="video-action"></button>
|
||||
</row>
|
||||
<row>
|
||||
<button actionRef="url-action"></button>
|
||||
</row>
|
||||
</keyboard>
|
||||
</screen>
|
||||
<screen id="20006" name="inline-photo-screen" mediaRef="40002">
|
||||
<text>My photo</text>
|
||||
<keyboard>
|
||||
<row>
|
||||
<button actionRef="to-inline-back-action"></button>
|
||||
</row>
|
||||
</keyboard>
|
||||
</screen>
|
||||
<screen id="20007" name="inline-video-screen" mediaRef="40001">
|
||||
<text>My Video</text>
|
||||
<keyboard>
|
||||
<row>
|
||||
<button actionRef="to-inline-back-action"></button>
|
||||
</row>
|
||||
</keyboard>
|
||||
</screen>
|
||||
</screens>
|
||||
<commands>
|
||||
<command actionRef="start-action" screenRef="on-start-screen" id="30001" name="startCommand"/>
|
||||
<command actionRef="help-action" screenRef="on-help-screen" id="30002" name="helpCommand"/>
|
||||
<command actionRef="to-inline-action" screenRef="inline-test-screen" id="30003" name="inlineTestCommand"/>
|
||||
<command actionRef="inline1-action" screenRef="inline-test-1-screen" edit="true" id="30004" name="inlineTest1Command"/>
|
||||
<command actionRef="inline2-action" screenRef="inline-test-2-screen" edit="true" id="30005" name="inlineTest2Command"/>
|
||||
<command actionRef="to-inline-back-action" screenRef="inline-test-screen" replace="true" id="30004" name="inlineTestCommand"/>
|
||||
<command actionRef="inline1-action" screenRef="inline-test-1-screen" edit="true" id="30005" name="inlineTest1Command"/>
|
||||
<command actionRef="inline2-action" screenRef="inline-test-2-screen" edit="true" id="30006" name="inlineTest2Command"/>
|
||||
<command actionRef="photo-action" screenRef="inline-photo-screen" replace="true" id="30005" name="photoCommand"/>
|
||||
<command actionRef="video-action" screenRef="inline-video-screen" replace="true" id="30006" name="videoCommand"/>
|
||||
</commands>
|
||||
</flow>
|
||||
@@ -7,10 +7,10 @@ import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
|
||||
import com.pengrad.telegrambot.model.request.KeyboardButton;
|
||||
import com.pengrad.telegrambot.model.request.ParseMode;
|
||||
import com.pengrad.telegrambot.model.request.ReplyKeyboardMarkup;
|
||||
import com.pengrad.telegrambot.request.AbstractSendRequest;
|
||||
import com.pengrad.telegrambot.request.DeleteMessage;
|
||||
import com.pengrad.telegrambot.request.EditMessageText;
|
||||
import com.pengrad.telegrambot.request.SendDocument;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import ru.penkrat.stbf.api.BotResponse;
|
||||
@@ -28,10 +28,7 @@ public class BotResponseImpl implements BotResponse {
|
||||
public void send(Screen screen) {
|
||||
log.debug("Send message: \n============\n{}\n============", screen.getText().trim());
|
||||
|
||||
SendMessage sendMessage = new SendMessage(chatId(), screen.getText().trim())
|
||||
.parseMode(screen.getScreenProperties().isParseModeHtml() ? ParseMode.HTML : ParseMode.MarkdownV2)
|
||||
.disableWebPagePreview(screen.getScreenProperties().isDisableWebPagePreview())
|
||||
.disableNotification(screen.getScreenProperties().isDisableNotification());
|
||||
AbstractSendRequest<? extends AbstractSendRequest> sendMessage= SendMethodUtils.createFromScreen(chatId(), screen);
|
||||
|
||||
if (screen.getKeyboard() instanceof KeyboardImpl) {
|
||||
KeyboardImpl kk = (KeyboardImpl) screen.getKeyboard();
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package ru.penkrat.stbf.impl.pengrad;
|
||||
|
||||
import com.pengrad.telegrambot.model.request.ParseMode;
|
||||
import com.pengrad.telegrambot.request.AbstractSendRequest;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import com.pengrad.telegrambot.request.SendPhoto;
|
||||
import com.pengrad.telegrambot.request.SendVideo;
|
||||
import lombok.NonNull;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import ru.penkrat.stbf.api.Media;
|
||||
import ru.penkrat.stbf.api.Screen;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@UtilityClass
|
||||
class SendMethodUtils {
|
||||
|
||||
public AbstractSendRequest<? extends AbstractSendRequest> createFromScreen(@NonNull Object chatId, @NonNull Screen screen) {
|
||||
if (isMedia(screen)) {
|
||||
final Media media = screen.getMedia();
|
||||
switch (media.getMediaType()) {
|
||||
case PHOTO:
|
||||
final SendPhoto sendPhoto = new SendPhoto(chatId, media.getUrl());
|
||||
apply(sendPhoto, sendPhoto::caption, screen.getText());
|
||||
sendPhoto.parseMode(screen.getScreenProperties().isParseModeHtml()
|
||||
? ParseMode.HTML
|
||||
: ParseMode.MarkdownV2);
|
||||
return sendPhoto;
|
||||
case VIDEO:
|
||||
final SendVideo sendVideo = new SendVideo(chatId, media.getUrl());
|
||||
apply(sendVideo, sendVideo::caption, screen.getText());
|
||||
apply(sendVideo, sendVideo::width, media.getWidth());
|
||||
apply(sendVideo, sendVideo::height, media.getHeight());
|
||||
apply(sendVideo, sendVideo::duration, media.getDuration());
|
||||
sendVideo.parseMode(screen.getScreenProperties().isParseModeHtml()
|
||||
? ParseMode.HTML
|
||||
: ParseMode.MarkdownV2);
|
||||
return sendVideo;
|
||||
}
|
||||
}
|
||||
|
||||
return new SendMessage(chatId, screen.getText().trim())
|
||||
.parseMode(screen.getScreenProperties().isParseModeHtml() ? ParseMode.HTML : ParseMode.MarkdownV2)
|
||||
.disableWebPagePreview(screen.getScreenProperties().isDisableWebPagePreview())
|
||||
.disableNotification(screen.getScreenProperties().isDisableNotification());
|
||||
}
|
||||
|
||||
private boolean isMedia(Screen screen) {
|
||||
return screen.getMedia() != null;
|
||||
}
|
||||
|
||||
private <T, V> T apply(T target, Function<V, T> setter, V value) {
|
||||
if (value != null) {
|
||||
setter.apply(value);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
<actions> </actions>
|
||||
<screens> </screens>
|
||||
<commands> </commands>
|
||||
<media> </media>
|
||||
</flow>
|
||||
```
|
||||
|
||||
@@ -51,6 +52,8 @@ Screen - то, что бот ответит пользователю, обычн
|
||||
</screen>
|
||||
```
|
||||
|
||||
`mediaRef` - ссылка на элемент медиа, который будет оправлен ботом
|
||||
|
||||
`text` - выводимый текст
|
||||
|
||||
`keyboard` - описание клавиатуры
|
||||
@@ -65,7 +68,7 @@ Screen - то, что бот ответит пользователю, обычн
|
||||
|
||||
#### Button
|
||||
|
||||
`if` - видомость кнопки, значение `true`, `false` или имя метода из контекста экрана (для программной обработки)
|
||||
`if` - видимость кнопки, значение `true`, `false` или имя метода из контекста экрана (для программной обработки)
|
||||
|
||||
`actionRef` - `id` или `name` action, описанный в соответсвующей секции
|
||||
|
||||
@@ -89,4 +92,21 @@ Screen - то, что бот ответит пользователю, обычн
|
||||
```
|
||||
|
||||
`actionRef` - ссылка на action, может использоваться id или name
|
||||
`screenRef` - ссылка на screen, может использоваться id или name
|
||||
|
||||
`screenRef` - ссылка на screen, может использоваться id или name
|
||||
|
||||
`edit` = `true|false`- исходное сообщение будет отредактировано (актуально для callback)
|
||||
|
||||
`replace` = `true|false`- исходное сообщение будет удалено, и отправлено новое (актуально для callback,
|
||||
если меняется тип сообщения т.е. сообщение с фото, видео должно быть заменено на текстовое и наоборот)
|
||||
|
||||
### Media
|
||||
|
||||
Описывает медиа-ресурсы, доступные для отправки ботом
|
||||
|
||||
```xml
|
||||
<media>
|
||||
<video id="40001" url="https://example.com/video.mp4"/>
|
||||
<photo id="40002" url="https://example.com//photo.png"/>
|
||||
</media>
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
package ru.penkrat.stbf.templates;
|
||||
|
||||
import ru.penkrat.stbf.api.Media;
|
||||
|
||||
public interface MediaResolver {
|
||||
|
||||
Media getMedia(String name);
|
||||
|
||||
}
|
||||
@@ -24,4 +24,7 @@ public class CommandItem extends NamedItem {
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private boolean edit;
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private boolean replace;
|
||||
|
||||
}
|
||||
|
||||
@@ -62,19 +62,22 @@ public class FlowCommandResolverDelegate implements CommandResolver {
|
||||
screenFactory = screenResolver.getScreenFactory(commandItem.getScreenRef());
|
||||
}
|
||||
if (actionMatcher != null && screen != null) {
|
||||
return simpleCommand(actionMatcher, screen, commandItem.isEdit(), commandItem.getId(), commandItem.getName());
|
||||
return simpleCommand(actionMatcher, screen, commandItem.isEdit(), commandItem.isReplace(), commandItem.getId(), commandItem.getName());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Command simpleCommand(RequestMatcher matcher, Screen screen, boolean edit, String id, String name) {
|
||||
private Command simpleCommand(RequestMatcher matcher, Screen screen, boolean edit, boolean replace, String id, String name) {
|
||||
return new Command() {
|
||||
|
||||
@Override
|
||||
public void process(BotRequest botRequest, BotResponse botResponse, CommandChain chain) {
|
||||
if (matcher.match(botRequest)) {
|
||||
if (edit) {
|
||||
if (replace) {
|
||||
botResponse.deleteMessage();
|
||||
}
|
||||
if (edit && !replace) {
|
||||
botResponse.edit(screen);
|
||||
} else {
|
||||
botResponse.send(screen);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import ru.penkrat.stbf.api.Media;
|
||||
import ru.penkrat.stbf.api.MediaType;
|
||||
import ru.penkrat.stbf.templates.MediaResolver;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
class FlowMediaResolverDelegate implements MediaResolver {
|
||||
|
||||
private final NamedItemResolver<MediaItem> videosResolver;
|
||||
private final NamedItemResolver<MediaItem> photosResolver;
|
||||
|
||||
FlowMediaResolverDelegate(FlowRoot src) {
|
||||
videosResolver = new NamedItemResolver<>(Traversal.traverse(src, FlowMediaResolverDelegate::videos));
|
||||
photosResolver = new NamedItemResolver<>(Traversal.traverse(src, FlowMediaResolverDelegate::photos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Media getMedia(String name) {
|
||||
Optional<Media> media = videosResolver.getOpt(name)
|
||||
.map(FlowMediaResolverDelegate::toVideo);
|
||||
if(media.isPresent()){
|
||||
return media.get();
|
||||
}
|
||||
|
||||
media = photosResolver.getOpt(name)
|
||||
.map(FlowMediaResolverDelegate::toPhoto);
|
||||
if(media.isPresent()){
|
||||
return media.get();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("MediaElement not found by 'id' or 'name' " + name);
|
||||
}
|
||||
|
||||
private static Media toVideo(MediaItem item) {
|
||||
return Media.builder()
|
||||
.mediaType(MediaType.VIDEO)
|
||||
.url(item.getUrl())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Media toPhoto(MediaItem item) {
|
||||
return Media.builder()
|
||||
.mediaType(MediaType.PHOTO)
|
||||
.url(item.getUrl())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Collection<MediaItem> videos(FlowRoot root) {
|
||||
return root.getMedia().getVideos();
|
||||
}
|
||||
|
||||
private static Collection<MediaItem> photos(FlowRoot root) {
|
||||
return root.getMedia().getPhotos();
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,10 @@ class FlowRoot {
|
||||
@JsonProperty("command")
|
||||
private List<CommandItem> commands = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
@JsonProperty("media")
|
||||
private MediaRoot media = new MediaRoot();
|
||||
|
||||
@Getter
|
||||
private transient List<FlowRoot> included = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -6,10 +6,13 @@ import lombok.val;
|
||||
import ru.penkrat.stbf.api.Action;
|
||||
import ru.penkrat.stbf.api.Keyboard;
|
||||
import ru.penkrat.stbf.api.KeyboardBuilder;
|
||||
import ru.penkrat.stbf.api.Media;
|
||||
import ru.penkrat.stbf.api.Screen;
|
||||
import ru.penkrat.stbf.common.screen.MediaScreen;
|
||||
import ru.penkrat.stbf.common.screen.TextScreen;
|
||||
import ru.penkrat.stbf.templates.ActionResolver;
|
||||
import ru.penkrat.stbf.templates.KeyboardProvider;
|
||||
import ru.penkrat.stbf.templates.MediaResolver;
|
||||
import ru.penkrat.stbf.templates.ScreenResolver;
|
||||
import ru.penkrat.stbf.templates.TemplateRenderer;
|
||||
import ru.penkrat.stbf.templates.utils.ReflectionUtils;
|
||||
@@ -25,11 +28,14 @@ class FlowScreenResolverDelegate implements ScreenResolver {
|
||||
|
||||
private final ActionResolver actionResolver;
|
||||
|
||||
private final MediaResolver mediaResolver;
|
||||
|
||||
@Setter
|
||||
private TemplateRenderer templateRenderer = new NoopTemplateRenderer();
|
||||
|
||||
FlowScreenResolverDelegate(FlowRoot src, ActionResolver actionResolver) {
|
||||
FlowScreenResolverDelegate(FlowRoot src, ActionResolver actionResolver, MediaResolver mediaResolver) {
|
||||
this.actionResolver = actionResolver;
|
||||
this.mediaResolver = mediaResolver;
|
||||
resolver = new NamedItemResolver<>(Traversal.traverse(src, FlowRoot::getScreens));
|
||||
}
|
||||
|
||||
@@ -37,6 +43,11 @@ class FlowScreenResolverDelegate implements ScreenResolver {
|
||||
public Screen getScreen(String name) {
|
||||
ScreenItem item = resolver.get(name);
|
||||
|
||||
if (StringUtils.isNotEmpty(item.getMediaRef())) {
|
||||
final Media media = mediaResolver.getMedia(item.getMediaRef());
|
||||
return new MediaScreen(item.getText(), media, buildKeyboard(item.getKeyboard(), null));
|
||||
}
|
||||
|
||||
return new TextScreen(item.getText(), buildKeyboard(item.getKeyboard(), null));
|
||||
}
|
||||
|
||||
@@ -44,6 +55,12 @@ class FlowScreenResolverDelegate implements ScreenResolver {
|
||||
public Screen getScreen(String name, Object context) {
|
||||
ScreenItem item = resolver.get(name);
|
||||
|
||||
if (StringUtils.isNotEmpty(item.getMediaRef())) {
|
||||
final Media media = mediaResolver.getMedia(item.getMediaRef());
|
||||
return new MediaScreen(templateRenderer.render(item.getText(), context), media,
|
||||
resolveKeyboard(item.getKeyboard(), context));
|
||||
}
|
||||
|
||||
return new TextScreen(templateRenderer.render(item.getText(), context),
|
||||
resolveKeyboard(item.getKeyboard(), context));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MediaItem extends NamedItem {
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private String url;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MediaRoot {
|
||||
|
||||
@Getter
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
@JsonProperty("video")
|
||||
private List<MediaItem> videos = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
@JsonProperty("photo")
|
||||
private List<MediaItem> photos = new ArrayList<>();
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import ru.penkrat.stbf.templates.utils.StringUtils;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class NamedItemResolver<T extends NamedItem> {
|
||||
@@ -39,4 +40,22 @@ class NamedItemResolver<T extends NamedItem> {
|
||||
throw new IllegalStateException("Element not found by 'id' or 'name' " + key);
|
||||
}
|
||||
|
||||
Optional<T> getOpt(String key) {
|
||||
List<T> list = byId.get(key);
|
||||
if (list != null) {
|
||||
if (list.size() > 1) {
|
||||
throw new IllegalStateException("Non unique 'id' " + key);
|
||||
}
|
||||
return Optional.of(list.get(0));
|
||||
}
|
||||
list = byName.get(key);
|
||||
if (list != null) {
|
||||
if (list.size() > 1) {
|
||||
throw new IllegalStateException("Non unique 'name' " + key);
|
||||
}
|
||||
return Optional.of(list.get(0));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@@ -9,6 +10,9 @@ class ScreenItem extends NamedItem {
|
||||
|
||||
private String text;
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private String mediaRef;
|
||||
|
||||
private KeyboardWrapper keyboard = new KeyboardWrapper();
|
||||
|
||||
}
|
||||
|
||||
@@ -18,18 +18,21 @@ public class XmlFlowResolver implements FlowResolver {
|
||||
private final FlowActionResolverDelegate actionDelegate;
|
||||
private final FlowScreenResolverDelegate screenDelegate;
|
||||
private final FlowCommandResolverDelegate commandResolver;
|
||||
private final FlowMediaResolverDelegate mediaResolver;
|
||||
|
||||
public XmlFlowResolver(String filename) {
|
||||
FlowRoot flow = reader.read(filename);
|
||||
actionDelegate = new FlowActionResolverDelegate(flow);
|
||||
screenDelegate = new FlowScreenResolverDelegate(flow, this);
|
||||
mediaResolver = new FlowMediaResolverDelegate(flow);
|
||||
screenDelegate = new FlowScreenResolverDelegate(flow, this, mediaResolver);
|
||||
commandResolver = new FlowCommandResolverDelegate(flow, actionDelegate, screenDelegate);
|
||||
}
|
||||
|
||||
public XmlFlowResolver(InputStream is) {
|
||||
FlowRoot flow = reader.read(is);
|
||||
actionDelegate = new FlowActionResolverDelegate(flow);
|
||||
screenDelegate = new FlowScreenResolverDelegate(flow, this);
|
||||
mediaResolver = new FlowMediaResolverDelegate(flow);
|
||||
screenDelegate = new FlowScreenResolverDelegate(flow, this, mediaResolver);
|
||||
commandResolver = new FlowCommandResolverDelegate(flow, actionDelegate, screenDelegate);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package ru.penkrat.stbf.templates.xml;
|
||||
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import lombok.val;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import ru.penkrat.stbf.api.Command;
|
||||
@@ -42,6 +43,7 @@ public class XmlWriterTest {
|
||||
item2.setId("2");
|
||||
item2.setName("screen-2");
|
||||
item2.setText("Hello, {{ name }}");
|
||||
item2.setMediaRef("12");
|
||||
|
||||
item2.getKeyboard().setFactoryMethod("getKeyboard");
|
||||
|
||||
@@ -58,6 +60,16 @@ public class XmlWriterTest {
|
||||
commandItem.setClazz(Command.class.getCanonicalName());
|
||||
root.getCommands().add(commandItem);
|
||||
|
||||
|
||||
MediaItem video1 = new MediaItem();
|
||||
video1.setId("11");
|
||||
video1.setUrl("https://example.com/test.mpg");
|
||||
MediaItem photo1 = new MediaItem();
|
||||
photo1.setId("12");
|
||||
photo1.setUrl("https://example.com/test.jpg");
|
||||
root.getMedia().getVideos().add(video1);
|
||||
root.getMedia().getPhotos().add(photo1);
|
||||
|
||||
String xml = mapper.writeValueAsString(root);
|
||||
|
||||
System.out.println(xml);
|
||||
|
||||
Reference in New Issue
Block a user