/**
* 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);
}
}
}