/** * Does the work for the decoding. May throw an unchecked exception, for instance a * ClassCastException if certain metadata items are present but have the wrong type (not likely * excepting deliberate sabotage, but conceivable). * * @param table encoded table * @param location table location string * @param controlWindow control window * @return topcat model, or null */ private TopcatModel doDecode(StarTable inTable, String location, ControlWindow controlWindow) { CodecTable codec = new CodecTable(inTable); /* Determine if this is a TopcatModel encoded by this class. */ if (!Boolean.TRUE.equals(codec.getCodecValue(IS_TCMODEL_INFO))) { return null; } TopcatModel tcModel = TopcatModel.createRawTopcatModel(codec.getDataTable(), location, controlWindow); /* Get label. */ tcModel.setLabel((String) codec.getCodecValue(LABEL_INFO)); /* Get columns. This is a bit involved, since a TopcatModel has * both a TableColumnModel and a ColumnList which must be updated * in a consistent way, to reflect the column order and which * columns are currently visible. */ /* First get a record of the order of columns and their visibility. */ int[] icols = (int[]) codec.getCodecValue(COLS_INDEX_INFO); boolean[] activs = (boolean[]) codec.getCodecValue(COLS_VISIBLE_INFO); TableColumnModel colModel = tcModel.getColumnModel(); ColumnList colList = tcModel.getColumnList(); int ncol = colModel.getColumnCount(); assert ncol == colList.size(); TableColumn[] tcols = new TableColumn[ncol]; for (int ic = 0; ic < ncol; ic++) { tcols[ic] = colList.getColumn(icols[ic]); } /* Reorder the columns in the TableColumnModel to match the saved * order. This has the effect of updating the ColumnList as well, * since it is a listener. */ for (int ic = 0; ic < ncol; ic++) { TableColumn tcol = tcols[ic]; if (colModel.getColumn(ic) != tcol) { int kc = -1; for (int jc = ic; jc < ncol && kc < 0; jc++) { if (colModel.getColumn(jc) == tcol) { kc = jc; } } assert kc >= 0; colModel.moveColumn(kc, ic); } } for (int ic = 0; ic < ncol; ic++) { assert colModel.getColumn(ic) == tcols[ic]; assert colList.getColumn(ic) == tcols[ic]; } /* Finally flag each column as visible or not, according to the saved * state. */ for (int ic = 0; ic < ncol; ic++) { colList.setActive(ic, activs[ic]); } /* Get whether to broadcast rows. */ tcModel.getRowSendModel().setSelected(Boolean.TRUE.equals(codec.getCodecValue(SEND_ROWS_INFO))); /* Get current subset index. */ Integer indexCurrentSubset = (Integer) codec.getCodecValue(CURRENT_SUBSET_INFO); int iCurrentSubset = indexCurrentSubset != null ? indexCurrentSubset.intValue() : -1; /* Get subsets. */ String[] subsetNames = (String[]) codec.getCodecValue(SUBSET_NAMES_INFO); if (subsetNames != null && subsetNames.length > 0) { RowSubset currentSubset = null; int nset = subsetNames.length; int icolSubsets = codec.getCodecColumnIndex(SUBSET_FLAGS_INFO); List<RowSubset> setList = new ArrayList<RowSubset>(); for (int is = 0; is < nset; is++) { RowSubset rset = createRowSubset(subsetNames[is], inTable, icolSubsets, is); if (rset != null) { setList.add(rset); } if (is == iCurrentSubset) { currentSubset = rset; } } for (RowSubset rset : setList) { tcModel.addSubset(rset); } if (currentSubset != null) { tcModel.applySubset(currentSubset); } } /* Get sort order. */ Integer icolSort = (Integer) codec.getCodecValue(SORT_COLUMN_INFO); if (icolSort != null) { int icSort = icolSort.intValue(); boolean sortSense = Boolean.TRUE.equals(codec.getCodecValue(SORT_SENSE_INFO)); TableColumn tcolSort = colList.getColumn(icSort); tcModel.getSortSenseModel().setSelected(sortSense); tcModel.sortBy(new SortOrder(tcolSort), sortSense); } /* Return result. */ return tcModel; }