Java tutorial
/** * Copyright Notice * * This is a work of the U.S. Government and is not subject to copyright * protection in the United States. Foreign copyrights may apply. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package gov.va.isaac.gui.refexViews.refexEdit; import java.util.ArrayList; import java.util.Set; import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.glassfish.hk2.api.PerLookup; import org.glassfish.hk2.runlevel.RunLevelException; import org.jvnet.hk2.annotations.Service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sun.javafx.collections.ObservableListWrapper; import gov.va.isaac.AppContext; import gov.va.isaac.ExtendedAppContext; import gov.va.isaac.gui.ConceptNode; import gov.va.isaac.gui.SimpleDisplayConcept; import gov.va.isaac.gui.dragAndDrop.DragRegistry; import gov.va.isaac.gui.refexViews.util.SememeGUIDataTypeFXNodeBuilder; import gov.va.isaac.gui.refexViews.util.SememeGUIDataTypeNodeDetails; import gov.va.isaac.gui.util.CopyableLabel; import gov.va.isaac.gui.util.ErrorMarkerUtils; import gov.va.isaac.gui.util.FxUtils; import gov.va.isaac.gui.util.Images; import gov.va.isaac.interfaces.gui.views.PopupViewI; import gov.va.isaac.util.CommonlyUsedConcepts; import gov.va.isaac.util.OchreUtility; import gov.va.isaac.util.UpdateableBooleanBinding; import gov.va.isaac.util.Utility; import gov.va.isaac.util.ValidBooleanBinding; import gov.vha.isaac.metadata.coordinates.EditCoordinates; import gov.vha.isaac.ochre.api.Get; import gov.vha.isaac.ochre.api.State; import gov.vha.isaac.ochre.api.chronicle.ObjectChronologyType; import gov.vha.isaac.ochre.api.commit.ChangeCheckerMode; import gov.vha.isaac.ochre.api.component.concept.ConceptSnapshot; import gov.vha.isaac.ochre.api.component.sememe.SememeChronology; import gov.vha.isaac.ochre.api.component.sememe.SememeType; import gov.vha.isaac.ochre.api.component.sememe.version.DynamicSememe; import gov.vha.isaac.ochre.api.component.sememe.version.SememeVersion; import gov.vha.isaac.ochre.api.component.sememe.version.dynamicSememe.DynamicSememeColumnInfo; import gov.vha.isaac.ochre.api.component.sememe.version.dynamicSememe.DynamicSememeDataBI; import gov.vha.isaac.ochre.api.component.sememe.version.dynamicSememe.DynamicSememeDataType; import gov.vha.isaac.ochre.api.component.sememe.version.dynamicSememe.DynamicSememeUsageDescriptionBI; import gov.vha.isaac.ochre.api.component.sememe.version.dynamicSememe.DynamicSememeValidatorType; import gov.vha.isaac.ochre.impl.sememe.DynamicSememeUsageDescription; import gov.vha.isaac.ochre.model.constants.IsaacMetadataConstants; import gov.vha.isaac.ochre.model.sememe.dataTypes.DynamicSememeData; import gov.vha.isaac.ochre.model.sememe.dataTypes.DynamicSememeNid; import gov.vha.isaac.ochre.model.sememe.dataTypes.DynamicSememeString; import gov.vha.isaac.ochre.model.sememe.dataTypes.DynamicSememeUUID; import gov.vha.isaac.ochre.model.sememe.version.DynamicSememeImpl; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.TextField; import javafx.scene.control.Tooltip; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.StageStyle; import javafx.stage.Window; import javafx.util.StringConverter; /** * * Refset View * * @author <a href="mailto:daniel.armbrust.list@gmail.com">Dan Armbrust</a> */ @Service @PerLookup public class AddSememePopup extends Stage implements PopupViewI { private SememeView callingView_; private ViewFocus createRefexFocus_; private int focusNid_; private SememeGUI editRefex_; private Label unselectableComponentLabel_;; private ScrollPane sp_; //TODO (artf231426) improve 'ConceptNode' - this mess of Conceptnode or TextField will work for now, if they set a component type restriction //But if they don't set a component type restriction, we still need the field (conceptNode) to allow nids or UUIDs of other types of things. //both here, and in the GUI that creates the sememe - when specifying the default value. private ConceptNode selectableConcept_; private StackPane selectableComponentNode_; private ValidBooleanBinding selectableComponentNodeValid_; private TextField selectableComponent_; private boolean conceptNodeIsConceptType_ = false; private DynamicSememeUsageDescriptionBI assemblageInfo_; private SimpleBooleanProperty assemblageIsValid_ = new SimpleBooleanProperty(false); private Logger logger_ = LoggerFactory.getLogger(this.getClass()); private UpdateableBooleanBinding allValid_; private ArrayList<ReadOnlyStringProperty> currentDataFieldWarnings_ = new ArrayList<>(); private ArrayList<SememeGUIDataTypeNodeDetails> currentDataFields_ = new ArrayList<>(); private ObservableList<SimpleDisplayConcept> refexDropDownOptions = FXCollections.observableArrayList(); private GridPane gp_; private Label title_; private SememeType st_; private AddSememePopup() { super(); BorderPane root = new BorderPane(); VBox topItems = new VBox(); topItems.setFillWidth(true); title_ = new Label("Create new sememe instance"); title_.getStyleClass().add("titleLabel"); title_.setAlignment(Pos.CENTER); title_.prefWidthProperty().bind(topItems.widthProperty()); topItems.getChildren().add(title_); VBox.setMargin(title_, new Insets(10, 10, 10, 10)); gp_ = new GridPane(); gp_.setHgap(10.0); gp_.setVgap(10.0); VBox.setMargin(gp_, new Insets(5, 5, 5, 5)); topItems.getChildren().add(gp_); Label referencedComponent = new Label("Referenced Component"); referencedComponent.getStyleClass().add("boldLabel"); gp_.add(referencedComponent, 0, 0); unselectableComponentLabel_ = new CopyableLabel(); unselectableComponentLabel_.setWrapText(true); AppContext.getService(DragRegistry.class).setupDragOnly(unselectableComponentLabel_, () -> { if (editRefex_ == null) { return focusNid_ + ""; } else { return Get.identifierService().getConceptNid(editRefex_.getSememe().getAssemblageSequence()) + ""; } }); //delay adding till we know which row Label assemblageConceptLabel = new Label("Assemblage Concept"); assemblageConceptLabel.getStyleClass().add("boldLabel"); gp_.add(assemblageConceptLabel, 0, 1); selectableConcept_ = new ConceptNode(null, true, refexDropDownOptions, null); selectableConcept_.getConceptProperty().addListener(new ChangeListener<ConceptSnapshot>() { @Override public void changed(ObservableValue<? extends ConceptSnapshot> observable, ConceptSnapshot oldValue, ConceptSnapshot newValue) { if (createRefexFocus_ != null && createRefexFocus_ == ViewFocus.REFERENCED_COMPONENT) { if (selectableConcept_.isValid().get()) { //Its a valid concept, but is it a valid assemblage concept? try { assemblageInfo_ = DynamicSememeUsageDescription .read(selectableConcept_.getConceptNoWait().getNid()); assemblageIsValid_.set(true); if (assemblageInfo_.getReferencedComponentTypeRestriction() != null) { String result = DynamicSememeValidatorType.COMPONENT_TYPE .passesValidatorStringReturn(new DynamicSememeNid(focusNid_), new DynamicSememeString(assemblageInfo_ .getReferencedComponentTypeRestriction().name()), null, null); //don't need coordinates for component type validator if (result.length() > 0) { selectableConcept_.isValid() .setInvalid("The selected assemblage requires the component type to be " + assemblageInfo_.getReferencedComponentTypeRestriction() .toString() + ", which doesn't match the referenced component."); logger_.info("The selected assemblage requires the component type to be " + assemblageInfo_.getReferencedComponentTypeRestriction().toString() + ", which doesn't match the referenced component."); assemblageIsValid_.set(false); } } } catch (Exception e) { selectableConcept_.isValid().setInvalid( "The selected concept is not properly constructed for use as an Assemblage concept"); logger_.info("Concept not a valid concept for a sememe assemblage", e); assemblageIsValid_.set(false); } } else { assemblageInfo_ = null; assemblageIsValid_.set(false); } buildDataFields(assemblageIsValid_.get(), null); } } }); selectableComponent_ = new TextField(); selectableComponentNodeValid_ = new ValidBooleanBinding() { { setComputeOnInvalidate(true); bind(selectableComponent_.textProperty()); invalidate(); } @Override protected boolean computeValue() { if (createRefexFocus_ != null && createRefexFocus_ == ViewFocus.ASSEMBLAGE && !conceptNodeIsConceptType_) { //If the assembly nid was what was set - the component node may vary - validate if we are using the text field String value = selectableComponent_.getText().trim(); if (value.length() > 0) { try { if (Utility.isUUID(value)) { String result = DynamicSememeValidatorType.COMPONENT_TYPE .passesValidatorStringReturn(new DynamicSememeUUID(UUID.fromString(value)), new DynamicSememeString(assemblageInfo_ .getReferencedComponentTypeRestriction().name()), null, null); //component type validator doesn't use vc, so null is ok if (result.length() > 0) { setInvalidReason(result); logger_.info(result); return false; } } else if (Utility.isInt(value)) { String result = DynamicSememeValidatorType.COMPONENT_TYPE .passesValidatorStringReturn(new DynamicSememeNid(Integer.parseInt(value)), new DynamicSememeString(assemblageInfo_ .getReferencedComponentTypeRestriction().name()), null, null); //component type validator doesn't use vc, so null is ok if (result.length() > 0) { setInvalidReason(result); logger_.info(result); return false; } } else { setInvalidReason( "Value cannot be parsed as a component identifier. Must be a UUID or a valid NID"); return false; } } catch (Exception e) { logger_.error("Error checking component type validation", e); setInvalidReason("Unexpected error validating entry"); return false; } } else { setInvalidReason("Component identifier is required"); return false; } } clearInvalidReason(); return true; } }; selectableComponentNode_ = ErrorMarkerUtils.setupErrorMarker(selectableComponent_, null, selectableComponentNodeValid_); //delay adding concept / component till we know if / where ColumnConstraints cc = new ColumnConstraints(); cc.setHgrow(Priority.NEVER); cc.setMinWidth(FxUtils.calculateNecessaryWidthOfBoldLabel(referencedComponent)); gp_.getColumnConstraints().add(cc); cc = new ColumnConstraints(); cc.setHgrow(Priority.ALWAYS); gp_.getColumnConstraints().add(cc); Label l = new Label("Data Fields"); l.getStyleClass().add("boldLabel"); VBox.setMargin(l, new Insets(5, 5, 5, 5)); topItems.getChildren().add(l); root.setTop(topItems); sp_ = new ScrollPane(); sp_.visibleProperty().bind(assemblageIsValid_); sp_.setFitToHeight(true); sp_.setFitToWidth(true); root.setCenter(sp_); allValid_ = new UpdateableBooleanBinding() { { addBinding(assemblageIsValid_, selectableConcept_.isValid(), selectableComponentNodeValid_); } @Override protected boolean computeValue() { if (assemblageIsValid_.get() && (conceptNodeIsConceptType_ ? selectableConcept_.isValid().get() : selectableComponentNodeValid_.get())) { boolean allDataValid = true; for (ReadOnlyStringProperty ssp : currentDataFieldWarnings_) { if (ssp.get().length() > 0) { allDataValid = false; break; } } if (allDataValid) { clearInvalidReason(); return true; } } setInvalidReason("All errors must be corrected before save is allowed"); return false; } }; GridPane bottomRow = new GridPane(); //spacer col bottomRow.add(new Region(), 0, 0); Button cancelButton = new Button("Cancel"); cancelButton.setOnAction((action) -> { close(); }); GridPane.setMargin(cancelButton, new Insets(5, 20, 5, 0)); GridPane.setHalignment(cancelButton, HPos.RIGHT); bottomRow.add(cancelButton, 1, 0); Button saveButton = new Button("Save"); saveButton.disableProperty().bind(allValid_.not()); saveButton.setOnAction((action) -> { doSave(); }); Node wrappedSave = ErrorMarkerUtils.setupDisabledInfoMarker(saveButton, allValid_.getReasonWhyInvalid()); GridPane.setMargin(wrappedSave, new Insets(5, 0, 5, 20)); bottomRow.add(wrappedSave, 2, 0); //spacer col bottomRow.add(new Region(), 3, 0); cc = new ColumnConstraints(); cc.setHgrow(Priority.SOMETIMES); cc.setFillWidth(true); bottomRow.getColumnConstraints().add(cc); cc = new ColumnConstraints(); cc.setHgrow(Priority.NEVER); bottomRow.getColumnConstraints().add(cc); cc = new ColumnConstraints(); cc.setHgrow(Priority.NEVER); bottomRow.getColumnConstraints().add(cc); cc = new ColumnConstraints(); cc.setHgrow(Priority.SOMETIMES); cc.setFillWidth(true); bottomRow.getColumnConstraints().add(cc); root.setBottom(bottomRow); Scene scene = new Scene(root); scene.getStylesheets().add(AddSememePopup.class.getResource("/isaac-shared-styles.css").toString()); setScene(scene); } public void finishInit(SememeGUI refexToEdit, SememeView viewToRefresh) { callingView_ = viewToRefresh; createRefexFocus_ = null; editRefex_ = refexToEdit; st_ = refexToEdit.getSememe().getChronology().getSememeType(); title_.setText("Edit existing sememe instance"); gp_.add(unselectableComponentLabel_, 1, 1); unselectableComponentLabel_ .setText(Get.conceptDescriptionText(editRefex_.getSememe().getAssemblageSequence())); //TODO this assuming that the referenced component is a concept, which I don't think is a safe assumption. //don't actually put this in the view selectableConcept_.set(new SimpleDisplayConcept(editRefex_.getSememe().getReferencedComponentNid())); Label refComp = new CopyableLabel( Get.conceptDescriptionText(editRefex_.getSememe().getReferencedComponentNid())); refComp.setWrapText(true); AppContext.getService(DragRegistry.class).setupDragOnly(refComp, () -> { return editRefex_.getSememe().getReferencedComponentNid() + ""; }); gp_.add(refComp, 1, 0); refexDropDownOptions.clear(); try { assemblageInfo_ = DynamicSememeUsageDescription .mockOrRead(((SememeVersion<?>) editRefex_.getSememe()).getChronology()); assemblageIsValid_.set(true); buildDataFields(true, SememeGUI.getData(editRefex_.getSememe())); } catch (Exception e) { logger_.error("Unexpected", e); AppContext.getCommonDialogs().showErrorDialog("Unexpected Error reading Assembly concept", e); } } public void finishInit(ViewFocus viewFocus, int focusNid, SememeView viewToRefresh) { callingView_ = viewToRefresh; createRefexFocus_ = viewFocus; focusNid_ = focusNid; editRefex_ = null; st_ = SememeType.DYNAMIC; //TODO add to the GUI, the option to choose other types title_.setText("Create new sememe instance"); if (createRefexFocus_ == ViewFocus.REFERENCED_COMPONENT) { gp_.add(unselectableComponentLabel_, 1, 0); unselectableComponentLabel_.setText(Get.conceptDescriptionText(focusNid_)); gp_.add(selectableConcept_.getNode(), 1, 1); refexDropDownOptions.clear(); refexDropDownOptions.addAll(buildAssemblageConceptList()); } else { try { assemblageInfo_ = DynamicSememeUsageDescription.read(focusNid_); gp_.add(unselectableComponentLabel_, 1, 1); unselectableComponentLabel_.setText(Get.conceptDescriptionText(focusNid_)); if (assemblageInfo_.getReferencedComponentTypeRestriction() != null && ObjectChronologyType.CONCEPT != assemblageInfo_ .getReferencedComponentTypeRestriction()) { conceptNodeIsConceptType_ = false; gp_.add(selectableComponentNode_, 1, 0); selectableComponent_.setPromptText("UUID or NID of a " + assemblageInfo_.getReferencedComponentTypeRestriction().toString()); selectableComponent_.setTooltip(new Tooltip("UUID or NID of a " + assemblageInfo_.getReferencedComponentTypeRestriction().toString())); selectableComponentNodeValid_.invalidate(); } else { conceptNodeIsConceptType_ = true; gp_.add(selectableConcept_.getNode(), 1, 0); } refexDropDownOptions.clear(); refexDropDownOptions .addAll(AppContext.getService(CommonlyUsedConcepts.class).getObservableConcepts()); assemblageIsValid_.set(true); buildDataFields(true, null); } catch (Exception e) { logger_.error("Unexpected", e); AppContext.getCommonDialogs().showErrorDialog("Unexpected Error reading Assembly concept", e); } } } private void buildDataFields(boolean assemblageValid, DynamicSememeDataBI[] currentValues) { if (assemblageValid) { for (ReadOnlyStringProperty ssp : currentDataFieldWarnings_) { allValid_.removeBinding(ssp); } currentDataFieldWarnings_.clear(); for (SememeGUIDataTypeNodeDetails nd : currentDataFields_) { nd.cleanupListener(); } currentDataFields_.clear(); GridPane gp = new GridPane(); gp.setHgap(10.0); gp.setVgap(10.0); gp.setStyle("-fx-padding: 5;"); int row = 0; boolean extraInfoColumnIsRequired = false; for (DynamicSememeColumnInfo ci : assemblageInfo_.getColumnInfo()) { SimpleStringProperty valueIsRequired = (ci.isColumnRequired() ? new SimpleStringProperty("") : null); SimpleStringProperty defaultValueTooltip = ((ci.getDefaultColumnValue() == null && ci.getValidator() == null) ? null : new SimpleStringProperty()); ComboBox<DynamicSememeDataType> polymorphicType = null; Label l = new Label(ci.getColumnName()); l.getStyleClass().add("boldLabel"); l.setMinWidth(FxUtils.calculateNecessaryWidthOfBoldLabel(l)); Tooltip.install(l, new Tooltip(ci.getColumnDescription())); int col = 0; gp.add(l, col++, row); if (ci.getColumnDataType() == DynamicSememeDataType.POLYMORPHIC) { polymorphicType = new ComboBox<>(); polymorphicType.setEditable(false); polymorphicType.setConverter(new StringConverter<DynamicSememeDataType>() { @Override public String toString(DynamicSememeDataType object) { return object.getDisplayName(); } @Override public DynamicSememeDataType fromString(String string) { throw new RuntimeException("unecessary"); } }); for (DynamicSememeDataType type : DynamicSememeDataType.values()) { if (type == DynamicSememeDataType.POLYMORPHIC || type == DynamicSememeDataType.UNKNOWN) { continue; } else { polymorphicType.getItems().add(type); } } polymorphicType.getSelectionModel() .select((currentValues == null ? DynamicSememeDataType.STRING : (currentValues[row] == null ? DynamicSememeDataType.STRING : currentValues[row].getDynamicSememeDataType()))); } SememeGUIDataTypeNodeDetails nd = SememeGUIDataTypeFXNodeBuilder.buildNodeForType( ci.getColumnDataType(), ci.getDefaultColumnValue(), (currentValues == null ? null : currentValues[row]), valueIsRequired, defaultValueTooltip, (polymorphicType == null ? null : polymorphicType.getSelectionModel().selectedItemProperty()), allValid_, ci.getValidator(), ci.getValidatorData()); currentDataFieldWarnings_.addAll(nd.getBoundToAllValid()); if (ci.getColumnDataType() == DynamicSememeDataType.POLYMORPHIC) { nd.addUpdateParentListListener(currentDataFieldWarnings_); } currentDataFields_.add(nd); gp.add(nd.getNodeForDisplay(), col++, row); Label colType = new Label(ci.getColumnDataType().getDisplayName()); colType.setMinWidth(FxUtils.calculateNecessaryWidthOfLabel(colType)); gp.add((polymorphicType == null ? colType : polymorphicType), col++, row); if (ci.isColumnRequired() || ci.getDefaultColumnValue() != null || ci.getValidator() != null) { extraInfoColumnIsRequired = true; StackPane stackPane = new StackPane(); stackPane.setMaxWidth(Double.MAX_VALUE); if (ci.getDefaultColumnValue() != null || ci.getValidator() != null) { ImageView information = Images.INFORMATION.createImageView(); Tooltip tooltip = new Tooltip(); tooltip.textProperty().bind(defaultValueTooltip); Tooltip.install(information, tooltip); tooltip.setAutoHide(true); information.setOnMouseClicked( event -> tooltip.show(information, event.getScreenX(), event.getScreenY())); stackPane.getChildren().add(information); } if (ci.isColumnRequired()) { ImageView exclamation = Images.EXCLAMATION.createImageView(); final BooleanProperty showExclamation = new SimpleBooleanProperty( StringUtils.isNotBlank(valueIsRequired.get())); valueIsRequired.addListener((ChangeListener<String>) (observable, oldValue, newValue) -> showExclamation.set(StringUtils.isNotBlank(newValue))); exclamation.visibleProperty().bind(showExclamation); Tooltip tooltip = new Tooltip(); tooltip.textProperty().bind(valueIsRequired); Tooltip.install(exclamation, tooltip); tooltip.setAutoHide(true); exclamation.setOnMouseClicked( event -> tooltip.show(exclamation, event.getScreenX(), event.getScreenY())); stackPane.getChildren().add(exclamation); } gp.add(stackPane, col++, row); } row++; } ColumnConstraints cc = new ColumnConstraints(); cc.setHgrow(Priority.NEVER); gp.getColumnConstraints().add(cc); cc = new ColumnConstraints(); cc.setHgrow(Priority.ALWAYS); gp.getColumnConstraints().add(cc); cc = new ColumnConstraints(); cc.setHgrow(Priority.NEVER); gp.getColumnConstraints().add(cc); if (extraInfoColumnIsRequired) { cc = new ColumnConstraints(); cc.setHgrow(Priority.NEVER); gp.getColumnConstraints().add(cc); } if (row == 0) { sp_.setContent(new Label("This assemblage does not allow data fields")); } else { sp_.setContent(gp); } allValid_.invalidate(); } else { sp_.setContent(null); } } @SuppressWarnings("unchecked") private void doSave() { try { DynamicSememeDataBI[] data = new DynamicSememeData[assemblageInfo_.getColumnInfo().length]; int i = 0; for (DynamicSememeColumnInfo ci : assemblageInfo_.getColumnInfo()) { data[i] = SememeGUIDataTypeFXNodeBuilder.getDataForType(currentDataFields_.get(i++).getDataField(), ci); } SememeChronology<?> sememe; if (createRefexFocus_ != null) { int componentNid; int assemblageSequence; if (createRefexFocus_ == ViewFocus.ASSEMBLAGE) { if (conceptNodeIsConceptType_) { componentNid = selectableConcept_.getConcept().getNid(); } else { String value = selectableComponent_.getText().trim(); if (Utility.isUUID(value)) { componentNid = Get.identifierService().getNidForUuids(UUID.fromString(value)); } else { componentNid = Integer.parseInt(value); } } assemblageSequence = Get.identifierService().getConceptSequence(focusNid_); } else { componentNid = focusNid_; assemblageSequence = selectableConcept_.getConcept().getConceptSequence(); } if (st_ == SememeType.DYNAMIC) { sememe = Get.sememeBuilderService() .getDyanmicSememeBuilder(componentNid, assemblageSequence, data) .build(EditCoordinates.getDefaultUserMetadata(), ChangeCheckerMode.ACTIVE); } else { //TODO implement throw new RuntimeException("Edit of non-dynamic sememe types not yet implemented"); } } else { if (st_ == SememeType.DYNAMIC) { @SuppressWarnings("rawtypes") DynamicSememeImpl ms = (DynamicSememeImpl) ((SememeChronology) editRefex_.getSememe()) .createMutableVersion(DynamicSememeImpl.class, State.ACTIVE, ExtendedAppContext.getUserProfileBindings().getEditCoordinate().get()); ms.setData(data); sememe = (SememeChronology<? extends DynamicSememe<?>>) ms; } else { //TODO implement throw new RuntimeException("Edit of non-dynamic sememe types not yet implemented"); } } Get.commitService().addUncommitted(sememe); Get.commitService().commit(sememe, ExtendedAppContext.getUserProfileBindings().getEditCoordinate().get(), "Sememe Created").get(); if (callingView_ != null) { callingView_.refresh(); } close(); } catch (Exception e) { logger_.error("Error saving sememe", e); AppContext.getCommonDialogs().showErrorDialog("Unexpected error", "There was an error saving the sememe", e.getMessage(), this); } } /** * Call setReferencedComponent first * * @see gov.va.isaac.interfaces.gui.views.PopupViewI#showView(javafx.stage.Window) */ @Override public void showView(Window parent) { if (createRefexFocus_ == null && editRefex_ == null) { throw new RunLevelException("referenced component nid must be set first"); } setTitle("Create new Sememe"); setResizable(true); initOwner(parent); initModality(Modality.NONE); initStyle(StageStyle.DECORATED); setWidth(600); setHeight(400); show(); } private ObservableList<SimpleDisplayConcept> buildAssemblageConceptList() { ObservableList<SimpleDisplayConcept> assemblageConcepts = new ObservableListWrapper<>( new ArrayList<SimpleDisplayConcept>()); try { //TODO Dan should we use sememe usage instead now? Set<Integer> colCons = OchreUtility.getAllChildrenOfConcept( IsaacMetadataConstants.DYNAMIC_SEMEME_ASSEMBLAGES.getSequence(), false, false); for (Integer col : colCons) { assemblageConcepts.add(new SimpleDisplayConcept(col)); } } catch (Exception e) { logger_.error("Unexpected error reading existing assemblage concepts", e); } return assemblageConcepts; } }