/** * This file is a part of EpnTAPClient. * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. * * 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 3 of the License, or (at your option) any later * version. 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. You should have received a copy of * the GNU General Public License along with this program. If not, see * . */ package eu.omp.irap.vespa.epntapclient.controller; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.logging.Level; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import com.google.gson.Gson; import eu.omp.irap.vespa.epntapclient.model.TAPField; import eu.omp.irap.vespa.epntapclient.model.TAPService; import eu.omp.irap.vespa.epntapclient.model.VOTableTags; import eu.omp.irap.vespa.epntapclient.utils.Const; import eu.omp.irap.vespa.epntapclient.utils.Err; import eu.omp.irap.vespa.epntapclient.utils.Log; /** * This class provide methods to get and use TAP services. * * @author N. Jourdane **/ public class TAPServices { /** The list of all fields (ie. columns VOTABLE). */ private List fields; /** The list of all services returned by the query. */ private List tapServices; /** The byte array representation of the stream data stored in the XML document. */ private byte[] byteArray; /** * Method constructor * * @param xmlFileName The name of XML file to parse in order to get the list of services. */ public TAPServices(String xmlFileName) { // Get document Document doc = null; try { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); doc = dBuilder.parse(new File(xmlFileName)); doc.getDocumentElement().normalize(); } catch (FileNotFoundException e1) { Log.LOGGER.log(Level.SEVERE, Err.NOT_FOUND + xmlFileName, e1); return; } catch (Exception e2) { Log.LOGGER.log(Level.SEVERE, Err.BAD_XML_DOC + xmlFileName, e2); return; } // Get fields NodeList nodeList = doc.getElementsByTagName(VOTableTags.TAG_NAME_FIELD); fields = new ArrayList<>(); for (int i = 0; i < nodeList.getLength(); i++) { fields.add(new TAPField(nodeList.item(i))); } // Get byte array String stream = doc.getElementsByTagName(VOTableTags.TAG_NAME_STREAM).item(0) .getTextContent() .replaceAll("(\\r|\\n)", ""); //$NON-NLS-1$ //$NON-NLS-2$ byteArray = Base64.getDecoder().decode(stream); } /** * Fill the services list from the byte array. */ public void fillServices() { List services = new ArrayList<>(); TAPService service = new TAPService(); for (int cursor = 0, nValue = 0; cursor < byteArray.length; nValue++) { TAPField column = fields.get(nValue % fields.size()); Object value = null; if (column.getDatatype().equals(VOTableTags.SHORT_TYPE)) { byte[] shortArray = { byteArray[cursor + 0], byteArray[cursor + 1] }; value = Integer.valueOf(shortArray[0] * (2 ^ 8) + shortArray[1]); cursor += shortArray.length; } else { byte[] head = { byteArray[cursor + 0], byteArray[cursor + 1], byteArray[cursor + 2], byteArray[cursor + 3] }; int charSize = column.getDatatype().equals(VOTableTags.UNICODE_CHAR_TYPE) ? 2 : 1; int stringLength = ByteBuffer.wrap(head).getInt() * charSize; cursor += head.length; value = new String(); for (int j = 0; j < stringLength && cursor < byteArray.length; cursor += charSize, j += charSize) { int c = (0xFF) & (charSize == 2 ? (int) (byteArray[cursor] * (2 ^ 8) + byteArray[cursor + 1]) : byteArray[cursor]); value = value + Character.toString((char) c); } } if (nValue % fields.size() == 0) { service = new TAPService(); } else if (nValue % fields.size() == fields.size() - 1) { services.add(service); } else { service.setProperty(column.getName(), value); } } tapServices = services; } /** * @return The list of services. */ public List getServices() { return tapServices; } /** * @return The list of VOTable columns. */ public List getFileds() { return fields; } /** * Print the content of all the services in the specified file in JSON format. * * @param fileName The name of the file where the services lists is printed. */ public void printToFile(String fileName) { PrintWriter writer; String json = new Gson().toJson(tapServices); try { writer = new PrintWriter(fileName, Const.CHARACTER_SET); writer.println(json); writer.close(); } catch (FileNotFoundException e1) { Log.LOGGER.log(Level.SEVERE, Err.NOT_FOUND, e1); } catch (UnsupportedEncodingException e2) { Log.LOGGER.log(Level.SEVERE, Err.WRONG_ENCODING, e2); } } }