001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2025 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas/ 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see https://www.gnu.org/licenses/. 027 */ 028 029package edu.wisc.ssec.mcidasv.data; 030 031import java.util.ArrayList; 032import java.util.Collections; 033import java.util.Comparator; 034import java.util.HashMap; 035import java.util.Map; 036 037import ucar.unidata.data.DataChoice; 038import ucar.unidata.data.DataContext; 039import ucar.unidata.data.DataManager; 040import ucar.unidata.data.DataSource; 041 042import ucar.unidata.util.TwoFacedObject; 043 044import ucar.unidata.xml.XmlResourceCollection; 045 046import edu.wisc.ssec.mcidasv.control.HydraControl; 047import edu.wisc.ssec.mcidasv.control.MultiSpectralControl; 048 049import edu.wisc.ssec.mcidasv.display.hydra.MultiSpectralDisplay; 050 051/** 052 * <p> 053 * The McvDataManager exists purely as a UI nicety. In the IDV, the list of 054 * {@link DataSource}s are presented in the same ordering found in 055 * {@code datasources.xml}. 056 * </p> 057 * 058 * <p> 059 * While ordering the contents of {@code datasources.xml} certainly would have 060 * been easier, the approach taken here is a bit more future-proof. McV simply 061 * sorts the data sources known to the IDV. 062 * </p> 063 */ 064public class McvDataManager extends DataManager { 065 066 /** 067 * ID of the "I'm Still Feeling Lucky" data source. The IDV lowercases it 068 * automatically. 069 */ 070 private static final String STILL_LUCKY_ID = "file.any"; 071 072 private final Map<DataChoice, HydraControl> hydraDataToControl = new HashMap<DataChoice, HydraControl>(); 073 private final Map<DataChoice, MultiSpectralDisplay> hydraDataToDisplay = new HashMap<DataChoice, MultiSpectralDisplay>(); 074 075 /** 076 * Default constructor. 077 */ 078 public McvDataManager() { 079 super(null); 080 } 081 082 /** 083 * Creates a new DataManager with the given {@link DataContext}. 084 * 085 * @param dataContext The {@code DataContext} that this DataManager exists 086 * within (this is usually an instance of 087 * {@link ucar.unidata.idv.IntegratedDataViewer}). 088 */ 089 public McvDataManager(final DataContext dataContext) { 090 super(dataContext); 091 } 092 093 public boolean containsHydraControl(final DataChoice choice) { 094 return hydraDataToControl.containsKey(choice); 095 } 096 097 public boolean containsHydraDisplay(final DataChoice choice) { 098 return hydraDataToDisplay.containsKey(choice); 099 } 100 101 public void setHydraControl(final DataChoice choice, final HydraControl control) { 102 hydraDataToControl.put(choice, control); 103 } 104 105 public void setHydraDisplay(final DataChoice choice, final MultiSpectralDisplay display) { 106 hydraDataToDisplay.put(choice, display); 107 } 108 109 public HydraControl getHydraControl(final DataChoice choice) { 110 return hydraDataToControl.get(choice); 111 } 112 113 public MultiSpectralDisplay getHydraDisplay(final DataChoice choice) { 114 return hydraDataToDisplay.get(choice); 115 } 116 117 /** 118 * Process the list of xml documents that define the different 119 * {@link DataSource}s used within the idv. Overridden so that McIDAS-V 120 * can alphabetize the lists of {@link DataSource}s presented in the UI. 121 * 122 * @param resources The {@link XmlResourceCollection} that holds the set of 123 * datasource xml documents. This may be null. 124 */ 125 @Override public void loadDataSourceXml( 126 final XmlResourceCollection resources) { 127 super.loadDataSourceXml(resources); 128 allDataSourceIds = sortTwoFacedObjects(allDataSourceIds); 129 fileDataSourceIds = sortTwoFacedObjects(fileDataSourceIds); 130 } 131 132 /** 133 * <p> 134 * Sorts an {@link ArrayList} of {@link TwoFacedObject}s by label. Case is 135 * ignored. 136 * </p> 137 * 138 * <p> 139 * <b>NOTE:</b> If the ID of one of the objects represents the "I'm Still 140 * Feeling Lucky" data source, it'll always wind up at the end of the list. 141 * </p> 142 * 143 * @param objs The list that needs some sortin' out. 144 * 145 * @return The sorted contents of {@code objs}. 146 */ 147 private ArrayList<TwoFacedObject> sortTwoFacedObjects(final ArrayList<TwoFacedObject> objs) { 148 Comparator<TwoFacedObject> comp = new Comparator<TwoFacedObject>() { 149 150 public int compare(final TwoFacedObject a, final TwoFacedObject b) { 151 152 // make sure "I'm still feeling lucky" is always last. 153 if (a.getId().equals(STILL_LUCKY_ID)) 154 return 1; 155 156 // same as above! 157 if (b.getId().equals(STILL_LUCKY_ID)) 158 return -1; 159 160 // otherwise sorting by label is just fine. 161 return ((String)a.getLabel()).compareToIgnoreCase((String)b.getLabel()); 162 } 163 164 @Override public boolean equals(Object o) { 165 return (o == this); 166 } 167 }; 168 169 ArrayList<TwoFacedObject> reordered = new ArrayList<TwoFacedObject>(objs); 170 Collections.sort(reordered, comp); 171 return reordered; 172 } 173}