Add possibility to group models through a dialog

This commit is contained in:
0xb00bface 2021-05-08 14:15:39 +02:00
parent d52b728c1c
commit 0358a35a84
14 changed files with 333 additions and 182 deletions

View File

@ -3,7 +3,6 @@ package ctbrec.ui;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import javax.xml.bind.JAXBException;
@ -14,7 +13,6 @@ import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import ctbrec.Model;
import ctbrec.ModelGroupEntry;
import ctbrec.SubsequentAction;
import ctbrec.recorder.download.Download;
import ctbrec.recorder.download.HttpHeaderFactory;
@ -331,16 +329,4 @@ public class JavaFxModel implements Model {
public void setMarkedForLaterRecording(boolean marked) {
delegate.setMarkedForLaterRecording(marked);
}
@Override
public void setModelGroup(ModelGroupEntry modelGroupEntry) {
delegate.setModelGroup(modelGroupEntry);
}
@Override
public Optional<ModelGroupEntry> getModelGroup() {
return delegate.getModelGroup();
}
}

View File

@ -0,0 +1,183 @@
package ctbrec.ui.action;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.ModelGroup;
import ctbrec.StringUtil;
import ctbrec.recorder.Recorder;
import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.controls.autocomplete.ObservableListSuggester;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
public class AddToGroupAction {
private Node source;
private Model model;
private Recorder recorder;
public AddToGroupAction(Node source, Recorder recorder, Model model) {
this.source = source;
this.recorder = recorder;
this.model = model;
}
public void execute() {
source.setCursor(Cursor.WAIT);
try {
var dialog = new ModelGroupDialog();
boolean ok = Dialogs.showCustomInput(source.getScene(), "Add model to group", dialog.getMainPane());
dialog.requestFocus();
if (ok) {
String text = dialog.getText();
if (StringUtil.isBlank(text)) {
return;
}
Set<ModelGroup> modelGroups = Config.getInstance().getSettings().modelGroups;
Optional<ModelGroup> existingGroup = modelGroups.stream().filter(mg -> mg.getName().equalsIgnoreCase(text)).findFirst();
if (existingGroup.isPresent()) {
existingGroup.get().add(model);
recorder.saveModelGroup(existingGroup.get());
} else {
var group = new ModelGroup();
group.setId(UUID.randomUUID());
group.setName(text);
group.add(model);
modelGroups.add(group);
recorder.saveModelGroup(group);
}
}
} catch (IOException e) {
Dialogs.showError(source.getScene(), "Add model to group", "Saving model group failed", e);
} finally {
source.setCursor(Cursor.DEFAULT);
}
}
private static class ModelGroupDialog {
private ComboBox<ModelGroupListItem> comboBox;
private TextField editor;
private ObservableListSuggester suggester;
public String getText() {
return comboBox.getEditor().getText();
}
public void requestFocus() {
comboBox.requestFocus();
editor.requestFocus();
}
Region getMainPane() {
var dialogPane = new GridPane();
Set<ModelGroup> modelGroups = Config.getInstance().getSettings().modelGroups;
List<ModelGroupListItem> comboBoxItems = modelGroups.stream().map(ModelGroupListItem::new).sorted().collect(Collectors.toList());
ObservableList<ModelGroupListItem> comboBoxModel = FXCollections.observableArrayList(comboBoxItems);
suggester = new ObservableListSuggester(comboBoxModel);
comboBox = new ComboBox<>(comboBoxModel);
comboBox.setEditable(true);
editor = comboBox.getEditor();
comboBox.getEditor().addEventHandler(KeyEvent.KEY_RELEASED, evt -> {
if (evt.getCode().isLetterKey() || evt.getCode().isDigitKey()) {
autocomplete(false);
} else if (evt.getCode() == KeyCode.ENTER) {
if (editor.getSelection().getLength() > 0) {
editor.selectRange(0, 0);
editor.insertText(editor.lengthProperty().get(), ":");
editor.positionCaret(editor.lengthProperty().get());
evt.consume();
}
} else if (evt.getCode() == KeyCode.SPACE && evt.isControlDown()) {
autocomplete(true);
}
});
comboBox.setPlaceholder(new Label(" type in a name to a add a new group "));
dialogPane.add(new Label("Model group "), 0, 0);
dialogPane.add(comboBox, 1, 0);
return dialogPane;
}
private void autocomplete(boolean fulltextSearch) {
String oldtext = getOldText();
if(oldtext.isEmpty()) {
return;
}
Optional<String> match;
if (fulltextSearch) {
match = suggester.fulltext(oldtext);
} else {
match = suggester.startsWith(oldtext);
}
if (match.isPresent()) {
editor.setText(match.get());
int pos = oldtext.length();
editor.positionCaret(pos);
editor.selectRange(pos, match.get().length());
}
}
private String getOldText() {
if(editor.getSelection().getLength() > 0) {
return editor.getText().substring(0, editor.getSelection().getStart());
} else {
return editor.getText();
}
}
}
private static class ModelGroupListItem implements Comparable<ModelGroupListItem> {
private ModelGroup modelGroup;
public ModelGroupListItem(ModelGroup modelGroup) {
this.modelGroup = modelGroup;
}
@Override
public String toString() {
return this.modelGroup.getName();
}
@Override
public int hashCode() {
return java.util.Objects.hash(modelGroup);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ModelGroupListItem other = (ModelGroupListItem) obj;
return java.util.Objects.equals(modelGroup, other.modelGroup);
}
@Override
public int compareTo(ModelGroupListItem o) {
return this.modelGroup.getName().compareTo(o.modelGroup.getName());
}
}
}

