Search in sources :

Example 6 with TypeDefinition

use of CCDD.CcddTableTypeHandler.TypeDefinition 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]);
}
Also used : CCDDException(CCDD.CcddClassesDataTable.CCDDException) ArrayListMultiple(CCDD.CcddClassesComponent.ArrayListMultiple) ArrayList(java.util.ArrayList) TypeDefinition(CCDD.CcddTableTypeHandler.TypeDefinition) AvailabilityType(CCDD.CcddConstants.AvailabilityType)

Example 7 with TypeDefinition

use of CCDD.CcddTableTypeHandler.TypeDefinition in project CCDD by nasa.

the class CcddSearchHandler method removeArrayMemberReferences.

/**
 ********************************************************************************************
 * Remove data type or macro search references where the match occurs in an array size column
 * of an array member (the reference in the array's definition is all that's needed)
 *
 * @param matches
 *            list containing the search results for the data type or macro reference
 *
 * @param tbleTypeHndlr
 *            reference to the table type handler
 ********************************************************************************************
 */
protected static void removeArrayMemberReferences(List<String> matches, CcddTableTypeHandler tbleTypeHndlr) {
    // Step through each match (in reverse since an entry in the list may need to be removed)
    for (int index = matches.size() - 1; index >= 0; index--) {
        // Separate the match components
        String[] tblColDescAndCntxt = matches.get(index).split(TABLE_DESCRIPTION_SEPARATOR, 4);
        // Separate the user-viewable table name and table type
        String[] tableAndType = tblColDescAndCntxt[SearchResultsQueryColumn.COMMENT.ordinal()].split(",", 2);
        // Get the table's type definition
        TypeDefinition typeDefn = tbleTypeHndlr.getTypeDefinition(tableAndType[1]);
        // Check if the reference is in an array size column
        if (typeDefn.getDbColumnNameByInputType(InputDataType.ARRAY_INDEX).equals(tblColDescAndCntxt[SearchResultsQueryColumn.COLUMN.ordinal()])) {
            // Separate the location into the individual columns. Commas between double quotes
            // are ignored so that an erroneous column separation doesn't occur
            String[] columns = CcddUtilities.splitAndRemoveQuotes(tblColDescAndCntxt[SearchResultsQueryColumn.CONTEXT.ordinal()]);
            // Get the index of the variable name column
            int varNameIndex = typeDefn.getColumnIndexByInputType(InputDataType.VARIABLE);
            // Check if the variable name is an array member
            if (varNameIndex != -1 && ArrayVariable.isArrayMember(columns[varNameIndex])) {
                // Remove the match
                matches.remove(index);
            }
        }
    }
}
Also used : TypeDefinition(CCDD.CcddTableTypeHandler.TypeDefinition)

Example 8 with TypeDefinition

use of CCDD.CcddTableTypeHandler.TypeDefinition in project CCDD by nasa.

the class CcddDbControlHandler method createStructureColumnFunctions.

/**
 ********************************************************************************************
 * Create the reusable database functions for obtaining structure table members and
 * structure-defining column values
 *
 * @return true if an error occurs creating the structure functions
 ********************************************************************************************
 */
