diff --git a/pom.xml b/pom.xml
index c36f818..233ebe8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,15 +65,6 @@
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.8.1
-
- ${java.source.version}
- ${java.target.version}
-
-
org.codehaus.mojo
appassembler-maven-plugin
@@ -197,6 +188,69 @@
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ src/main/java
+ target/generated-sources/annotations
+
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ testCompile
+ test-compile
+
+ testCompile
+
+
+
+
+ ${java.source.version}
+ ${java.target.version}
+
+
@@ -277,9 +331,10 @@
UTF-8
17
17
- 3.3-SNAPSHOT
+ 3.6-SNAPSHOT
3.1-SNAPSHOT
[5.10,5.11-alpha)
+ 1.9.22
@@ -335,6 +390,17 @@
javafx-swing
21.0.1
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin.version}
+ test
+
diff --git a/src/main/java/org/openbase/bco/registry/editor/RegistryEditor.java b/src/main/java/org/openbase/bco/registry/editor/RegistryEditor.java
index 1a34a6f..8af17bc 100644
--- a/src/main/java/org/openbase/bco/registry/editor/RegistryEditor.java
+++ b/src/main/java/org/openbase/bco/registry/editor/RegistryEditor.java
@@ -94,6 +94,7 @@ public void start(Stage primaryStage) {
globalTabPane.getTabs().add(new RegistryRemoteTab<>(Registries.getClassRegistry(), getClassRegistryGrouping()));
globalTabPane.getTabs().add(new RegistryRemoteTab<>(Registries.getTemplateRegistry()));
globalTabPane.getTabs().add(new RegistryRemoteTab<>(Registries.getActivityRegistry()));
+ globalTabPane.getTabs().add(new RegistryRemoteTab<>(Registries.getMessageRegistry()));
final StackPane stackPane = new StackPane();
// make login panel appear in the top right with small margins at the top and right
diff --git a/src/main/java/org/openbase/bco/registry/editor/struct/RegistryMessageTreeItem.java b/src/main/java/org/openbase/bco/registry/editor/struct/RegistryMessageTreeItem.java
deleted file mode 100644
index 1db1b75..0000000
--- a/src/main/java/org/openbase/bco/registry/editor/struct/RegistryMessageTreeItem.java
+++ /dev/null
@@ -1,327 +0,0 @@
-package org.openbase.bco.registry.editor.struct;
-
-/*-
- * #%L
- * BCO Registry Editor
- * %%
- * Copyright (C) 2014 - 2024 openbase.org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.Message;
-import javafx.application.Platform;
-import javafx.scene.Node;
-import javafx.scene.control.*;
-import javafx.scene.control.Alert.AlertType;
-import javafx.scene.layout.HBox;
-import org.openbase.bco.registry.editor.visual.RequiredFieldAlert;
-import org.openbase.bco.registry.remote.Registries;
-import org.openbase.jul.exception.CouldNotPerformException;
-import org.openbase.jul.exception.ExceptionProcessor;
-import org.openbase.jul.exception.InitializationException;
-import org.openbase.jul.exception.NotAvailableException;
-import org.openbase.jul.exception.printer.ExceptionPrinter;
-import org.openbase.jul.exception.printer.LogLevel;
-import org.openbase.jul.extension.protobuf.processing.ProtoBufFieldProcessor;
-import org.openbase.jul.extension.type.processing.LabelProcessor;
-import org.openbase.jul.iface.Identifiable;
-import org.openbase.jul.schedule.GlobalCachedExecutorService;
-
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-/**
- * @author Tamino Huxohl
- */
-public class RegistryMessageTreeItem extends BuilderTreeItem {
-
- private final FieldDescriptor idField, labelField;
-
- private boolean inUpdate;
- private boolean changed;
- private Future registryTask;
-
- public RegistryMessageTreeItem(FieldDescriptor fieldDescriptor, MB builder, Boolean editable) throws InitializationException {
- super(fieldDescriptor, builder, editable);
- try {
- idField = ProtoBufFieldProcessor.getFieldDescriptor(builder, Identifiable.TYPE_FIELD_ID);
- labelField = ProtoBufFieldProcessor.getFieldDescriptor(builder, org.openbase.type.language.LabelType.Label.class.getSimpleName().toLowerCase());
-
- changed = false;
- inUpdate = false;
-
- this.addEventHandler(valueChangedEvent(), event -> {
- // this is triggered when the value of this node or one of its children changes
- updateDescriptionGraphic();
-
- if (!inUpdate && !(event.getSource().equals(RegistryMessageTreeItem.this))) {
- logger.trace("Set changed");
- changed = true;
- }
-
- updateValueGraphic();
- });
- } catch (CouldNotPerformException ex) {
- throw new InitializationException(this, ex);
- }
- }
-
- public String getId() {
- return (String) getBuilder().getField(idField);
- }
-
- /**
- * Match a builder by comparing their ids.
- *
- * @param builder {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- protected boolean matchesBuilder(final MB builder) {
- final Object id1 = getBuilder().getField(idField);
- final Object id2 = builder.getField(idField);
- return id1.equals(id2);
- }
-
- @Override
- protected Set getUneditableFields() {
- Set uneditableFieldSet = new HashSet<>();
- uneditableFieldSet.add(idField.getNumber());
- return uneditableFieldSet;
- }
-
- @Override
- protected String createDescriptionText() {
- try {
- return LabelProcessor.getBestMatch((org.openbase.type.language.LabelType.Label) getBuilder().getField(labelField));
- } catch (NotAvailableException e) {
- return super.createDescriptionText();
- }
- }
-
- @Override
- protected Node createValueGraphic() {
- // task is not done yet so display loading graphic
- if (registryTask != null && !registryTask.isDone()) {
- final Label label = new Label("Waiting for registry update...");
- final ProgressIndicator progressIndicator = new ProgressIndicator();
- progressIndicator.setMaxHeight(16);
-
- final HBox hBox = new HBox();
- hBox.setSpacing(5);
- hBox.getChildren().addAll(progressIndicator, label);
- return hBox;
- }
-
- final Label errorLabel = new Label();
- // task is done but not reset meaning it failed, so generate an error label
- if (registryTask != null) {
- errorLabel.setStyle("-fx-text-background-color: rgb(255,0,0); -fx-font-weight: bold;");
- // done but failed
- try {
- registryTask.get();
- } catch (InterruptedException ex) {
- // this should not because the task should already be done
- } catch (ExecutionException ex) {
- errorLabel.setText(ExceptionProcessor.getInitialCause(ex).getMessage());
- }
- }
-
- if (changed) {
- logger.trace("Create buttons");
- final Button applyButton, cancelButton;
- final HBox buttonLayout;
- applyButton = new Button("Apply");
- applyButton.setOnAction(event -> handleApplyEvent());
- cancelButton = new Button("Cancel");
- cancelButton.setOnAction(event -> handleCancelEvent());
- buttonLayout = new HBox(applyButton, cancelButton);
- if (registryTask != null) {
- // if task failed add error to button layout
- buttonLayout.getChildren().add(errorLabel);
- }
- return buttonLayout;
- }
-
- if (registryTask != null) {
- return errorLabel;
- }
-
- return super.createValueGraphic();
- }
-
- @Override
- public void update(MB value) throws CouldNotPerformException {
- //TODO handle local changes but global update
-
- inUpdate = true;
- try {
- changed = false;
- if (registryTask != null) {
- registryTask = null;
- }
-
- super.update(value);
- } finally {
- inUpdate = false;
- }
- }
-
- private void handleCancelEvent() {
- final String id = (String) getBuilder().getField(idField);
- if (id.isEmpty()) {
- getParent().getChildren().remove(RegistryMessageTreeItem.this);
- } else {
- try {
- final MB oldBuilder = (MB) Registries.getById(id, getBuilder()).toBuilder();
- try {
- update(oldBuilder);
- } catch (CouldNotPerformException ex) {
- logger.error("Could not update tree item with old builder from registry", ex);
- }
- } catch (CouldNotPerformException ex) {
- ExceptionPrinter.printHistory("Could not retrieve message with id[" + id + "] for type[" + getBuilder().getClass().getName() + "] from registry", ex, logger, LogLevel.WARN);
- }
- }
- }
-
- private void handleApplyEvent() {
- logger.info("Apply button pressed");
- handleRequiredFields();
-
- try {
- Message message;
- try {
- message = getBuilder().build();
- } catch (Throwable ex) {
- logger.info("Build failed", ex);
- throw ex;
- }
-
- if (Registries.contains(message)) {
- // save original value from model
- final Message original = Registries.getById(ProtoBufFieldProcessor.getId(message));
- changed = false;
- registryTask = Registries.update(message);
- GlobalCachedExecutorService.submit(() -> {
- final Message update;
- try {
- update = registryTask.get();
-
- // check if update and original are the same, then the changed values where reset and a registry update is not triggered
- if (original.equals(update)) {
- // reset the container to its old value
- Platform.runLater(() -> {
- try {
- RegistryMessageTreeItem.this.update((MB) original.toBuilder());
- } catch (CouldNotPerformException e) {
- logger.error("Could not reset tree item", e);
- }
- });
- }
- } catch (InterruptedException e) {
- // just let the thread finish
- } catch (ExecutionException e) {
- changed = true;
- // update the current value which will trigger an update of the displayed graphics,
- // this will display the exception to the user
- setValue(getValueCasted().createNew(getBuilder()));
- }
- });
-
- } else {
- registryTask = Registries.register(message);
- GlobalCachedExecutorService.submit(() -> {
- try {
- registryTask.get();
- Platform.runLater(() -> getParent().getChildren().remove(this));
- } catch (InterruptedException e) {
- // just let the thread finish
- } catch (ExecutionException e) {
- // update the current value which will trigger an update of the displayed graphics,
- // this will display the exception to the user
- setValue(getValueCasted().createNew(getBuilder()));
- }
- });
- }
- setValue(getValueCasted().createNew(getBuilder()));
- } catch (CouldNotPerformException ex) {
- logger.error("Error while applying event", ex);
- }
- }
-
- private void handleRequiredFields() {
- if (!getBuilder().isInitialized()) {
- if (ProtoBufFieldProcessor.checkIfSomeButNotAllRequiredFieldsAreSet(getBuilder())) {
- new RequiredFieldAlert(getBuilder());
- } else {
- ProtoBufFieldProcessor.clearRequiredFields(getBuilder());
- }
- }
- }
-
- void handleRemoveEvent() {
- final String id = (String) getBuilder().getField(idField);
- try {
- logger.debug("Removing message with Id [" + id + "]");
- if (!"".equals(id) && Registries.containsById(id, getBuilder())) {
-
- final Alert alert = new Alert(AlertType.CONFIRMATION);
- alert.setTitle("Remove Action");
- alert.setHeaderText("Attention! Irreversible Action!");
- alert.setContentText("Do you really want to remove " + getDescriptionText() + "?");
-
- final Optional result = alert.showAndWait();
- if (result.isPresent() && result.get() != ButtonType.OK) {
- return;
- }
-
- // always remove by id to ignore not initialized fields of the builder
- registryTask = Registries.remove(Registries.getById(id, getBuilder()));
- setValue(getValueCasted().createNew(getBuilder()));
- GlobalCachedExecutorService.submit(() -> {
- try {
- registryTask.get();
- } catch (InterruptedException e) {
- // just let the thread finish
- } catch (ExecutionException e) {
- // update the current value which will trigger an update of the displayed graphics,
- // this will display the exception to the user
- setValue(getValueCasted().createNew(getBuilder()));
- }
- });
- } else {
- Platform.runLater(() -> RegistryMessageTreeItem.this.getParent().getChildren().remove(RegistryMessageTreeItem.this));
- }
- } catch (CouldNotPerformException ex) {
- //TODO: handle better
- ExceptionPrinter.printHistory(ex, logger);
- }
- }
-
- public boolean isChanged() {
- return changed;
- }
-
- public void setChanged(final Boolean changed) {
- this.changed = changed;
- }
-}
diff --git a/src/main/java/org/openbase/bco/registry/editor/struct/RegistryMessageTreeItem.kt b/src/main/java/org/openbase/bco/registry/editor/struct/RegistryMessageTreeItem.kt
new file mode 100644
index 0000000..98545f1
--- /dev/null
+++ b/src/main/java/org/openbase/bco/registry/editor/struct/RegistryMessageTreeItem.kt
@@ -0,0 +1,313 @@
+package org.openbase.bco.registry.editor.struct
+
+import com.google.protobuf.Descriptors
+import com.google.protobuf.Message
+import javafx.application.Platform
+import javafx.event.ActionEvent
+import javafx.event.EventHandler
+import javafx.scene.Node
+import javafx.scene.control.*
+import javafx.scene.control.Alert.AlertType
+import javafx.scene.layout.HBox
+import org.openbase.bco.registry.editor.visual.RequiredFieldAlert
+import org.openbase.bco.registry.remote.Registries
+import org.openbase.jul.exception.CouldNotPerformException
+import org.openbase.jul.exception.ExceptionProcessor.getInitialCause
+import org.openbase.jul.exception.InitializationException
+import org.openbase.jul.exception.NotAvailableException
+import org.openbase.jul.exception.printer.ExceptionPrinter
+import org.openbase.jul.exception.printer.LogLevel
+import org.openbase.jul.extension.protobuf.processing.ProtoBufFieldProcessor
+import org.openbase.jul.extension.type.processing.LabelProcessor
+import org.openbase.jul.iface.Identifiable
+import org.openbase.jul.schedule.GlobalCachedExecutorService
+import org.openbase.type.language.LabelType
+import java.util.*
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.Future
+import kotlin.collections.HashSet
+
+/**
+ * @author [Tamino Huxohl](mailto:pleminoq@openbase.org)
+ */
+open class RegistryMessageTreeItem(
+ fieldDescriptor: Descriptors.FieldDescriptor,
+ builder: MB,
+ editable: Boolean?,
+ labelProvider: (() -> String)? = null
+) : BuilderTreeItem(fieldDescriptor, builder, editable) {
+ private var idField: Descriptors.FieldDescriptor? = null //, labelField;
+ private val labelProvider: () -> String = labelProvider ?: {
+ try {
+ ProtoBufFieldProcessor.getFieldDescriptor(
+ builder,
+ LabelType.Label::class.java.getSimpleName().lowercase()
+ ).let { defaultLabelField ->
+ LabelProcessor.getBestMatch(
+ getBuilder().getField(defaultLabelField) as LabelType.Label,
+ super.createDescriptionText()
+ )
+ ?: super.createDescriptionText()
+ }
+ } catch (e: NotAvailableException) {
+ super.createDescriptionText()
+ }
+ }
+
+ private var inUpdate = false
+ var isChanged: Boolean = false
+ private var registryTask: Future? = null
+
+ constructor(
+ fieldDescriptor: Descriptors.FieldDescriptor,
+ builder: MB,
+ editable: Boolean?
+ ) : this(fieldDescriptor, builder, editable, null)
+
+ init {
+ try {
+ idField = ProtoBufFieldProcessor.getFieldDescriptor(builder, Identifiable.TYPE_FIELD_ID)
+ isChanged = false
+ inUpdate = false
+
+ this.addEventHandler(
+ valueChangedEvent(),
+ EventHandler> { event: TreeModificationEvent ->
+ // this is triggered when the value of this node or one of its children changes
+ updateDescriptionGraphic()
+
+ if (!inUpdate && event.source != this@RegistryMessageTreeItem) {
+ logger.trace("Set changed")
+ isChanged = true
+ }
+ updateValueGraphic()
+ })
+ } catch (ex: CouldNotPerformException) {
+ throw InitializationException(this, ex)
+ }
+ }
+
+ val id: String
+ get() = builder!!.getField(idField) as String
+
+ /**
+ * Match a builder by comparing their ids.
+ *
+ * @param builder {@inheritDoc}
+ * @return {@inheritDoc}
+ */
+ override fun matchesBuilder(builder: MB): Boolean {
+ val id1 = getBuilder()!!.getField(idField)
+ val id2 = builder!!.getField(idField)
+ return id1 == id2
+ }
+
+ override fun getUneditableFields(): Set {
+ val uneditableFieldSet: MutableSet = HashSet()
+ uneditableFieldSet.add(idField!!.number)
+ return uneditableFieldSet
+ }
+
+ override fun createDescriptionText(): String = labelProvider()
+
+ override fun createValueGraphic(): Node? {
+ // task is not done yet so display loading graphic
+ if (registryTask != null && !registryTask!!.isDone) {
+ val label = Label("Waiting for registry update...")
+ val progressIndicator = ProgressIndicator()
+ progressIndicator.maxHeight = 16.0
+
+ val hBox = HBox()
+ hBox.spacing = 5.0
+ hBox.children.addAll(progressIndicator, label)
+ return hBox
+ }
+
+ val errorLabel = Label()
+ // task is done but not reset meaning it failed, so generate an error label
+ if (registryTask != null) {
+ errorLabel.style = "-fx-text-background-color: rgb(255,0,0); -fx-font-weight: bold;"
+ // done but failed
+ try {
+ registryTask!!.get()
+ } catch (ex: InterruptedException) {
+ // this should not because the task should already be done
+ } catch (ex: ExecutionException) {
+ errorLabel.text = getInitialCause(ex).message
+ }
+ }
+
+ if (isChanged) {
+ logger.trace("Create buttons")
+ val buttonLayout: HBox
+ val applyButton = Button("Apply")
+ applyButton.onAction = EventHandler { event: ActionEvent? -> handleApplyEvent() }
+ val cancelButton = Button("Cancel")
+ cancelButton.onAction = EventHandler { event: ActionEvent? -> handleCancelEvent() }
+ buttonLayout = HBox(applyButton, cancelButton)
+ if (registryTask != null) {
+ // if task failed add error to button layout
+ buttonLayout.children.add(errorLabel)
+ }
+ return buttonLayout
+ }
+
+ if (registryTask != null) {
+ return errorLabel
+ }
+
+ return super.createValueGraphic()
+ }
+
+ @Throws(CouldNotPerformException::class)
+ override fun update(value: MB) {
+ //TODO handle local changes but global update
+
+ inUpdate = true
+ try {
+ isChanged = false
+ if (registryTask != null) {
+ registryTask = null
+ }
+
+ super.update(value)
+ } finally {
+ inUpdate = false
+ }
+ }
+
+ private fun handleCancelEvent() {
+ val id = builder!!.getField(idField) as String
+ if (id.isEmpty()) {
+ parent.children.remove(this@RegistryMessageTreeItem)
+ } else {
+ try {
+ val oldBuilder = Registries.getById(id, builder).toBuilder() as MB
+ try {
+ update(oldBuilder)
+ } catch (ex: CouldNotPerformException) {
+ logger.error("Could not update tree item with old builder from registry", ex)
+ }
+ } catch (ex: CouldNotPerformException) {
+ ExceptionPrinter.printHistory(
+ "Could not retrieve message with id[" + id + "] for type[" + builder.javaClass.name + "] from registry",
+ ex,
+ logger,
+ LogLevel.WARN
+ )
+ }
+ }
+ }
+
+ private fun handleApplyEvent() {
+ logger.info("Apply button pressed")
+ handleRequiredFields()
+
+ try {
+ val message: Message
+ try {
+ message = builder!!.build()
+ } catch (ex: Throwable) {
+ logger.info("Build failed", ex)
+ throw ex
+ }
+
+ if (Registries.contains(message)) {
+ // save original value from model
+ val original = Registries.getById(ProtoBufFieldProcessor.getId(message))
+ isChanged = false
+ registryTask = Registries.update(message)
+ GlobalCachedExecutorService.submit {
+ val update: Message?
+ try {
+ update = registryTask?.get()
+
+ // check if update and original are the same, then the changed values where reset and a registry update is not triggered
+ if (original == update) {
+ // reset the container to its old value
+ Platform.runLater {
+ try {
+ this@RegistryMessageTreeItem.update(original.toBuilder() as MB)
+ } catch (e: CouldNotPerformException) {
+ logger.error("Could not reset tree item", e)
+ }
+ }
+ }
+ } catch (e: InterruptedException) {
+ // just let the thread finish
+ } catch (e: ExecutionException) {
+ isChanged = true
+ // update the current value which will trigger an update of the displayed graphics,
+ // this will display the exception to the user
+ setValue(valueCasted.createNew(builder))
+ }
+ }
+ } else {
+ registryTask = Registries.register(message)
+ GlobalCachedExecutorService.submit {
+ try {
+ registryTask?.get()
+ Platform.runLater { parent.children.remove(this) }
+ } catch (e: InterruptedException) {
+ // just let the thread finish
+ } catch (e: ExecutionException) {
+ // update the current value which will trigger an update of the displayed graphics,
+ // this will display the exception to the user
+ setValue(valueCasted.createNew(builder))
+ }
+ }
+ }
+ setValue(valueCasted.createNew(builder))
+ } catch (ex: CouldNotPerformException) {
+ logger.error("Error while applying event", ex)
+ }
+ }
+
+ private fun handleRequiredFields() {
+ if (!builder!!.isInitialized) {
+ if (ProtoBufFieldProcessor.checkIfSomeButNotAllRequiredFieldsAreSet(builder)) {
+ RequiredFieldAlert(builder)
+ } else {
+ ProtoBufFieldProcessor.clearRequiredFields(builder)
+ }
+ }
+ }
+
+ fun handleRemoveEvent() {
+ val id = builder!!.getField(idField) as String
+ try {
+ logger.debug("Removing message with Id [$id]")
+ if ("" != id && Registries.containsById(id, builder)) {
+ val alert = Alert(AlertType.CONFIRMATION)
+ alert.title = "Remove Action"
+ alert.headerText = "Attention! Irreversible Action!"
+ alert.contentText = "Do you really want to remove $descriptionText?"
+
+ val result = alert.showAndWait()
+ if (result.isPresent && result.get() != ButtonType.OK) {
+ return
+ }
+
+ // always remove by id to ignore not initialized fields of the builder
+ registryTask = Registries.remove(Registries.getById(id, builder))
+ value = valueCasted.createNew(builder)
+ GlobalCachedExecutorService.submit {
+ try {
+ registryTask?.get()
+ } catch (e: InterruptedException) {
+ // just let the thread finish
+ } catch (e: ExecutionException) {
+ // update the current value which will trigger an update of the displayed graphics,
+ // this will display the exception to the user
+ value = valueCasted.createNew(builder)
+ }
+ }
+ } else {
+ Platform.runLater { parent.children.remove(this@RegistryMessageTreeItem) }
+ }
+ } catch (ex: CouldNotPerformException) {
+ //TODO: handle better
+ ExceptionPrinter.printHistory(ex, logger)
+ }
+ }
+}
diff --git a/src/main/java/org/openbase/bco/registry/editor/struct/preset/UserMessageTreeItem.kt b/src/main/java/org/openbase/bco/registry/editor/struct/preset/UserMessageTreeItem.kt
new file mode 100644
index 0000000..cedc962
--- /dev/null
+++ b/src/main/java/org/openbase/bco/registry/editor/struct/preset/UserMessageTreeItem.kt
@@ -0,0 +1,37 @@
+package org.openbase.bco.registry.editor.struct.preset
+
+import com.google.protobuf.Descriptors
+import org.openbase.bco.registry.editor.struct.RegistryMessageTreeItem
+import org.openbase.bco.registry.remote.Registries
+import org.openbase.jul.exception.NotAvailableException
+import org.openbase.jul.extension.protobuf.processing.ProtoBufFieldProcessor
+import org.openbase.jul.extension.type.processing.LabelProcessor
+import org.openbase.type.domotic.communication.UserMessageType.UserMessage
+import org.openbase.type.language.LabelType
+
+/**
+ * @author [Tamino Huxohl](mailto:pleminoq@openbase.org)
+ */
+class UserMessageTreeItem(
+ fieldDescriptor: Descriptors.FieldDescriptor?,
+ builder: UserMessage.Builder,
+ editable: Boolean?,
+) : RegistryMessageTreeItem(
+ fieldDescriptor!!, builder, editable, {
+ "${builder.messageType.takeIf { it != UserMessage.MessageType.UNKNOWN } ?: "Message"}${
+ try {
+ Registries.getUnitRegistry().getUnitConfigById(builder.senderId)
+ .let { LabelProcessor.getBestMatch(it.label, "") }
+ } catch (e: NotAvailableException) {
+ builder.senderId
+ }?.trim().takeIf { !it.isNullOrBlank() }?.let { " from $it" } ?: ""
+ } ${
+ try {
+ Registries.getUnitRegistry().getUnitConfigById(builder.recipientId)
+ .let { LabelProcessor.getBestMatch(it.label, "") }
+ } catch (e: NotAvailableException) {
+ builder.recipientId
+ }?.trim().takeIf { !it.isNullOrBlank() }?.let { " to $it" } ?: ""
+ }"
+ }
+)