use of CCDD.CcddClassesDataTable.CCDDException in project CCDD by nasa.
the class CcddJSONHandler method importFromFile.
/**
********************************************************************************************
* Build the information from the table definition(s) in the current file
*
* @param importFile
* import file reference
*
* @param importAll
* ImportType.IMPORT_ALL to import the table type, data type, and macro definitions,
* and the data from all the table definitions; ImportType.FIRST_DATA_ONLY to load
* only the data for the first table defined
*
* @throws CCDDException
* If a data is missing, extraneous, or in error in the import file
*
* @throws IOException
* If an import file I/O error occurs
*
* @throws Exception
* For any unanticipated errors
********************************************************************************************
*/
@Override
public void importFromFile(FileEnvVar importFile, ImportType importType) throws CCDDException, IOException, Exception {
BufferedReader br = null;
try {
List<TableTypeDefinition> tableTypeDefinitions = new ArrayList<TableTypeDefinition>();
tableDefinitions = new ArrayList<TableDefinition>();
// Flags indicating if importing should continue after an input error is detected
boolean continueOnTableTypeError = false;
boolean continueOnDataTypeError = false;
boolean continueOnMacroError = false;
boolean continueOnReservedMsgIDError = false;
boolean continueOnColumnError = false;
boolean continueOnDataFieldError = false;
boolean continueOnTableTypeFieldError = false;
// Create a JSON parser and use it to parse the import file contents
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(new FileReader(importFile));
// Get the table type definitions JSON object
Object defn = jsonObject.get(JSONTags.TABLE_TYPE_DEFN.getTag());
// Check if the table type definitions exist
if (defn != null && defn instanceof JSONArray) {
// Step through each table type definition
for (JSONObject tableTypeJO : parseJSONArray(defn)) {
// Get the table type definition components
String typeName = getString(tableTypeJO, JSONTags.TABLE_TYPE_NAME.getTag());
String typeDesc = getString(tableTypeJO, JSONTags.TABLE_TYPE_DESCRIPTION.getTag());
Object typeColumn = getObject(tableTypeJO, JSONTags.TABLE_TYPE_COLUMN.getTag());
// Check if the expected inputs are present
if (!typeName.isEmpty() && typeColumn != null && typeColumn instanceof JSONArray) {
// Create a new table type definition
TableTypeDefinition tableTypeDefn = new TableTypeDefinition(typeName, typeDesc);
int columnNumber = 0;
// Step through each table type column definition
for (JSONObject typeJO : parseJSONArray(typeColumn)) {
// Check if the expected input is present
if (typeJO.keySet().size() == TableTypeEditorColumnInfo.values().length - 1) {
// Add the table type column definition, checking for (and if
// possible, correcting) errors
continueOnTableTypeError = addImportedTableTypeDefinition(continueOnTableTypeError, tableTypeDefn, new String[] { String.valueOf(columnNumber), getString(typeJO, TableTypeEditorColumnInfo.NAME.getColumnName()), getString(typeJO, TableTypeEditorColumnInfo.DESCRIPTION.getColumnName()), getString(typeJO, TableTypeEditorColumnInfo.INPUT_TYPE.getColumnName()), getString(typeJO, TableTypeEditorColumnInfo.UNIQUE.getColumnName()), getString(typeJO, TableTypeEditorColumnInfo.REQUIRED.getColumnName()), getString(typeJO, CcddUtilities.removeHTMLTags(TableTypeEditorColumnInfo.STRUCTURE_ALLOWED.getColumnName())), getString(typeJO, CcddUtilities.removeHTMLTags(TableTypeEditorColumnInfo.POINTER_ALLOWED.getColumnName())) }, importFile.getAbsolutePath(), parent);
// Update the column index number for the next column definition
columnNumber++;
} else // The number of inputs is incorrect
{
// Check if the error should be ignored or the import canceled
continueOnTableTypeError = getErrorResponse(continueOnTableTypeError, "<html><b>Table type '" + typeName + "' definition has missing or extra " + "input(s) in import file '</b>" + importFile.getAbsolutePath() + "<b>'; continue?", "Table Type Error", "Ignore this table type", "Ignore this and any remaining invalid table types", "Stop importing", parent);
}
}
// Get the data fields for this table type
Object typeField = getObject(tableTypeJO, JSONTags.TABLE_TYPE_FIELD.getTag());
// Check if any data fields exists for this table type
if (typeField != null) {
// Step through each table type data field definition
for (JSONObject typeJO : parseJSONArray(typeField)) {
// Add the data field definition, checking for (and if possible,
// correcting) errors
continueOnTableTypeFieldError = addImportedDataFieldDefinition(continueOnTableTypeFieldError, tableTypeDefn, new String[] { CcddFieldHandler.getFieldTypeName(tableTypeDefn.getTypeName()), getString(typeJO, FieldEditorColumnInfo.NAME.getColumnName()), getString(typeJO, FieldEditorColumnInfo.DESCRIPTION.getColumnName()), getString(typeJO, FieldEditorColumnInfo.SIZE.getColumnName()), getString(typeJO, FieldEditorColumnInfo.INPUT_TYPE.getColumnName()), getString(typeJO, FieldEditorColumnInfo.REQUIRED.getColumnName()), getString(typeJO, FieldEditorColumnInfo.APPLICABILITY.getColumnName()), getString(typeJO, FieldEditorColumnInfo.VALUE.getColumnName()) }, importFile.getAbsolutePath(), parent);
}
}
// Add the table type definition to the list
tableTypeDefinitions.add(tableTypeDefn);
}
}
}
// Add the table type if it's new or match it to an existing one with the same name if
// the type definitions are the same
String badDefn = tableTypeHandler.updateTableTypes(tableTypeDefinitions, fieldHandler);
// Check if a table type isn't new and doesn't match an existing one with the same name
if (badDefn != null) {
throw new CCDDException("Imported table type '" + badDefn + "' doesn't match the existing definition");
}
// Check if all definitions are to be loaded
if (importType == ImportType.IMPORT_ALL) {
List<String[]> dataTypeDefns = new ArrayList<String[]>();
List<String[]> macroDefns = new ArrayList<String[]>();
List<String[]> reservedMsgIDDefns = new ArrayList<String[]>();
// Get the data type definitions JSON object
defn = jsonObject.get(JSONTags.DATA_TYPE_DEFN.getTag());
// Check if the data type definitions exist
if (defn != null && defn instanceof JSONArray) {
// Step through each data type definition
for (JSONObject typeJO : parseJSONArray(defn)) {
// Get the data type definition components
String userName = getString(typeJO, DataTypeEditorColumnInfo.USER_NAME.getColumnName());
String cName = getString(typeJO, DataTypeEditorColumnInfo.C_NAME.getColumnName());
String size = getString(typeJO, DataTypeEditorColumnInfo.SIZE.getColumnName());
String baseType = getString(typeJO, DataTypeEditorColumnInfo.BASE_TYPE.getColumnName());
// Check if the expected inputs are present
if ((!userName.isEmpty() || !cName.isEmpty()) && !size.isEmpty() && !baseType.isEmpty() && typeJO.keySet().size() < DataTypeEditorColumnInfo.values().length) {
// Add the data type definition (add a blank to represent the OID)
dataTypeDefns.add(new String[] { userName, cName, size, baseType, "" });
} else // The number of inputs is incorrect
{
// Check if the error should be ignored or the import canceled
continueOnDataTypeError = getErrorResponse(continueOnDataTypeError, "<html><b>Missing or extra data type definition " + "input(s) in import file '</b>" + importFile.getAbsolutePath() + "<b>'; continue?", "Data Type Error", "Ignore this data type", "Ignore this and any remaining invalid data types", "Stop importing", parent);
}
}
}
// Get the macro definitions JSON object
defn = jsonObject.get(JSONTags.MACRO_DEFN.getTag());
// Check if the macro definitions exist
if (defn != null && defn instanceof JSONArray) {
// Step through each macro definition
for (JSONObject macroJO : parseJSONArray(defn)) {
// Get the macro definition components
String name = getString(macroJO, MacroEditorColumnInfo.NAME.getColumnName());
String value = getString(macroJO, MacroEditorColumnInfo.VALUE.getColumnName());
// Check if the expected inputs are present
if (!name.isEmpty() && macroJO.keySet().size() < MacroEditorColumnInfo.values().length) {
// Add the macro definition (add a blank to represent the OID)
macroDefns.add(new String[] { name, value, "" });
} else // The number of inputs is incorrect
{
// Check if the error should be ignored or the import canceled
continueOnMacroError = getErrorResponse(continueOnMacroError, "<html><b>Missing or extra macro definition " + "input(s) in import file '</b>" + importFile.getAbsolutePath() + "<b>'; continue?", "Macro Error", "Ignore this macro", "Ignore this and any remaining invalid macros", "Stop importing", parent);
}
}
}
// Get the reserved message ID definitions JSON object
defn = jsonObject.get(JSONTags.RESERVED_MSG_ID_DEFN.getTag());
// Check if the reserved message ID definitions exist
if (defn != null && defn instanceof JSONArray) {
// Step through each reserved message ID definition
for (JSONObject reservedMsgIDJO : parseJSONArray(defn)) {
// Get the reserved message ID definition components
String name = getString(reservedMsgIDJO, ReservedMsgIDEditorColumnInfo.MSG_ID.getColumnName());
String value = getString(reservedMsgIDJO, ReservedMsgIDEditorColumnInfo.DESCRIPTION.getColumnName());
// Check if the expected inputs are present
if (!name.isEmpty() && reservedMsgIDJO.keySet().size() < ReservedMsgIDEditorColumnInfo.values().length) {
// Add the reserved message ID definition (add a blank to represent the
// OID)
reservedMsgIDDefns.add(new String[] { name, value, "" });
} else // The number of inputs is incorrect
{
// Check if the error should be ignored or the import canceled
continueOnReservedMsgIDError = getErrorResponse(continueOnReservedMsgIDError, "<html><b>Missing or extra reserved message ID " + "definition input(s) in import file '</b>" + importFile.getAbsolutePath() + "<b>'; continue?", "Reserved Message ID Error", "Ignore this reserved message ID", "Ignore this and any remaining invalid reserved message IDs", "Stop importing", parent);
}
}
}
// Add the data type if it's new or match it to an existing one with the same name
// if the type definitions are the same
badDefn = dataTypeHandler.updateDataTypes(dataTypeDefns);
// name
if (badDefn != null) {
throw new CCDDException("Imported data type '" + badDefn + "' doesn't match the existing definition");
}
// Add the macro if it's new or match it to an existing one with the same name if
// the values are the same
badDefn = macroHandler.updateMacros(macroDefns);
// Add the reserved message ID definition if it's new
rsvMsgIDHandler.updateReservedMsgIDs(reservedMsgIDDefns);
// Check if a macro isn't new and doesn't match an existing one with the same name
if (badDefn != null) {
throw new CCDDException("Imported macro '" + badDefn + "' doesn't match the existing definition");
}
}
// Get the table definitions JSON object
defn = jsonObject.get(JSONTags.TABLE_DEFN.getTag());
// Check if the table definitions exist
if (defn != null && defn instanceof JSONArray) {
// Step through each table definition
for (JSONObject tableJO : parseJSONArray(defn)) {
// Get the table definition components
String tableName = getString(tableJO, JSONTags.TABLE_NAME.getTag());
String tableType = getString(tableJO, JSONTags.TABLE_TYPE.getTag());
String tableDesc = getString(tableJO, JSONTags.TABLE_DESCRIPTION.getTag());
Object tableDataJA = getObject(tableJO, JSONTags.TABLE_DATA.getTag());
Object dataFieldsJA = getObject(tableJO, JSONTags.TABLE_FIELD.getTag());
// Check if the expected inputs are present
if (!tableName.isEmpty() && tableDataJA != null && tableDataJA instanceof JSONArray && (dataFieldsJA == null || dataFieldsJA instanceof JSONArray)) {
// Create a new table type definition
TableDefinition tableDefn = new TableDefinition(tableName, tableDesc);
// Get the table's type definition
TypeDefinition typeDefn = tableTypeHandler.getTypeDefinition(tableType);
// Check if the table type doesn't exist
if (typeDefn == null) {
throw new CCDDException("Unknown table type '" + tableType + "'");
}
// Store the table's type name
tableDefn.setTypeName(tableType);
// Get the number of expected columns (the hidden columns, primary key and
// row index, should not be included in the JSON file)
int numColumns = typeDefn.getColumnCountVisible();
// Create storage for the row of cell data
String[] rowData = new String[numColumns];
// Step through each row of data
for (JSONObject rowDataJO : parseJSONArray(tableDataJA)) {
// Initialize the column values to blanks
Arrays.fill(rowData, null);
// Step through each key (column name)
for (Object columnName : rowDataJO.keySet()) {
// Get the column index based on the column name
int column = typeDefn.getVisibleColumnIndexByUserName(columnName.toString());
// Check if a column by this name exists
if (column != -1) {
// Get the value from the JSON input, if present; use a blank
// if a value for this column doesn't exist
rowData[column] = getString(rowDataJO, typeDefn.getColumnNamesVisible()[column]);
} else // The number of inputs is incorrect
{
// Check if the error should be ignored or the import canceled
continueOnColumnError = getErrorResponse(continueOnColumnError, "<html><b>Table '</b>" + tableName + "<b>' column name '</b>" + columnName + "<b>' unrecognized in import file '</b>" + importFile.getAbsolutePath() + "<b>'; continue?", "Column Error", "Ignore this invalid column name", "Ignore this and any remaining invalid column names", "Stop importing", parent);
}
}
// Add the row of data read in from the file to the cell data list
tableDefn.addData(rowData);
}
// defined
if (dataFieldsJA != null) {
// Step through each data field definition
for (JSONObject dataFieldJO : parseJSONArray(dataFieldsJA)) {
// Add the data field definition, checking for (and if possible,
// correcting) errors
continueOnDataFieldError = addImportedDataFieldDefinition(continueOnDataFieldError, tableDefn, new String[] { tableName, getString(dataFieldJO, FieldEditorColumnInfo.NAME.getColumnName()), getString(dataFieldJO, FieldEditorColumnInfo.DESCRIPTION.getColumnName()), getString(dataFieldJO, FieldEditorColumnInfo.SIZE.getColumnName()), getString(dataFieldJO, FieldEditorColumnInfo.INPUT_TYPE.getColumnName()), getString(dataFieldJO, FieldEditorColumnInfo.REQUIRED.getColumnName()), getString(dataFieldJO, FieldEditorColumnInfo.APPLICABILITY.getColumnName()), getString(dataFieldJO, FieldEditorColumnInfo.VALUE.getColumnName()) }, importFile.getAbsolutePath(), parent);
}
}
// Add the table's definition to the list
tableDefinitions.add(tableDefn);
}
// Check if only the data from the first table is to be read
if (importType == ImportType.FIRST_DATA_ONLY) {
// Stop reading table definitions
break;
}
}
}
} catch (ParseException pe) {
// Inform the user that the file cannot be closed
new CcddDialogHandler().showMessageDialog(parent, "<html><b>Cannot parse import file<br>'</b>" + importFile.getAbsolutePath() + "<b>'; cause '" + pe.getMessage() + "'", "File Warning", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
} finally {
try {
// Check that the buffered reader exists
if (br != null) {
// Close the file
br.close();
}
} catch (IOException ioe) {
// Inform the user that the file cannot be closed
new CcddDialogHandler().showMessageDialog(parent, "<html><b>Cannot close import file<br>'</b>" + importFile.getAbsolutePath() + "<b>'", "File Warning", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
}
}
}
use of CCDD.CcddClassesDataTable.CCDDException in project CCDD by nasa.
the class CcddMacroEditorDialog method createMacroTable.
/**
********************************************************************************************
* Create the macro table
*
* @return Reference to the scroll pane in which the table is placed
********************************************************************************************
*/
private JScrollPane createMacroTable() {
// Define the macro editor JTable
macroTable = new CcddJTableHandler() {
/**
************************************************************************************
* Highlight any macros in the macro values column
*
* @param component
* reference to the table cell renderer component
*
* @param text
* cell text
*
* @param isSelected
* true if the cell is to be rendered with the selection highlighted
*
* @param int
* row cell row, view coordinates
*
* @param column
* cell column, view coordinates
************************************************************************************
*/
@Override
protected void doSpecialRendering(Component component, String text, boolean isSelected, int row, int column) {
// Check if this is the macro values column
if (column == MacroEditorColumnInfo.VALUE.ordinal()) {
// Highlight any macro names in the table cell. Adjust the highlight color to
// account for the cell selection highlighting so that the macro is easily
// readable
macroHandler.highlightMacro(component, text, isSelected ? ModifiableColorInfo.INPUT_TEXT.getColor() : ModifiableColorInfo.TEXT_HIGHLIGHT.getColor());
// Highlight 'sizeof(data type)' instances
CcddDataTypeHandler.highlightSizeof(component, text, isSelected ? ModifiableColorInfo.INPUT_TEXT.getColor() : ModifiableColorInfo.TEXT_HIGHLIGHT.getColor());
}
}
/**
************************************************************************************
* Get the tool tip text for a table cell, showing any macro name replaced with its
* corresponding macro value
************************************************************************************
*/
@Override
public String getToolTipText(MouseEvent me) {
String toolTipText = null;
// Get the row and column of the cell over which the mouse pointer is hovering
Point point = me.getPoint();
int row = rowAtPoint(point);
int column = columnAtPoint(point);
// Check if a cell is beneath the mouse pointer
if (row != -1 && column != -1) {
// Expand any macros in the cell text and display this as the cell's tool tip
// text
toolTipText = macroHandler.getMacroToolTipText(getValueAt(row, column).toString());
}
return toolTipText;
}
/**
************************************************************************************
* Allow multiple line display in all columns
************************************************************************************
*/
@Override
protected boolean isColumnMultiLine(int column) {
return true;
}
/**
************************************************************************************
* Hide the the specified columns
************************************************************************************
*/
@Override
protected boolean isColumnHidden(int column) {
return column == MacroEditorColumnInfo.OID.ordinal();
}
/**
************************************************************************************
* Override isCellEditable so that all columns can be edited
************************************************************************************
*/
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
/**
************************************************************************************
* Allow pasting data into the macro cells
************************************************************************************
*/
@Override
protected boolean isDataAlterable(Object[] rowData, int row, int column) {
return isCellEditable(convertRowIndexToView(row), convertColumnIndexToView(column));
}
/**
************************************************************************************
* Validate changes to the editable cells
*
* @param tableData
* list containing the table data row arrays
*
* @param row
* table model row number
*
* @param column
* table model column number
*
* @param oldValue
* original cell contents
*
* @param newValue
* new cell contents
*
* @param showMessage
* true to display the invalid input dialog, if applicable
*
* @param isMultiple
* true if this is one of multiple cells to be entered and checked; false if
* only a single input is being entered
*
* @return Always returns false
************************************************************************************
*/
@Override
protected Boolean validateCellContent(List<Object[]> tableData, int row, int column, Object oldValue, Object newValue, Boolean showMessage, boolean isMultiple) {
// Reset the flag that indicates the last edited cell's content is invalid
setLastCellValid(true);
// Create a string version of the new value
String newValueS = newValue.toString();
try {
// Check if the value isn't blank
if (!newValueS.isEmpty()) {
// Check if the macro name has been changed and if the name isn't blank
if (column == MacroEditorColumnInfo.NAME.ordinal()) {
// Check if the macro name does not match the alphanumeric input type
if (!newValueS.matches(InputDataType.ALPHANUMERIC.getInputMatch())) {
throw new CCDDException("Illegal character(s) in macro name");
}
// creating a duplicate
for (int otherRow = 0; otherRow < getRowCount(); otherRow++) {
// name matches the one being added (case insensitive)
if (otherRow != row && newValueS.equalsIgnoreCase(tableData.get(otherRow)[column].toString())) {
throw new CCDDException("Macro name already in use");
}
}
} else // Check if the macro value changed
if (column == MacroEditorColumnInfo.VALUE.ordinal()) {
// Create a macro handler using the values currently displayed in the
// macro editor
CcddMacroHandler newMacroHandler = new CcddMacroHandler(ccddMain, getUpdatedData());
newMacroHandler.setHandlers(ccddMain.getVariableHandler());
// Get the macro's index and name
String index = tableData.get(row)[MacroEditorColumnInfo.OID.ordinal()].toString();
String macroName = tableData.get(row)[MacroEditorColumnInfo.NAME.ordinal()].toString();
// (doesn't cause a recursive reference)
if (!macroName.isEmpty() && newMacroHandler.isMacroRecursive(macroName)) {
throw new CCDDException("Macro '</b>" + macroName + "<b>' contains a recursive reference");
}
// Step through the committed macros
for (int commRow = 0; commRow < committedData.length; commRow++) {
// Check if the index matches that for the committed macro
if (index.equals(committedData[commRow][MacroEditorColumnInfo.OID.ordinal()])) {
List<String> tableNames = new ArrayList<String>();
// Get the macro name. Use the committed name (in place of the
// current name in the editor, in case it's been changed) since
// this is how the macro is referenced in the data tables
macroName = committedData[commRow][MacroEditorColumnInfo.NAME.ordinal()];
MacroReference macroRefs = null;
// loaded
for (MacroReference loadedRef : loadedReferences) {
// searched macro
if (macroName.equals(loadedRef.getMacroName())) {
// Store the macro search reference and stop searching
macroRefs = loadedRef;
break;
}
}
// Check if the macro references haven't already been loaded
if (macroRefs == null) {
// Search for references to this macro
macroRefs = new MacroReference(macroName);
// Add the search results to the list so that this search
// doesn't get performed again
loadedReferences.add(macroRefs);
}
// Step through each reference to the macro in the tables
for (String macroRef : macroRefs.getReferences()) {
// Split the reference into table name, column name, table
// type, and context
String[] tblColDescAndCntxt = macroRef.split(TABLE_DESCRIPTION_SEPARATOR, 4);
String refComment = tblColDescAndCntxt[SearchResultsQueryColumn.COMMENT.ordinal()];
// table
if (!refComment.isEmpty()) {
// Extract the viewable name and type of the table and
// the name of the column containing the data type, and
// separate the column string into the individual
// column values
String[] refNameAndType = refComment.split(",");
// contain a type mismatch
if (!tableNames.contains(refNameAndType[0])) {
String refColumn = tblColDescAndCntxt[SearchResultsQueryColumn.COLUMN.ordinal()];
String[] refContext = CcddUtilities.splitAndRemoveQuotes(tblColDescAndCntxt[SearchResultsQueryColumn.CONTEXT.ordinal()]);
// Use the type and column to get the column's
// input data type
TypeDefinition typeDefn = ccddMain.getTableTypeHandler().getTypeDefinition(refNameAndType[1]);
int columnIndex = typeDefn.getColumnIndexByDbName(refColumn);
InputDataType inputType = typeDefn.getInputTypes()[columnIndex];
// column value
for (String oldName : macroHandler.getReferencedMacros(refContext[columnIndex])) {
String newName = oldName;
String oid = "";
// Step through the updated macro definitions
for (String[] oldMacro : macroHandler.getMacroData()) {
// Check if the macro names match
if (oldName.equals(oldMacro[MacrosColumn.MACRO_NAME.ordinal()])) {
// Store the OID value for the macro
// and stop searching
oid = oldMacro[MacrosColumn.OID.ordinal()];
break;
}
}
// Step through the updated macro definitions
for (String[] newMacro : newMacroHandler.getMacroData()) {
// the target one
if (oid.equals(newMacro[MacrosColumn.OID.ordinal()])) {
// Since the OIDs match these are the
// same macro. Store the macro's new
// name (in case it changed) and stop
// searching
newName = newMacro[MacrosColumn.MACRO_NAME.ordinal()];
break;
}
}
// Replace all instances of the macro's old
// name with its new name
refContext[columnIndex] = macroHandler.replaceMacroName(CcddMacroHandler.getFullMacroName(oldName), CcddMacroHandler.getFullMacroName(newName), refContext[columnIndex]);
}
// macro's user
if (!newMacroHandler.getMacroExpansion(refContext[columnIndex]).matches(inputType.getInputMatch())) {
// Add the affected table name to the list
tableNames.add(refNameAndType[0]);
}
}
}
}
// were found
if (!tableNames.isEmpty()) {
throw new CCDDException("Macro value is not consistent with macro usage in table(s) '</b>" + dbTable.getShortenedTableNames(tableNames.toArray(new String[0])) + "<b>'");
}
break;
}
}
}
}
} catch (CCDDException ce) {
// Set the flag that indicates the last edited cell's content is invalid
setLastCellValid(false);
// Check if the input error dialog should be displayed
if (showMessage) {
// Inform the user that the input value is invalid
new CcddDialogHandler().showMessageDialog(CcddMacroEditorDialog.this, "<html><b>" + ce.getMessage(), "Invalid Input", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
}
// Restore the cell contents to its original value and pop the edit from the
// stack
tableData.get(row)[column] = oldValue;
macroTable.getUndoManager().undoRemoveEdit();
}
return false;
}
/**
************************************************************************************
* Load the table macro definition values into the table and format the table cells
************************************************************************************
*/
@Override
protected void loadAndFormatData() {
// Place the data into the table model along with the column names, set up the
// editors and renderers for the table cells, set up the table grid lines, and
// calculate the minimum width required to display the table information
setUpdatableCharacteristics(committedData, MacroEditorColumnInfo.getColumnNames(), null, MacroEditorColumnInfo.getToolTips(), true, true, true);
}
/**
************************************************************************************
* Override prepareRenderer to allow adjusting the background colors of table cells
************************************************************************************
*/
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
JComponent comp = (JComponent) super.prepareRenderer(renderer, row, column);
// invalid highlighting, if applicable)
if (!(isFocusOwner() && isRowSelected(row) && (isColumnSelected(column) || !getColumnSelectionAllowed()))) {
boolean found = true;
// Check if the cell is required and is empty
if (MacroEditorColumnInfo.values()[macroTable.convertColumnIndexToModel(column)].isRequired() && macroTable.getValueAt(row, column).toString().isEmpty()) {
// Set the flag indicating that the cell value is invalid
found = false;
}
// Check if the cell value is invalid
if (!found) {
// Change the cell's background color
comp.setBackground(ModifiableColorInfo.REQUIRED_BACK.getColor());
}
}
return comp;
}
/**
************************************************************************************
* Override the CcddJTableHandler method to produce an array containing empty values
* for a new row in this table
*
* @return Array containing blank cell values for a new row
************************************************************************************
*/
@Override
protected Object[] getEmptyRow() {
return MacroEditorColumnInfo.getEmptyRow();
}
/**
************************************************************************************
* Handle a change to the table's content
************************************************************************************
*/
@Override
protected void processTableContentChange() {
// Add or remove the change indicator based on whether or not any unstored changes
// exist
setTitle(DIALOG_TITLE + (macroTable.isTableChanged(committedData) ? "*" : ""));
// Force the table to redraw so that changes to the cells are displayed
repaint();
}
};
// Place the table into a scroll pane
JScrollPane scrollPane = new JScrollPane(macroTable);
// Disable storage of edit operations during table creation
macroTable.getUndoHandler().setAllowUndo(false);
// Set common table parameters and characteristics
macroTable.setFixedCharacteristics(scrollPane, true, ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, TableSelectionMode.SELECT_BY_CELL, false, ModifiableColorInfo.TABLE_BACK.getColor(), true, true, ModifiableFontInfo.DATA_TABLE_CELL.getFont(), true);
// Re-enable storage of edit operations
macroTable.getUndoHandler().setAllowUndo(true);
return scrollPane;
}
use of CCDD.CcddClassesDataTable.CCDDException in project CCDD by nasa.
the class CcddScriptHandler method getAssociationsPanel.
/**
********************************************************************************************
* Create the panel containing the script associations table
*
* @param title
* text to display above the script associations table; null or blank if no text is
* to be displayed
*
* @param allowSelectDisabled
* true if disabled associations can be selected; false if not. In the script
* manager disabled associations are selectable so that these can be deleted if
* desired. Scripts that are selected and disabled are ignored when executing
* scripts
*
* @param parent
* GUI component calling this method
*
* @return Reference to the JPanel containing the script associations table
********************************************************************************************
*/
@SuppressWarnings("serial")
protected JPanel getAssociationsPanel(String title, final boolean allowSelectDisabled, final Component parent) {
// Set the initial layout manager characteristics
GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing(), 0, 0, 0), 0, 0);
// Define the panel to contain the table
JPanel assnsPnl = new JPanel(new GridBagLayout());
// Check if a table title is provided
if (title != null && !title.isEmpty()) {
// Create the script associations label
JLabel assnsLbl = new JLabel(title);
assnsLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
assnsLbl.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
assnsPnl.add(assnsLbl, gbc);
gbc.gridy++;
}
// Create the table to display the search results
assnsTable = new CcddJTableHandler() {
/**
************************************************************************************
* Allow multiple line display in all columns
************************************************************************************
*/
@Override
protected boolean isColumnMultiLine(int column) {
return true;
}
/**
************************************************************************************
* Allow HTML-formatted text in the specified column(s)
************************************************************************************
*/
@Override
protected boolean isColumnHTML(int column) {
return column == AssociationsTableColumnInfo.MEMBERS.ordinal();
}
/**
************************************************************************************
* Hide the the specified columns
************************************************************************************
*/
@Override
protected boolean isColumnHidden(int column) {
return column == AssociationsTableColumnInfo.AVAILABLE.ordinal();
}
/**
************************************************************************************
* Allow editing the description in the script manager's associations table
************************************************************************************
*/
@Override
public boolean isCellEditable(int row, int column) {
return (column == convertColumnIndexToModel(AssociationsTableColumnInfo.NAME.ordinal()) || column == convertColumnIndexToModel(AssociationsTableColumnInfo.DESCRIPTION.ordinal())) && allowSelectDisabled;
}
/**
************************************************************************************
* Validate changes to the editable cells
*
* @param tableData
* list containing the table data row arrays
*
* @param row
* table model row number
*
* @param column
* table model column number
*
* @param oldValue
* original cell contents
*
* @param newValue
* new cell contents
*
* @param showMessage
* true to display the invalid input dialog, if applicable
*
* @param isMultiple
* true if this is one of multiple cells to be entered and checked; false if
* only a single input is being entered
*
* @return Always returns false
***********************************************************************************
*/
@Override
protected Boolean validateCellContent(List<Object[]> tableData, int row, int column, Object oldValue, Object newValue, Boolean showMessage, boolean isMultiple) {
// Reset the flag that indicates the last edited cell's content is invalid
setLastCellValid(true);
// Create a string version of the new value
String newValueS = newValue.toString();
try {
// Check if the value isn't blank
if (!newValueS.isEmpty()) {
// blank
if (column == AssociationsTableColumnInfo.NAME.ordinal()) {
// type
if (!newValueS.matches(InputDataType.ALPHANUMERIC.getInputMatch())) {
throw new CCDDException("Illegal character(s) in association name");
}
// avoid creating a duplicate
for (int otherRow = 0; otherRow < getRowCount(); otherRow++) {
// association name matches the one being added (case insensitive)
if (otherRow != row && newValueS.equalsIgnoreCase(tableData.get(otherRow)[column].toString())) {
throw new CCDDException("Association name already in use");
}
}
}
}
} catch (CCDDException ce) {
// Set the flag that indicates the last edited cell's content is invalid
setLastCellValid(false);
// Check if the input error dialog should be displayed
if (showMessage) {
// Inform the user that the input value is invalid
new CcddDialogHandler().showMessageDialog(parent, "<html><b>" + ce.getMessage(), "Invalid Input", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
}
// Restore the cell contents to its original value and pop the edit from the
// stack
tableData.get(row)[column] = oldValue;
getUndoManager().undoRemoveEdit();
}
return false;
}
/**
************************************************************************************
* Load the script associations data into the table and format the table cells
************************************************************************************
*/
@Override
protected void loadAndFormatData() {
// Place the data into the table model along with the column names, set up the
// editors and renderers for the table cells, set up the table grid lines, and
// calculate the minimum width required to display the table information
int totalWidth = setUpdatableCharacteristics(getScriptAssociationData(allowSelectDisabled, parent), AssociationsTableColumnInfo.getColumnNames(), null, AssociationsTableColumnInfo.getToolTips(), true, true, true);
// Check if the script manager or executive is active
if (scriptDialog != null) {
// Set the script manager or executive width to the associations table width
scriptDialog.setTableWidth(totalWidth + LAF_SCROLL_BAR_WIDTH + ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing() * 2);
}
}
/**
************************************************************************************
* Alter the association table cell color or contents
*
* @param component
* reference to the table cell renderer component
*
* @param value
* cell value
*
* @param isSelected
* true if the cell is to be rendered with the selection highlighted
*
* @param int
* row cell row, view coordinates
*
* @param column
* cell column, view coordinates
************************************************************************************
*/
@Override
protected void doSpecialRendering(Component component, String text, boolean isSelected, int row, int column) {
// Check if the association on the specified row is flagged as unavailable
if (!isAssociationAvailable(convertRowIndexToModel(row))) {
// Set the text color for this row to indicate it's not available
((JTextComponent) component).setForeground(Color.GRAY);
// Check if selection of disabled associations isn't allowed
if (!allowSelectDisabled) {
// Set the background color to indicate the row isn't selectable
((JTextComponent) component).setBackground(ModifiableColorInfo.TABLE_BACK.getColor());
}
}
// displayed
if (column == convertColumnIndexToView(AssociationsTableColumnInfo.SCRIPT_FILE.ordinal()) && hideScriptFilePath.isSelected()) {
// Remove the path, leaving only the script file name
((JTextComponent) component).setText(((JTextComponent) component).getText().replaceFirst(".*" + Pattern.quote(File.separator), ""));
}
}
/**
************************************************************************************
* Override the method that sets the row sorter so that special sorting can be
* performed on the script file column
************************************************************************************
*/
@Override
protected void setTableSortable() {
super.setTableSortable();
// Get a reference to the sorter
@SuppressWarnings("unchecked") TableRowSorter<UndoableTableModel> sorter = (TableRowSorter<UndoableTableModel>) getRowSorter();
// rows in the table
if (sorter != null) {
// Add a sort comparator for the script file column
sorter.setComparator(AssociationsTableColumnInfo.SCRIPT_FILE.ordinal(), new Comparator<String>() {
/**
************************************************************************
* Override the comparison when sorting the script file column to ignore
* the script file paths if these are currently hidden
************************************************************************
*/
@Override
public int compare(String filePath1, String filePath2) {
return (hideScriptFilePath.isSelected() ? filePath1.replaceFirst(".*" + Pattern.quote(File.separator), "") : filePath1).compareTo(hideScriptFilePath.isSelected() ? filePath2.replaceFirst(".*" + Pattern.quote(File.separator), "") : filePath2);
}
});
}
}
/**
************************************************************************************
* Handle a change to the table's content
************************************************************************************
*/
@Override
protected void processTableContentChange() {
// associations manager dialog is open)
if (scriptDialog != null && scriptDialog instanceof CcddScriptManagerDialog) {
// Update the script associations manager change indicator
((CcddScriptManagerDialog) scriptDialog).updateChangeIndicator();
}
}
};
// Set the list selection model in order to detect table rows that aren't allowed to be
// selected
assnsTable.setSelectionModel(new DefaultListSelectionModel() {
/**
************************************************************************************
* Check if the script association table item is selected, ignoring associations that
* are flagged as unavailable
************************************************************************************
*/
@Override
public boolean isSelectedIndex(int row) {
return allowSelectDisabled || isAssociationAvailable(assnsTable.convertRowIndexToModel(row)) ? super.isSelectedIndex(row) : false;
}
});
// Place the table into a scroll pane
JScrollPane scrollPane = new JScrollPane(assnsTable);
// Set up the search results table parameters
assnsTable.setFixedCharacteristics(scrollPane, false, ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, TableSelectionMode.SELECT_BY_ROW, true, ModifiableColorInfo.TABLE_BACK.getColor(), true, true, ModifiableFontInfo.OTHER_TABLE_CELL.getFont(), true);
// Define the panel to contain the table and add it to the dialog
JPanel assnsTblPnl = new JPanel();
assnsTblPnl.setLayout(new BoxLayout(assnsTblPnl, BoxLayout.X_AXIS));
assnsTblPnl.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
assnsTblPnl.add(scrollPane);
gbc.weighty = 1.0;
assnsPnl.add(assnsTblPnl, gbc);
// Create the check box for hiding/showing the file paths in the associations table script
// file column
hideScriptFilePath = new JCheckBox("Hide script file path", ccddMain.getProgPrefs().getBoolean(HIDE_SCRIPT_PATH, false));
hideScriptFilePath.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
hideScriptFilePath.setBorder(BorderFactory.createEmptyBorder());
hideScriptFilePath.setToolTipText(CcddUtilities.wrapText("Remove the file paths from the script file column", ModifiableSizeInfo.MAX_TOOL_TIP_LENGTH.getSize()));
// Add a listener for check box selection changes
hideScriptFilePath.addActionListener(new ActionListener() {
/**
************************************************************************************
* Handle a change in the hide script file path check box state
************************************************************************************
*/
@Override
public void actionPerformed(ActionEvent ae) {
assnsTable.repaint();
ccddMain.getProgPrefs().putBoolean(HIDE_SCRIPT_PATH, hideScriptFilePath.isSelected());
}
});
gbc.weighty = 0.0;
gbc.gridy++;
assnsPnl.add(hideScriptFilePath, gbc);
// Create a panel to contain the environment variable override label and field
JPanel envVarOverridePnl = new JPanel(new GridBagLayout());
JLabel envVarOverrideLbl = new JLabel("Environment variable override");
envVarOverrideLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
gbc.insets.right = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing();
gbc.weightx = 0.0;
gbc.gridy++;
envVarOverridePnl.add(envVarOverrideLbl, gbc);
envVarOverrideFld = new JTextField(ModifiableOtherSettingInfo.ENV_VAR_OVERRIDE.getValue());
envVarOverrideFld.setFont(ModifiableFontInfo.INPUT_TEXT.getFont());
envVarOverrideFld.setEditable(true);
envVarOverrideFld.setForeground(ModifiableColorInfo.INPUT_TEXT.getColor());
envVarOverrideFld.setBackground(ModifiableColorInfo.INPUT_BACK.getColor());
envVarOverrideFld.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.LIGHT_GRAY, Color.GRAY), BorderFactory.createEmptyBorder(ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing())));
// Add a listener for focus changes on the environment variable override field
envVarOverrideFld.addFocusListener(new FocusAdapter() {
/**
************************************************************************************
* Handle a loss of focus
************************************************************************************
*/
@Override
public void focusLost(FocusEvent fe) {
// Update the environment variable map and association availability
getEnvironmentVariableMap(parent);
}
});
gbc.insets.right = 0;
gbc.weightx = 1.0;
gbc.gridx++;
envVarOverridePnl.add(envVarOverrideFld, gbc);
gbc.gridx = 0;
assnsPnl.add(envVarOverridePnl, gbc);
// Initialize the environment variable map
getEnvironmentVariableMap(parent);
return assnsPnl;
}
use of CCDD.CcddClassesDataTable.CCDDException in project CCDD by nasa.
the class CcddScriptHandler method getScriptAssociationData.
/**
********************************************************************************************
* Retrieve the script associations stored in the database and from these build the array for
* display and selection of the script associations
*
* @param allowSelectDisabled
* true if disabled associations can be selected; false if not. In the script
* manager disabled associations are selectable so that these can be deleted if
* desired. Scripts that are selected and disabled are ignored when executing
* scripts
*
* @param parent
* GUI component calling this method
*
* @return Object array containing the script associations
********************************************************************************************
*/
private Object[][] getScriptAssociationData(boolean allowSelectDisabled, Component parent) {
List<Object[]> associationsData = new ArrayList<Object[]>();
// Read the stored script associations from the database
List<String[]> committedAssociations = dbTable.retrieveInformationTable(InternalTable.ASSOCIATIONS, parent);
// Get the list of table names and their associated table type
ArrayListMultiple protoNamesAndTableTypes = new ArrayListMultiple();
protoNamesAndTableTypes.addAll(dbTable.queryTableAndTypeList(parent));
// Load the group information from the database
CcddGroupHandler groupHandler = new CcddGroupHandler(ccddMain, null, parent);
// Create a list to contain the variables (dataType.variableName) that have been verified
// to exist. This reduces the number of database transactions in the event the same
// variable is used in multiple associations
List<String> verifiedVars = new ArrayList<String>();
// Step through each script association
for (String[] assn : committedAssociations) {
AvailabilityType availableStatus = AvailabilityType.AVAILABLE;
int numVerifications = 0;
StringBuilder verifications = new StringBuilder("");
try {
// Get the list of association table paths
List<String> tablePaths = getAssociationTablePaths(assn[AssociationsColumn.MEMBERS.ordinal()].toString(), groupHandler, parent);
// Check if at least one table is assigned to this script association
if (!tablePaths.isEmpty()) {
// Step through each table referenced in this association
for (String tablePath : tablePaths) {
String parentTable = "";
// Step through each data type and variable name pair
for (String variable : tablePath.split(",")) {
// Split the variable reference into the data type and variable name
String[] typeAndVar = variable.split(Pattern.quote("."));
// Check if the variable hasn't already been verified to exist
if (!verifiedVars.contains(variable)) {
// Locate the table's prototype in the list
int index = protoNamesAndTableTypes.indexOf(typeAndVar[0]);
// Check if the prototype table doesn't exist
if (index == -1) {
throw new CCDDException();
}
// root table, so there is no variable name)
if (typeAndVar.length == 2) {
// Get the table's type definition
TypeDefinition typeDefn = ccddMain.getTableTypeHandler().getTypeDefinition(protoNamesAndTableTypes.get(index)[2]);
// Check if the table doesn't represent a structure
if (!typeDefn.isStructure()) {
throw new CCDDException();
}
// Get the name of the column that represents the variable name
String varColumn = typeDefn.getDbColumnNameByInputType(InputDataType.VARIABLE);
// Add the command to verify the existence of the variable in
// the parent table to the overall verification command for
// this association
verifications.append("SELECT " + varColumn + " FROM " + parentTable + " WHERE " + varColumn + " = '" + typeAndVar[1] + "' UNION ALL ");
numVerifications++;
// Add the variable to the list of those verified to exist
verifiedVars.add(variable);
}
}
// Store the data type, which is the parent for the next variable (if
// any)
parentTable = typeAndVar[0];
}
}
// Check if there are any variables to verify
if (numVerifications != 0) {
// Complete the verification command
verifications = CcddUtilities.removeTrailer(verifications, "UNION ALL ").append(";");
// Query the tables for the variables to be checked
List<String[]> result = dbTable.queryDatabase(verifications.toString(), parent);
// were found
if (result == null || result.size() != numVerifications) {
throw new CCDDException();
}
}
}
} catch (CCDDException ce) {
// The script file or associated table doesn't exist; set the flag to indicate the
// association isn't available
availableStatus = AvailabilityType.TABLE_MISSING;
}
// Add the association to the script associations list
associationsData.add(new Object[] { assn[AssociationsColumn.NAME.ordinal()], assn[AssociationsColumn.DESCRIPTION.ordinal()], assn[AssociationsColumn.SCRIPT_FILE.ordinal()], CcddUtilities.highlightDataType(assn[AssociationsColumn.MEMBERS.ordinal()]), availableStatus });
}
return associationsData.toArray(new Object[0][0]);
}
use of CCDD.CcddClassesDataTable.CCDDException in project CCDD by nasa.
the class CcddPatchHandler method updateAssociationsTable.
/**
********************************************************************************************
* Update the associations table to include a description column and to change the table
* separator characters in the member_table column. Older versions of CCDD are not compatible
* with the project database after applying this patch
*
* @throws CCDDException
* If the user elects to not install the patch or an error occurs while applying
* the patch
********************************************************************************************
*/
private void updateAssociationsTable() throws CCDDException {
CcddEventLogDialog eventLog = ccddMain.getSessionEventLog();
CcddDbControlHandler dbControl = ccddMain.getDbControlHandler();
try {
CcddDbCommandHandler dbCommand = ccddMain.getDbCommandHandler();
CcddDbTableCommandHandler dbTable = ccddMain.getDbTableCommandHandler();
// Create lists to contain the old and new associations table items
List<String[]> tableData = new ArrayList<String[]>();
// Read the contents of the associations table
ResultSet assnsData = dbCommand.executeDbQuery("SELECT * FROM " + InternalTable.ASSOCIATIONS.getTableName() + " ORDER BY OID;", ccddMain.getMainFrame());
// Check if the patch hasn't already been applied
if (assnsData.getMetaData().getColumnCount() == 2) {
// Check if the user elects to not apply the patch
if (new CcddDialogHandler().showMessageDialog(ccddMain.getMainFrame(), "<html><b>Apply patch to update the script " + "associations table?<br><br></b>" + "Incorporates a description column in the " + "script associations table.<br><b><i>Older " + "versions of CCDD will be incompatible " + "with this project database after " + "applying the patch", "Apply Patch #07212017", JOptionPane.QUESTION_MESSAGE, DialogOption.OK_CANCEL_OPTION) != OK_BUTTON) {
assnsData.close();
throw new CCDDException("user elected to not install patch (#0712017)");
}
// Step through each of the query results
while (assnsData.next()) {
// Create an array to contain the column values
String[] columnValues = new String[3];
// Step through each column in the row
for (int column = 0; column < 2; column++) {
// Add the column value to the array. Note that the first column's index in
// the database is 1, not 0. Also, shift the old data over one column to
// make room for the description
columnValues[column + 1] = assnsData.getString(column + 1);
// Check if the value is null
if (columnValues[column] == null) {
// Replace the null with a blank
columnValues[column] = "";
}
}
// Add the row data to the list
tableData.add(columnValues);
}
assnsData.close();
// Check if there are any associations in the table
if (tableData.size() != 0) {
// Indicate in the log that the old data successfully loaded
eventLog.logEvent(SUCCESS_MSG, InternalTable.ASSOCIATIONS.getTableName() + " retrieved");
// Step through each script association
for (int row = 0; row < tableData.size(); row++) {
// Set the description to a blank and replace the table name separator
// characters with the new ones
tableData.set(row, new String[] { "", tableData.get(row)[1], tableData.get(row)[2].replaceAll(" \\+ ", ASSN_TABLE_SEPARATOR) });
}
}
// Back up the project database before applying the patch
dbControl.backupDatabase(dbControl.getDatabaseName(), new FileEnvVar(ModifiablePathInfo.DATABASE_BACKUP_PATH.getPath() + File.separator + dbControl.getDatabaseName() + "_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()) + FileExtension.DBU.getExtension()));
// Store the updated associations table
dbTable.storeInformationTable(InternalTable.ASSOCIATIONS, tableData, null, ccddMain.getMainFrame());
// Inform the user that updating the database associations table completed
eventLog.logEvent(EventLogMessageType.SUCCESS_MSG, "Project '" + dbControl.getProjectName() + "' associations table conversion complete");
}
} catch (Exception e) {
// Inform the user that converting the associations table failed
eventLog.logFailEvent(ccddMain.getMainFrame(), "Cannot convert project '" + dbControl.getProjectName() + "' associations table to new format; cause '" + e.getMessage() + "'", "<html><b>Cannot convert project '" + dbControl.getProjectName() + "' associations table to new format " + "(project database will be closed)");
throw new CCDDException();
}
}
Aggregations