protected boolean createStructureColumnFunctions() {
    boolean errorFlag = false;
    // Check if connected to a project database
    if (isDatabaseConnected()) {
        try {
            // Structure-defining column names, as used by the database
            String dbVariableName = null;
            String dbDataType = null;
            String dbArraySize = null;
            String dbBitLength = null;
            String dbRate = null;
            String dbEnumeration = null;
            String compareColumns = "";
            // Use the default structure column names for certain default columns
            dbVariableName = DefaultColumn.VARIABLE_NAME.getDbName();
            dbDataType = DefaultColumn.DATA_TYPE.getDbName();
            dbArraySize = DefaultColumn.ARRAY_SIZE.getDbName();
            dbBitLength = DefaultColumn.BIT_LENGTH.getDbName();
            // Create a string containing the partial command for determining if the columns
            // that are necessary to define a structure table are present in a table
            String defStructCols = "(column_name = '" + dbVariableName + "' OR " + "column_name = '" + dbDataType + "' OR " + "column_name = '" + dbArraySize + "' OR " + "column_name = '" + dbBitLength + "' OR ";
            List<String> rateAndEnums = new ArrayList<String>();
            // Step through each table type definition
            for (TypeDefinition typeDefn : ccddMain.getTableTypeHandler().getTypeDefinitions()) {
                // Check if the type represents a structure
                if (typeDefn.isStructure()) {
                    // Get this type's first rate and enumeration column names
                    dbRate = typeDefn.getDbColumnNameByInputType(InputDataType.RATE);
                    dbEnumeration = typeDefn.getDbColumnNameByInputType(InputDataType.ENUMERATION);
                    // Create the portion of the command comparing the column name to the first
                    // rate and enumeration column names
                    String rateAndEnum = "column_name = '" + dbRate + "' OR " + "column_name = '" + dbEnumeration + "') OR ";
                    // exist in the comparison
                    if (!rateAndEnums.contains(rateAndEnum)) {
                        // Add the rate and enumeration name pair so that it won't be added
                        // again
                        rateAndEnums.add(rateAndEnum);
                        // Create a string containing the partial command for determining if
                        // the columns that are necessary to define a structure table are
                        // present in a table
                        compareColumns += defStructCols + "column_name = '" + dbRate + "' OR " + "column_name = '" + dbEnumeration + "') OR ";
                    }
                }
            }
            // Check if no structure table type exists
            if (compareColumns.isEmpty()) {
                // Get the default rate and enumeration column names
                dbRate = DefaultColumn.RATE.getDbName();
                dbEnumeration = DefaultColumn.ENUMERATION.getDbName();
                // Create a string containing the partial command for determining if the
                // columns that are necessary to define a structure table are present in a
                // table
                compareColumns = defStructCols + "column_name = '" + dbRate + "' OR " + "column_name = '" + dbEnumeration + "')";
            } else // At least one structure table type exists
            {
                compareColumns = CcddUtilities.removeTrailer(compareColumns, " OR ");
            }
            // alphabetically by name or numerically by row index
            for (String[] functionParm : functionParameters) {
                // Create function to get the table name, data type, variable name, bit length,
                // sample rate, and enumeration for all structure tables that contain at least
                // one row, sorted by table name or index, and then by variable name. For
                // arrays, only the members are retrieved; the array definitions are ignored
                dbCommand.executeDbCommand(deleteFunction("get_table_members_by_" + functionParm[0]) + "CREATE FUNCTION get_table_members_by_" + functionParm[0] + "() RETURNS TABLE(tbl_name text, data_type " + "text, variable_name text, bit_length text, " + "rate text, enumeration text) AS $$ BEGIN " + "DECLARE row record; BEGIN DROP TABLE IF EXISTS " + TEMP_TABLES + "; CREATE TEMP TABLE " + TEMP_TABLES + " AS SELECT t.tablename AS real_name FROM " + "pg_tables AS t WHERE t.schemaname = 'public' " + "AND substr(t.tablename, 1, 2) != '" + INTERNAL_TABLE_PREFIX + "' ORDER BY real_name ASC; FOR row IN SELECT * FROM " + TEMP_TABLES + " LOOP IF EXISTS (SELECT * FROM " + "(SELECT COUNT(*) FROM information_schema.columns " + "WHERE table_name = row.real_name AND (" + compareColumns + ")) AS alias1 WHERE count = '" + DefaultColumn.getTypeRequiredColumnCount(TYPE_STRUCTURE) + "') THEN RETURN QUERY EXECUTE E'SELECT ''' || " + "row.real_name || '''::text, * FROM get_def_columns_by_" + functionParm[0] + "(''' || row.real_name || ''')'; END IF; " + "END LOOP; END; END; $$ LANGUAGE plpgsql; " + buildOwnerCommand(DatabaseObject.FUNCTION, "get_table_members_by_" + functionParm[0] + "()"), ccddMain.getMainFrame());
            }
            String rateCol = "";
            String rateJoin = "";
            // Check if any rate columns are defined
            if (ccddMain.getRateParameterHandler().getNumRateColumns() != 0) {
                // Step through each data stream
                for (RateInformation rateInfo : ccddMain.getRateParameterHandler().getRateInformation()) {
                    // Get the rate column name (in its database form)
                    String rateColName = DefaultColumn.convertVisibleToDatabase(rateInfo.getRateName(), InputDataType.RATE, true);
                    // Add detection for the rate column. If the column doesn't exist in the
                    // table then a blank is returned for that column's rate value
                    rateCol += "CASE WHEN " + rateColName + "_exists THEN " + rateColName + "::text ELSE ''''::text END || '','' || ";
                    rateJoin += " CROSS JOIN (SELECT EXISTS (SELECT 1 FROM " + "pg_catalog.pg_attribute WHERE attrelid = ''' " + "|| name || '''::regclass AND attname  = ''" + rateColName + "'' " + "AND NOT attisdropped AND attnum > 0) AS " + rateColName + "_exists) " + rateColName;
                }
                // Remove the trailing separator text
                rateCol = CcddUtilities.removeTrailer(rateCol, " || '','' || ");
            } else // No rate columns exist
            {
                // Return a blank for the rate column value
                rateCol = "''''::text";
            }
            String enumCol = "";
            String enumJoin = "";
            // Get the unique structure enumeration column names
            List<String> enumColumns = ccddMain.getTableTypeHandler().getStructEnumColNames(true);
            // Check if any enumeration columns are defined
            if (enumColumns.size() != 0) {
                // Build the enumeration separator (triple backslashes) portion of the command
                String enumSep = " || E''' || E'\\\\\\\\\\\\\\\\\\\\\\\\' || ''' || ";
                // Step through each enumeration column name (in its database form)
                for (String enumColName : enumColumns) {
                    // Add detection for the enumeration column. If the column doesn't exist in
                    // the table then a blank is returned for that column's enumeration value
                    enumCol += "CASE WHEN " + enumColName + "_exists THEN " + enumColName + "::text ELSE ''''::text END" + enumSep;
                    enumJoin += " CROSS JOIN (SELECT EXISTS (SELECT 1 FROM " + "pg_catalog.pg_attribute WHERE attrelid = ''' " + "|| name || '''::regclass AND attname  = ''" + enumColName + "'' " + "AND NOT attisdropped AND attnum > 0) AS " + enumColName + "_exists) " + enumColName;
                }
                // Remove the trailing separator text
                enumCol = CcddUtilities.removeTrailer(enumCol, enumSep);
            } else // No enumeration columns exist
            {
                // Return a blank for the enumeration column value
                enumCol += "''''::text";
            }
            // alphabetically by name or numerically by row index
            for (String[] functionParm : functionParameters) {
                // Create function to get the data type and variable name column data for the
                // specified table, sorted by variable name. For arrays, only the members are
                // retrieved; the array definitions are ignored
                dbCommand.executeDbCommand(deleteFunction("get_def_columns_by_" + functionParm[0]) + "CREATE FUNCTION get_def_columns_by_" + functionParm[0] + "(name text) RETURNS TABLE(data_type " + "text, variable_name text, bit_length text, " + "rate text, enumeration text) AS $$ " + "BEGIN RETURN QUERY EXECUTE 'SELECT " + dbDataType + ", " + dbVariableName + ", " + dbBitLength + ", " + rateCol + ", " + enumCol + " FROM ' || name || '" + rateJoin + enumJoin + " WHERE " + dbArraySize + " = E'''' OR (array_size ~ E''^" + MACRO_IDENTIFIER + "'' AND (SELECT EXISTS (SELECT " + MacrosColumn.VALUE.getColumnName() + " FROM " + InternalTable.MACROS.getTableName() + " WHERE " + MacrosColumn.MACRO_NAME.getColumnName() + " = replace('''' || array_size || '''', ''" + MACRO_IDENTIFIER + "'', '''') AND " + MacrosColumn.VALUE.getColumnName() + " = ''''))) OR " + dbVariableName + " ~ E''^.+]'' ORDER BY " + functionParm[1] + " ASC'; END $$ LANGUAGE plpgsql; " + buildOwnerCommand(DatabaseObject.FUNCTION, "get_def_columns_by_" + functionParm[0] + "(name text)"), ccddMain.getMainFrame());
            }
            // Database function to search for all tables containing a data type column, and
            // replace a target value with a new value
            dbCommand.executeDbCommand(deleteFunction("update_data_type_names") + "CREATE FUNCTION update_data_type_names(oldType text, " + "newType text) RETURNS VOID AS $$ BEGIN DECLARE row " + "record; BEGIN DROP TABLE IF EXISTS " + TEMP_TABLES + "; CREATE TEMP TABLE " + TEMP_TABLES + " AS SELECT t.tablename AS real_name " + "FROM pg_tables AS t WHERE t.schemaname = 'public' " + "AND substr(t.tablename, 1, " + INTERNAL_TABLE_PREFIX.length() + ") != '" + INTERNAL_TABLE_PREFIX + "'; FOR row IN SELECT * FROM " + TEMP_TABLES + " LOOP IF EXISTS (SELECT 1 FROM " + "information_schema.columns WHERE table_name = " + "row.real_name AND column_name = '" + dbDataType + "') THEN EXECUTE E'UPDATE ' || row.real_name || E' SET " + dbDataType + " = ''' || newType || E''' WHERE " + dbDataType + " = ''' || oldType || E''''; END IF; " + "END LOOP; END; END; $$ LANGUAGE plpgsql; " + buildOwnerCommand(DatabaseObject.FUNCTION, "update_data_type_names(oldType text," + " newType text)"), ccddMain.getMainFrame());
            // Inform the user that the database function creation succeeded
            eventLog.logEvent(SUCCESS_MSG, "Database structure functions created");
        } catch (SQLException se) {
            // Inform the user that creating the database functions failed
            eventLog.logFailEvent(ccddMain.getMainFrame(), "Cannot create structure functions in project database '" + activeDatabase + "' as user '" + activeUser + "'; cause '" + se.getMessage() + "'", "<html><b>Cannot create structure functions in project database '</b>" + activeDatabase + "<b>'");
            errorFlag = true;
        }
    }
    return errorFlag;
}
Also used : SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) RateInformation(CCDD.CcddClassesDataTable.RateInformation) TypeDefinition(CCDD.CcddTableTypeHandler.TypeDefinition)

