Skip to content
Snippets Groups Projects
Commit c2bb6a35 authored by vforchi's avatar vforchi
Browse files

aligned with commits from Mantelet

Merge remote-tracking branch 'upstream/master'
parents 56d6d774 1e98ff3b
No related branches found
No related tags found
No related merge requests found
......@@ -16,7 +16,7 @@ package tap.metadata;
* You should have received a copy of the GNU Lesser General Public License
* along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
......@@ -64,7 +64,7 @@ import uws.UWSToolBox;
* </p>
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 2.1 (07/2016)
* @version 2.1 (03/2017)
*/
public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResource {
......@@ -386,6 +386,32 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
return tables;
}
/**
* Get the description of the ObsCore table, if it is defined.
*
* <p>
* This function is case sensitive only on the schema name
* (i.e. <code>ivoa</code>) which must be defined in full lower case.
* The table name (i.e. <code>ObsCore</code>) will be found whatever
* the case it is written in.
* </p>
*
* @return Description of the ObsCore table,
* or <code>NULL</code> if this table is not provided by this TAP service.
*
* @since 2.1
*/
public TAPTable getObsCoreTable(){
TAPSchema ivoaSchema = getSchema("ivoa");
if (ivoaSchema != null){
for(TAPTable t : ivoaSchema){
if (t.getADQLName().equalsIgnoreCase("obscore"))
return t;
}
}
return null;
}
/**
* Get the number of all tables contained in this TAP metadata set.
*
......
......@@ -16,7 +16,7 @@ package tap.resource;
* You should have received a copy of the GNU Lesser General Public License
* along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
......@@ -30,6 +30,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import adql.db.DBColumn;
import adql.db.FunctionDef;
import tap.ServiceConnection;
import tap.ServiceConnection.LimitUnit;
......@@ -38,6 +39,7 @@ import tap.error.DefaultTAPErrorWriter;
import tap.formatter.OutputFormat;
import tap.log.TAPLog;
import tap.metadata.TAPMetadata;
import tap.metadata.TAPTable;
import uk.ac.starlink.votable.VOSerializer;
import uws.UWSException;
import uws.UWSToolBox;
......@@ -53,7 +55,7 @@ import uws.service.log.UWSLog.LogLevel;
* <p>At its creation it is creating and configuring the other resources in function of the given description of the TAP service.</p>
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 2.1 (08/2016)
* @version 2.1 (03/2017)
*/
public class TAP implements VOSIResource {
......@@ -489,6 +491,9 @@ public class TAP implements VOSIResource {
xml.append("\t\t<accessURL use=\"base\">").append((getAccessURL() == null) ? "" : VOSerializer.formatText(getAccessURL())).append("</accessURL>\n");
xml.append("\t</interface>\n");
// Data models:
appendDataModels(xml, "\t");
// Language description:
xml.append("\t<language>\n");
xml.append("\t\t<name>ADQL</name>\n");
......@@ -623,6 +628,92 @@ public class TAP implements VOSIResource {
return xml.toString();
}
/**
* List and declare all IVOA Data Models supported by this TAP service.
*
* <p>Currently, only the following DMs are natively supported:</p>
* <ul>
* <li>Obscore (1.0 and PR-1.1)</li>
* </ul>
*
* <p>
* More can be supported by extending this function
* (but not overwriting it completely otherwise the above
* supported DMs won't be anymore).
* </p>
*
* <p>A DM declaration should follow this XML syntax:</p>
* <pre>&lt;dataModel ivo-id="{DM-IVO_ID}"&gt;{DM-NAME}&lt;/dataModel&gt;</pre>
*
* @param xml The <code>/capabilities</code> in-progress content in which
* implemented DMs can be declared.
* @param linePrefix Tabulations/Spaces that should prefix all lines
* (for human readability).
*
* @since 2.1
*/
protected void appendDataModels(final StringBuffer xml, final String linePrefix){
appendObsCoreDM(xml, linePrefix);
}
/**
* <p>Append the ObsCore DM declaration in the given {@link StringBuffer}
* if an <code>ivoa.Obscore</code> table can be found in <code>TAP_SCHEMA</code>.</p>
*
* <p>
* This function has no effect if <code>ivoa.Obscore</code> can not
* be found. The <code>ivoa</code> schema is searched case sensitively,
* but not the table name <code>Obscore</code> which can be written
* in any possible case.
* </p>
*
* <p>
* If an <code>ivoa.Obscore</code> table is found, this function
* detects automatically which version of Obscore is implemented.
* It will be declared as Obscore 1.1 if ALL the following columns
* are found (case INsensitively): <code>s_xel1</code>, <code>x_xel2</code>,
* <code>t_xel</code>, <code>em_xel</code> and <code>pol_xel</code>.
* If not, the Obscore table will be declared as Obscore 1.0.
* </p>
*
* @param xml The <code>/capabilities</code> in-progress content in which
* Obscore-DM should be declared if found.
* @param linePrefix Tabulations/Spaces that should prefix all lines
* (for human readability).
*
* @see TAPMetadata#getObsCoreTable()
*
* @since 2.1
*/
protected void appendObsCoreDM(final StringBuffer xml, final String linePrefix){
// Try to get the ObsCore table definition:
TAPTable obscore = service.getTAPMetadata().getObsCoreTable();
// If there is one, determine the supported DM version and declare it:
if (obscore != null){
/* ObsCore 1.1 MUST have s_xel1, s_xel2, t_xel, em_xel and pol_xel
* These columns do not exist in ObsCore 1.0. */
byte hasAllXel = 0x0;
for(DBColumn col : obscore){
if (col.getADQLName().equalsIgnoreCase("s_xel1"))
hasAllXel |= 1; // 2^0 = 0000 0001
else if (col.getADQLName().equalsIgnoreCase("s_xel2"))
hasAllXel |= 2; // 2^1 = 0000 0010
else if (col.getADQLName().equalsIgnoreCase("t_xel"))
hasAllXel |= 4; // 2^2 = 0000 0100
else if (col.getADQLName().equalsIgnoreCase("em_xel"))
hasAllXel |= 8; // 2^3 = 0000 1000
else if (col.getADQLName().equalsIgnoreCase("pol_xel"))
hasAllXel |= 16; // 2^4 = 0001 0000
}
// Finally add the appropriate DM declaration:
if (hasAllXel == 31) // 2^5 - 1 = 0001 1111
xml.append(linePrefix + "<dataModel ivo-id=\"ivo://ivoa.net/std/ObsCore/v1.1\">ObsCore-1.1</dataModel>\n");
else
xml.append(linePrefix + "<dataModel ivo-id=\"ivo://ivoa.net/std/ObsCore/v1.0\">ObsCore-1.0</dataModel>\n");
}
}
/* ************************************* */
/* MANAGEMENT OF THIS RESOURCE'S CONTENT */
/* ************************************* */
......
......@@ -3,16 +3,27 @@ package tap.formatter;
import java.util.Collection;
import java.util.Iterator;
import adql.db.FunctionDef;
import tap.ServiceConnection;
import tap.TAPFactory;
import tap.log.TAPLog;
import tap.metadata.TAPMetadata;
import uws.service.UserIdentifier;
import uws.service.file.UWSFileManager;
import adql.db.FunctionDef;
public class ServiceConnection4Test implements ServiceConnection {
private TAPMetadata metadata = null;
private TAPFactory factory = null;
private UWSFileManager fileManager = null;
public ServiceConnection4Test(){}
public ServiceConnection4Test(final TAPMetadata metadata, final UWSFileManager fileManager){
this.metadata = metadata;
this.fileManager = fileManager;
}
@Override
public int[] getOutputLimit(){
return new int[]{1000000,1000000};
......@@ -80,7 +91,7 @@ public class ServiceConnection4Test implements ServiceConnection {
@Override
public TAPMetadata getTAPMetadata(){
return null;
return metadata;
}
@Override
......@@ -105,12 +116,16 @@ public class ServiceConnection4Test implements ServiceConnection {
@Override
public TAPFactory getFactory(){
return null;
return factory;
}
public void setFactory(TAPFactory factory){
this.factory = factory;
}
@Override
public UWSFileManager getFileManager(){
return null;
return fileManager;
}
@Override
......
package tap.metadata;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import tap.metadata.TAPTable.TableType;
public class TestTAPMetadata {
@Test
public void testGetObsCoreTable(){
TAPMetadata metadata = new TAPMetadata();
// CASE: no IVOA schema:
assertNull(metadata.getObsCoreTable());
// CASE: empty IVOA schema:
TAPSchema ivoaSchema = new TAPSchema("ivoa");
metadata.addSchema(ivoaSchema);
assertNull(metadata.getObsCoreTable());
// CASE: with ObsCore table as defined in the ObsCore's IVOA standard:
TAPTable obscore = new TAPTable("ObsCore");
ivoaSchema.addTable(obscore);
assertNotNull(metadata.getObsCoreTable());
assertEquals("ivoa.ObsCore", metadata.getObsCoreTable().getFullName());
// CASE: with "obscore" (all lower-case):
obscore = new TAPTable("obscore", TableType.view);
ivoaSchema.removeAllTables();
ivoaSchema.addTable(obscore);
assertNotNull(metadata.getObsCoreTable());
assertEquals("ivoa.obscore", metadata.getObsCoreTable().getFullName());
// CASE: ObsCore table BUT in a different schema:
metadata.removeAllSchemas();
TAPSchema differentSchema = new TAPSchema("different");
metadata.addSchema(differentSchema);
differentSchema.addTable("ObsCore");
assertNull(metadata.getObsCoreTable());
}
}
package tap.resource;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import org.junit.Test;
import adql.db.DBType;
import adql.db.DBType.DBDatatype;
import tap.AbstractTAPFactory;
import tap.ServiceConnection;
import tap.TAPException;
import tap.db.DBConnection;
import tap.formatter.ServiceConnection4Test;
import tap.metadata.TAPMetadata;
import tap.metadata.TAPSchema;
import tap.metadata.TAPTable;
import uws.service.file.LocalUWSFileManager;
public class TestTAP {
@Test
public void testAppendObsCoreDM(){
// Create the TAPMetadata:
TAPMetadata metadata = new TAPMetadata();
TAPSchema ivoaSchema = new TAPSchema("ivoa");
TAPTable obscore = new TAPTable("ObsCore");
// Create a TAP instance:
try{
ServiceConnection4Test serviceConn = new ServiceConnection4Test(metadata, new LocalUWSFileManager(new File(System.getProperty("java.io.tmpdir"))));
serviceConn.setFactory(new TAPFactory4Test(serviceConn));
TAP tap = new TAP(serviceConn);
StringBuffer xml = new StringBuffer();
// CASE: no Obscore table:
tap.appendObsCoreDM(xml, "");
assertEquals(0, xml.length());
// CASE: with an IVOA schema:
metadata.addSchema(ivoaSchema);
tap.appendObsCoreDM(xml, "");
assertEquals(0, xml.length());
// CASE: with an Obscore table (with no *_xel columns) - ObsCore 1.0:
ivoaSchema.addTable(obscore);
tap.appendObsCoreDM(xml, "\t");
assertEquals("\t<dataModel ivo-id=\"ivo://ivoa.net/std/ObsCore/v1.0\">ObsCore-1.0</dataModel>\n", xml.toString());
// CASE: with an Obscore 1.1 table but not with all *_xel columns:
obscore.addColumn("s_xel1", new DBType(DBDatatype.BIGINT), null, null, null, null);
obscore.addColumn("s_xel2", new DBType(DBDatatype.BIGINT), null, null, null, null);
obscore.addColumn("t_xel", new DBType(DBDatatype.BIGINT), null, null, null, null);
obscore.addColumn("em_xel", new DBType(DBDatatype.BIGINT), null, null, null, null);
xml.delete(0, xml.length());
tap.appendObsCoreDM(xml, "\t");
assertEquals("\t<dataModel ivo-id=\"ivo://ivoa.net/std/ObsCore/v1.0\">ObsCore-1.0</dataModel>\n", xml.toString());
// CASE: correct Obscore 1.1 table:
obscore.addColumn("pol_xel", new DBType(DBDatatype.BIGINT), null, null, null, null);
xml.delete(0, xml.length());
tap.appendObsCoreDM(xml, "\t");
assertEquals("\t<dataModel ivo-id=\"ivo://ivoa.net/std/ObsCore/v1.1\">ObsCore-1.1</dataModel>\n", xml.toString());
}catch(Exception e){
e.printStackTrace();
fail("Unexpected error while creating a TAP instance! (see console for more details)");
}
}
private static class TAPFactory4Test extends AbstractTAPFactory {
protected TAPFactory4Test(ServiceConnection service) throws NullPointerException{
super(service);
}
@Override
public DBConnection getConnection(String jobID) throws TAPException{
return null;
}
@Override
public void freeConnection(DBConnection conn){}
@Override
public void destroy(){}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment