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