Example 9 with TypeDefinition

use of CCDD.CcddTableTypeHandler.TypeDefinition in project CCDD by nasa.

the class CcddDbTableCommandHandler method modifyTableType.

/**
 ********************************************************************************************
 * Add, rename, or delete table type column names in the table definitions table and update the
 * existing tables of the specified type
 *
 * @param typeName
 *            table type name to modify
 *
 * @param fieldInformation
 *            data field information list
 *
 * @param overwriteFields
 *            true if the content of existing fields should be overwritten by the default
 *            values; false to not overwrite existing values
 *
 * @param additions
 *            list of new columns to add to the tables. Each list item is an array containing:
 *            [0] column name (user), [1] column input type
 *
 * @param modifications
 *            list of name changes of existing columns in the tables. Each list item is an
 *            array containing: [0] original column name (user), [1] new column name (user),
 *            [2] column input type
 *
 * @param deletions
 *            list of columns to remove from the tables. Each list item is an array containing:
 *            [0] column name (user), [1] column input type
 *
 * @param columnOrderChange
 *            true if the table type's column order changed
 *
 * @param originalDefn
 *            reference to the table type definition prior to making any changes; null if this
 *            is a new table type
 *
 * @param editorDialog
 *            reference to the table type editor dialog
 *
 * @param editor
 *            reference to the table type editor where the change(s) occurred
 ********************************************************************************************
 */
