Commit d5e04ec7 authored by vforchi's avatar vforchi
Browse files

aligned with commits from Mantelet

Merge remote-tracking branch 'upstream/master'
parents 56d6d774 1e98ff3b
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
@@ -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.
	 * 
+93 −2
Original line number Diff line number Diff line
@@ -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 */
	/* ************************************* */
+19 −4
Original line number Diff line number Diff line
@@ -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
+46 −0
Original line number Diff line number Diff line
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());
	}

}
+91 −0
Original line number Diff line number Diff line
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(){}
	}

}