001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2024
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.chooser;
030
031
032import edu.wisc.ssec.mcidasv.*;
033
034import java.util.ArrayList;
035import java.util.List;
036
037import org.w3c.dom.Document;
038import org.w3c.dom.Element;
039import org.w3c.dom.NodeList;
040
041import ucar.unidata.idv.IntegratedDataViewer;
042import ucar.unidata.idv.IdvResourceManager;
043
044import ucar.unidata.idv.chooser.adde.AddeServer;
045
046import ucar.unidata.xml.XmlResourceCollection;
047import ucar.unidata.xml.XmlUtil;
048
049
050/**
051 * {@code ServerInfo} objects have methods for accessing the contents of
052 * {@code servers.xml}.
053 */
054public class ServerInfo {
055
056    private IntegratedDataViewer myIdv;
057
058    /** tags */
059    public static final String TAG_SERVER = "server";
060    public static final String TAG_SERVERS = "servers";
061    public static final String TAG_GROUP = "group";
062
063    /** attributes */
064    public static final String ATTR_ACTIVE = "active";
065    public static final String ATTR_NAME = "name";
066    public static final String ATTR_NAMES = "names";
067    public static final String ATTR_USER = "user";
068    public static final String ATTR_PROJ = "proj";
069    public static final String ATTR_TYPE = "type";
070
071    private XmlResourceCollection serversXRC;
072    private Document serversDocument;
073    private Element serversRoot;
074
075    private static String user = "idv";
076    private static String proj = "0";
077
078    private List typeList = new ArrayList();
079    private List groups = new ArrayList();
080
081    private List serverDescriptors = new ArrayList();
082
083    private String[] defTypes = {"image", "point", "grid", "text", "nav"};
084
085    /**
086     * Creates a new {@code ServerInfo} object.
087     *
088     * @param idv Reference to the main application object.
089     * @param servers ADDE server definitions.
090     */
091    public ServerInfo(IntegratedDataViewer idv, XmlResourceCollection servers) {
092        myIdv = idv;
093        serversXRC = servers;
094
095        if (serversXRC.hasWritableResource()) {
096            serversDocument = 
097                serversXRC.getWritableDocument("<servers></servers>");
098            serversRoot =
099                serversXRC.getWritableRoot("<servers></servers>");
100            String tagName = serversRoot.getTagName();
101        }
102        getServersFromXml(serversXRC);
103    }
104
105
106    /**
107     * Read and parse servers.xml.
108     *
109     * @param servers Collection of ADDE server definitions.
110     */
111    private void getServersFromXml(XmlResourceCollection servers) {
112        servers.clearCache();
113        serverDescriptors.clear();
114        if (serversXRC.hasWritableResource()) {
115            serversDocument =
116                serversXRC.getWritableDocument("<tabs></tabs>");
117            serversRoot =
118                serversXRC.getWritableRoot("<tabs></tabs>");
119            try {
120                Element root = serversRoot;
121                if (root == null) return;
122//                if ((user.equals("")) && (proj.equals(""))) {
123                    if (serversRoot.hasAttribute(ATTR_USER))
124                        user = serversRoot.getAttribute(ATTR_USER);
125                    if (serversRoot.hasAttribute(ATTR_PROJ))
126                        proj = serversRoot.getAttribute(ATTR_PROJ);
127//                }
128                List serverElements = XmlUtil.getElements(root, TAG_SERVER);
129                for (int serverIdx = 0; serverIdx < serverElements.size(); serverIdx++) {
130                    Element serverElement = (Element) serverElements.get(serverIdx);
131                    String nameServer = XmlUtil.getAttribute(serverElement, ATTR_NAME);
132                    String activeServer = XmlUtil.getAttribute(serverElement, ATTR_ACTIVE);
133                    List groupElements = XmlUtil.getElements(serverElement, TAG_GROUP);
134                    for (int groupIdx = 0; groupIdx < groupElements.size(); groupIdx++) {
135                        Element groupElement = (Element) groupElements.get(groupIdx);
136                        String activeGroup = XmlUtil.getAttribute(groupElement, ATTR_ACTIVE);
137                        String nameGroup = XmlUtil.getAttribute(groupElement, ATTR_NAMES);
138                        String type = XmlUtil.getAttribute(groupElement, ATTR_TYPE);
139                        if (!typeList.contains(type)) {
140                            typeList.add(type);
141                        }
142                        ServerDescriptor sd =
143                            new ServerDescriptor(type, nameServer, nameGroup, activeGroup);
144                            serverDescriptors.add(sd);
145                    }
146                }
147            } catch (Exception e) {
148                System.out.println("getServersFromXml e=" + e);
149            }
150        }
151        return;
152    }
153
154    /**
155     * Return userId, default="idv".
156     *
157     * @return User ID. Default value is {@code "idv"}.
158     */
159    public String getUser() {
160        return user;
161    }
162
163    /**
164     * Return project number, default="0"
165     *
166     * @return Project number. Default value is {@code "0"}.
167     */
168    public String getProj() {
169        return proj;
170    }
171
172    /**
173     * Change the user id and project number for this instance.
174     *
175     * @param user New user ID.
176     * @param proj New project number.
177     */
178    public void setUserProj(String user, String proj) {
179        Element serverRoot = serversXRC.getWritableRoot("<tabs></tabs>");
180        Document serverDocument = serversXRC.getWritableDocument("<tabs></tabs>");
181        try {
182            serverRoot.setAttribute(ATTR_USER, user);
183            serverRoot.setAttribute(ATTR_PROJ, proj);
184            serversXRC.setWritableDocument(serverDocument, serverRoot);
185            serversXRC.writeWritable();
186        } catch (Exception e) {
187            System.out.println("updateXml AddeServer.toXml e=" + e);
188        }
189    }
190
191    /**
192     * Get the different {@literal "types"} supported by the server.
193     *
194     * @return A list whose possible values may contain {@literal "image",
195     * "point", "grid", "text", "nav"}.
196     */
197    public List getServerTypes() {
198        for (int i=0; i<defTypes.length; i++) {
199            if (!typeList.contains(defTypes[i])) typeList.add(defTypes[i]);
200        }
201        return typeList;
202    }
203
204    /**
205     * Get list of {@link ServerDescriptor ServerDescriptors} that match the
206     * given {@code type}.
207     *
208     * @param type Data type. Should be one of
209     *             {@literal "image", "point", "grid", "text", "nav"}.
210     * @param all Includes all definitions, even duplicates.
211     * @param includeDuplicates Whether or not duplicate definitions are
212     *                          included.
213     *
214     * @return List of {@code ServerDescriptor} objects that match
215     *         {@code type}.
216     */
217    public List getServers(String type, boolean all, boolean includeDuplicates) {
218        init();
219        List servers = new ArrayList();
220        List sds = new ArrayList();
221        groups = new ArrayList();
222        for (int i=0; i<serverDescriptors.size(); i++) {
223            ServerDescriptor sd = (ServerDescriptor)serverDescriptors.get(i);
224            if (sd.isDataType(type)) {
225                String name = sd.getServerName();
226                if (!all) {
227                    if (!sd.getIsActive()) continue;
228                    if (!includeDuplicates) {
229                        if (servers.contains(name)) continue;
230                    }
231                }
232                servers.add(name);
233                sds.add(sd);
234                groups.add(sd.getGroupName());
235            }
236        }
237        return sds;
238    }
239
240    /**
241     * Get list of server names that match {@code type}.
242     *
243     * @param type Data type. Should be one of
244     *             {@literal "image", "point", "grid", "text", "nav"}.
245     * @param all Includes all definitions, even duplicates.
246     * @param includeDuplicates Whether or not duplicate definitions are
247     *                          included.
248     *
249     * @return List of server name strings.
250     */
251     public List getServerNames(String type, boolean all, boolean includeDuplicates) {
252        if (serverDescriptors == null) init();
253        List servers = new ArrayList();
254        if (typeList.contains(type)) {
255            for (int i=0; i<serverDescriptors.size(); i++) {
256                ServerDescriptor sd = (ServerDescriptor)serverDescriptors.get(i);
257                if (sd.isDataType(type)) {
258                    String name = sd.getServerName();
259                    if (!all) {
260                        if (!sd.getIsActive()) continue;
261                        if (!includeDuplicates) {
262                            if (servers.contains(name)) continue;
263                        }
264                    }
265                    servers.add(name);
266                }
267            }
268        }
269        return servers;
270     }
271
272    /**
273     * Get list of {@link AddeServer AddeServers} that match {@code type}.
274     *
275     * @param type Data type. Should be one of
276     *             {@literal "image", "point", "grid", "text", "nav"}.
277     * @param all Includes all definitions, even duplicates.
278     * @param includeDuplicates Whether or not duplicate definitions are
279     *                          included.
280     *
281     * @return List of {@code AddeServer} objects.
282     */
283     public List getAddeServers(String type, boolean all, boolean includeDuplicates) {
284        if (serverDescriptors == null) init();
285        List servers = new ArrayList();
286        List names = new ArrayList();
287        if (typeList.contains(type)) {
288            for (int i=0; i<serverDescriptors.size(); i++) {
289                ServerDescriptor sd = (ServerDescriptor)serverDescriptors.get(i);
290                if (sd.isDataType(type)) {
291                    String name = sd.getServerName();
292                    if (!all) {
293                        if (!sd.getIsActive()) continue;
294                    }
295                    if (!includeDuplicates) {
296                        if (names.contains(name)) continue;
297                    }
298                    AddeServer as = new AddeServer(sd.getServerName());
299                    AddeServer.Group g = new AddeServer.Group(sd.getDataType(), sd.getGroupName(), "");
300                    g.setActive(sd.getIsActive());
301                    as.addGroup(g);
302                    servers.add(as);
303                    names.add(as.getName());
304                }
305            }
306        }
307        return servers;
308     }
309
310    /**
311     * Re-reads {@code servers.xml} and re-initialize all lists.
312     *
313     * @param type Data type. Should be one of
314     *             {@literal "image", "point", "grid", "text", "nav"}.
315     * @param all Includes all definitions, even duplicates.
316     * @param includeDuplicates Whether or not duplicate definitions are
317     *                          included.
318     *
319     * @return List of server name strings that support {@code type} data.
320     */
321     public List updateAddeServers(String type, boolean all, boolean includeDuplicates) {
322         init();
323         return getAddeServers(type, all, includeDuplicates);
324     }
325
326    /**
327     * Read servers.xml and initialize all lists.
328     *
329     * @return {@code false} if {@link #serverDescriptors} is {@code null},
330     * {@code true} otherwise.
331     */
332    private boolean init() {
333       serversXRC =
334           myIdv.getResourceManager().getXmlResources(
335           IdvResourceManager.RSC_ADDESERVER);
336       getServersFromXml(serversXRC);
337       if (serverDescriptors == null) return false;
338       return true;
339    }
340
341    /**
342     * Get all group names for a given data {@code type}.
343     *
344     * @param type Data type. Should be one of
345     *             {@literal "image", "point", "grid", "text", "nav"}.
346     *
347     * @return List of groups that support {@code type} data.
348     */
349    public List getGroups(String type) {
350        init();
351        getServers(type, false, true);
352        return groups;
353    }
354
355
356    /**
357     * Adds {@code serverList} to {@code servers.xml}.
358     *
359     * @param idv Reference to main application object.
360     * @param serverList alternating strings: name1, group1, name2, group2...
361     */
362    public void addServers(IntegratedDataViewer idv, List serverList) {
363        int num = serverList.size();
364        List addeServers = new ArrayList();
365        if (num > 0) {
366            try {
367                for (int i=0; i<num; i++) {
368                    ServerDescriptor sd = (ServerDescriptor) serverList.get(i);
369                    String servName = sd.getServerName();
370                    AddeServer as = new AddeServer(sd.getServerName());
371                    AddeServer.Group g = new AddeServer.Group(sd.getDataType(), sd.getGroupName(), "");
372                    g.setActive(sd.getIsActive());
373                    as.addGroup(g);
374                    addeServers.add(as);
375                }
376            } catch (Exception e) {
377                System.out.println("addServers e=" + e);
378            };
379        }
380        List serversFinal = AddeServer.coalesce(addeServers);
381
382        XmlResourceCollection serverCollection =
383           idv.getResourceManager().getXmlResources(
384           IdvResourceManager.RSC_ADDESERVER);
385        Element serverRoot = serverCollection.getWritableRoot("<tabs></tabs>");
386        Document serverDocument = serverCollection.getWritableDocument("<tabs></tabs>");
387        try {
388            Element serversEle = AddeServer.toXml(serversFinal, false);
389            serverCollection.setWritableDocument(serverDocument, serversEle);
390            serverCollection.writeWritable();
391        } catch (Exception e) {
392            System.out.println("AddeServer.toXml e=" + e);
393        }
394    }
395
396    /**
397     * Clear {@code servers.xml}.
398     *
399     * @param serversXRC Collection of server definitions.
400     */
401    public void clear(XmlResourceCollection serversXRC) {
402        List typeElements = XmlUtil.getElements(serversRoot, TAG_SERVER);
403        for (int typeIdx = 0; typeIdx < typeElements.size(); typeIdx++) {
404            Element typeElement = (Element) typeElements.get(typeIdx);
405            XmlUtil.removeChildren(typeElement);
406        }
407        try {
408            serversXRC.writeWritable();
409        } catch (Exception e) {
410        }
411        serversXRC.setWritableDocument(serversDocument, serversRoot);
412    }
413}