protected void modifyTableType(String typeName, List<FieldInformation> fieldInformation, boolean overwriteFields, List<String[]> additions, List<String[]> modifications, List<String[]> deletions, boolean columnOrderChange, TypeDefinition originalDefn, CcddTableTypeEditorDialog editorDialog, CcddTableTypeEditorHandler editor) {
    try {
        boolean errorFlag = false;
        String[] tableNames = null;
        String names = "";
        // Get the type definition based on the table type name
        TypeDefinition typeDefn = tableTypeHandler.getTypeDefinition(typeName);
        // Set the flags that indicates if the table type definition represents a structure
        // prior to and after making the updates
        boolean wasStructure = originalDefn != null ? originalDefn.isStructure() : false;
        boolean isStructure = typeDefn.isStructure();
        // Create the command to update the table definitions table
        StringBuilder command = new StringBuilder(storeTableTypesInfoTableCommand());
        // Check if this isn't a new table type
        if (originalDefn != null) {
            // Get an array containing all of the prototype tables of the specified type
            String[] protoTableNames = queryTablesOfTypeList(typeName, editorDialog);
            String columnOrder = "";
            // Check if the column order changed or if any columns were added or deleted
            if (columnOrderChange || !additions.isEmpty() || !deletions.isEmpty()) {
                // Step through each column in the table type
                for (int index = 0; index < typeDefn.getColumnNamesDatabase().length; index++) {
                    // Add the column index and a separator
                    columnOrder += index + ":";
                }
                // Remove the trailing separator
                columnOrder = CcddUtilities.removeTrailer(columnOrder, ":");
            }
            // Create a list to store the names of all tables of the specified type
            List<String> tableNamesList = new ArrayList<String>();
            // Build a table tree with all prototype and instance tables
            CcddTableTreeHandler tableTree = new CcddTableTreeHandler(ccddMain, TableTreeType.TABLES, editorDialog);
            // Step through each prototype table of the specified type
            for (String protoName : protoTableNames) {
                // Create a list of table path arrays for instances of this prototype table
                // name
                tableNamesList.addAll(tableTree.getTableTreePathList(protoName));
                // Get the database form of the table name
                String dbTable = protoName.toLowerCase();
                // Step through each addition
                for (String[] add : additions) {
                    // Get the input data type, and the column name in database form
                    InputDataType inputDataType = InputDataType.getInputTypeByName(add[1]);
                    String dbName = DefaultColumn.convertVisibleToDatabase(add[0], inputDataType, isStructure);
                    // Append the add command
                    command.append("ALTER TABLE " + dbTable + " ADD COLUMN " + dbName + " text DEFAULT ''; ");
                }
                // Step through each modification
                for (String[] mod : modifications) {
                    // Get the old and new column names in database form
                    String oldDbName = DefaultColumn.convertVisibleToDatabase(mod[0], InputDataType.getInputTypeByName(mod[2]), isStructure);
                    String newDbName = DefaultColumn.convertVisibleToDatabase(mod[1], InputDataType.getInputTypeByName(mod[3]), isStructure);
                    // Check if the database form of the name changed
                    if (!oldDbName.equals(newDbName)) {
                        // Append the modify command
                        command.append("ALTER TABLE " + dbTable + " RENAME COLUMN " + oldDbName + " TO " + newDbName + "; ");
                    }
                }
                // Step through each deletion
                for (String[] del : deletions) {
                    // Get the input data type, and the column name in database form
                    InputDataType inputDataType = InputDataType.getInputTypeByName(del[1]);
                    String dbName = DefaultColumn.convertVisibleToDatabase(del[0], inputDataType, isStructure);
                    // Append the delete command
                    command.append("ALTER TABLE " + dbTable + " DROP COLUMN " + dbName + "; ");
                }
                // Check if the column order changed
                if (columnOrder.length() != 0) {
                    // Replace the column order for all tables matching this table name. This
                    // resets the column order for all users
                    command.append("UPDATE " + InternalTable.ORDERS.getTableName() + " SET " + OrdersColumn.COLUMN_ORDER.getColumnName() + " = '" + columnOrder + "' WHERE " + OrdersColumn.TABLE_PATH.getColumnName() + " ~ E'^" + protoName + "(,|$)'; ");
                }
            }
            // exist
            if ((!modifications.isEmpty() || !deletions.isEmpty()) && protoTableNames.length != 0) {
                // ////////////////////////////////////////////////////////////////////////////
                // Build the sub-command required to detect references to tables of the
                // affected type in the custom values, links, and telemetry scheduler tables
                // ////////////////////////////////////////////////////////////////////////////
                StringBuilder valuesCmd = new StringBuilder("");
                StringBuilder linksCmd = new StringBuilder("");
                StringBuilder tlmSchCmd = new StringBuilder("");
                // Step through each prototype table of the specified type
                for (String protoName : protoTableNames) {
                    // Build the table name comparison command for the custom values table
                    valuesCmd.append(ValuesColumn.TABLE_PATH.getColumnName() + " ~ E'[^,]+," + protoName + "\\.[^,]+,[^,]+$' OR ");
                }
                // Remove the trailing 'OR' and prepend an 'AND' to complete the custom values
                // command
                valuesCmd = CcddUtilities.removeTrailer(valuesCmd, " OR ");
                valuesCmd.insert(0, " AND (");
                valuesCmd.append(")");
                // Check if the table type represents a structure
                if (isStructure && wasStructure) {
                    // Step through each prototype table of the specified type
                    for (String protoName : protoTableNames) {
                        // Build the table name comparison command for the links and telemetry
                        // scheduler tables
                        linksCmd.append(LinksColumn.MEMBER.getColumnName() + " ~ E'(?:" + protoName + ",|[^,]+," + protoName + "\\.[^,]+,[^,]+$)' OR ");
                        tlmSchCmd.append(TlmSchedulerColumn.MEMBER.getColumnName() + " ~ E'(?:" + tlmSchSeparator + protoName + ",|[^,]+," + protoName + "\\.[^,]+,[^,]+$)' OR ");
                    }
                    // Remove the trailing 'OR' and prepend an 'AND' to complete the links and
                    // telemetry scheduler table commands
                    linksCmd = CcddUtilities.removeTrailer(linksCmd, " OR ");
                    linksCmd.insert(0, " AND (");
                    linksCmd.append(")");
                    tlmSchCmd = CcddUtilities.removeTrailer(tlmSchCmd, " OR ");
                    tlmSchCmd.insert(0, " AND (");
                    tlmSchCmd.append(")");
                }
                // doing so
                if (!isStructure && wasStructure) {
                    boolean hasSharedRate = false;
                    // Step through each rate column in the table type definition
                    for (int column : originalDefn.getColumnIndicesByInputType(InputDataType.RATE)) {
                        // Get the rate column name (as seen by the user)
                        String rateName = originalDefn.getColumnNamesUser()[column];
                        // Check if this is the only table type using this rate column name
                        if (rateHandler.getRateInformationByRateName(rateName).getNumSharedTableTypes() == 1) {
                            // Delete all entries in the links and telemetry scheduler tables
                            // that reference this rate name
                            command.append(deleteAllLinkAndTlmRateRefs(rateName));
                        } else // The rate is shared with another table type
                        {
                            // Set the flag indicating the table type has a shared rate
                            hasSharedRate = true;
                        }
                    }
                    // the specific table references in these internal tables
                    if (hasSharedRate) {
                        // Remove all references to tables of the changed type in the links and
                        // telemetry scheduler tables
                        command.append(deleteLinkAndTlmRateRef(".+", linksCmd, tlmSchCmd));
                    }
                }
                // Step through each modification
                for (String[] mod : modifications) {
                    // Check if the column name changed
                    if (!mod[0].equals(mod[1])) {
                        // Append the modify command for the custom values table
                        command.append("UPDATE " + InternalTable.VALUES.getTableName() + " SET " + ValuesColumn.COLUMN_NAME.getColumnName() + " = '" + mod[1] + "' WHERE " + ValuesColumn.COLUMN_NAME.getColumnName() + " = '" + mod[0] + "'" + valuesCmd + "; ");
                    }
                    // was a rate
                    if (isStructure && wasStructure && mod[2].equals(InputDataType.RATE.getInputName())) {
                        // column
                        if (!mod[3].equals(InputDataType.RATE.getInputName())) {
                            // Check if the rate name is used by another structure table type
                            if (rateHandler.getRateInformationByRateName(mod[0]).getNumSharedTableTypes() > 1) {
                                // Remove all references to tables of the changed type in the
                                // links and telemetry scheduler tables
                                command.append(deleteLinkAndTlmRateRef(mod[0], linksCmd, tlmSchCmd));
                            } else // The rate name is unique to this table type
                            {
                                // Remove all references to the original rate column name in
                                // the links and telemetry scheduler tables
                                command.append(deleteAllLinkAndTlmRateRefs(mod[0]));
                            }
                        } else // Check if the rate column name changed
                        if (!mod[0].equals(mod[1])) {
                            // table type
                            if (rateHandler.getRateInformationByRateName(mod[0]).getNumSharedTableTypes() > 1) {
                                // Remove all references to tables of the changed type in the
                                // links and telemetry scheduler tables
                                command.append(deleteLinkAndTlmRateRef(mod[0], linksCmd, tlmSchCmd));
                            } else // type (i.e., the rate name is unique to this table type)
                            if (rateHandler.getRateInformationByRateName(mod[1]) == null) {
                                // Append the modify command for the links and telemetry
                                // scheduler table
                                command.append("UPDATE " + InternalTable.LINKS.getTableName() + " SET " + LinksColumn.RATE_NAME.getColumnName() + " = '" + mod[1] + "' WHERE " + LinksColumn.RATE_NAME.getColumnName() + " = '" + mod[0] + "'; UPDATE " + InternalTable.TLM_SCHEDULER.getTableName() + " SET " + TlmSchedulerColumn.RATE_NAME.getColumnName() + " = '" + mod[1] + "' WHERE " + TlmSchedulerColumn.RATE_NAME.getColumnName() + " = '" + mod[0] + "'; ");
                            } else // The new rate name is already in use
                            {
                                // Remove all references to the original rate column name in
                                // the links and telemetry scheduler tables
                                command.append(deleteAllLinkAndTlmRateRefs(mod[0]));
                            }
                        }
                    }
                }
                // Step through each deletion
                for (String[] del : deletions) {
                    // Append the delete command for the custom values table
                    command.append("DELETE FROM " + InternalTable.VALUES.getTableName() + " WHERE " + ValuesColumn.COLUMN_NAME.getColumnName() + " = '" + del[0] + "'" + valuesCmd + "; ");
                    // deleted
                    if (isStructure && wasStructure && del[1].equals(InputDataType.RATE.getInputName())) {
                        // Check if the rate name is used by another structure table type
                        if (rateHandler.getRateInformationByRateName(del[0]).getNumSharedTableTypes() > 1) {
                            // Remove all references to tables of the changed type in the links
                            // and telemetry scheduler tables
                            command.append(deleteLinkAndTlmRateRef(del[0], linksCmd, tlmSchCmd));
                        } else // The rate name is unique to this table type
                        {
                            // Remove all references to the original rate column name in the
                            // links and telemetry/scheduler tables
                            command.append(deleteAllLinkAndTlmRateRefs(del[0]));
                        }
                    }
                }
            }
            // Create a field handler to store the data field information
            CcddFieldHandler fieldHandler = new CcddFieldHandler(ccddMain, null, editorDialog);
            // Step through each table of the specified type
            for (String tableName : tableNamesList) {
                // Set the flag to indicate if the table is a root structure
                boolean isRootStruct = isStructure && rootStructures.contains(tableName);
                // Get the existing data fields for this table
                fieldHandler.buildFieldInformation(tableName);
                // Get the number of separator and line break fields
                int numSep = fieldHandler.getFieldTypeCount(InputDataType.SEPARATOR);
                int numBrk = fieldHandler.getFieldTypeCount(InputDataType.BREAK);
                int sepCount = 0;
                int brkCount = 0;
                boolean isChanges = false;
                // Step through the default data fields for this table type
                for (FieldInformation fieldInfo : fieldInformation) {
                    // Check if this is a separator
                    if (fieldInfo.getInputType().equals(InputDataType.SEPARATOR)) {
                        // Increment the separator counter
                        sepCount++;
                    } else // Check if this is a line break
                    if (fieldInfo.getInputType().equals(InputDataType.BREAK)) {
                        // Increment the line break counter
                        brkCount++;
                    }
                    // Check if the data field meets the criteria of a new field for this table
                    if ((// The table doesn't have this data field
                    (fieldHandler.getFieldInformationByName(tableName, fieldInfo.getFieldName()) == null)) && // this table
                    (!tableName.contains(".") || fieldHandler.isFieldApplicable(tableName, fieldInfo.getApplicabilityType().getApplicabilityName(), isRootStruct)) || // separator in the type editor exceeds the number already in the table
                    (fieldInfo.getInputType().equals(InputDataType.SEPARATOR) && sepCount > numSep) || (fieldInfo.getInputType().equals(InputDataType.BREAK) && brkCount > numBrk)) {
                        // Add the data field to the table and set the flag indicating a change
                        // has been made
                        fieldHandler.addField(tableName, fieldInfo.getFieldName(), fieldInfo.getDescription(), fieldInfo.getSize(), fieldInfo.getInputType().getInputName(), fieldInfo.isRequired(), fieldInfo.getApplicabilityType().getApplicabilityName(), fieldInfo.getValue());
                        isChanges = true;
                    } else // overwritten, and if the field value(s) changed
                    if (overwriteFields && fieldHandler.updateField(new FieldInformation(tableName, fieldInfo.getFieldName(), fieldInfo.getDescription(), fieldInfo.getSize(), fieldInfo.getInputType().getInputName(), fieldInfo.isRequired(), fieldInfo.getApplicabilityType().getApplicabilityName(), fieldInfo.getValue()))) {
                        // Set the flag indicating a change has been made
                        isChanges = true;
                    }
                }
                // Check if any fields were added
                if (isChanges) {
                    // Create the command to modify the table's data field entries
                    command.append(modifyFieldsCommand(tableName, fieldHandler.getFieldInformation()));
                }
            }
            // Convert the list of modified tables names to an array
            tableNames = tableNamesList.toArray(new String[0]);
            // Check if any table of this type exists
            if (tableNames.length != 0) {
                // Convert the array of tables names into a single string and shorten it if too
                // long
                names = " and table(s) '</b>" + getShortenedTableNames(tableNames) + "<b>'";
            }
            // Build the command to update the data fields table and the telemetry scheduler
            // table comment (rate parameters)
            command.append(modifyFieldsCommand(CcddFieldHandler.getFieldTypeName(typeName), fieldInformation));
        }
        try {
            // Execute the command to change the table type and any table's of this type
            dbCommand.executeDbCommand(command.toString(), editorDialog);
            // Check if the type changed from being a structure to not being a structure
            if (!isStructure && wasStructure) {
                // Update the list of root structure tables
                rootStructures = getRootStructures(editorDialog);
            }
            // Log that updating the table type succeeded
            eventLog.logEvent(SUCCESS_MSG, "Table type '" + typeName + "'" + CcddUtilities.removeHTMLTags(names) + " updated");
        } catch (SQLException se) {
            // Inform the user that updating the tables failed
            eventLog.logFailEvent(editorDialog, "Cannot update table type '" + typeName + "'" + CcddUtilities.removeHTMLTags(names) + "; cause '" + se.getMessage() + "'", "<html><b>Cannot update table type '</b>" + typeName + "<b>'" + names);
            errorFlag = true;
        }
        // structure
        if (!errorFlag && (isStructure || wasStructure)) {
            // Step through each column addition
            for (String[] add : additions) {
                // Check if the column is a rate column
                if (add[1].equals(InputDataType.RATE.getInputName())) {
                    // Add the rate column to the rate information
                    rateHandler.addRateInformation(add[0]);
                }
            }
            // Step through each column modification
            for (String[] mod : modifications) {
                // Check if the column changed from a rate column to not being a rate column
                if (mod[2].equals(InputDataType.RATE.getInputName()) && !mod[3].equals(InputDataType.RATE.getInputName())) {
                    // Delete the rate column from the rate information
                    rateHandler.deleteRateInformation(mod[2]);
                } else // Check if the column changed from not being a rate column to a rate column
                if (!mod[2].equals(InputDataType.RATE.getInputName()) && mod[3].equals(InputDataType.RATE.getInputName())) {
                    // Add the rate column to the rate information
                    rateHandler.addRateInformation(mod[3]);
                } else // changed)
                if (mod[3].equals(InputDataType.RATE.getInputName())) {
                    // Rename (or add if the rate column is shared with another table type) the
                    // rate column in the rate information
                    rateHandler.renameRateInformation(mod[0], mod[1]);
                }
            }
            // Step through each column deletion
            for (String[] del : deletions) {
                // Check if the column is a rate column
                if (del[1].equals(InputDataType.RATE.getInputName())) {
                    // Delete the rate column from the rate information
                    rateHandler.deleteRateInformation(del[0]);
                }
            }
            // Update the rate column information and store it in the project database
            rateHandler.setRateInformation();
            storeRateParameters(editorDialog);
            // Update the database functions that collect structure table members and
            // structure-defining column data
            dbControl.createStructureColumnFunctions();
        }
        // Perform the type modification clean-up steps
        editorDialog.doTypeModificationComplete(errorFlag, editor, tableNames);
    } catch (Exception e) {
        // Display a dialog providing details on the unanticipated error
        CcddUtilities.displayException(e, editorDialog);
    }
}
Also used : SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) CCDDException(CCDD.CcddClassesDataTable.CCDDException) SQLException(java.sql.SQLException) TypeDefinition(CCDD.CcddTableTypeHandler.TypeDefinition) InputDataType(CCDD.CcddConstants.InputDataType) FieldInformation(CCDD.CcddClassesDataTable.FieldInformation)

