/* * File : TableColumnManager.java * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.table.impl; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableColumnCoreCreationListener; import com.aelitis.azureus.ui.common.table.TableStructureEventDispatcher; import com.aelitis.azureus.util.MapUtils; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.*; /** Holds a list of column definitions (TableColumnCore) for * all the tables in Azureus. * * Column definitions are added via * PluginInterface.addColumn(TableColumn) * See Use javadoc section for more uses. * * @author Oliver (Original Code) * @author TuxPaper (Modifications to make generic & comments) */ @SuppressWarnings("rawtypes") public class TableColumnManager { private static final String CONFIG_FILE = "tables.config"; static{ COConfigurationManager.addResetToDefaultsListener( new COConfigurationManager.ResetToDefaultsListener() { public void reset() { getInstance().resetAllTables(); } }); } private static TableColumnManager instance; private static AEMonitor class_mon = new AEMonitor( "TableColumnManager" ); /* Holds all the TableColumnCore objects. * key = TABLE_* type (see TableColumnCore) * value = Map: * key = column name * value = TableColumnCore object */ private Map<String,Map> items; private AEMonitor items_mon = new AEMonitor( "TableColumnManager:items" ); /** * Holds the order in which the columns are auto-hidden * * key = TABLE_* type * value = List of TableColumn, indexed in the order they should be removed */ private Map autoHideOrder = new LightHashMap(); /** * key = table; value = map of columns * * Do not access directly. Use {@link #getTableConfigMap(String)} * or {@link #saveTableConfigs()} */ private Object tablesConfig; private long lastTableConfigAccess; private static Comparator<TableColumn> orderComparator; private Map<String, TableColumnCreationListener> mapColumnIDsToListener = new LightHashMap<String, TableColumnCreationListener>(); private Map<Class, List> mapDataSourceTypeToColumnIDs = new LightHashMap<Class, List>(); /** * key = TableID; value = table column ids */ private Map<String, String[]> mapTableDefaultColumns = new LightHashMap<String, String[]>(); private static final Map<String, String> mapResetTable_Version; private static final boolean RERESET = false; static { orderComparator = new Comparator<TableColumn>() { public int compare(TableColumn col0, TableColumn col1) { if (col0 == null || col1 == null) { return 0; } int iPositionA = col0.getPosition(); if (iPositionA < 0) iPositionA = 0xFFFF + iPositionA; int iPositionB = col1.getPosition(); if (iPositionB < 0) iPositionB = 0xFFFF + iPositionB; int i = iPositionA - iPositionB; if (i != 0 || iPositionA == (0xFFFF + TableColumn.POSITION_LAST)) { return i; } String name0 = col0.getName(); String name1 = col1.getName(); String[] names = getInstance().getDefaultColumnNames(col0.getTableID()); if (names != null) { for (String name : names) { if (name.equals(name0)) { return -1; } if (name.equals(name1)) { return 1; } } } return name0.compareTo(name1); } }; mapResetTable_Version = new HashMap<String, String>(); mapResetTable_Version.put("DeviceLibrary", "4.4.0.7"); mapResetTable_Version.put("TranscodeQueue", "4.4.0.7"); mapResetTable_Version.put(TableManager.TABLE_MYTORRENTS_COMPLETE_BIG, "4.4.0.7"); mapResetTable_Version.put(TableManager.TABLE_MYTORRENTS_ALL_BIG, "4.4.0.7"); mapResetTable_Version.put(TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG, "4.4.0.7"); mapResetTable_Version.put(TableManager.TABLE_MYTORRENTS_UNOPENED_BIG, "4.6.0.1"); mapResetTable_Version.put(TableManager.TABLE_MYTORRENTS_UNOPENED, "4.6.0.1"); } private TableColumnManager() { items = new HashMap<String,Map>(); } /** Retrieve the static TableColumnManager instance * @return the static TableColumnManager instance */ public static TableColumnManager getInstance() { try{ class_mon.enter(); if(instance == null) instance = new TableColumnManager(); return instance; }finally{ class_mon.exit(); } } /** Adds a column definition to the list * @param item The column definition object */ public void addColumns(TableColumnCore[] itemsToAdd) { try { items_mon.enter(); for (int i = 0; i < itemsToAdd.length; i++) { TableColumnCore item = itemsToAdd[i]; if (item == null || item.isRemoved()){ continue; } String name = item.getName(); String sTableID = item.getTableID(); Map mTypes = (Map) items.get(sTableID); if (mTypes == null) { // LinkedHashMap to preserve order mTypes = new LinkedHashMap(); items.put(sTableID, mTypes); } if (!mTypes.containsKey(name)) { mTypes.put(name, item); Map mapColumnConfig = getTableConfigMap(sTableID); item.loadSettings(mapColumnConfig); } } for (int i = 0; i < itemsToAdd.length; i++) { TableColumnCore item = itemsToAdd[i]; if (item != null && !item.isRemoved() && !item.getColumnAdded()) { item.setColumnAdded(); } } } catch (Exception e) { System.out.println("Error while adding Table Column Extension"); Debug.printStackTrace(e); } finally { items_mon.exit(); } } /** Adds a column definition to the list * @param item The column definition object */ public void removeColumns(TableColumnCore[] itemsToRemove) { try { items_mon.enter(); for (int i = 0; i < itemsToRemove.length; i++) { TableColumnCore item = itemsToRemove[i]; String name = item.getName(); String sTableID = item.getTableID(); Map mTypes = (Map) items.get(sTableID); if (mTypes != null) { if ( mTypes.remove(name) != null ){ } } } } catch (Exception e) { System.out.println("Error while adding Table Column Extension"); Debug.printStackTrace(e); } finally { items_mon.exit(); } } /** Retrieves TableColumnCore objects of a particular type. * @param sTableID TABLE_* constant. See {@link TableColumn} for list * of constants * @param forDataSourceType * * @return Map of column definition objects matching the supplied criteria. * key = name * value = TableColumnCore object */ public Map<String, TableColumnCore> getTableColumnsAsMap( Class forDataSourceType, String sTableID) { //System.out.println("getTableColumnsAsMap(" + sTableID + ")"); try{ items_mon.enter(); Map<String, TableColumnCore> mReturn = new LinkedHashMap(); Map<String, TableColumnCore> mTypes = getAllTableColumnCore( forDataSourceType, sTableID); if (mTypes != null) { mReturn.putAll(mTypes); } //System.out.println("getTableColumnsAsMap(" + sTableID + ") returnsize: " + mReturn.size()); return mReturn; }finally{ items_mon.exit(); } } public int getTableColumnCount(String sTableID) { Map mTypes = (Map)items.get(sTableID); if (mTypes == null) { return 0; } return mTypes.size(); } public TableColumnCore[] getAllTableColumnCoreAsArray( Class forDataSourceType, String tableID) { Map mTypes = getAllTableColumnCore(forDataSourceType, tableID); TableColumnCore[] columns = (TableColumnCore[]) mTypes.values().toArray( new TableColumnCore[mTypes.values().size()]); return columns; } public String[] getDefaultColumnNames(String tableID) { String[] columnNames = mapTableDefaultColumns.get(tableID); return columnNames; } public void setDefaultColumnNames(String tableID, TableColumn[] columns) { List<String>names = new ArrayList<String>( columns.length ); for ( TableColumn column: columns ){ if ( column.isVisible()){ names.add( column.getName()); } } setDefaultColumnNames( tableID, names.toArray( new String[ names.size()] )); } public void setDefaultColumnNames(String tableID, String[] columnNames) { mapTableDefaultColumns.put(tableID, columnNames); } /* private Map getAllTableColumnCore( Class forDataSourceType, String tableID) { String[] dstColumnIDs = new String[0]; if (forDataSourceType != null) { List listDST = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (listDST != null) { dstColumnIDs = (String[]) listDST.toArray(new String[0]); } if (forDataSourceType.equals(DownloadTypeComplete.class) || forDataSourceType.equals(DownloadTypeIncomplete.class)) { listDST = (List) mapDataSourceTypeToColumnIDs.get(Download.class); if (listDST != null && listDST.size() > 0) { String[] ids1 = (String[]) listDST.toArray(new String[0]); String[] ids2 = dstColumnIDs; dstColumnIDs = new String[ids2.length + ids1.length]; System.arraycopy(ids2, 0, dstColumnIDs, 0, ids2.length); System.arraycopy(ids1, 0, dstColumnIDs, ids2.length, ids1.length); } } else if (forDataSourceType.equals(Download.class)) { listDST = (List) mapDataSourceTypeToColumnIDs.get(DownloadTypeComplete.class); if (listDST != null && listDST.size() > 0) { String[] ids = (String[]) listDST.toArray(new String[listDST.size()]); dstColumnIDs = appendLists(ids, dstColumnIDs); } listDST = (List) mapDataSourceTypeToColumnIDs.get(DownloadTypeIncomplete.class); if (listDST != null && listDST.size() > 0) { String[] ids = (String[]) listDST.toArray(new String[listDST.size()]); dstColumnIDs = appendLists(ids, dstColumnIDs); } } } try { items_mon.enter(); Map mTypes = (Map) items.get(tableID); if (mTypes == null) { mTypes = new LinkedHashMap(); items.put(tableID, mTypes); } for (int i = 0; i < dstColumnIDs.length; i++) { String columnID = dstColumnIDs[i]; if (!mTypes.containsKey(columnID)) { try { TableColumnCreationListener l = mapColumnIDsToListener.get(forDataSourceType + "." + columnID); TableColumnCore tc = null; if (l instanceof TableColumnCoreCreationListener) { tc = ((TableColumnCoreCreationListener) l).createTableColumnCore( tableID, columnID); } if (tc == null) { tc = new TableColumnImpl(tableID, columnID); } l.tableColumnCreated(tc); addColumns(new TableColumnCore[] { tc }); } catch (Exception e) { Debug.out(e); } } } return mTypes; } finally { items_mon.exit(); } } */ /** * Will create columns for tableID if needed */ private Map<String, TableColumnCore> getAllTableColumnCore( Class forDataSourceType, String tableID) { Map mapExisting = null; try { items_mon.enter(); mapExisting = items.get(tableID); if (mapExisting == null) { mapExisting = new LinkedHashMap(); items.put(tableID, mapExisting); } if (forDataSourceType != null) { Map<Class<?>, List> mapDST = new HashMap<Class<?>, List>(); List listDST = mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (listDST != null && listDST.size() > 0) { mapDST.put(forDataSourceType, listDST); } if (forDataSourceType.equals(DownloadTypeComplete.class) || forDataSourceType.equals(DownloadTypeIncomplete.class)) { listDST = mapDataSourceTypeToColumnIDs.get(Download.class); if (listDST != null && listDST.size() > 0) { mapDST.put(Download.class, listDST); } } else if (Download.class.equals(forDataSourceType)) { listDST = mapDataSourceTypeToColumnIDs.get(DownloadTypeComplete.class); if (listDST != null && listDST.size() > 0) { mapDST.put(DownloadTypeComplete.class, listDST); } listDST = mapDataSourceTypeToColumnIDs.get(DownloadTypeIncomplete.class); if (listDST != null && listDST.size() > 0) { mapDST.put(DownloadTypeIncomplete.class, listDST); } } doAddCreate(mapExisting, tableID, mapDST); } } finally { items_mon.exit(); } return mapExisting; } /** * Helper for getAllTableColumnCore * @param types * @param listDST * * @since 4.0.0.5 */ private void doAddCreate(Map mTypes, String tableID, Map<Class<?>, List> mapDST) { ArrayList<TableColumnCore> listAdded = new ArrayList<TableColumnCore>(); for (Class forDataSourceType : mapDST.keySet()) { List listDST = mapDST.get(forDataSourceType); for (Iterator iter = listDST.iterator(); iter.hasNext();) { String columnID = (String) iter.next(); if (!mTypes.containsKey(columnID)) { try { TableColumnCreationListener l = mapColumnIDsToListener.get(forDataSourceType + "." + columnID); TableColumnCore tc = null; if (l instanceof TableColumnCoreCreationListener) { tc = ((TableColumnCoreCreationListener) l).createTableColumnCore( forDataSourceType, tableID, columnID); } if (tc == null) { tc = new TableColumnImpl(tableID, columnID); tc.addDataSourceType(forDataSourceType); } if (l != null) { l.tableColumnCreated(tc); } listAdded.add(tc); } catch (Exception e) { Debug.out(e); } } } } // this adds it to #items (among other things) addColumns(listAdded.toArray(new TableColumnCore[0])); } public String[] getTableIDs() { try { items_mon.enter(); Set<String> ids = items.keySet(); return( ids.toArray( new String[ids.size()])); } finally { items_mon.exit(); } } public String[] appendLists(String[] list1, String[] list2) { int size = list1.length + list2.length; String[] list = new String[size]; System.arraycopy(list1, 0, list, 0, list1.length); System.arraycopy(list2, 0, list, list1.length, list2.length); return list; } public TableColumnCore getTableColumnCore(String sTableID, String sColumnName) { Map mTypes = (Map)items.get(sTableID); if (mTypes == null) return null; return (TableColumnCore)mTypes.get(sColumnName); } public void ensureIntegrety(String sTableID) { Map mTypes = (Map)items.get(sTableID); if (mTypes == null) return; TableColumnCore[] tableColumns = (TableColumnCore[])mTypes.values().toArray(new TableColumnCore[mTypes.values().size()]); Arrays.sort(tableColumns, getTableColumnOrderComparator()); int iPos = 0; for (int i = 0; i < tableColumns.length; i++) { int iCurPos = tableColumns[i].getPosition(); if (iCurPos == TableColumnCore.POSITION_INVISIBLE) { tableColumns[i].setVisible(false); } else { tableColumns[i].setPositionNoShift(iPos++); } } if (iPos == 0) { String[] defaultColumnNames = getDefaultColumnNames(sTableID); if (defaultColumnNames != null) { int i = 0; for (String name : defaultColumnNames) { TableColumnCore column = getTableColumnCore(sTableID, name); if (column != null) { column.reset(); column.setVisible(true); column.setPositionNoShift(i++); } } saveTableColumns(null, sTableID); TableStructureEventDispatcher.getInstance(sTableID).tableStructureChanged(true, null); } } } public String getDefaultSortColumnName(String tableID) { Map mapTableConfig = getTableConfigMap(tableID); Object object = mapTableConfig.get("SortColumn"); if( object instanceof byte[]) object = new String((byte[])object); if (object instanceof String) { return (String) object; } String s = COConfigurationManager.getStringParameter(tableID + ".sortColumn"); if (s != null) { COConfigurationManager.removeParameter(tableID + ".sortColumn"); COConfigurationManager.removeParameter(tableID + ".sortAsc"); } return s; } public void setDefaultSortColumnName(String tableID, String columnName) { Map mapTableConfig = getTableConfigMap(tableID); Object existing = mapTableConfig.get( "SortColumn" ); if ( existing != null ){ String str = existing instanceof byte[]?new String((byte[])existing):(String)existing; if ( str.equals( columnName )){ return; } } mapTableConfig.put("SortColumn", columnName); saveTableConfigs(); } private void saveTableConfigs() { if (tablesConfig instanceof Map) { FileUtil.writeResilientConfigFile(CONFIG_FILE, (Map) tablesConfig); } } /** Saves all the user configurable Table Column settings at once, complete * with a COConfigurationManager.save(). * * @param sTableID Table to save settings for */ public void saveTableColumns(Class forDataSourceType, String sTableID) { try { Map mapTableConfig = getTableConfigMap(sTableID); TableColumnCore[] tcs = getAllTableColumnCoreAsArray(forDataSourceType, sTableID); for (int i = 0; i < tcs.length; i++) { if (tcs[i] != null) tcs[i].saveSettings(mapTableConfig); } saveTableConfigs(); } catch (Exception e) { Debug.out(e); } } public boolean loadTableColumnSettings(Class forDataSourceType, String sTableID) { try { Map mapTableConfig = getTableConfigMap(sTableID); int size = mapTableConfig.size(); if (size == 0) { return false; } boolean hasColumnInfo = false; for (Object key : mapTableConfig.keySet()) { if (key instanceof String) { if (((String) key).startsWith("Column.")) { hasColumnInfo = true; break; } } } if (!hasColumnInfo) { return false; } TableColumnCore[] tcs = getAllTableColumnCoreAsArray(forDataSourceType, sTableID); for (int i = 0; i < tcs.length; i++) { if (tcs[i] != null) tcs[i].loadSettings(mapTableConfig); } } catch (Exception e) { Debug.out(e); } return true; } private Map getTablesConfigMap() { lastTableConfigAccess = SystemTime.getMonotonousTime(); if (tablesConfig == null) { tablesConfig = FileUtil.readResilientConfigFile(CONFIG_FILE); if (RERESET) { for (Object map : ((Map) tablesConfig).values()) { ((Map) map).remove("last.reset"); } } // Dispose of tableconfigs after XXs.. saves up to 50k SimpleTimer.addEvent( "DisposeTableConfigMap", SystemTime.getOffsetTime(30000), new TimerEventPerformer() { public void perform( TimerEvent event ) { synchronized( TableColumnManager.this ){ long now = SystemTime.getMonotonousTime(); if ( now - lastTableConfigAccess > 25000 ){ tablesConfig = null; }else{ SimpleTimer.addEvent( "DisposeTableConfigMap", SystemTime.getOffsetTime(30000), this ); } } } }); } return (Map) tablesConfig; } public Map getTableConfigMap(String sTableID) { synchronized (this) { String key = "Table." + sTableID; Map mapTablesConfig = getTablesConfigMap(); Map mapTableConfig = (Map) mapTablesConfig.get(key); if (mapTableConfig == null) { mapTableConfig = new HashMap(); mapTablesConfig.put("Table." + sTableID, mapTableConfig); } else { String resetIfLastResetBelowVersion = mapResetTable_Version.get(sTableID); if (resetIfLastResetBelowVersion != null) { String lastReset = MapUtils.getMapString(mapTableConfig, "last.reset", "0.0.0.0"); if (Constants.compareVersions(lastReset, resetIfLastResetBelowVersion) < 0) { mapTableConfig.clear(); mapTableConfig.put("last.reset", Constants.getBaseVersion()); saveTableConfigs(); mapResetTable_Version.remove(sTableID); } } } return mapTableConfig; } } public void setAutoHideOrder(String sTableID, String[] autoHideOrderColumnIDs) { ArrayList autoHideOrderList = new ArrayList(autoHideOrderColumnIDs.length); for (int i = 0; i < autoHideOrderColumnIDs.length; i++) { String sColumnID = autoHideOrderColumnIDs[i]; TableColumnCore column = getTableColumnCore(sTableID, sColumnID); if (column != null) { autoHideOrderList.add(column); } } autoHideOrder.put(sTableID, autoHideOrderList); } public List getAutoHideOrder(String sTableID) { List list = (List) autoHideOrder.get(sTableID); if (list == null) { return Collections.EMPTY_LIST; } return list; } /** * @param writer */ public void generateDiagnostics(IndentWriter writer) { try{ items_mon.enter(); writer.println("TableColumns"); for (Iterator iter = items.keySet().iterator(); iter.hasNext();) { String sTableID = (String)iter.next(); Map mTypes = (Map)items.get(sTableID); writer.indent(); writer.println(sTableID + ": " + mTypes.size() + " columns:"); writer.indent(); for (Iterator iter2 = mTypes.values().iterator(); iter2.hasNext();) { TableColumnCore tc = (TableColumnCore)iter2.next(); tc.generateDiagnostics(writer); } writer.exdent(); writer.exdent(); } } catch (Exception e) { e.printStackTrace(); } finally { items_mon.exit(); } } public static Comparator<TableColumn> getTableColumnOrderComparator() { return orderComparator; } /** * @param forDataSourceType * @param columnID * @param listener * * @since 3.1.1.1 */ public void registerColumn(Class forDataSourceType, String columnID, TableColumnCreationListener listener) { if (listener != null) { mapColumnIDsToListener.put(forDataSourceType + "." + columnID, listener); } try { items_mon.enter(); List list = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (list == null) { list = new ArrayList(1); mapDataSourceTypeToColumnIDs.put(forDataSourceType, list); } if (!list.contains(columnID)) { list.add(columnID); } } finally { items_mon.exit(); } } public void unregisterColumn(Class forDataSourceType, String columnID, TableColumnCreationListener listener) { try { items_mon.enter(); mapColumnIDsToListener.remove(forDataSourceType + "." + columnID); List list = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (list != null) { list.remove(columnID); } } finally { items_mon.exit(); } } public TableColumnInfo getColumnInfo(Class forDataSourceType, String forTableID, String columnID) { TableColumnCore column = getTableColumnCore(forTableID, columnID); return column == null ? null : getColumnInfo(column); } public TableColumnInfo getColumnInfo( TableColumnCore column ){ TableColumnInfoImpl columnInfo = new TableColumnInfoImpl(column); List<TableColumnExtraInfoListener> listeners = column.getColumnExtraInfoListeners(); for (TableColumnExtraInfoListener l : listeners) { l.fillTableColumnInfo(columnInfo); } if (columnInfo.getCategories() == null && !(column instanceof CoreTableColumn)) { columnInfo.addCategories(new String[] { "plugin" }); columnInfo.setProficiency( TableColumnInfo.PROFICIENCY_BEGINNER ); } return columnInfo; } private void resetAllTables() { for ( String tableID: new ArrayList<String>( mapTableDefaultColumns.keySet())){ String[] defaultColumnNames = getDefaultColumnNames( tableID ); if ( defaultColumnNames != null ){ TableStructureEventDispatcher disp = TableStructureEventDispatcher.getInstance( tableID ); Set<Class<?>> dataSourceTypes = disp.prepareForTableReset(); int i = 0; for (String name : defaultColumnNames) { TableColumnCore column = getTableColumnCore(tableID, name); if (column != null) { column.reset(); column.setVisible(true); column.setPositionNoShift(i++); } } for ( Class<?> cla: dataSourceTypes ){ saveTableColumns( cla, tableID); TableStructureEventDispatcher.getInstance( tableID ).tableStructureChanged(true, cla ); } } } } public Object getColumnData(String columnID, String key) { Map mapTablesConfig = getTablesConfigMap(); Map mapColumns = MapUtils.getMapMap(mapTablesConfig, "Columns", null); if (mapColumns != null) { Map mapConfig = MapUtils.getMapMap(mapColumns, columnID, null); if (mapConfig != null) { return mapConfig.get(key); } } return null; } public void setColumnData(String columnID, String key, Object value) { synchronized (tablesConfig) { Map mapTablesConfig = getTablesConfigMap(); Map mapColumns = MapUtils.getMapMap(mapTablesConfig, "Columns", null); if (mapColumns == null) { mapColumns = new LightHashMap(2); mapTablesConfig.put("Columns", mapColumns); } Map mapConfig = MapUtils.getMapMap(mapColumns, columnID, null); if (mapConfig == null) { mapConfig = new LightHashMap(2); mapColumns.put(columnID, mapConfig); } mapConfig.put(key, value); } } public void removeColumnData(String columnID, String key) { synchronized (tablesConfig) { Map mapTablesConfig = getTablesConfigMap(); Map mapColumns = MapUtils.getMapMap(mapTablesConfig, "Columns", null); if (mapColumns != null) { Map mapConfig = MapUtils.getMapMap(mapColumns, columnID, null); if (mapConfig != null) { mapConfig.remove(key); if (mapConfig.size() < 1) { mapColumns.remove(columnID); } } } } } }