From b74c06febb338fa650b0517a30a15ef180dd368a Mon Sep 17 00:00:00 2001 From: gmantele <gmantele@ari.uni-heidelberg.de> Date: Fri, 27 Jun 2014 16:29:52 +0200 Subject: [PATCH] [TAP] Remove TAPTypes and create a new class to represent a TAP column type: TAPType. + Improve the conversion between VOTable type and TAP type by embedding it in TAPType. + Modify TAPColumn in order to integrate TAPType and that its VotType is just a conversion of a TAPType. {This commit is not compilable.} --- src/tap/metadata/TAPColumn.java | 97 ++------ src/tap/metadata/TAPMetadata.java | 10 +- src/tap/metadata/TAPTable.java | 23 +- src/tap/metadata/TAPType.java | 257 +++++++++++++++++++++ src/tap/metadata/TAPTypes.java | 359 ------------------------------ src/tap/metadata/VotType.java | 112 ++++++++-- 6 files changed, 380 insertions(+), 478 deletions(-) create mode 100644 src/tap/metadata/TAPType.java delete mode 100644 src/tap/metadata/TAPTypes.java diff --git a/src/tap/metadata/TAPColumn.java b/src/tap/metadata/TAPColumn.java index 94b69da..2fca36d 100644 --- a/src/tap/metadata/TAPColumn.java +++ b/src/tap/metadata/TAPColumn.java @@ -22,6 +22,7 @@ package tap.metadata; import java.util.ArrayList; import java.util.Iterator; +import tap.metadata.TAPType.TAPDatatype; import adql.db.DBColumn; import adql.db.DBTable; @@ -41,11 +42,9 @@ public class TAPColumn implements DBColumn { private String utype = null; - private String datatype = null; + private TAPType datatype = new TAPType(TAPDatatype.VARCHAR); - private int size = TAPTypes.NO_SIZE; - - private VotType votType = null; + private VotType votType = datatype.toVotType(); private boolean principal = false; @@ -67,21 +66,25 @@ public class TAPColumn implements DBColumn { dbName = adqlName; lstTargets = new ArrayList<TAPForeignKey>(1); lstSources = new ArrayList<TAPForeignKey>(1); - setDefaultType(); } - public TAPColumn(String columnName, String description){ + public TAPColumn(String columnName, TAPType type){ this(columnName); + setDatatype(type); + } + + public TAPColumn(String columnName, TAPType type, String description){ + this(columnName, type); this.description = description; } - public TAPColumn(String columnName, String description, String unit){ - this(columnName, description); + public TAPColumn(String columnName, TAPType type, String description, String unit){ + this(columnName, type, description); this.unit = unit; } - public TAPColumn(String columnName, String description, String unit, String ucd, String utype){ - this(columnName, description, unit); + public TAPColumn(String columnName, TAPType type, String description, String unit, String ucd, String utype){ + this(columnName, type, description, unit); this.ucd = ucd; this.utype = utype; } @@ -111,6 +114,7 @@ public class TAPColumn implements DBColumn { /** * @return The table. */ + @Override public final DBTable getTable(){ return table; } @@ -181,79 +185,25 @@ public class TAPColumn implements DBColumn { /** * @return The datatype. */ - public final String getDatatype(){ + public final TAPType getDatatype(){ return datatype; } /** - * @return Array size (>0 or 2 special values: {@link TAPTypes#NO_SIZE} and {@link TAPTypes#STAR_SIZE}). - */ - public final int getArraySize(){ - return size; - } - - /** - * <p>Sets the DB datatype, the size and uses these information to set the corresponding VOTable type.</p> - * <b>Important:</b> - * <ul> - * <li>If the given datatype is not known according to {@link TAPTypes#getDBType(String)}, the datatype of this column is set to its default value (see {@link #setDefaultType()}),</li> - * <li>The VOTable type is set automatically thanks to {@link TAPTypes#getVotType(String, int)}.</li> - * </ul> - * - * @param datatype The datatype to set. - * @param size Array size (>0 or 2 special values: {@link TAPTypes#NO_SIZE} and {@link TAPTypes#STAR_SIZE}). - * - * @see TAPTypes#getDBType(VotType) - * @see TAPTypes#getVotType(String, int) - * @see #setDefaultType() + * @param type The new column datatype. */ - public final void setDatatype(String datatype, int size){ - this.datatype = TAPTypes.getDBType(datatype); - this.size = (size <= 0 && size != TAPTypes.STAR_SIZE) ? TAPTypes.NO_SIZE : size; - - if (this.datatype == null) - setDefaultType(); - else - this.votType = TAPTypes.getVotType(this.datatype, this.size); + public final void setDatatype(final TAPType type){ + datatype = type; + votType = datatype.toVotType(); } /** - * @return The VOTable type to use. + * @return The votType. */ public final VotType getVotType(){ return votType; } - /** - * <p>Sets the VOTable type and uses it to set the DB datatype and its size.</p> - * <b>Important:</b> - * <ul> - * <li>If the given VOTable type is not known according to {@link TAPTypes#getDBType(VotType)}, the DB datatype of this column and its size are set to the default value (see {@link #setDefaultType()}).</li> - * </ul> - * - * @param type A full VOTable type (that's to say: <code>datatype</code>, <code>arraysize</code> and <code>xtype</code>). - * - * @see TAPTypes#getDBType(VotType) - * @see #setDefaultType() - */ - public final void setVotType(final VotType type){ - this.votType = type; - this.datatype = TAPTypes.getDBType(type); - this.size = type.arraysize; - - if (this.datatype == null) - setDefaultType(); - } - - /** - * Sets the default DB datatype (VARCHAR) and its corresponding VOTable type (char , *). - */ - protected final void setDefaultType(){ - datatype = TAPTypes.VARCHAR; - size = TAPTypes.STAR_SIZE; - votType = TAPTypes.getVotType(datatype, size); - } - /** * @return The principal. */ @@ -346,12 +296,12 @@ public class TAPColumn implements DBColumn { lstSources.clear(); } + @Override public DBColumn copy(final String dbName, final String adqlName, final DBTable dbTable){ - TAPColumn copy = new TAPColumn((adqlName == null) ? this.adqlName : adqlName, description, unit, ucd, utype); + TAPColumn copy = new TAPColumn((adqlName == null) ? this.adqlName : adqlName, datatype, description, unit, ucd, utype); copy.setDBName((dbName == null) ? this.dbName : dbName); copy.setTable(dbTable); - copy.setDatatype(datatype, size); copy.setIndexed(indexed); copy.setPrincipal(principal); copy.setStd(std); @@ -361,10 +311,9 @@ public class TAPColumn implements DBColumn { } public DBColumn copy(){ - TAPColumn copy = new TAPColumn(adqlName, description, unit, ucd, utype); + TAPColumn copy = new TAPColumn(adqlName, datatype, description, unit, ucd, utype); copy.setDBName(dbName); copy.setTable(table); - copy.setDatatype(datatype, size); copy.setIndexed(indexed); copy.setPrincipal(principal); copy.setStd(std); diff --git a/src/tap/metadata/TAPMetadata.java b/src/tap/metadata/TAPMetadata.java index e3c36c7..fde3103 100644 --- a/src/tap/metadata/TAPMetadata.java +++ b/src/tap/metadata/TAPMetadata.java @@ -21,7 +21,6 @@ package tap.metadata; import java.io.IOException; import java.io.PrintWriter; - import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -30,14 +29,13 @@ import java.util.NoSuchElementException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import adql.db.DBTable; import tap.resource.Capabilities; import tap.resource.TAPResource; import tap.resource.VOSIResource; +import adql.db.DBTable; public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResource { @@ -314,13 +312,13 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour if (c.getDatatype() != null){ writer.print(prefix); writer.print("<dataType xsi:type=\"vod:TAPType\""); - if (c.getArraySize() >= 0){ + if (c.getDatatype().length > 0){ writer.print(" size=\""); - writer.print(c.getArraySize()); + writer.print(c.getDatatype().length); writer.print("\""); } writer.print('>'); - writer.print(c.getDatatype().toUpperCase()); + writer.print(c.getDatatype().type.toString().toUpperCase()); writer.println("</dataType>"); } diff --git a/src/tap/metadata/TAPTable.java b/src/tap/metadata/TAPTable.java index 92fd803..5486377 100644 --- a/src/tap/metadata/TAPTable.java +++ b/src/tap/metadata/TAPTable.java @@ -199,34 +199,20 @@ public class TAPTable implements DBTable { return c; } - public TAPColumn addColumn(String columnName, String description, String unit, String ucd, String utype){ + public TAPColumn addColumn(String columnName, TAPType datatype, String description, String unit, String ucd, String utype){ if (columnName == null) return null; - TAPColumn c = new TAPColumn(columnName, description, unit, ucd, utype); + TAPColumn c = new TAPColumn(columnName, datatype, description, unit, ucd, utype); addColumn(c); return c; } - public TAPColumn addColumn(String columnName, String description, String unit, String ucd, String utype, String datatype, int size, boolean principal, boolean indexed, boolean std){ + public TAPColumn addColumn(String columnName, TAPType datatype, String description, String unit, String ucd, String utype, boolean principal, boolean indexed, boolean std){ if (columnName == null) return null; - TAPColumn c = new TAPColumn(columnName, description, unit, ucd, utype); - c.setDatatype(datatype, size); - c.setPrincipal(principal); - c.setIndexed(indexed); - c.setStd(std); - addColumn(c); - return c; - } - - public TAPColumn addColumn(String columnName, String description, String unit, String ucd, String utype, VotType votType, boolean principal, boolean indexed, boolean std){ - if (columnName == null) - return null; - - TAPColumn c = new TAPColumn(columnName, description, unit, ucd, utype); - c.setVotType(votType); + TAPColumn c = new TAPColumn(columnName, datatype, description, unit, ucd, utype); c.setPrincipal(principal); c.setIndexed(indexed); c.setStd(std); @@ -482,6 +468,7 @@ public class TAPTable implements DBTable { } } + @Override public DBTable copy(final String dbName, final String adqlName){ TAPTable copy = new TAPTable((adqlName == null) ? this.adqlName : adqlName); copy.setDBName((dbName == null) ? this.dbName : dbName); diff --git a/src/tap/metadata/TAPType.java b/src/tap/metadata/TAPType.java new file mode 100644 index 0000000..a36c1c3 --- /dev/null +++ b/src/tap/metadata/TAPType.java @@ -0,0 +1,257 @@ +package tap.metadata; + +/* + * This file is part of TAPLibrary. + * + * TAPLibrary is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TAPLibrary 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 Lesser General Public License for more details. + * + * 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 2014 - Astronomishes Rechen Institute (ARI) + */ + +import tap.metadata.VotType.VotDatatype; + +/** + * + * <p> + * Describe a full TAP column type as it is described in the IVOA document. + * Thus, this object contains 2 attributes: <code>type</code> (or datatype) and <code>length</code> (or size). + * </p> + * + * <p>The length/size may be not defined ; in this case, its value is set to {@link #NO_LENGTH} or is negative or null.</p> + * + * <p>All datatypes declared in the IVOA recommendation document of TAP are listed in an enumeration type: {@link TAPDatatype}. + * It is used to set the attribute type/datatype of this class.</p> + * + * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de + * @version 2.0 (06/2014) + * @since 2.0 + */ +public class TAPType { + + /** + * List of all datatypes declared in the IVOA recommendation of TAP (in the section UPLOAD). + * + * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de + * @version 2.0 (06/2014) + * @since 2.0 + */ + public static enum TAPDatatype{ + SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION; + } + + /** Special value in case no length/size is specified. */ + public static final int NO_LENGTH = -1; + + /** Datatype of a column. */ + public final TAPDatatype type; + + /** The length parameter (only few datatypes need this parameter: char, varchar, binary and varbinary). */ + public final int length; + + /** + * Build a TAP column type by specifying a datatype. + * + * @param datatype Column datatype. + */ + public TAPType(final TAPDatatype datatype){ + this(datatype, NO_LENGTH); + } + + /** + * Build a TAP column type by specifying a datatype and a length (needed only for datatypes like char, varchar, binary and varbinary). + * + * @param datatype Column datatype. + * @param length Length of the column value (needed only for datatypes like char, varchar, binary and varbinary). + */ + public TAPType(final TAPDatatype datatype, final int length){ + if (datatype == null) + throw new NullPointerException("Missing TAP column datatype !"); + this.type = datatype; + this.length = length; + } + + /** + * Convert this TAP column type into a VOTable field type. + * + * @return The corresponding VOTable field type. + * + * @see #convertIntoVotType(TAPType) + */ + public VotType toVotType(){ + return convertIntoVotType(this); + } + + @Override + public String toString(){ + if (length > 0) + return type + "(" + length + ")"; + else + return type.toString(); + } + + /** + * Convert the given TAP column type into a VOTable field type. + * + * @param taptype The TAP column type to convert. + * + * @return The corresponding VOTable field type. + */ + public static VotType convertIntoVotType(final TAPType taptype){ + VotType vot = new VotType(VotDatatype.CHAR, VotType.NO_SIZE, false); + + switch(taptype.type){ + case SMALLINT: + vot = new VotType(VotDatatype.SHORT, 1, false); + break; + + case INTEGER: + vot = new VotType(VotDatatype.INT, 1, false); + break; + + case BIGINT: + vot = new VotType(VotDatatype.LONG, 1, false); + break; + + case REAL: + vot = new VotType(VotDatatype.FLOAT, 1, false); + break; + + case DOUBLE: + vot = new VotType(VotDatatype.DOUBLE, 1, false); + break; + + case CHAR: + vot = new VotType(VotDatatype.CHAR, (taptype.length > 0 ? taptype.length : 1), false); + break; + + case BINARY: + vot = new VotType(VotDatatype.UNSIGNED_BYTE, (taptype.length > 0 ? taptype.length : VotType.NO_SIZE), false); + break; + + case VARBINARY: + vot = new VotType(VotDatatype.UNSIGNED_BYTE, (taptype.length > 0 ? taptype.length : VotType.NO_SIZE), (taptype.length > 0)); + break; + + case BLOB: + vot = new VotType(VotDatatype.UNSIGNED_BYTE, VotType.NO_SIZE, true, VotType.XTYPE_BLOB); + break; + + case CLOB: + vot = new VotType(VotDatatype.CHAR, VotType.NO_SIZE, true, VotType.XTYPE_CLOB); + break; + + case TIMESTAMP: + vot = new VotType(VotDatatype.CHAR, VotType.NO_SIZE, true, VotType.XTYPE_TIMESTAMP); + break; + + case POINT: + vot = new VotType(VotDatatype.CHAR, VotType.NO_SIZE, true, VotType.XTYPE_POINT); + break; + + case REGION: + vot = new VotType(VotDatatype.CHAR, VotType.NO_SIZE, true, VotType.XTYPE_REGION); + break; + + case VARCHAR: + default: + vot = new VotType(VotDatatype.CHAR, (taptype.length > 0 ? taptype.length : VotType.NO_SIZE), (taptype.length > 0), null); + break; + } + + return vot; + } + + /** + * Convert the given VOTable field type into a TAP column type. + * + * @param vottype The VOTable field type to convert. + * + * @return The corresponding TAP column type. + */ + public static TAPType convertFromVotType(final VotType vottype){ + if (vottype == null) + return new TAPType(TAPDatatype.VARCHAR); + + switch(vottype.datatype){ + case SHORT: + case BOOLEAN: + if ((vottype.arraysize <= 1 || vottype.arraysize == VotType.NO_SIZE) && !vottype.unlimitedArraysize) + return new TAPType(TAPDatatype.SMALLINT); + else + return new TAPType(TAPDatatype.VARBINARY); + + case INT: + if ((vottype.arraysize <= 1 || vottype.arraysize == VotType.NO_SIZE) && !vottype.unlimitedArraysize) + return new TAPType(TAPDatatype.INTEGER); + else + return new TAPType(TAPDatatype.VARBINARY); + + case LONG: + if ((vottype.arraysize <= 1 || vottype.arraysize == VotType.NO_SIZE) && !vottype.unlimitedArraysize) + return new TAPType(TAPDatatype.BIGINT); + else + return new TAPType(TAPDatatype.VARBINARY); + + case FLOAT: + if ((vottype.arraysize <= 1 || vottype.arraysize == VotType.NO_SIZE) && !vottype.unlimitedArraysize) + return new TAPType(TAPDatatype.REAL); + else + return new TAPType(TAPDatatype.VARBINARY); + + case DOUBLE: + if ((vottype.arraysize <= 1 || vottype.arraysize == VotType.NO_SIZE) && !vottype.unlimitedArraysize) + return new TAPType(TAPDatatype.DOUBLE); + else + return new TAPType(TAPDatatype.VARBINARY); + + case UNSIGNED_BYTE: + if (vottype.arraysize > 0){ + if (vottype.unlimitedArraysize) + return new TAPType(TAPDatatype.VARBINARY, vottype.arraysize); + else + return new TAPType(TAPDatatype.BINARY, vottype.arraysize); + }else + return new TAPType(TAPDatatype.VARBINARY); + + case CHAR: + default: + TAPType taptype = null; + if (vottype.xtype != null && vottype.xtype.trim().length() > 0){ + if (vottype.xtype.equalsIgnoreCase(VotType.XTYPE_BLOB)) + taptype = new TAPType(TAPDatatype.BLOB); + else if (vottype.xtype.equalsIgnoreCase(VotType.XTYPE_CLOB)) + taptype = new TAPType(TAPDatatype.CLOB); + else if (vottype.xtype.equalsIgnoreCase(VotType.XTYPE_TIMESTAMP)) + taptype = new TAPType(TAPDatatype.TIMESTAMP); + else if (vottype.xtype.equalsIgnoreCase(VotType.XTYPE_POINT)) + taptype = new TAPType(TAPDatatype.POINT); + else if (vottype.xtype.equalsIgnoreCase(VotType.XTYPE_REGION)) + taptype = new TAPType(TAPDatatype.REGION); + } + if (taptype == null){ + if (vottype.unlimitedArraysize) + taptype = new TAPType(TAPDatatype.VARCHAR, (vottype.arraysize > 0) ? vottype.arraysize : NO_LENGTH); + else{ + if (vottype.arraysize <= 0 || vottype.arraysize == VotType.NO_SIZE) + taptype = new TAPType(TAPDatatype.VARCHAR); + else if (vottype.arraysize == 1) + taptype = new TAPType(TAPDatatype.CHAR, 1); + else + taptype = new TAPType(TAPDatatype.CHAR, vottype.arraysize); + } + } + return taptype; + } + } +} diff --git a/src/tap/metadata/TAPTypes.java b/src/tap/metadata/TAPTypes.java deleted file mode 100644 index 423b854..0000000 --- a/src/tap/metadata/TAPTypes.java +++ /dev/null @@ -1,359 +0,0 @@ -package tap.metadata; - -/* - * This file is part of TAPLibrary. - * - * TAPLibrary is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * TAPLibrary 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 Lesser General Public License for more details. - * - * 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 - UDS/Centre de Données astronomiques de Strasbourg (CDS) - */ - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -/** - * <p> - * Gathers all types used by a TAP service and described in the IVOA document for TAP. - * This class lets "translating" a DB type into a VOTable field type and vice-versa. - * You can also add some DB type aliases, that's to say other other names for the existing DB types: - * smallint, integer, bigint, real, double, binary, varbinary, char, varchar, blob, clob, timestamp, point, region. - * For instance: TEXT <-> VARCHAR. - * </p> - * - * @author Grégory Mantelet (CDS) - * @version 11/2011 - * - * @see VotType - */ -public final class TAPTypes { - - private static final Map<String,VotType> dbTypes; - private static final Map<String,String> dbTypeAliases; - private static final Map<VotType,String> votTypes; - - public static final String SMALLINT = "SMALLINT"; - public static final String INTEGER = "INTEGER"; - public static final String BIGINT = "BIGINT"; - public static final String REAL = "REAL"; - public static final String DOUBLE = "DOUBLE"; - public static final String BINARY = "BINARY"; - public static final String VARBINARY = "VARBINARY"; - public static final String CHAR = "CHAR"; - public static final String VARCHAR = "VARCHAR"; - public static final String BLOB = "BLOB"; - public static final String CLOB = "CLOB"; - public static final String TIMESTAMP = "TIMESTAMP"; - public static final String POINT = "POINT"; - public static final String REGION = "REGION"; - - /** No array size. */ - public static final int NO_SIZE = -1; - - /** Means '*' (i.e. char(*)). */ - public static final int STAR_SIZE = -12345; - - static{ - dbTypes = new HashMap<String,VotType>(14); - votTypes = new HashMap<VotType,String>(7); - - VotType type = new VotType("short", 1, null); - dbTypes.put(SMALLINT, type); - votTypes.put(type, SMALLINT); - - type = new VotType("int", 1, null); - dbTypes.put(INTEGER, type); - votTypes.put(type, INTEGER); - - type = new VotType("long", 1, null); - dbTypes.put(BIGINT, type); - votTypes.put(type, BIGINT); - - type = new VotType("float", 1, null); - dbTypes.put(REAL, type); - votTypes.put(type, REAL); - - type = new VotType("double", 1, null); - dbTypes.put(DOUBLE, type); - votTypes.put(type, DOUBLE); - - dbTypes.put(BINARY, new VotType("unsignedByte", 1, null)); - - type = new VotType("unsignedByte", STAR_SIZE, null); - dbTypes.put(VARBINARY, type); - votTypes.put(type, VARBINARY); - - dbTypes.put(CHAR, new VotType("char", 1, null)); - - type = new VotType("char", STAR_SIZE, null); - dbTypes.put(VARCHAR, type); - votTypes.put(type, VARCHAR); - - type = new VotType("unsignedByte", STAR_SIZE, "adql:BLOB"); - dbTypes.put(BLOB, type); - votTypes.put(type, BLOB); - - type = new VotType("char", STAR_SIZE, "adql:CLOB"); - dbTypes.put(CLOB, type); - votTypes.put(type, CLOB); - - type = new VotType("char", STAR_SIZE, "adql:TIMESTAMP"); - dbTypes.put(TIMESTAMP, type); - votTypes.put(type, TIMESTAMP); - - type = new VotType("char", STAR_SIZE, "adql:POINT"); - dbTypes.put(POINT, type); - votTypes.put(type, POINT); - - type = new VotType("char", STAR_SIZE, "adql:REGION"); - dbTypes.put(REGION, type); - votTypes.put(type, REGION); - - dbTypeAliases = new HashMap<String,String>(8); - // PostgreSQL data types: - dbTypeAliases.put("INT2", SMALLINT); - dbTypeAliases.put("INT", INTEGER); - dbTypeAliases.put("INT4", INTEGER); - dbTypeAliases.put("INT8", BIGINT); - dbTypeAliases.put("FLOAT4", REAL); - dbTypeAliases.put("FLOAT8", DOUBLE); - dbTypeAliases.put("TEXT", VARCHAR); - dbTypeAliases.put("SPOINT", POINT); - } - - /** - * Gets all DB types. - * @return An iterator on DB type name. - */ - public static final Iterator<String> getDBTypes(){ - return dbTypes.keySet().iterator(); - } - - /** - * Gets all DB type aliases. - * @return An iterator on Entry<String,String> whose the key is the alias and the value is its corresponding DB type. - */ - public static final Iterator<Entry<String,String>> getDBTypeAliases(){ - return dbTypeAliases.entrySet().iterator(); - } - - /** - * Gets all VOTable types. - * @return An iterator on {@link VotType}. - */ - public static final Iterator<VotType> getVotTypes(){ - return votTypes.keySet().iterator(); - } - - /** - * <p>Gets the VOTable type corresponding to the given DB type (or a DB type alias).</p> - * <b>Important:</b> - * <ul> - * <li>Spaces before and after the DB type are automatically removed,</li> - * <li>The DB type is automatically formatted in UPPER-CASE,</li> - * <li>Nothing is done if the given DB type is <code>null</code> or empty.</li> - * </ul> - * - * @param dbType A DB type (ex: SMALLINT, INTEGER, VARCHAR, POINT, ...) - * - * @return The corresponding VOTable type or <code>null</code> if not found. - */ - public static final VotType getVotType(String dbType){ - if (dbType == null) - return null; - - // Normalize the type name (upper case and with no leading and trailing spaces): - dbType = dbType.trim().toUpperCase(); - if (dbType.length() == 0) - return null; - - // Search the corresponding VOTable type: - VotType votType = dbTypes.get(dbType); - // If no match, try again considering the given type as an alias: - if (votType == null) - votType = dbTypes.get(dbTypeAliases.get(dbType)); - - return votType; - } - - /** - * <p>Gets the VOTable type (with the given arraysize) corresponding to the given DB type (or a DB type alias).</p> - * <b>Important:</b> - * <ul> - * <li>Spaces before and after the DB type are automatically removed,</li> - * <li>The DB type is automatically formatted in UPPER-CASE,</li> - * <li>Nothing is done if the given DB type is <code>null</code> or empty,</li> - * <li>The given arraysize is used only if the found VOTable type is not special (that's to say: <code>xtype</code> is <code>null</code>).</li> - * </ul> - * - * @param dbType A DB type (ex: SMALLINT, INTEGER, VARCHAR, POINT, ...) - * @param arraysize Arraysize to set in the found VOTable type. - * - * @return The corresponding VOTable type or <code>null</code> if not found. - */ - public static final VotType getVotType(String dbType, int arraysize){ - VotType votType = getVotType(dbType); - - // If there is a match, set the arraysize: - if (votType != null && votType.xtype == null && arraysize > 0) - votType = new VotType(votType.datatype, arraysize, null); - - return votType; - } - - /** - * - * <p>Gets the DB type corresponding to the given DB type alias.</p> - * <b>Important:</b> - * <ul> - * <li>Spaces before and after the DB type are automatically removed,</li> - * <li>The DB type is automatically formatted in UPPER-CASE,</li> - * <li>If the given DB type is not alias but directly a DB type, it is immediately return.</li> - * </ul> - * - * @param dbTypeAlias A DB type alias. - * - * @return The corresponding DB type or <code>null</code> if not found. - */ - public static final String getDBType(String dbTypeAlias){ - if (dbTypeAlias == null) - return null; - - // Normalize the type name: - dbTypeAlias = dbTypeAlias.trim().toUpperCase(); - if (dbTypeAlias.length() == 0) - return null; - - // Get the corresponding DB type: - if (dbTypes.containsKey(dbTypeAlias)) - return dbTypeAlias; - else - return dbTypeAliases.get(dbTypeAlias); - } - - /** - * - * <p>Gets the DB type corresponding to the given VOTable field type.</p> - * <b>Important:</b> - * <ul> - * <li>The research is made only on the following fields: <code>datatype</code> and <code>xtype</code>,</li> - * <li>Case <b>insensitive</b> research.</li> - * </ul> - * - * @param type A VOTable type. - * - * @return The corresponding DB type or <code>null</code> if not found. - */ - public static final String getDBType(final VotType type){ - if (type == null) - return null; - return votTypes.get(type); - } - - /** - * <p>Adds, replaces or removes a DB type alias.</p> - * <b>Important:</b> - * <ul> - * <li>Spaces before and after the DB type are automatically removed,</li> - * <li>The DB type is automatically formatted in UPPER-CASE,</li> - * <li>The same "normalizations" are done on the given alias (so the case sensitivity is ignored),</li> - * <li>Nothing is done if the given alias is <code>null</code> or empty,</li> - * <li>If the given DB type is <code>null</code>, the given alias is removed,</li> - * <li>Nothing is done if the given DB type (!= null) does not match with a known DB type.</li> - * </ul> - * - * @param alias A DB type alias (ex: spoint) - * @param dbType A DB type (ex: POINT). - * - * @return <code>true</code> if the association has been updated, <code>false</code> otherwise. - */ - public static final boolean putDBTypeAlias(String alias, String dbType){ - if (alias == null) - return false; - - // Normalize the given alias: - alias = alias.trim().toUpperCase(); - if (alias.length() == 0) - return false; - - // Check the existence of the given DB type: - if (dbType != null){ - dbType = dbType.trim().toUpperCase(); - if (dbType.length() == 0) - return false; - else if (!dbTypes.containsKey(dbType)) - return false; - } - - // Update the map of aliases: - if (dbType == null) - dbTypeAliases.remove(alias); - else - dbTypeAliases.put(alias, dbType); - - return true; - } - - /** SELF TEST */ - public final static void main(final String[] args) throws Exception{ - System.out.println("***** DB TYPES *****"); - Iterator<String> itDB = TAPTypes.getDBTypes(); - while(itDB.hasNext()) - System.out.println("\t- " + itDB.next()); - - System.out.println("\n***** DB TYPE ALIASES *****"); - Iterator<Entry<String,String>> itAliases = TAPTypes.getDBTypeAliases(); - while(itAliases.hasNext()){ - Entry<String,String> e = itAliases.next(); - System.out.println("\t- " + e.getKey() + " = " + e.getValue()); - } - - System.out.println("\n***** VOTABLE TYPES *****"); - Iterator<VotType> itVot = TAPTypes.getVotTypes(); - while(itVot.hasNext()) - System.out.println("\t- " + itVot.next()); - - byte[] buffer = new byte[1024]; - int nbRead = 0; - String type = null; - - System.out.print("\nDB Type ? "); - nbRead = System.in.read(buffer); - type = new String(buffer, 0, nbRead); - System.out.println(TAPTypes.getVotType(type)); - - int arraysize = 1; - String xtype = null; - VotType votType = null; - System.out.print("\nVOTable datatype ? "); - nbRead = System.in.read(buffer); - type = (new String(buffer, 0, nbRead)).trim(); - System.out.print("VOTable arraysize ? "); - nbRead = System.in.read(buffer); - try{ - arraysize = Integer.parseInt((new String(buffer, 0, nbRead)).trim()); - }catch(NumberFormatException nfe){ - arraysize = STAR_SIZE; - } - System.out.print("VOTable xtype ? "); - nbRead = System.in.read(buffer); - xtype = (new String(buffer, 0, nbRead)).trim(); - if (xtype != null && xtype.length() == 0) - xtype = null; - votType = new VotType(type, arraysize, xtype); - System.out.println(TAPTypes.getDBType(votType)); - } - -} diff --git a/src/tap/metadata/VotType.java b/src/tap/metadata/VotType.java index 27daede..c72db5c 100644 --- a/src/tap/metadata/VotType.java +++ b/src/tap/metadata/VotType.java @@ -16,7 +16,8 @@ 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 - UDS/Centre de Données astronomiques de Strasbourg (CDS) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomishes Rechen Institute (ARI) */ import cds.savot.writer.SavotWriter; @@ -29,25 +30,88 @@ import cds.savot.writer.SavotWriter; * <li><code>xtype</code>.</li> * </ul> * - * @author Grégory Mantelet (CDS) - * @version 11/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 06/2014 */ public final class VotType { - public final String datatype; + /** + * All possible values for a VOTable datatype (i.e. boolean, short, char, ...). + * + * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de + * @version 2.0 (06/2014) + * @since 2.0 + */ + public static enum VotDatatype{ + BOOLEAN("boolean"), SHORT("short"), INT("int"), LONG("long"), FLOAT("float"), DOUBLE("double"), CHAR("char"), UNSIGNED_BYTE("unsignedByte"); + + private final String strExpr; + + private VotDatatype(final String str){ + strExpr = (str == null || str.trim().length() == 0) ? name() : str; + } + + @Override + public String toString(){ + return strExpr; + } + } + + /** Special VOTable type (XType) for TAP/DB type BLOB. + * @since 2.0*/ + public final static String XTYPE_BLOB = "adql:BLOB"; + /** Special VOTable type (XType) for TAP/DB type CLOB. + * @since 2.0 */ + public final static String XTYPE_CLOB = "adql:CLOB"; + /** Special VOTable type (XType) for TAP/DB type TIMESTAMP. + * @since 2.0 */ + public final static String XTYPE_TIMESTAMP = "adql:TIMESTAMP"; + /** Special VOTable type (XType) for TAP/DB type POINT. + * @since 2.0 */ + public final static String XTYPE_POINT = "adql:POINT"; + /** Special VOTable type (XType) for TAP/DB type REGION. + * @since 2.0 */ + public final static String XTYPE_REGION = "adql:REGION"; + + /** No array size. + * @since 2.0 */ + public static final int NO_SIZE = -1; + + /** VOTable datatype + * @since 2.0 */ + public final VotDatatype datatype; /** A negative or null value means "*" (that's to say: an undetermined arraysize). */ - public int arraysize; + public final int arraysize; + /** If true, it means either "n*" (where n is the arraysize when > 0) or "*". + * @since 2.0*/ + public final boolean unlimitedArraysize; + /** Special type specification (i.e. POINT, TIMESTAMP, ...). */ public final String xtype; /** - * @param datatype A datatype (ex: char, int, long, ...). <b>Null value forbidden</b> - * @param arraysize A non-null positive integer. (any value ≤ 0 will be considered as an undetermined arraysize). + * Build a VOTable field type. + * + * @param datatype A datatype. <b>Null value forbidden</b> + * @param arraysize A non-null positive integer. (any value ≤ 0 will be considered as an undetermined arraysize, that's to say {@link #NO_SIZE}). + * @param unlimitedSize Indicate whether a * must be appended at the end of the arraysize attribute (so in these 2 cases: "n*" or "*"). + */ + public VotType(final VotDatatype datatype, final int arraysize, final boolean unlimitedSize){ + this(datatype, arraysize, unlimitedSize, null); + } + + /** + * Build a VOTable field type. + * + * @param datatype A datatype. <b>Null value forbidden</b> + * @param arraysize A non-null positive integer. (any value ≤ 0 will be considered as an undetermined arraysize, that's to say {@link #NO_SIZE}). + * @param unlimitedSize Indicate whether a * must be appended at the end of the arraysize attribute (so in these 2 cases: "n*" or "*"). * @param xtype A special type (ex: adql:POINT, adql:TIMESTAMP, ...). Null value allowed. */ - public VotType(final String datatype, final int arraysize, final String xtype){ + public VotType(final VotDatatype datatype, final int arraysize, final boolean unlimitedSize, final String xtype){ if (datatype == null) - throw new NullPointerException("Null VOTable datatype !"); + throw new NullPointerException("Missing VOTable datatype !"); this.datatype = datatype; - this.arraysize = arraysize; + this.arraysize = (arraysize > 0) ? arraysize : NO_SIZE; + this.unlimitedArraysize = unlimitedSize; this.xtype = xtype; } @@ -56,13 +120,7 @@ public final class VotType { if (obj == null) return false; try{ - VotType vot = (VotType)obj; - if (datatype.equalsIgnoreCase(vot.datatype)){ - if (xtype == null) - return (vot.xtype == null); - else - return xtype.equalsIgnoreCase(vot.xtype); - } + return toString().equals(obj); }catch(ClassCastException cce){ ; } @@ -71,7 +129,7 @@ public final class VotType { @Override public int hashCode(){ - return datatype.toLowerCase().hashCode(); + return datatype.toString().hashCode(); } @Override @@ -79,10 +137,13 @@ public final class VotType { StringBuffer str = new StringBuffer("datatype=\""); str.append(datatype).append('"'); - if (arraysize == TAPTypes.STAR_SIZE) + if (arraysize > 0){ + str.append(" arraysize=\"").append(SavotWriter.encodeAttribute("" + arraysize)); + if (unlimitedArraysize) + str.append("*"); + str.append('"'); + }else if (unlimitedArraysize) str.append(" arraysize=\"*\""); - else if (arraysize != TAPTypes.NO_SIZE && arraysize > 0) - str.append(" arraysize=\"").append(SavotWriter.encodeAttribute("" + arraysize)).append('"'); if (xtype != null) str.append(" xtype=\"").append(SavotWriter.encodeAttribute(xtype)).append('"'); @@ -90,4 +151,13 @@ public final class VotType { return str.toString(); } + /** + * Convert this VOTable type definition into a TAPColumn type. + * + * @return The corresponding {@link TAPType}. + */ + public TAPType toTAPType(){ + return TAPType.convertFromVotType(this); + } + } -- GitLab