Example 10 with TypeDefinition

use of CCDD.CcddTableTypeHandler.TypeDefinition in project CCDD by nasa.

the class CcddFileIOHandler method createTablesFromDefinitions.

/**
 ********************************************************************************************
 * Create one or more data tables from the supplied table definitions
 *
 * @param tableDefinitions
 *            list of table definitions for the table(s) to create
 *
 * @param replaceExisting
 *            true to replace a table that already exists in the database
 *
 * @param parent
 *            GUI component calling this method
 *
 * @throws CCDDException
 *             If the table path name is invalid or the table cannot be created from the table
 *             definition
 ********************************************************************************************
 */
private void createTablesFromDefinitions(List<TableDefinition> tableDefinitions, boolean replaceExisting, final Component parent) throws CCDDException {
    cancelImport = false;
    boolean prototypesOnly = true;
    List<String> skippedTables = new ArrayList<String>();
    // Get the list of all tables, including the paths for child structure tables
    CcddTableTreeHandler tableTree = new CcddTableTreeHandler(ccddMain, TableTreeType.TABLES, parent);
    List<String> allTables = tableTree.getTableTreePathList(null);
    // tables
    for (int loop = 1; loop <= 2 && !cancelImport; loop++) {
        // Step through each table definition
        for (TableDefinition tableDefn : tableDefinitions) {
            // Check if the table path/name format is valid
            if (!tableDefn.getName().matches(InputDataType.VARIABLE.getInputMatch() + "(?:$|(?:," + InputDataType.VARIABLE.getInputMatch() + "\\." + InputDataType.VARIABLE.getInputMatch() + ")+)")) {
                // Inform the user the table path/name isn't in the correct format
                throw new CCDDException("Invalid table path/name '</b>" + tableDefn.getName() + "<b>' format");
            }
            // Check if the table import was canceled by the user
            if (cancelImport) {
                // Add the table to the list of those skipped
                skippedTables.add(tableDefn.getName());
                continue;
            }
            // or if this is a child table and this is the second pass
            if (!tableDefn.getData().isEmpty() && (!tableDefn.getName().contains(",") != !prototypesOnly)) {
                // Get the table type definition for this table
                TypeDefinition typeDefn = tableTypeHandler.getTypeDefinition(tableDefn.getTypeName());
                // Get the number of table columns
                int numColumns = typeDefn.getColumnCountVisible();
                // Create the table information for the new table
                TableInformation tableInfo = new TableInformation(tableDefn.getTypeName(), tableDefn.getName(), new String[0][0], tableTypeHandler.getDefaultColumnOrder(tableDefn.getTypeName()), tableDefn.getDescription(), !tableDefn.getName().contains("."), tableDefn.getDataFields().toArray(new String[0][0]));
                // Check if the new table is not a prototype
                if (!tableInfo.isPrototype()) {
                    // Break the path into the individual structure variable references
                    String[] ancestors = tableInfo.getTablePath().split(",");
                    // table
                    for (int index = ancestors.length - 1; index >= 0 && !cancelImport; index--) {
                        // Split the ancestor into the data type (i.e., structure name) and
                        // variable name
                        String[] typeAndVar = ancestors[index].split("\\.");
                        // Check if the ancestor prototype table doesn't exist
                        if (!dbTable.isTableExists(typeAndVar[0].toLowerCase(), ccddMain.getMainFrame())) {
                            // Create the table information for the new prototype table
                            TableInformation ancestorInfo = new TableInformation(tableDefn.getTypeName(), typeAndVar[0], new String[0][0], tableTypeHandler.getDefaultColumnOrder(tableDefn.getTypeName()), "", true, tableDefn.getDataFields().toArray(new String[0][0]));
                            // Check if this is the child table and not one of its ancestors
                            if (index == ancestors.length - 1) {
                                // Create a list to store a copy of the cell data
                                List<String> protoData = new ArrayList<String>(tableDefn.getData());
                                // Step through each row of the cell data
                                for (int cellIndex = 0; cellIndex < tableDefn.getData().size(); cellIndex += numColumns) {
                                    // Step through each column in the row
                                    for (int colIndex = 0; colIndex < numColumns; colIndex++) {
                                        // type
                                        if (!DefaultColumn.isTypeRequiredColumn((typeDefn.isStructure() ? TYPE_STRUCTURE : (typeDefn.isCommand() ? TYPE_COMMAND : TYPE_OTHER)), typeDefn.getInputTypesVisible()[colIndex])) {
                                            // Replace the non-required column value with a
                                            // blank. The child's non-required values are
                                            // therefore not inherited from the prototype
                                            protoData.set(cellIndex + colIndex, "");
                                        }
                                    }
                                }
                                // the protected column data
                                if (!createImportedTable(ancestorInfo, protoData, numColumns, replaceExisting, "Cannot create prototype '" + ancestorInfo.getPrototypeName() + "' of child table", allTables, parent)) {
                                    // Add the skipped table to the list
                                    skippedTables.add(ancestorInfo.getTablePath());
                                }
                            } else // This is an ancestor of the child table
                            {
                                // Split the ancestor into the data type (i.e., structure name)
                                // and variable name
                                typeAndVar = ancestors[index + 1].split("\\.|$", -1);
                                // Add the variable reference to the new table
                                String[] rowData = new String[typeDefn.getColumnCountVisible()];
                                Arrays.fill(rowData, "");
                                rowData[typeDefn.getVisibleColumnIndexByUserName(typeDefn.getColumnNameByInputType(InputDataType.VARIABLE))] = typeAndVar[1];
                                rowData[typeDefn.getVisibleColumnIndexByUserName(typeDefn.getColumnNameByInputType(InputDataType.PRIM_AND_STRUCT))] = typeAndVar[0];
                                // the protected column data
                                if (!createImportedTable(ancestorInfo, Arrays.asList(rowData), numColumns, replaceExisting, "Cannot create prototype '" + ancestorInfo.getPrototypeName() + "' of child table's ancestor", allTables, parent)) {
                                    // Add the skipped table to the list
                                    skippedTables.add(ancestorInfo.getTablePath());
                                }
                            }
                        }
                    }
                    // Load the table's prototype data from the database and copy the
                    // prototype's data to the table
                    TableInformation protoInfo = dbTable.loadTableData(tableInfo.getPrototypeName(), false, false, false, ccddMain.getMainFrame());
                    tableInfo.setData(protoInfo.getData());
                }
                // Create a table from the imported information
                if (!createImportedTable(tableInfo, tableDefn.getData(), numColumns, replaceExisting, "Cannot create prototype '" + tableInfo.getPrototypeName() + "'", allTables, parent)) {
                    // Add the skipped table to the list
                    skippedTables.add(tableInfo.getTablePath());
                }
            }
        }
        prototypesOnly = false;
    }
    // Check if any tables were skipped
    if (!skippedTables.isEmpty()) {
        // Inform the user that one or more tables were not imported
        new CcddDialogHandler().showMessageDialog(parent, "<html><b>Table(s) not imported<br>'</b>" + dbTable.getShortenedTableNames(skippedTables.toArray(new String[0])) + "<b>';<br>table already exists", "Import Warning", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
    }
    // Store the table types
    dbTable.storeInformationTable(InternalTable.TABLE_TYPES, null, null, parent);
    // Store the data types
    dbTable.storeInformationTable(InternalTable.DATA_TYPES, CcddUtilities.removeArrayListColumn(dataTypeHandler.getDataTypeData(), DataTypesColumn.OID.ordinal()), null, parent);
    // Check if any macros are defined
    if (!macroHandler.getMacroData().isEmpty()) {
        // Store the macros in the database
        dbTable.storeInformationTable(InternalTable.MACROS, CcddUtilities.removeArrayListColumn(macroHandler.getMacroData(), MacrosColumn.OID.ordinal()), null, parent);
    }
    // Check if any reserved message IDs are defined
    if (!rsvMsgIDHandler.getReservedMsgIDData().isEmpty()) {
        // Store the reserved message IDs in the database
        dbTable.storeInformationTable(InternalTable.RESERVED_MSG_IDS, CcddUtilities.removeArrayListColumn(rsvMsgIDHandler.getReservedMsgIDData(), ReservedMsgIDsColumn.OID.ordinal()), null, parent);
    }
}
Also used : CCDDException(CCDD.CcddClassesDataTable.CCDDException) ArrayList(java.util.ArrayList) TableDefinition(CCDD.CcddClassesDataTable.TableDefinition) TableInformation(CCDD.CcddClassesDataTable.TableInformation) TypeDefinition(CCDD.CcddTableTypeHandler.TypeDefinition)

Aggregations

TypeDefinition (CCDD.CcddTableTypeHandler.TypeDefinition)64 TableInformation (CCDD.CcddClassesDataTable.TableInformation)30 ArrayList (java.util.ArrayList)24 CCDDException (CCDD.CcddClassesDataTable.CCDDException)18 AssociatedColumns (CCDD.CcddClassesDataTable.AssociatedColumns)10 SQLException (java.sql.SQLException)9 JSONArray (org.json.simple.JSONArray)8 JSONObject (org.json.simple.JSONObject)8 TableTypeDefinition (CCDD.CcddClassesDataTable.TableTypeDefinition)6 IOException (java.io.IOException)6 TableDefinition (CCDD.CcddClassesDataTable.TableDefinition)5 BackgroundCommand (CCDD.CcddBackgroundCommand.BackgroundCommand)4 ArrayListMultiple (CCDD.CcddClassesComponent.ArrayListMultiple)4 FileEnvVar (CCDD.CcddClassesComponent.FileEnvVar)3 FieldInformation (CCDD.CcddClassesDataTable.FieldInformation)3 Component (java.awt.Component)3 GridBagConstraints (java.awt.GridBagConstraints)3 GridBagLayout (java.awt.GridBagLayout)3 Insets (java.awt.Insets)3 ResultSet (java.sql.ResultSet)3