View File

@ -4,16 +4,26 @@ import static javafx.scene.control.ButtonType.*;
import java.io.InputStream;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.ModelGroup;
import ctbrec.StringUtil;
import ctbrec.ui.AutosizeAlert;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
@ -63,7 +73,7 @@ public class Dialogs {
Dialog<String> dialog = new Dialog<>();
dialog.setTitle(title);
dialog.setHeaderText(header);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
dialog.getDialogPane().getButtonTypes().addAll(OK, CANCEL);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.setResizable(true);
InputStream icon = Dialogs.class.getResourceAsStream("/icon.png");
@ -86,7 +96,7 @@ public class Dialogs {
Platform.runLater(notes::requestFocus);
dialog.setResultConverter(dialogButton -> {
if (dialogButton == ButtonType.OK) {
if (dialogButton == OK) {
return notes.getText();
}
return null;
@ -98,7 +108,7 @@ public class Dialogs {
public static Boolean showCustomInput(Scene parent, String title, Region region) {
Dialog<?> dialog = new Dialog<>();
dialog.setTitle(title);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
dialog.getDialogPane().getButtonTypes().addAll(OK, CANCEL);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.setResizable(true);
InputStream icon = Dialogs.class.getResourceAsStream("/icon.png");
@ -109,7 +119,7 @@ public class Dialogs {
}
dialog.getDialogPane().setContent(region);
dialog.showAndWait();
return dialog.getResult() == ButtonType.OK;
return dialog.getResult() == OK;
}
public static boolean showConfirmDialog(String title, String message, String header, Scene parent) {
@ -117,7 +127,7 @@ public class Dialogs {
confirm.setTitle(title);
confirm.setHeaderText(header);
confirm.showAndWait();
return confirm.getResult() == ButtonType.YES;
return confirm.getResult() == YES;
}
public static ButtonType showShutdownDialog(Scene parent) {
@ -134,4 +144,36 @@ public class Dialogs {
confirm.showAndWait();
return confirm.getResult();
}
public static Optional<ModelGroup> showModelGroupSelectionDialog(Scene parent, Model model) {
GridPane dialogPane = new GridPane();
Set<ModelGroup> modelGroups = Config.getInstance().getSettings().modelGroups;
ObservableList<ModelGroup> comboBoxModel = FXCollections.observableArrayList(modelGroups);
ComboBox<ModelGroup> comboBox = new ComboBox<>(comboBoxModel);
comboBox.setEditable(true);
comboBox.setPlaceholder(new Label(" type in a name to a add a new group "));
dialogPane.add(new Label("Model group"), 0, 0);
dialogPane.add(comboBox, 1, 0);
boolean ok = showCustomInput(parent, "Add model to group", dialogPane);
if (ok) {
String text = comboBox.getEditor().getText();
if (StringUtil.isBlank(text)) {
return Optional.empty();
}
Optional<ModelGroup> existingGroup = modelGroups.stream().filter(mg -> mg.getName().equalsIgnoreCase(text)).findFirst();
if (existingGroup.isPresent()) {
existingGroup.get().add(model);
return existingGroup;
} else {
ModelGroup group = new ModelGroup();
group.setId(UUID.randomUUID());
group.setName(text);
group.add(model);
modelGroups.add(group);
return Optional.of(group);
}
} else {
return Optional.empty();
}
}
}

View File

@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model;
import ctbrec.ModelGroup;
import ctbrec.event.EventBusHolder;
import ctbrec.recorder.Recorder;
import ctbrec.sites.Site;
@ -39,6 +40,7 @@ import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.TipDialog;
import ctbrec.ui.TokenLabel;
import ctbrec.ui.action.AddToGroupAction;
import ctbrec.ui.action.IgnoreModelsAction;
import ctbrec.ui.action.OpenRecordingsDir;
import ctbrec.ui.action.SetStopDateAction;
@ -501,6 +503,11 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
MenuItem unfollow = new MenuItem("Unfollow");
unfollow.setOnAction(e -> follow(getSelectedThumbCells(cell), false));
MenuItem addToGroup = new MenuItem("Add to group");
addToGroup.setOnAction(e -> addToGroup(model));
MenuItem editGroup = new MenuItem("Edit group");
editGroup.setOnAction(e -> editGroup(model));
MenuItem ignore = new MenuItem("Ignore");
ignore.setOnAction(e -> ignore(getSelectedThumbCells(cell)));
@ -535,6 +542,8 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
if (site.supportsTips()) {
contextMenu.getItems().add(sendTip);
}
Optional<ModelGroup> modelGroup = Config.getInstance().getModelGroup(model);
contextMenu.getItems().add(modelGroup.isEmpty() ? addToGroup : editGroup);
contextMenu.getItems().addAll(copyUrl, openInBrowser, ignore, refresh, openRecDir);
if (model instanceof MyFreeCamsModel && Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
MenuItem debug = new MenuItem("debug");
@ -545,6 +554,13 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
return contextMenu;
}
private void editGroup(Model model) {
}
private void addToGroup(Model model) {
new AddToGroupAction(this.getContent(), recorder, model).execute();
}
private void recordLater(List<ThumbCell> list, boolean recordLater) {
for (ThumbCell cell : list) {
cell.recordLater(recordLater);

View File

@ -41,7 +41,6 @@ public abstract class AbstractModel implements Model {
private Instant lastRecorded;
private Instant recordUntil;
private SubsequentAction recordUntilSubsequentAction;
private Optional<ModelGroupEntry> modelGroup = Optional.empty(); // NOSONAR
@Override
public boolean isOnline() throws IOException, ExecutionException, InterruptedException {
@ -310,14 +309,4 @@ public abstract class AbstractModel implements Model {
}
return true;
}
@Override
public Optional<ModelGroupEntry> getModelGroup() {
return modelGroup;
}
@Override
public void setModelGroup(ModelGroupEntry modelGroup) {
this.modelGroup = Optional.ofNullable(modelGroup);
}
}

View File

@ -18,8 +18,8 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
@ -185,11 +185,11 @@ public class Config {
}
// 3.11.0 make Cam4 model names lower case
settings.models.stream()
.filter(Cam4Model.class::isInstance)
.forEach(m -> m.setName(m.getName().toLowerCase()));
.filter(Cam4Model.class::isInstance)
.forEach(m -> m.setName(m.getName().toLowerCase()));
settings.modelsIgnored.stream()
.filter(Cam4Model.class::isInstance)
.forEach(m -> m.setName(m.getName().toLowerCase()));
.filter(Cam4Model.class::isInstance)
.forEach(m -> m.setName(m.getName().toLowerCase()));
// 4.1.2 reduce models ignore to store only the URL
if (settings.modelsIgnored != null && !settings.modelsIgnored.isEmpty()) {
settings.ignoredModels = settings.modelsIgnored.stream()
@ -230,9 +230,9 @@ public class Config {
}
public synchronized void save() throws IOException {
if (savingDisabled) {
return;
}
if (savingDisabled) {
return;
}
Moshi moshi = new Moshi.Builder()
.add(Model.class, new ModelJsonAdapter())
.add(PostProcessor.class, new PostProcessorJsonAdapter())
@ -303,12 +303,18 @@ public class Config {
public String getModelNotes(Model m) {
return Config.getInstance().getSettings().modelNotes.getOrDefault(m.getUrl(), "");
}
public void disableSaving() {
savingDisabled = true;
savingDisabled = true;
}
public void enableSaving() {
savingDisabled = false;
savingDisabled = false;
}
public Optional<ModelGroup> getModelGroup(Model model) {
return getSettings().modelGroups.stream()
.filter(mg -> mg.getModelUrls().contains(model.getUrl()))
.findFirst();
}
}

View File

@ -4,7 +4,6 @@ import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import javax.xml.bind.JAXBException;
@ -149,7 +148,4 @@ public interface Model extends Comparable<Model>, Serializable {
*/
public boolean exists() throws IOException;
public void setModelGroup(ModelGroupEntry modelGroupEntry);
public Optional<ModelGroupEntry> getModelGroup();
}

View File

@ -1,7 +1,6 @@
package ctbrec;
import java.io.Serializable;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
@ -12,7 +11,7 @@ public class ModelGroup implements Serializable {
private UUID id;
private String name;
private transient List<Model> models = new LinkedList<>();
private List<String> modelUrls = new LinkedList<>();
public UUID getId() {
return id;
@ -30,12 +29,12 @@ public class ModelGroup implements Serializable {
this.name = name;
}
public List<Model> getModels() {
return models;
public List<String> getModelUrls() {
return modelUrls;
}
public void setModels(List<Model> models) {
this.models = models;
public void setModelUrls(List<String> modelUrls) {
this.modelUrls = modelUrls;
}
@Override
@ -60,15 +59,14 @@ public class ModelGroup implements Serializable {
@Override
public String toString() {
return "ModelGroup [id=" + id + ", name=" + name + ", models=" + models + "]";
return "ModelGroup [id=" + id + ", name=" + name + ", models=" + modelUrls + "]";
}
public void add(String modelUrl) {
modelUrls.add(modelUrl);
}
public void add(Model model) {
models.add(model);
Collections.sort(models, (m1, m2) -> {
int index1 = m1.getModelGroup().map(ModelGroupEntry::getIndex).orElse(0);
int index2 = m2.getModelGroup().map(ModelGroupEntry::getIndex).orElse(0);
return index1 - index2;
});
modelUrls.add(model.getUrl());
}
}

View File

@ -1,53 +0,0 @@
package ctbrec;
import java.io.Serializable;
import java.util.Objects;
import java.util.UUID;
public class ModelGroupEntry implements Serializable {
private static final long serialVersionUID = 0L;
private UUID id;
private int index;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public int hashCode() {
return Objects.hash(id, index);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ModelGroupEntry other = (ModelGroupEntry) obj;
return Objects.equals(id, other.id) && index == other.index;
}
@Override
public String toString() {
return "ModelGroupEntry [id=" + id + ", index=" + index + "]";
}
}

View File

@ -5,7 +5,6 @@ import java.lang.reflect.InvocationTargetException;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -16,7 +15,6 @@ import com.squareup.moshi.JsonReader.Token;
import com.squareup.moshi.JsonWriter;
import ctbrec.Model;
import ctbrec.ModelGroupEntry;
import ctbrec.SubsequentAction;
import ctbrec.sites.Site;
import ctbrec.sites.chaturbate.ChaturbateModel;
@ -71,18 +69,6 @@ public class ModelJsonAdapter extends JsonAdapter<Model> {
model.setRecordUntil(Instant.ofEpochMilli(reader.nextLong()));
} else if (key.equals("recordUntilSubsequentAction")) {
model.setRecordUntilSubsequentAction(SubsequentAction.valueOf(reader.nextString()));
} else if (key.equals("groupId")) {
ModelGroupEntry entry = new ModelGroupEntry();
entry.setId(UUID.fromString(reader.nextString()));
model.setModelGroup(entry);
} else if (key.equals("groupIndex")) {
model.getModelGroup().ifPresent(mg -> {
try {
mg.setIndex(reader.nextInt());
} catch (IOException e) {
LOG.error("Error while reading model group index", e);
}
});
} else if (key.equals("siteSpecific")) {
reader.beginObject();
try {
@ -128,8 +114,6 @@ public class ModelJsonAdapter extends JsonAdapter<Model> {
writer.name("lastRecorded").value(model.getLastRecorded().toEpochMilli());
writer.name("recordUntil").value(model.getRecordUntil().toEpochMilli());
writer.name("recordUntilSubsequentAction").value(model.getRecordUntilSubsequentAction().name());
writer.name("groupId").value(model.getModelGroup().map(ModelGroupEntry::getId).map(Object::toString).orElse(null));
writer.name("groupIndex").value(model.getModelGroup().map(ModelGroupEntry::getIndex).orElse(0));
writer.name("siteSpecific");
writer.beginObject();
model.writeSiteSpecificData(writer);

View File

@ -47,7 +47,6 @@ import com.google.common.eventbus.Subscribe;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.ModelGroup;
import ctbrec.ModelGroupEntry;
import ctbrec.Recording;
import ctbrec.Recording.State;
import ctbrec.event.Event;
@ -93,7 +92,6 @@ public class NextGenLocalRecorder implements Recorder {
threadPoolScaler = new ThreadPoolScaler((ThreadPoolExecutor) downloadPool, 5);
recordingManager = new RecordingManager(config, sites);
loadModels();
createModelGroups();
int ppThreads = config.getSettings().postProcessingThreads;
ppPool = new ThreadPoolExecutor(ppThreads, ppThreads, 5, TimeUnit.MINUTES, ppQueue, createThreadFactory("PP", MIN_PRIORITY));
@ -135,16 +133,6 @@ public class NextGenLocalRecorder implements Recorder {
});
}
private void createModelGroups() {
for (Model model : models) {
if(model.getModelGroup().isPresent()) {
ModelGroupEntry groupEntry = model.getModelGroup().get(); // NOSONAR
ModelGroup group = getModelGroup(groupEntry.getId());
group.add(model);
}
}
}
private void startCompletionHandler() {
downloadCompletionPool.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
@ -796,38 +784,26 @@ public class NextGenLocalRecorder implements Recorder {
}
@Override
public ModelGroup getModelGroup(UUID id) {
public Optional<ModelGroup> getModelGroup(UUID id) {
for (ModelGroup group : getModelGroups()) {
if (Objects.equals(group.getId(), id)) {
return group;
return Optional.of(group);
}
}
throw new NoSuchElementException("ModelGroup with id " + id + " not found");
return Optional.empty();
}
@Override
public ModelGroup createModelGroup(String name) {
ModelGroup group = new ModelGroup();
group.setName(name);
config.getSettings().modelGroups.add(group);
try {
config.save();
} catch (IOException e) {
LOG.error("Couldn't save new model group", e);
}
return group;
public void saveModelGroup(ModelGroup group) throws IOException {
Set<ModelGroup> modelGroups = config.getSettings().modelGroups;
modelGroups.remove(group);
modelGroups.add(group);
config.save();
}
@Override
public void deleteModelGroup(ModelGroup group) {
for (Model model : group.getModels()) {
model.setModelGroup(null);
}
public void deleteModelGroup(ModelGroup group) throws IOException {
config.getSettings().modelGroups.remove(group);
try {
config.save();
} catch (IOException e) {
LOG.error("Couldn't delete model group", e);
}
config.save();
}
}

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@ -153,7 +154,16 @@ public interface Recorder {
public int getModelCount();
public Set<ModelGroup> getModelGroups();
public ModelGroup createModelGroup(String name);
public ModelGroup getModelGroup(UUID uuid);
public void deleteModelGroup(ModelGroup group);
/**
* Saves a model group. If the group already exists, it will be overwritten. Otherwise it will
* be saved as a new group.
* @param group
* @throws IOException
*/
public void saveModelGroup(ModelGroup group) throws IOException;
public Optional<ModelGroup> getModelGroup(UUID uuid);
public void deleteModelGroup(ModelGroup group) throws IOException;
}

View File

@ -2,7 +2,10 @@ package ctbrec.recorder;
import static ctbrec.recorder.NextGenLocalRecorder.*;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@ -13,7 +16,6 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.ModelGroup;
import ctbrec.ModelGroupEntry;
import ctbrec.Recording;
import ctbrec.recorder.download.Download;
@ -28,7 +30,7 @@ public class RecordingPreconditions {
this.recorder = recorder;
}
void check(Model model) throws IOException {
void check(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
ensureRecorderIsActive();
ensureModelIsNotSuspended(model);
ensureModelIsNotMarkedForLaterRecording(model);
@ -134,20 +136,38 @@ public class RecordingPreconditions {
return concurrentRecordings == 0 || concurrentRecordings > 0 && recorder.getRecordingProcesses().size() < concurrentRecordings;
}
private void ensureNoOtherFromModelGroupIsRecording(Model model) {
if (model.getModelGroup().isPresent()) {
ModelGroupEntry modelGroupEntry = model.getModelGroup().get(); // NOSONAR
ModelGroup modelGroup = recorder.getModelGroup(modelGroupEntry.getId());
for (Model groupModel : modelGroup.getModels()) {
if (groupModel.equals(model)) {
return; // no other model with lower group index is online, start recording
} else if (otherModelCanBeRecorded(groupModel)) {
throw new PreconditionNotMetException(groupModel + " from the same group is already recorded");
private void ensureNoOtherFromModelGroupIsRecording(Model model) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
Optional<ModelGroup> modelGroup = Config.getInstance().getModelGroup(model);
if (modelGroup.isPresent()) {
for (String modelUrl : modelGroup.get().getModelUrls()) {
if (modelUrl.equals(model.getUrl())) {
// no other model with higher prio is online, start recording
// but before that stop all recordings of models with lower prio
stopModelsWithLowerPrio(modelGroup.get());
return;
} else {
Optional<Model> otherModel = getModelForUrl(modelUrl);
if (otherModel.isPresent() && otherModelCanBeRecorded(otherModel.get())) {
throw new PreconditionNotMetException(otherModel.get() + " from the same group is already recorded");
}
}
}
}
}
private void stopModelsWithLowerPrio(ModelGroup modelGroup) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
recorder.getCurrentlyRecording().stream()
.filter(m -> modelGroup.getModelUrls().contains(m.getUrl()))
.forEach(recorder::stopRecordingProcess);
}
private Optional<Model> getModelForUrl(String modelUrl) {
return Config.getInstance().getSettings().models.stream()
.filter(m -> Objects.equals(m.getUrl(), modelUrl))
.findFirst();
}
private boolean otherModelCanBeRecorded(Model model) {
try {
ensureRecorderIsActive();

View File

@ -11,7 +11,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@ -616,9 +615,8 @@ public class RemoteRecorder implements Recorder {
}
@Override
public ModelGroup createModelGroup(String name) {
public void saveModelGroup(ModelGroup group) {
// TODO Auto-generated method stub
return null;
}
@Override
@ -627,12 +625,12 @@ public class RemoteRecorder implements Recorder {
}
@Override
public ModelGroup getModelGroup(UUID id) {
public Optional<ModelGroup> getModelGroup(UUID id) {
for (ModelGroup group : getModelGroups()) {
if (Objects.equals(group.getId(), id)) {
return group;
return Optional.of(group);
}
}
throw new NoSuchElementException("ModelGroup with id " + id + " not found");
return Optional.empty();
}
}