001/*****************************************************************************
002 * Copyright by The HDF Group.                                               *
003 * Copyright by the Board of Trustees of the University of Illinois.         *
004 * All rights reserved.                                                      *
005 *                                                                           *
006 * This file is part of the HDF Java Products distribution.                  *
007 * The full copyright notice, including terms governing use, modification,   *
008 * and redistribution, is contained in the COPYING file, which can be found  *
009 * at the root of the source code distribution tree,                         *
010 * or in https://www.hdfgroup.org/licenses.                                  *
011 * If you do not have access to either file, you may request a copy from     *
012 * help@hdfgroup.org.                                                        *
013 ****************************************************************************/
014
015package hdf.view.DataView;
016
017import java.util.List;
018
019import hdf.view.ImageView.DefaultImageViewFactory;
020import hdf.view.MetaDataView.DefaultMetaDataViewFactory;
021import hdf.view.PaletteView.DefaultPaletteViewFactory;
022import hdf.view.TableView.DefaultTableViewFactory;
023import hdf.view.Tools;
024import hdf.view.TreeView.DefaultTreeViewFactory;
025import hdf.view.ViewProperties;
026import hdf.view.ViewProperties.DataViewType;
027
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031/**
032 * Following the Abstract Factory Pattern, represents a class to produce
033 * different types of DataView factory classes depending on the given
034 * DataViewType enum value.
035 *
036 * @author jhenderson
037 * @version 1.0 4/17/2018
038 */
039public class DataViewFactoryProducer {
040
041    private static final Logger log = LoggerFactory.getLogger(DataViewFactoryProducer.class);
042
043    /**
044     * get the requested DataViewFactory
045     *
046     *
047     * @param viewType
048     *             The data view type requested
049     *
050     * @throws Exception
051     *             If there is an error getting the class for a data view factory.
052     *
053     * @return the data view factory.
054     */
055    public static DataViewFactory getFactory(DataViewType viewType) throws Exception
056    {
057        String factoryClassName    = null;
058        DataViewFactory theFactory = null;
059        List<?> moduleList         = null;
060
061        /*
062         * First determine if we are using the default module for the requested DataViewFactory
063         * class. If not, we will attempt to load the given DataViewFactory class.
064         */
065        switch (viewType) {
066        case TABLE:
067            /* Retrieve the "currently selected" TableViewFactory class to use */
068            moduleList = ViewProperties.getTableViewList();
069            if ((moduleList == null) || (moduleList.size() <= 0)) {
070                return null;
071            }
072
073            factoryClassName = (String)moduleList.get(0);
074
075            if (factoryClassName.equals(ViewProperties.DEFAULT_MODULE_TEXT)) {
076                log.trace("getFactory(): returning default TableView factory instance");
077                return new DefaultTableViewFactory();
078            }
079
080            break;
081
082        case IMAGE:
083            /* Retrieve the "currently selected" ImageViewFactory class to use */
084            moduleList = ViewProperties.getImageViewList();
085            if ((moduleList == null) || (moduleList.size() <= 0)) {
086                return null;
087            }
088
089            factoryClassName = (String)moduleList.get(0);
090
091            if (factoryClassName.equals(ViewProperties.DEFAULT_MODULE_TEXT)) {
092                log.trace("getFactory(): returning default ImageView factory instance");
093                return new DefaultImageViewFactory();
094            }
095
096            break;
097
098        case PALETTE:
099            /* Retrieve the "currently selected" PaletteViewFactory class to use */
100            moduleList = ViewProperties.getPaletteViewList();
101            if ((moduleList == null) || (moduleList.size() <= 0)) {
102                return null;
103            }
104
105            factoryClassName = (String)moduleList.get(0);
106
107            if (factoryClassName.equals(ViewProperties.DEFAULT_MODULE_TEXT)) {
108                log.trace("getFactory(): returning default PaletteView factory instance");
109                return new DefaultPaletteViewFactory();
110            }
111
112            break;
113
114        case METADATA:
115            /* Retrieve the "currently selected" MetaDataViewFactory class to use */
116            moduleList = ViewProperties.getMetaDataViewList();
117            if ((moduleList == null) || (moduleList.size() <= 0)) {
118                return null;
119            }
120
121            factoryClassName = (String)moduleList.get(0);
122
123            if (factoryClassName.equals(ViewProperties.DEFAULT_MODULE_TEXT)) {
124                log.trace("getFactory(): returning default MetaDataView factory instance");
125                return new DefaultMetaDataViewFactory();
126            }
127
128            break;
129
130        case TREEVIEW:
131            /* Retrieve the "currently selected" TreeViewFactory class to use */
132            moduleList = ViewProperties.getTreeViewList();
133            if ((moduleList == null) || (moduleList.size() <= 0)) {
134                return null;
135            }
136
137            factoryClassName = (String)moduleList.get(0);
138
139            if (factoryClassName.equals(ViewProperties.DEFAULT_MODULE_TEXT)) {
140                log.trace("getFactory(): returning default TreeView factory instance");
141                return new DefaultTreeViewFactory();
142            }
143
144            break;
145
146        default:
147            throw new Exception("getFactory(): invalid DataViewType");
148        }
149
150        Class<?> theClass = null;
151        try {
152            log.trace("getFactory(): ViewProperties.loadExtClass().loadClass({})", factoryClassName);
153
154            /* Attempt to load the class as an external module */
155            theClass = ViewProperties.loadExtClass().loadClass(factoryClassName);
156        }
157        catch (Exception ex) {
158            log.debug("getFactory(): ViewProperties.loadExtClass().loadClass({}) failure:", factoryClassName,
159                      ex);
160
161            try {
162                log.trace("getFactory(): Class.forName({})", factoryClassName);
163
164                /* Attempt to load the class directly by the given name */
165                theClass = Class.forName(factoryClassName);
166            }
167            catch (Exception ex2) {
168                log.debug("getFactory(): Class.forName({}) failure:", factoryClassName, ex);
169
170                /* At this point, we have no choice but to fall back to the default modules */
171                switch (viewType) {
172                case TABLE:
173                    log.trace("getFactory(): returning default TableView factory instance");
174                    return new DefaultTableViewFactory();
175                case IMAGE:
176                    log.trace("getFactory(): returning default ImageView factory instance");
177                    return new DefaultImageViewFactory();
178                case PALETTE:
179                    log.trace("getFactory(): returning default PaletteView factory instance");
180                    return new DefaultPaletteViewFactory();
181                case METADATA:
182                    log.trace("getFactory(): returning default MetaDataView factory instance");
183                    return new DefaultMetaDataViewFactory();
184                case TREEVIEW:
185                    log.trace("getFactory(): returning default TreeView factory instance");
186                    return new DefaultTreeViewFactory();
187                default:
188                    throw new Exception("getFactory(): invalid DataViewType");
189                }
190            }
191        }
192
193        if (theClass == null)
194            throw new ClassNotFoundException();
195
196        try {
197            theFactory = (DataViewFactory)Tools.newInstance(theClass, null);
198
199            log.trace("getFactory(): returning DataViewFactory instance {}", theFactory);
200        }
201        catch (Exception ex) {
202            log.debug("getFactory(): Error instantiating class:", ex);
203            theFactory = null;
204        }
205
206        return theFactory;
207    }
208}