From 1f0ab4dc032fa1ba7c0fd7693dabc2637efd3c3a Mon Sep 17 00:00:00 2001 From: Frederick Vollbrecht <39002042+vollbrecht-work@users.noreply.github.com> Date: Thu, 28 Aug 2025 13:44:02 +0200 Subject: [PATCH 1/3] Refactor Add and Edit Description Forms into unified Controller The newly added DescriptionBaseController now holds all duplicated code that was present in the AddFullyQualifiedNameController, AddOtherNameController, EditFullyQualifiedNameController and EditDescriptionFormController. Four new controllers were edded that still holds the some controller specific's from the old above Controllers. They now are called Description{Edit/Add}{Other/Fqn}Controller. A unified FXML was introduced called description-form.fxml, to reduce copy pasted view's, helping reduce the UI bug surface. --- .../kview/mvvm/model/DescriptionFormType.java | 24 ++ .../DescriptionAddFqnController.java | 160 +++++++++ .../DescriptionAddOtherController.java | 165 +++++++++ .../properties/DescriptionBaseController.java | 331 ++++++++++++++++++ .../DescriptionEditFqnController.java | 243 +++++++++++++ .../DescriptionEditOtherController.java | 231 ++++++++++++ .../EditDescriptionFormController.java | 15 +- .../view/properties/PropertiesController.java | 50 +-- .../view/properties/description-form.fxml | 207 +++++++++++ 9 files changed, 1402 insertions(+), 24 deletions(-) create mode 100644 kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescriptionFormType.java create mode 100644 kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddFqnController.java create mode 100644 kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddOtherController.java create mode 100644 kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionBaseController.java create mode 100644 kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditFqnController.java create mode 100644 kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditOtherController.java create mode 100644 kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/properties/description-form.fxml diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescriptionFormType.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescriptionFormType.java new file mode 100644 index 000000000..66c8d90cc --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescriptionFormType.java @@ -0,0 +1,24 @@ +package dev.ikm.komet.kview.mvvm.model; + +public enum DescriptionFormType { + ADD_FQN("Add Description: Fully Qualified Name", "Fully Qualified Name", true), + ADD_OTHER_NAME("Add New Description: Other Name", "Other Name", true), + EDIT_FQN("Edit Description: Fully Qualified Name", "Fully Qualified Name", false), + EDIT_OTHER_NAME("Edit Description: Other Name", "Other Name", false); + + private final String title; + private final String typePrompt; + private final boolean isAddMode; + + DescriptionFormType(String title, String typePrompt, boolean isAddMode) { + this.title = title; + this.typePrompt = typePrompt; + this.isAddMode = isAddMode; + } + + public String getTitle() { return title; } + public String getTypePrompt() { return typePrompt; } + public boolean isAddMode() { return isAddMode; } + public boolean isEditMode() { return !isAddMode; } + public boolean isFqnType() { return this == ADD_FQN || this == EDIT_FQN; } +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddFqnController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddFqnController.java new file mode 100644 index 000000000..2f8c3ba64 --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddFqnController.java @@ -0,0 +1,160 @@ +package dev.ikm.komet.kview.mvvm.view.properties; + +import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; +import dev.ikm.komet.kview.events.CreateConceptEvent; +import dev.ikm.komet.kview.mvvm.model.DescrName; +import dev.ikm.komet.kview.mvvm.model.DescriptionFormType; +import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel; +import dev.ikm.tinkar.entity.ConceptEntity; +import dev.ikm.tinkar.entity.Entity; +import dev.ikm.tinkar.terms.EntityFacade; +import dev.ikm.tinkar.terms.State; +import dev.ikm.tinkar.terms.TinkarTerm; +import javafx.beans.InvalidationListener; +import javafx.scene.control.ComboBox; +import javafx.scene.control.ListCell; +import javafx.util.Callback; +import javafx.util.StringConverter; +import org.carlfx.cognitive.loader.InjectViewModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; + +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.*; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; + +public class DescriptionAddFqnController extends DescriptionBaseController{ + private static final Logger LOG = LoggerFactory.getLogger(DescriptionAddFqnController.class); + @InjectViewModel + private DescrNameViewModel fqnViewModel; + + public DescriptionAddFqnController(UUID conceptTopic) { + super(DescriptionFormType.ADD_FQN, conceptTopic); + } + + @Override + protected void initializeData() { + configureDialectVisibility(false); + + submitButton.setDisable(true); + + // Initialize the fqnViewModel + fqnViewModel + .setPropertyValue(NAME_TYPE, TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE) + .setPropertyValue(STATUS, TinkarTerm.ACTIVE_STATE); + + // register listeners + InvalidationListener formValid = (obs) -> { + boolean isFormValid = isFormPopulated(); + if (isFormValid) { + copyUIToViewModelProperties(); + } + submitButton.setDisable(!isFormValid); + }; + + // Initialize combo boxes with appropriate data for FQN add mode + nameTextField.textProperty().addListener(formValid); + setupComboBoxAdd(moduleComboBox, formValid); + setupComboBoxAdd(statusComboBox, formValid); + setupComboBoxAdd(caseSignificanceComboBox, formValid); + setupComboBoxAdd(languageComboBox, formValid); + + + } + + @Override + protected void onCancel() { + close(cancelButton); + } + + @Override + protected void onSubmit() { + // TODO assuming it's valid save() check for errors and publish event + + fqnViewModel.save(); + if (fqnViewModel.getValidationMessages().isEmpty()) { + // publish event with the fqnViewModel. + // ... This property may not be needed. + fqnViewModel.setPropertyValue(IS_SUBMITTED, true); + } + + LOG.info("Ready to add to the concept view model: " + fqnViewModel); + + ////////////////////////////////////////////////////////////////////////////////////////// + // event received in Details Controller that will call conceptViewModel.createConcept() + ////////////////////////////////////////////////////////////////////////////////////////// + DescrName fqnDescrName = fqnViewModel.create(); + eventBus.publish(conceptTopic, new CreateConceptEvent(this, CreateConceptEvent.ADD_FQN, fqnDescrName)); + + // clear the form after saving. otherwise when you navigate back to Add Other Name + // you would have the previous form values still there + clearView(); + close(submitButton); + } + + + private void populate(ComboBox comboBox, Collection entities) { + comboBox.getItems().setAll(entities); + } + + @Override + public void updateView() { + + // populate form combo fields module, status, case significance, lang. + populate(moduleComboBox, fqnViewModel.findAllModules(getViewProperties())); + populate(statusComboBox, fqnViewModel.findAllStatuses(getViewProperties())); + populate(caseSignificanceComboBox, fqnViewModel.findAllCaseSignificants(getViewProperties())); + populate(languageComboBox, fqnViewModel.findAllLanguages(getViewProperties())); + + // Set UI to default values + caseSignificanceComboBox.setValue(TinkarTerm.DESCRIPTION_NOT_CASE_SENSITIVE); + statusComboBox.setValue(Entity.getFast(State.ACTIVE.nid())); + moduleComboBox.setValue(TinkarTerm.DEVELOPMENT_MODULE); + languageComboBox.setValue(TinkarTerm.ENGLISH_LANGUAGE); + } + + @Override + public void clearView() { + nameTextField.setText(""); + moduleComboBox.setValue(null); + statusComboBox.setValue(null); + caseSignificanceComboBox.setValue(null); + languageComboBox.setValue(null); +// if (fqnViewModel != null) { +// copyUIToViewModelProperties(); +// fqnViewModel.save(true); // make UI properties as model values +// } + moduleComboBox.getItems().clear(); + statusComboBox.getItems().clear(); + caseSignificanceComboBox.getItems().clear(); + languageComboBox.getItems().clear(); + } + + /** + * TODO: This is appropriate. A better solution is binding properties on the view model. If so, we'd need to unbind. + * This copies form values into the ViewModel's property values. It does not save or validate. + */ + private void copyUIToViewModelProperties() { + if (fqnViewModel != null) { + fqnViewModel.setPropertyValue(NAME_TEXT, nameTextField.getText()) + .setPropertyValue(NAME_TYPE, TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE) + .setPropertyValue(CASE_SIGNIFICANCE, caseSignificanceComboBox.getSelectionModel().getSelectedItem()) + .setPropertyValue(STATUS, statusComboBox.getSelectionModel().getSelectedItem()) + .setPropertyValue(MODULE, moduleComboBox.getSelectionModel().getSelectedItem()) + .setPropertyValue(LANGUAGE, languageComboBox.getSelectionModel().getSelectedItem()); + } + } + + + @Override + public DescrNameViewModel getViewModel() { + return fqnViewModel; + } + + +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddOtherController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddOtherController.java new file mode 100644 index 000000000..3b5deabdb --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionAddOtherController.java @@ -0,0 +1,165 @@ +package dev.ikm.komet.kview.mvvm.view.properties; + +import dev.ikm.komet.framework.view.ViewProperties; +import dev.ikm.komet.kview.events.CreateConceptEvent; +import dev.ikm.komet.kview.mvvm.model.DescriptionFormType; +import dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel; +import dev.ikm.tinkar.entity.ConceptEntity; +import dev.ikm.tinkar.entity.Entity; +import dev.ikm.tinkar.terms.EntityFacade; +import dev.ikm.tinkar.terms.State; +import dev.ikm.tinkar.terms.TinkarTerm; +import javafx.beans.InvalidationListener; +import javafx.scene.control.ComboBox; +import org.carlfx.cognitive.loader.InjectViewModel; +import org.carlfx.cognitive.viewmodel.ViewModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.UUID; + +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.*; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; +import static dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel.OtherNameProperties.*; + +public class DescriptionAddOtherController extends DescriptionBaseController{ + private static final Logger LOG = LoggerFactory.getLogger(DescriptionAddOtherController.class); + @InjectViewModel + private OtherNameViewModel otherNameViewModel; // TODO why we need that wrapper only for this class but can get away in all 3 others + + + // TODO: how does it work with no UUID + //public DescriptionAddOtherController() { + // super(DescriptionFormType.ADD_OTHER_NAME, conceptTopic); + //} + + public DescriptionAddOtherController(UUID conceptTopic) { + super(DescriptionFormType.ADD_OTHER_NAME, conceptTopic); + } + + + @Override + protected void initializeData() { + configureDialectVisibility(false); + + submitButton.setDisable(true); + + titleLabel.setText("Add New Description: Other Name"); // TODO: check if needed ? + otherNameViewModel + .setPropertyValue(NAME_TYPE, TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE) + .setPropertyValue(STATUS, TinkarTerm.ACTIVE_STATE); + // register listeners + InvalidationListener formValid = (obs) -> { + boolean isFormValid = isFormPopulated(); + if (isFormValid) { + copyUIToViewModelProperties(); + } + submitButton.setDisable(!isFormValid); + }; + + nameTextField.textProperty().addListener(formValid); + setupComboBoxAdd(moduleComboBox, formValid); + setupComboBoxAdd(statusComboBox, formValid); + setupComboBoxAdd(caseSignificanceComboBox, formValid); + setupComboBoxAdd(languageComboBox, formValid); + } + + @Override + public void updateView() { + // populate form combo fields module, status, case significance, lang. + populate(moduleComboBox, otherNameViewModel.findAllModules(getViewProperties())); + populate(statusComboBox, otherNameViewModel.findAllStatuses(getViewProperties())); + populate(caseSignificanceComboBox, otherNameViewModel.findAllCaseSignificants(getViewProperties())); + populate(languageComboBox, otherNameViewModel.findAllLanguages(getViewProperties())); + + boolean hasOtherName = getViewModel().getValue(HAS_OTHER_NAME); + + if (hasOtherName) { + caseSignificanceComboBox.setValue(getViewModel().getValue(FQN_CASE_SIGNIFICANCE)); + } else { + caseSignificanceComboBox.setValue(TinkarTerm.DESCRIPTION_NOT_CASE_SENSITIVE); + } + statusComboBox.setValue(Entity.getFast(State.ACTIVE.nid())); + moduleComboBox.setValue(TinkarTerm.DEVELOPMENT_MODULE); + if (hasOtherName) { + languageComboBox.setValue(getViewModel().getValue(FQN_LANGUAGE)); + } else { + languageComboBox.setValue(TinkarTerm.ENGLISH_LANGUAGE); + } + } + + public void updateModel(final ViewProperties viewProperties) { + this.viewProperties = viewProperties; + } + + @Override + public void clearView() { + nameTextField.setText(""); + moduleComboBox.setValue(null); + statusComboBox.setValue(null); + caseSignificanceComboBox.setValue(null); + languageComboBox.setValue(null); + moduleComboBox.getItems().clear(); + statusComboBox.getItems().clear(); + caseSignificanceComboBox.getItems().clear(); + languageComboBox.getItems().clear(); + } + + @Override + protected void onCancel() { + close(cancelButton); + } + + @Override + protected void onSubmit() { + // TODO assuming it's valid save() check for errors and publish event + otherNameViewModel.setPropertyValue(IS_SUBMITTED, true); + otherNameViewModel.save(); + if (otherNameViewModel.hasNoErrorMsgs()) { + // publish event with the otherNameViewModel. + // ... + LOG.info("Ready to add to the concept view model: " + otherNameViewModel); + eventBus.publish(conceptTopic, new CreateConceptEvent(this, CreateConceptEvent.ADD_OTHER_NAME, + otherNameViewModel.create())); + clearView(); + close(submitButton); + } + } + + @Override + public OtherNameViewModel getViewModel() { + return otherNameViewModel; + } + + /** + * TODO: This is appropriate. A better solution is binding properties on the view model. If so, we'd need to unbind. + * This copies form values into the ViewModel's property values. It does not save or validate. + */ + private void copyUIToViewModelProperties() { + if (otherNameViewModel != null) { + otherNameViewModel.setPropertyValue(NAME_TEXT, nameTextField.getText()) + .setPropertyValue(NAME_TYPE, TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE) + .setPropertyValue(CASE_SIGNIFICANCE, caseSignificanceComboBox.getSelectionModel().getSelectedItem()) + .setPropertyValue(STATUS, statusComboBox.getSelectionModel().getSelectedItem()) + .setPropertyValue(MODULE, moduleComboBox.getSelectionModel().getSelectedItem()) + .setPropertyValue(LANGUAGE, languageComboBox.getSelectionModel().getSelectedItem()); + } + } + + public void setAddOtherNameTitleLabel(String addDescriptionTitleLabelText) { + this.titleLabel.setText(addDescriptionTitleLabelText); + } + + public void populate(ComboBox comboBox, Collection entities) { + comboBox.getItems().addAll(entities); + } + + public void hideNonUsed() { + dialect1.setVisible(false); + dialectComboBox1.setVisible(false); + + } +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionBaseController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionBaseController.java new file mode 100644 index 000000000..0a2c7fb14 --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionBaseController.java @@ -0,0 +1,331 @@ +package dev.ikm.komet.kview.mvvm.view.properties; + +import dev.ikm.komet.framework.view.ViewProperties; +import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; +import dev.ikm.komet.kview.mvvm.model.DescriptionFormType; +import dev.ikm.komet.kview.mvvm.view.AbstractBasicController; +import dev.ikm.komet.kview.mvvm.view.BasicController; +import dev.ikm.tinkar.common.id.PublicId; +import dev.ikm.tinkar.entity.ConceptEntity; +import dev.ikm.tinkar.entity.Entity; +import dev.ikm.tinkar.entity.EntityService; +import dev.ikm.tinkar.entity.EntityVersion; +import dev.ikm.tinkar.events.EvtBus; +import dev.ikm.tinkar.events.EvtBusFactory; +import dev.ikm.tinkar.terms.EntityFacade; +import dev.ikm.tinkar.terms.TinkarTerm; +import javafx.beans.InvalidationListener; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Region; +import javafx.scene.layout.RowConstraints; +import javafx.scene.layout.VBox; +import javafx.util.Callback; +import javafx.util.StringConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + + +public abstract class DescriptionBaseController extends AbstractBasicController { + + private static final Logger LOG = LoggerFactory.getLogger(DescriptionBaseController.class); + + protected UUID conceptTopic; + + protected ViewProperties viewProperties; + + protected EntityFacade entityFacade; + + protected PublicId publicId; + + @FXML + protected Label titleLabel; + + @FXML + protected TextField nameTextField; // TODO more descriptive name + + @FXML + protected ComboBox typeComboBox; + + @FXML + protected ComboBox moduleComboBox; + + @FXML + protected ComboBox statusComboBox; + + @FXML + protected ComboBox caseSignificanceComboBox; + + @FXML + protected ComboBox languageComboBox; + + // Dialects (only visible in edit mode) + @FXML + protected VBox dialectsContainer; + + @FXML + protected RowConstraints dialectRowConstraints; // Add fx:id to the row constraints + + @FXML + protected Label dialect1; + + @FXML + protected Label dialect2; + + @FXML + protected Label dialect3; + + @FXML + protected ComboBox dialectComboBox1; + + @FXML + protected ComboBox dialectComboBox2; + + @FXML + protected ComboBox dialectComboBox3; + + + // + @FXML + protected Button submitButton; + + @FXML + protected Button cancelButton; + + protected EvtBus eventBus; + + protected final DescriptionFormType formType; + + public DescriptionBaseController(DescriptionFormType formType, UUID conceptTopic) { + this.formType = formType; + this.conceptTopic = conceptTopic; + } + + @FXML + public final void initialize() { + // Common initialization that ALWAYS runs + eventBus = EvtBusFactory.getDefaultEvtBus(); + clearView(); + + + // Configure the form based on type + //configureForm(); + + // Let subclasses do their specific initialization + initializeData(); + + // Post-initialization hook for subclasses + //postInitialize(); + } + + protected abstract void initializeData(); + + @Override + public void clearView() { + // Common view clearing logic + if (nameTextField != null) { + nameTextField.clear(); + } + //if (commentsTextArea != null) { + // commentsTextArea.clear(); + //} + // Clear combo boxes + if (caseSignificanceComboBox != null) { + caseSignificanceComboBox.getSelectionModel().clearSelection(); + } + if (statusComboBox != null) { + statusComboBox.getSelectionModel().clearSelection(); + } + if (moduleComboBox != null) { + moduleComboBox.getSelectionModel().clearSelection(); + } + if (languageComboBox != null) { + languageComboBox.getSelectionModel().clearSelection(); + } + } + + @Override + public void cleanup() { + + } + + @FXML + protected void handleCancel() { + onCancel(); + } + + @FXML + protected void handleSubmit() { + // Common validation logic + //if (!validateForm()) { + // return; + //} + onSubmit(); + } + + protected abstract void onCancel(); + protected abstract void onSubmit(); + + private String getDisplayText(ConceptEntity conceptEntity) { + Optional stringOptional = getViewProperties().calculator().getRegularDescriptionText(conceptEntity.nid()); + return stringOptional.orElse(""); + } + + protected void setupComboBoxAdd(ComboBox comboBox, InvalidationListener listener) { + comboBox.setConverter(new StringConverter() { + + @Override + public String toString(ConceptEntity conceptEntity) { + return getDisplayText(conceptEntity); + } + + @Override + public ConceptEntity fromString(String string) { + return null; + } + }); + + comboBox.setCellFactory(new Callback<>() { + + /** + * @param param The single argument upon which the returned value should be + * determined. + * @return + */ + @Override + public ListCell call(Object param) { + return new ListCell<>(){ + @Override + protected void updateItem(ConceptEntity conceptEntity, boolean b) { + super.updateItem(conceptEntity, b); + if (conceptEntity != null) { + setText(getDisplayText(conceptEntity)); + } else { + setText(null); + } + + } + }; + } + }); + // register invalidation listener + comboBox.getSelectionModel().selectedItemProperty().addListener(listener); + + } + + protected void setupComboBoxEdit(ComboBox comboBox, Collection conceptEntities) { + + comboBox.getItems().clear(); + comboBox.setConverter(new StringConverter() { + + @Override + public String toString(ConceptEntity conceptEntity) { + return getDisplayText(conceptEntity); + } + + @Override + public ConceptEntity fromString(String string) { + return null; + } + }); + + comboBox.setCellFactory(new Callback<>() { + + /** + * @param param The single argument upon which the returned value should be + * determined. + * @return + */ + @Override + public ListCell call(Object param) { + return new ListCell<>(){ + @Override + protected void updateItem(ConceptEntity conceptEntity, boolean b) { + super.updateItem(conceptEntity, b); + if (conceptEntity != null) { + setText(getDisplayText(conceptEntity)); + } else { + setText(null); + } + + } + }; + } + }); + comboBox.getItems().addAll(conceptEntities); + } + + boolean isFormPopulated() { // 1 AddOther used + return (nameTextField.getText() != null && !nameTextField.getText().isEmpty()) + && (moduleComboBox.getSelectionModel().getSelectedItem() != null) + && (statusComboBox.getSelectionModel().getSelectedItem() != null) + && (caseSignificanceComboBox.getSelectionModel().getSelectedItem() != null) + && (languageComboBox.getSelectionModel().getSelectedItem() != null); + } + + protected void populateDialectComboBoxes() { + // currently no UNACCEPTABLE in TinkarTerm + Entity acceptable = EntityService.get().getEntityFast(TinkarTerm.ACCEPTABLE); + Entity preferred = EntityService.get().getEntityFast(TinkarTerm.PREFERRED); + + // each combo box has a separate list instance + setupComboBoxEdit(dialectComboBox1, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); + dialectComboBox1.getSelectionModel().select(Entity.getFast(acceptable.nid())); + setupComboBoxEdit(dialectComboBox2, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); + dialectComboBox2.getSelectionModel().select(Entity.getFast(preferred.nid())); + setupComboBoxEdit(dialectComboBox3, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); + dialectComboBox3.getSelectionModel().select(Entity.getFast(preferred.nid())); + } + + protected void validateForm() { + boolean isFqnTextEmpty = nameTextField.getText().trim().isEmpty(); + boolean isModuleComboBoxSelected = moduleComboBox.getValue() != null; + boolean isCaseSignificanceComboBoxSelected = caseSignificanceComboBox.getValue() != null; + boolean isStatusComboBoxComboBoxSelected = statusComboBox.getValue() != null; + boolean isLanguageComboBoxComboBoxSelected = languageComboBox.getValue() != null; + + submitButton.setDisable( + isFqnTextEmpty || !isModuleComboBoxSelected + || !isCaseSignificanceComboBoxSelected || !isLanguageComboBoxComboBoxSelected + || !isStatusComboBoxComboBoxSelected); + } + + + protected void close(Button button) { + // close the properties bump out + eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(button, + ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); + } + + protected void configureDialectVisibility(boolean showDialects) { + + if (dialectsContainer != null) { + dialectsContainer.setVisible(showDialects); + dialectsContainer.setManaged(showDialects); + + // Adjust BorderPane minimum height based on dialect visibility + BorderPane rootPane = (BorderPane) dialectsContainer.getParent().getParent(); // Adjust path as needed + if (showDialects) { // Height with dialects + rootPane.setMinHeight(670.0); + rootPane.setPrefWidth(670.0); + } else { // Height without dialects + rootPane.setMinHeight(450.0); + rootPane.setPrefWidth(450.0); + } + } + // Also hide the row constraints for dialects + if (dialectRowConstraints != null) { + dialectRowConstraints.setMaxHeight(showDialects ? Region.USE_COMPUTED_SIZE : 0); + dialectRowConstraints.setMinHeight(showDialects ? Region.USE_COMPUTED_SIZE : 0); + dialectRowConstraints.setPrefHeight(showDialects ? Region.USE_COMPUTED_SIZE : 0); + } + + + } + + + +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditFqnController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditFqnController.java new file mode 100644 index 000000000..e58cb4f32 --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditFqnController.java @@ -0,0 +1,243 @@ +package dev.ikm.komet.kview.mvvm.view.properties; + +import dev.ikm.komet.framework.view.ViewProperties; +import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; +import dev.ikm.komet.kview.events.CreateConceptEvent; +import dev.ikm.komet.kview.events.EditConceptEvent; +import dev.ikm.komet.kview.mvvm.model.DescrName; +import dev.ikm.komet.kview.mvvm.model.DescriptionFormType; +import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel; +import dev.ikm.tinkar.common.id.IntIdSet; +import dev.ikm.tinkar.common.id.PublicId; +import dev.ikm.tinkar.coordinate.stamp.calculator.Latest; +import dev.ikm.tinkar.coordinate.view.calculator.ViewCalculator; +import dev.ikm.tinkar.entity.*; +import dev.ikm.tinkar.terms.ConceptFacade; +import dev.ikm.tinkar.terms.EntityFacade; +import dev.ikm.tinkar.terms.TinkarTerm; +import javafx.beans.InvalidationListener; +import org.carlfx.cognitive.loader.InjectViewModel; +import org.carlfx.cognitive.viewmodel.ViewModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.*; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.STATUS; +import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_CASE_SIGNIFICANCE; +import static dev.ikm.tinkar.terms.TinkarTerm.LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION; + +public class DescriptionEditFqnController extends DescriptionBaseController{ + + private static final Logger LOG = LoggerFactory.getLogger(DescriptionEditFqnController.class); + + + @InjectViewModel + private DescrNameViewModel fqnViewModel; + + public DescriptionEditFqnController(UUID conceptTopic) { + super(DescriptionFormType.EDIT_FQN, conceptTopic); + } + + + @Override + protected void initializeData() { + titleLabel.setText("Edit Description: Fully Qualified Name"); + configureDialectVisibility(true); + populateDialectComboBoxes(); + + fqnViewModel.setPropertyValue(NAME_TYPE, TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE); + + // bind with viewmodel. + nameTextField.textProperty().bindBidirectional(fqnViewModel.getProperty(NAME_TEXT)); + moduleComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(MODULE)); + caseSignificanceComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(CASE_SIGNIFICANCE)); + statusComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(STATUS)); + languageComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(LANGUAGE)); + + InvalidationListener invalidationListener = obs -> validateForm(); + + nameTextField.textProperty().addListener(invalidationListener); + moduleComboBox.valueProperty().addListener(invalidationListener); + caseSignificanceComboBox.valueProperty().addListener(invalidationListener); + statusComboBox.valueProperty().addListener(invalidationListener); + languageComboBox.valueProperty().addListener(invalidationListener); + + validateForm(); + // submitButton.setOnAction(onSubmit); // this is already linked in the fxml not sure why ? + + } + + @Override + protected void onCancel() { + close(cancelButton); + } + + @Override + protected void onSubmit() { + fqnViewModel.save(); + // validate + if (fqnViewModel.hasErrorMsgs()) { + fqnViewModel.getValidationMessages().stream().forEach(msg -> LOG.error("Validation error " + msg)); + return; + } + fqnViewModel.setPropertyValue(IS_SUBMITTED, true); + + DescrName fqnDescrName = fqnViewModel.create(); + + + if(this.publicId != null) { + // delegate the transaction logic to the view model + fqnViewModel.updateFullyQualifiedName(this.publicId); + }else{ + // Concept is edited before the transaction is saved. Hence the pubicId would not be generated. + eventBus.publish(conceptTopic, new CreateConceptEvent(this, CreateConceptEvent.ADD_FQN, fqnDescrName)); + } + + LOG.info("transaction complete"); + clearView(); + + // publish the event of the updated FQN + eventBus.publish(conceptTopic, new EditConceptEvent(submitButton, + EditConceptEvent.EDIT_FQN, fqnDescrName)); + + // close the property bump out panel + eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(submitButton, + ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); + } + + @Override + public DescrNameViewModel getViewModel() { + return fqnViewModel; + } + + @Override + public void updateView() { + + } + + @Override + public void clearView() { + nameTextField.setText(""); + caseSignificanceComboBox.getSelectionModel().clearSelection(); + statusComboBox.getSelectionModel().clearSelection(); + moduleComboBox.getSelectionModel().clearSelection(); + languageComboBox.getSelectionModel().clearSelection(); + } + + /** + * This method prepopulates and sets up the form in edit mode. + * @param descrName model values that need to be prepopulated. + */ + public void setConceptAndPopulateForm(DescrName descrName) { + setupComboBoxEdit(moduleComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.MODULE.publicId())); + setupComboBoxEdit(statusComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.STATUS_VALUE.publicId())); + setupComboBoxEdit(caseSignificanceComboBox, fqnViewModel.findAllCaseSignificants(getViewProperties())); + setupComboBoxEdit(languageComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.LANGUAGE.publicId())); + fqnViewModel.setPropertyValue(NAME_TEXT, descrName.getNameText()) + .setPropertyValue(CASE_SIGNIFICANCE, descrName.getCaseSignificance()) + .setPropertyValue(STATUS, descrName.getStatus()) + .setPropertyValue(MODULE, descrName.getModule()) + .setPropertyValue(LANGUAGE, descrName.getLanguage()); + } + + public void setConceptAndPopulateForm(PublicId publicId) { + this.publicId = publicId; + + ViewCalculator viewCalculator = viewProperties.calculator(); + + int nid = EntityService.get().nidForPublicId(publicId); + + // this is the Other Name + Latest latestEntityVersion = viewCalculator.latest(nid); + latestEntityVersion.ifPresent(semanticEntityVersion -> { + StampEntity stampEntity = latestEntityVersion.get().stamp(); + String otherName = viewCalculator.getDescriptionText(nid).get(); + this.nameTextField.setText(otherName); + + // get all descendant modules + IntIdSet moduleDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.MODULE.nid()); + Set allModules = + moduleDescendents.intStream() + .mapToObj(moduleNid -> (ConceptEntity) Entity.getFast(moduleNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(moduleComboBox, allModules); + + // populate the current module and select it (e.g. 'SNOMED CT core module') + findByNid(moduleComboBox.getItems(), stampEntity.moduleNid()) + .ifPresent(concept -> fqnViewModel.setPropertyValue(MODULE, concept)); + + // get all statuses + IntIdSet statusDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.STATUS_VALUE.nid()); + Set allStatuses = statusDescendents.intStream() + .mapToObj(statusNid -> (ConceptEntity) Entity.getFast(statusNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(statusComboBox, allStatuses); + + // populate the current status (ACTIVE | INACTIVE) and select it + findByNid(statusComboBox.getItems(), stampEntity.stateNid()) + .ifPresent(concept -> fqnViewModel.setPropertyValue(STATUS, concept)); + + + // populate all case significance choices + IntIdSet caseSenseDescendents = viewProperties.parentView().calculator().descendentsOf(DESCRIPTION_CASE_SIGNIFICANCE.nid()); + Set allCaseDescendents = caseSenseDescendents.intStream() + .mapToObj(caseNid -> (ConceptEntity) Entity.getFast(caseNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(caseSignificanceComboBox, allCaseDescendents); + + // get case concept's case sensitivity (e.g. 'Case insensitive') + PatternEntity patternEntity = latestEntityVersion.get().pattern(); + PatternEntityVersion patternEntityVersion = viewCalculator.latest(patternEntity).get(); + int indexCaseSig = patternEntityVersion.indexForMeaning(DESCRIPTION_CASE_SIGNIFICANCE); + ConceptFacade caseSigConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexCaseSig); + findByNid(caseSignificanceComboBox.getItems(), caseSigConceptFacade.nid()) + .ifPresent(concept -> fqnViewModel.setPropertyValue(CASE_SIGNIFICANCE, concept)); + + + // get all available languages + IntIdSet languageDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.LANGUAGE.nid()); + Set allLangs = languageDescendents.intStream() + .mapToObj(langNid -> (ConceptEntity) Entity.getFast(langNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(languageComboBox, allLangs); + + // get the language (e.g. 'English language') + int indexLang = patternEntityVersion.indexForMeaning(LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION); + ConceptFacade langConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexLang); + + findByNid(languageComboBox.getItems(), langConceptFacade.nid()) + .ifPresent(concept -> fqnViewModel.setPropertyValue(LANGUAGE, concept)); + + //initial state of edit screen, the submit button should be disabled + submitButton.setDisable(true); + + LOG.info(publicId.toString()); + + }); + } + + private Optional findByNid(List items, int nid) { + + Optional conceptOption = items.stream().parallel() + .filter(item -> (item.nid() == nid)).findAny(); + + return conceptOption; + } + + public void updateModel(final ViewProperties viewProperties, EntityFacade entityFacade) { + this.viewProperties = viewProperties; + this.entityFacade = entityFacade; + } + + + +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditOtherController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditOtherController.java new file mode 100644 index 000000000..f868bffa4 --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/DescriptionEditOtherController.java @@ -0,0 +1,231 @@ +package dev.ikm.komet.kview.mvvm.view.properties; + +import dev.ikm.komet.framework.view.ViewProperties; +import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; +import dev.ikm.komet.kview.events.CreateConceptEvent; +import dev.ikm.komet.kview.mvvm.model.DescrName; +import dev.ikm.komet.kview.mvvm.model.DescriptionFormType; +import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel; +import dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel; +import dev.ikm.tinkar.common.id.IntIdSet; +import dev.ikm.tinkar.common.id.PublicId; +import dev.ikm.tinkar.coordinate.stamp.calculator.Latest; +import dev.ikm.tinkar.coordinate.view.calculator.ViewCalculator; +import dev.ikm.tinkar.entity.*; +import dev.ikm.tinkar.terms.ConceptFacade; +import dev.ikm.tinkar.terms.EntityFacade; +import dev.ikm.tinkar.terms.TinkarTerm; +import javafx.beans.InvalidationListener; +import org.carlfx.cognitive.loader.InjectViewModel; +import org.carlfx.cognitive.viewmodel.ViewModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.*; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; +import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.STATUS; +import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_CASE_SIGNIFICANCE; +import static dev.ikm.tinkar.terms.TinkarTerm.LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION; + +public class DescriptionEditOtherController extends DescriptionBaseController{ + private static final Logger LOG = LoggerFactory.getLogger(DescriptionEditOtherController.class); + + @InjectViewModel + private DescrNameViewModel otherNameViewModel; + + private DescrName editDescrName; + + public DescriptionEditOtherController(UUID conceptTopic) { + super(DescriptionFormType.EDIT_OTHER_NAME, conceptTopic); + } + @Override + protected void initializeData() { + + configureDialectVisibility(true); + + otherNameViewModel + .setPropertyValue(NAME_TYPE, TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE) + .setPropertyValue(STATUS, TinkarTerm.ACTIVE_STATE); + + populateDialectComboBoxes(); + + // bind with viewmodel. + nameTextField.textProperty().bindBidirectional(otherNameViewModel.getProperty(NAME_TEXT)); + moduleComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(MODULE)); + caseSignificanceComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(CASE_SIGNIFICANCE)); + statusComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(STATUS)); + languageComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(LANGUAGE)); + + InvalidationListener invalidationListener = obs -> validateForm(); + + nameTextField.textProperty().addListener(invalidationListener); + moduleComboBox.valueProperty().addListener(invalidationListener); + caseSignificanceComboBox.valueProperty().addListener(invalidationListener); + statusComboBox.valueProperty().addListener(invalidationListener); + languageComboBox.valueProperty().addListener(invalidationListener); + validateForm(); + + } + + @Override + protected void onCancel() { + close(cancelButton); + } + + @Override + protected void onSubmit() { + otherNameViewModel.save(); + + if (!otherNameViewModel.hasNoErrorMsgs()) { + otherNameViewModel.getValidationMessages().stream().forEach(msg -> LOG.error("Validation error " + msg)); + return; + } + + otherNameViewModel.setPropertyValue(IS_SUBMITTED, true); + + + LOG.info("Ready to update to the concept view model: " + otherNameViewModel); + + if(this.publicId != null) { //This if blocked is called when editing the exiting concept. + otherNameViewModel.updateOtherName(this.publicId); + }else{ // This block is called when editing the while creating the concept. + otherNameViewModel.updateData(editDescrName); + eventBus.publish(conceptTopic, new CreateConceptEvent(this, + CreateConceptEvent.EDIT_OTHER_NAME, editDescrName)); + } + eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(submitButton, + ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); + } + + @Override + public DescrNameViewModel getViewModel() { // TODO why diverge here from DescriptionAddOtherController with return type + return otherNameViewModel; + } + + @Override + public void updateView() { + + } + + @Override + public void clearView() { + caseSignificanceComboBox.getItems().clear(); + statusComboBox.getItems().clear(); + moduleComboBox.getItems().clear(); + languageComboBox.getItems().clear(); + } + + public void updateModel(final ViewProperties viewProperties, EntityFacade entityFacade) { + this.viewProperties = viewProperties; + this.entityFacade = entityFacade; + } + + /** + * This method prepopulates and sets up the form in edit mode. + * @param descrName model values that need to be prepopulated. + */ + public void setConceptAndPopulateForm(DescrName descrName) { + editDescrName = descrName; + setupComboBoxEdit(moduleComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.MODULE.publicId())); + setupComboBoxEdit(statusComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.STATUS_VALUE.publicId())); + setupComboBoxEdit(caseSignificanceComboBox, otherNameViewModel.findAllCaseSignificants(getViewProperties())); + setupComboBoxEdit(languageComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.LANGUAGE.publicId())); + otherNameViewModel.setPropertyValue(NAME_TEXT, descrName.getNameText()) + .setPropertyValue(CASE_SIGNIFICANCE, descrName.getCaseSignificance()) + .setPropertyValue(STATUS, descrName.getStatus()) + .setPropertyValue(MODULE, descrName.getModule()) + .setPropertyValue(LANGUAGE, descrName.getLanguage()); + } + + public void setConceptAndPopulateForm(PublicId publicId) { + editDescrName = null; + this.publicId = publicId; + ViewCalculator viewCalculator = viewProperties.calculator(); + int nid = EntityService.get().nidForPublicId(publicId); + + // this is the Other Name + Latest latestEntityVersion = viewCalculator.latest(nid); + latestEntityVersion.ifPresent(semanticEntityVersion -> { + StampEntity stampEntity = latestEntityVersion.get().stamp(); + + // populate the other name text field (e.g. 'Chronic lung disease') + String otherName = viewCalculator.getDescriptionText(nid).get(); + this.nameTextField.setText(otherName); + + Entity moduleEntity = EntityService.get().getEntityFast(TinkarTerm.MODULE); + IntIdSet moduleDescendents = viewProperties.parentView().calculator().descendentsOf(moduleEntity.nid()); + + // get all descendant modules + Set allModules = + moduleDescendents.intStream() + .mapToObj(moduleNid -> (ConceptEntity) Entity.getFast(moduleNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(moduleComboBox, allModules); + + // populate the current module and select it (e.g. 'SNOMED CT core module') + findByNid(moduleComboBox.getItems(), stampEntity.moduleNid()) + .ifPresent(concept -> otherNameViewModel.setPropertyValue(MODULE, concept)); + + // get all statuses + IntIdSet statusDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.STATUS_VALUE.nid()); + Set allStatuses = statusDescendents.intStream() + .mapToObj(statusNid -> (ConceptEntity) Entity.getFast(statusNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(statusComboBox, allStatuses); + + // populate the current status (ACTIVE | INACTIVE) and select it + findByNid(statusComboBox.getItems(), stampEntity.stateNid()) + .ifPresent(concept -> otherNameViewModel.setPropertyValue(STATUS, concept)); + + // populate all case significance choices + IntIdSet caseSenseDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.DESCRIPTION_CASE_SIGNIFICANCE.nid()); + Set allCaseDescendents = caseSenseDescendents.intStream() + .mapToObj(caseNid -> (ConceptEntity) Entity.getFast(caseNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(caseSignificanceComboBox, allCaseDescendents); + + // get case concept's case sensitivity (e.g. 'Case insensitive') + PatternEntity patternEntity = latestEntityVersion.get().pattern(); + PatternEntityVersion patternEntityVersion = viewCalculator.latest(patternEntity).get(); + int indexCaseSig = patternEntityVersion.indexForMeaning(DESCRIPTION_CASE_SIGNIFICANCE); + EntityFacade caseSigConceptFacade = (EntityFacade) latestEntityVersion.get().fieldValues().get(indexCaseSig); + findByNid(caseSignificanceComboBox.getItems(), caseSigConceptFacade.nid()) + .ifPresent(concept -> otherNameViewModel.setPropertyValue(CASE_SIGNIFICANCE, concept)); + + // get all available languages + IntIdSet languageDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.LANGUAGE.nid()); + Set allLangs = languageDescendents.intStream() + .mapToObj(langNid -> (ConceptEntity) Entity.getFast(langNid)) + .collect(Collectors.toSet()); + setupComboBoxEdit(languageComboBox, allLangs); + + // get the language (e.g. 'English language') + int indexLang = patternEntityVersion.indexForMeaning(LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION); + ConceptFacade langConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexLang); + findByNid(languageComboBox.getItems(), langConceptFacade.nid()) + .ifPresent(concept -> otherNameViewModel.setPropertyValue(LANGUAGE, concept)); + + //initial state of edit screen, the submit button should be disabled + submitButton.setDisable(true); + + LOG.info(publicId.toString()); + }); + } + + private Optional findByNid(List items, int nid) { + + Optional conceptOption = items.stream().parallel() + .filter(item -> (item.nid() == nid)).findAny(); + + return conceptOption; + } +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionFormController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionFormController.java index f2d08ff25..2cf00ccb4 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionFormController.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionFormController.java @@ -170,6 +170,7 @@ public void initialize() { statusComboBox.valueProperty().addListener(invalidationListener); languageComboBox.valueProperty().addListener(invalidationListener); validateForm(); + } @FXML @@ -187,6 +188,7 @@ private boolean isFormPopulated() { } private void validateForm() { + LOG.info("old validate form? EditDescriptionFormController"); boolean isOtherNameTextFieldEmpty = otherNameTextField.getText().trim().isEmpty(); boolean isModuleComboBoxSelected = moduleComboBox.getValue() != null; boolean isCaseSignificanceComboBoxSelected = caseSignificanceComboBox.getValue() != null; @@ -199,7 +201,9 @@ private void validateForm() { || !isStatusComboBoxComboBoxSelected); } - private void populateDialectComboBoxes() { + private void populateDialectComboBoxes() { + + LOG.info("populateDialectComboBoxes? EditDescriptionFormController"); // currently no UNACCEPTABLE in TinkarTerm Entity acceptable = EntityService.get().getEntityFast(TinkarTerm.ACCEPTABLE); Entity preferred = EntityService.get().getEntityFast(TinkarTerm.PREFERRED); @@ -214,16 +218,18 @@ private void populateDialectComboBoxes() { } public void setEditDescriptionTitleLabel(String addAxiomTitleLabelText) { + LOG.info("setEditDescriptionTitleLabel? EditDescriptionFormController"); this.editDescriptionTitleLabel.setText(addAxiomTitleLabelText); } @Override public void updateView() { - + LOG.info("updateView? EditDescriptionFormController"); } @Override public void clearView() { + LOG.info("clearView? EditDescriptionFormController"); caseSignificanceComboBox.getItems().clear(); statusComboBox.getItems().clear(); moduleComboBox.getItems().clear(); @@ -232,10 +238,11 @@ public void clearView() { @Override public void cleanup() { - + LOG.info("cleanup? EditDescriptionFormController"); } public void updateModel(final ViewProperties viewProperties, EntityFacade entityFacade) { + LOG.info("updateModel? EditDescriptionFormController"); this.viewProperties = viewProperties; this.entityFacade = entityFacade; } @@ -245,6 +252,7 @@ private ViewProperties getViewProperties() { } private String getDisplayText(ConceptEntity conceptEntity) { + LOG.info("getDisplayText? EditDescriptionFormController"); if (conceptEntity != null) { Optional stringOptional = getViewProperties().calculator().getRegularDescriptionText(conceptEntity.nid()); return stringOptional.orElse(""); @@ -254,6 +262,7 @@ private String getDisplayText(ConceptEntity conceptEntity) { } private void setupComboBox(ComboBox comboBox, Collection conceptEntities) { + LOG.info("setupComboBox? EditDescriptionFormController"); comboBox.getItems().clear(); comboBox.setConverter(new StringConverter() { diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/PropertiesController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/PropertiesController.java index 3c5dc53e2..fe6b0fee2 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/PropertiesController.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/PropertiesController.java @@ -67,6 +67,9 @@ public class PropertiesController implements Serializable { protected static final String ADD_FQN_FXML_FILE = "add-fully-qualified-name.fxml"; + // used in conjunction with all child's of DescriptionBaseController + protected static final String DESCRIPTION_FORM_FXML_FILE = "description-form.fxml"; + @FXML private SVGPath commentsButton; @@ -109,15 +112,16 @@ public class PropertiesController implements Serializable { private EditConceptController editConceptController; - private AddOtherNameController addOtherNameController; + private EditDescriptionsController editDescriptionsController; + + private DescriptionAddOtherController addOtherNameController; - private EditDescriptionFormController editDescriptionFormController; + private DescriptionEditOtherController editDescriptionFormController; - private EditDescriptionsController editDescriptionsController; + private DescriptionEditFqnController editFullyQualifiedNameController; - private EditFullyQualifiedNameController editFullyQualifiedNameController; + private DescriptionAddFqnController addFullyQualifiedNameController; - private AddFullyQualifiedNameController addFullyQualifiedNameController; private Pane commentsPane = new StackPane(genText("Comments Pane")); private ViewProperties viewProperties; @@ -192,34 +196,38 @@ public void initialize() throws IOException { editDescriptionsController = loaderEditDescriptions.getController(); // NOTE: New way of using injected View Models inside of Controllers. - JFXNode addOtherNameControllerNode = FXMLMvvmLoader.make( - getClass().getResource(ADD_OTHER_NAME_FXML_FILE), - new AddOtherNameController(conceptTopic)); + JFXNode addOtherNameControllerNode = FXMLMvvmLoader.make( + getClass().getResource(DESCRIPTION_FORM_FXML_FILE), + new DescriptionAddOtherController(conceptTopic)); addOtherNamePane = addOtherNameControllerNode.node(); addOtherNameController = addOtherNameControllerNode.controller(); - JFXNode editDescriptionFormControllerNode = FXMLMvvmLoader.make( - getClass().getResource(EDIT_OTHER_NAME_FXML_FILE), - new EditDescriptionFormController(conceptTopic)); + + + JFXNode editDescriptionFormControllerNode = FXMLMvvmLoader.make( + getClass().getResource(DESCRIPTION_FORM_FXML_FILE), + new DescriptionEditOtherController(conceptTopic)); editOtherNamePane = editDescriptionFormControllerNode.node(); editDescriptionFormController = editDescriptionFormControllerNode.controller(); //TODO for future there will be an edit axiom form - JFXNode editFqnControllerNode = FXMLMvvmLoader.make( - getClass().getResource(EDIT_FQN_FXML_FILE), - new EditFullyQualifiedNameController(conceptTopic) + JFXNode addFqnControllerNode = FXMLMvvmLoader.make( + getClass().getResource(DESCRIPTION_FORM_FXML_FILE), + new DescriptionAddFqnController(conceptTopic)); + addFqnPane = addFqnControllerNode.node(); + addFullyQualifiedNameController = addFqnControllerNode.controller(); + + + + JFXNode editFqnControllerNode = FXMLMvvmLoader.make( + getClass().getResource(DESCRIPTION_FORM_FXML_FILE), + new DescriptionEditFqnController(conceptTopic) ); editFqnPane = editFqnControllerNode.node(); editFullyQualifiedNameController = editFqnControllerNode.controller(); - // NOTE: New way of using injected View Models inside of Controllers. - JFXNode addFqnControllerNode = FXMLMvvmLoader.make( - getClass().getResource(ADD_FQN_FXML_FILE), - new AddFullyQualifiedNameController(conceptTopic)); - addFqnPane = addFqnControllerNode.node(); - addFullyQualifiedNameController = addFqnControllerNode.controller(); // initially a default selected tab and view is shown updateDefaultSelectedViews(); @@ -300,7 +308,7 @@ public void initialize() throws IOException { } // check if the center pane is already showing, we don't want duplicate entries in the dropdowns if (!contentBorderPane.getCenter().equals(editFqnPane)) { - editFullyQualifiedNameController.updateModel(getViewProperties(), null); + editFullyQualifiedNameController.updateModel(getViewProperties()); // TODO check if this change was correct contentBorderPane.setCenter(editFqnPane); editButton.setSelected(true); editButton.setText("EDIT"); diff --git a/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/properties/description-form.fxml b/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/properties/description-form.fxml new file mode 100644 index 000000000..74cb7585f --- /dev/null +++ b/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/properties/description-form.fxml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +