From e2e814ac94733ffaf5c8ccd4835935393e6c294b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Mantelet?= Date: Thu, 14 Dec 2023 13:36:47 +0100 Subject: [PATCH] [ADQL] Add prototype of new DataType --- ADQLLib/src/vollt/datatype/DataType.java | 130 +++++++++ .../src/vollt/datatype/DataTypeFactory.java | 9 + .../vollt/datatype/DataTypeFactoryImp.java | 255 ++++++++++++++++ .../src/vollt/datatype/ExactNumericType.java | 31 ++ ADQLLib/src/vollt/datatype/FloatingType.java | 31 ++ ADQLLib/src/vollt/datatype/GeometryType.java | 27 ++ .../datatype/IncorrectDataTypeClass.java | 19 ++ ADQLLib/src/vollt/datatype/ScalarType.java | 13 + ADQLLib/src/vollt/datatype/SimpleType.java | 57 ++++ ADQLLib/src/vollt/datatype/StringType.java | 26 ++ ADQLLib/src/vollt/datatype/TypeBit.java | 31 ++ ADQLLib/src/vollt/datatype/TypeBoolean.java | 35 +++ ADQLLib/src/vollt/datatype/TypeChar.java | 8 + .../vollt/datatype/TypeCircleWithDouble.java | 20 ++ .../vollt/datatype/TypeCircleWithFloat.java | 20 ++ ADQLLib/src/vollt/datatype/TypeDouble.java | 13 + ADQLLib/src/vollt/datatype/TypeFloat.java | 13 + ADQLLib/src/vollt/datatype/TypeInteger.java | 17 ++ ADQLLib/src/vollt/datatype/TypeInterval.java | 40 +++ .../vollt/datatype/TypeIntervalOfDouble.java | 9 + .../vollt/datatype/TypeIntervalOfFloat.java | 9 + .../vollt/datatype/TypeIntervalOfInteger.java | 9 + .../vollt/datatype/TypeIntervalOfLong.java | 9 + .../vollt/datatype/TypeIntervalOfShort.java | 9 + ADQLLib/src/vollt/datatype/TypeLong.java | 17 ++ ADQLLib/src/vollt/datatype/TypeMOC.java | 39 +++ ADQLLib/src/vollt/datatype/TypePoint.java | 19 ++ .../vollt/datatype/TypePointWithDouble.java | 8 + .../vollt/datatype/TypePointWithFloat.java | 8 + ADQLLib/src/vollt/datatype/TypePolygon.java | 20 ++ .../vollt/datatype/TypePolygonWithDouble.java | 8 + .../vollt/datatype/TypePolygonWithFloat.java | 8 + ADQLLib/src/vollt/datatype/TypeRegion.java | 34 +++ ADQLLib/src/vollt/datatype/TypeShape.java | 39 +++ ADQLLib/src/vollt/datatype/TypeShort.java | 17 ++ ADQLLib/src/vollt/datatype/TypeTimestamp.java | 38 +++ .../src/vollt/datatype/TypeUnicodeChar.java | 8 + .../src/vollt/datatype/TypeUnsignedByte.java | 31 ++ .../vollt/datatype/UnknownNumericType.java | 27 ++ ADQLLib/src/vollt/datatype/UnknownType.java | 61 ++++ ADQLLib/src/vollt/datatype/VectorType.java | 58 ++++ .../datatype/TestDataTypeFactoryImp.java | 275 ++++++++++++++++++ .../test/vollt/datatype/TestSimpleType.java | 128 ++++++++ 43 files changed, 1683 insertions(+) create mode 100644 ADQLLib/src/vollt/datatype/DataType.java create mode 100644 ADQLLib/src/vollt/datatype/DataTypeFactory.java create mode 100644 ADQLLib/src/vollt/datatype/DataTypeFactoryImp.java create mode 100644 ADQLLib/src/vollt/datatype/ExactNumericType.java create mode 100644 ADQLLib/src/vollt/datatype/FloatingType.java create mode 100644 ADQLLib/src/vollt/datatype/GeometryType.java create mode 100644 ADQLLib/src/vollt/datatype/IncorrectDataTypeClass.java create mode 100644 ADQLLib/src/vollt/datatype/ScalarType.java create mode 100644 ADQLLib/src/vollt/datatype/SimpleType.java create mode 100644 ADQLLib/src/vollt/datatype/StringType.java create mode 100644 ADQLLib/src/vollt/datatype/TypeBit.java create mode 100644 ADQLLib/src/vollt/datatype/TypeBoolean.java create mode 100644 ADQLLib/src/vollt/datatype/TypeChar.java create mode 100644 ADQLLib/src/vollt/datatype/TypeCircleWithDouble.java create mode 100644 ADQLLib/src/vollt/datatype/TypeCircleWithFloat.java create mode 100644 ADQLLib/src/vollt/datatype/TypeDouble.java create mode 100644 ADQLLib/src/vollt/datatype/TypeFloat.java create mode 100644 ADQLLib/src/vollt/datatype/TypeInteger.java create mode 100644 ADQLLib/src/vollt/datatype/TypeInterval.java create mode 100644 ADQLLib/src/vollt/datatype/TypeIntervalOfDouble.java create mode 100644 ADQLLib/src/vollt/datatype/TypeIntervalOfFloat.java create mode 100644 ADQLLib/src/vollt/datatype/TypeIntervalOfInteger.java create mode 100644 ADQLLib/src/vollt/datatype/TypeIntervalOfLong.java create mode 100644 ADQLLib/src/vollt/datatype/TypeIntervalOfShort.java create mode 100644 ADQLLib/src/vollt/datatype/TypeLong.java create mode 100644 ADQLLib/src/vollt/datatype/TypeMOC.java create mode 100644 ADQLLib/src/vollt/datatype/TypePoint.java create mode 100644 ADQLLib/src/vollt/datatype/TypePointWithDouble.java create mode 100644 ADQLLib/src/vollt/datatype/TypePointWithFloat.java create mode 100644 ADQLLib/src/vollt/datatype/TypePolygon.java create mode 100644 ADQLLib/src/vollt/datatype/TypePolygonWithDouble.java create mode 100644 ADQLLib/src/vollt/datatype/TypePolygonWithFloat.java create mode 100644 ADQLLib/src/vollt/datatype/TypeRegion.java create mode 100644 ADQLLib/src/vollt/datatype/TypeShape.java create mode 100644 ADQLLib/src/vollt/datatype/TypeShort.java create mode 100644 ADQLLib/src/vollt/datatype/TypeTimestamp.java create mode 100644 ADQLLib/src/vollt/datatype/TypeUnicodeChar.java create mode 100644 ADQLLib/src/vollt/datatype/TypeUnsignedByte.java create mode 100644 ADQLLib/src/vollt/datatype/UnknownNumericType.java create mode 100644 ADQLLib/src/vollt/datatype/UnknownType.java create mode 100644 ADQLLib/src/vollt/datatype/VectorType.java create mode 100644 ADQLLib/test/vollt/datatype/TestDataTypeFactoryImp.java create mode 100644 ADQLLib/test/vollt/datatype/TestSimpleType.java diff --git a/ADQLLib/src/vollt/datatype/DataType.java b/ADQLLib/src/vollt/datatype/DataType.java new file mode 100644 index 00000000..06386f7d --- /dev/null +++ b/ADQLLib/src/vollt/datatype/DataType.java @@ -0,0 +1,130 @@ +package vollt.datatype; + +import java.util.Optional; + +/** + * Representation of a data type. + * + *

VOTable type system

+ *

+ * Implementations can return the equivalent type in the VOTable type + * system. In other words: a {@link #getVotDatatype() datatype}, + * an {@link #getVotArraysize() arraysize} and a + * {@link #getVotXtype() xtype}. Only the VOTable datatype is mandatory and + * must never be NULL. + *

+ * + *

Type comparison

+ *

+ * In some cases, it is useful to merge two information. The condition to + * perform this operation is to ensure their data-types are compatible + * enough for a such purpose. That's the goal of the function + * {@link #canMergeWith(DataType)}. + *

+ * + *

Simple serialization

+ *

+ * Any {@link DataType} can be serialized into a string thanks to + * {@link #toString()}. This latter should use the VOTable type + * information. Example: char[*]. See + * {@link SimpleType#toString()} for inspiration. + *

+ * + *

Implementing {@link DataType}

+ *

+ * An implementation of the functions {@link #canMergeWith(DataType)} + * and {@link #toString()} is already provided in the abstract class + * {@link SimpleType}. It is recommended to extends this class when defining + * new {@link DataType} implementations. + *

+ * + * @author Grégory Mantelet (CDS) + * @version 1.0 (05/2023) + * + * @see SimpleType + */ +public interface DataType { + + boolean isNumeric(); + + boolean isBoolean(); + + boolean isBinary(); + + boolean isString(); + + boolean isGeometry(); + + boolean isTime(); + + boolean isArray(); + + /** + * Get the corresponding VOTable datatype. + * + *

IMPORTANT: + * This function MUST never return NULL or an empty string. + *

+ * + * @return The corresponding VOTable datatype. + */ + String getVotDatatype(); + + /** + * Get the size of the represented array in the VOTable representation. + * + *

+ * This function must return an empty {@link Optional} object if + * this data type does not represent an array. + *

+ * + * @return The corresponding VOTable array size. + */ + Optional getVotArraysize(); + + /** + * Get the special type corresponding to this data type in the VOTable + * representation. In VOTable term, this piece of information is called an + * XType. + * + *

+ * This function must return an empty {@link Optional} object if + * this data type does not represent a special VOTable type. + *

+ * + * @return The corresponding VOTable XType. + */ + Optional getVotXtype(); + + String toString(); + + /** + * Tell whether a data of this type could be merged with a data of the given + * type. + * + *

+ * To return true this function has to evaluate whether + * the two given types are compatible at some level so that the two data + * to merge can be implicitly casted in each other type. + *

+ * + *

+ * By default (see {@link SimpleType#canMergeWith(DataType)}), two + * data types are declared compatible for merge when they are exactly + * the same class. But in some cases, this merge compatibility should be + * extended. For instance for exact numeric types: int, short and long. + * To indicate their compatibility, the corresponding {@link DataType} + * implementations should implement the same interface. For instance: + * {@link ExactNumericType} is the interface making {@link TypeShort}, + * {@link TypeInteger} and {@link TypeLong} compatible for merge. + *

+ * + * @param otherDatatype The data type of another datum. + * + * @return true if the two data types are compatible for merge, + * false otherwise (and especially if otherDatatype is + * null). + */ + boolean canMergeWith(final DataType otherDatatype); + +} diff --git a/ADQLLib/src/vollt/datatype/DataTypeFactory.java b/ADQLLib/src/vollt/datatype/DataTypeFactory.java new file mode 100644 index 00000000..87d8847a --- /dev/null +++ b/ADQLLib/src/vollt/datatype/DataTypeFactory.java @@ -0,0 +1,9 @@ +package vollt.datatype; + +public interface DataTypeFactory { + + DataType fromVOTable(final String datatype, final String arraysize, final String xtype); + + static DataTypeFactory getDefault(){ return DataTypeFactoryImp.DEFAULT_INSTANCE; } + +} \ No newline at end of file diff --git a/ADQLLib/src/vollt/datatype/DataTypeFactoryImp.java b/ADQLLib/src/vollt/datatype/DataTypeFactoryImp.java new file mode 100644 index 00000000..e7da7962 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/DataTypeFactoryImp.java @@ -0,0 +1,255 @@ +package vollt.datatype; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +public class DataTypeFactoryImp implements DataTypeFactory { + + static final DataTypeFactoryImp DEFAULT_INSTANCE = new DataTypeFactoryImp(); + + /** Exhaustive collection of all supported scalar types. */ + protected Map> mapSupportedTypes = new HashMap<>(); + + public DataTypeFactoryImp() { + // Simple types: + support(TypeBit.class); + support(TypeBoolean.class); + support(TypeChar.class); + support(TypeDouble.class); + support(TypeFloat.class); + support(TypeInteger.class); + support(TypeLong.class); + support(TypeShort.class); + support(TypeUnicodeChar.class); + support(TypeUnsignedByte.class); + + // Special types: + support(TypeCircleWithDouble.class); + support(TypeCircleWithFloat.class); + support(TypeIntervalOfDouble.class); + support(TypeIntervalOfFloat.class); + support(TypeIntervalOfInteger.class); + support(TypeIntervalOfLong.class); + support(TypeIntervalOfShort.class); + support(TypeMOC.class); + support(TypePointWithDouble.class); + support(TypePointWithFloat.class); + support(TypePolygonWithDouble.class); + support(TypePolygonWithFloat.class); + support(TypeRegion.class); + support(TypeShape.class); + support(TypeTimestamp.class); + } + + /** + * Declare a data type to support. + * + *

+ * This function should be used only by the constructor to update the + * collection of supported scalar types: {@link #mapSupportedTypes}. + *

+ * + *

IMPORTANT: + * The given class must represent a scalar type and must provide an empty + * constructor. + *

+ * + * @param typeClass Class of the type to support. + * + * @throws IncorrectDataTypeClass If the given type cannot be instantiated + * or a similar type is already supported in + * this factory. + */ + protected void support(final Class typeClass) throws IncorrectDataTypeClass { + // Try to get an instance of the given type: + ScalarType typeInstance; + try { + final Constructor constructor = typeClass.getConstructor(); + typeInstance = constructor.newInstance(); + }catch(Exception ex) { + throw new IncorrectDataTypeClass("Cannot create a "+this.getClass().getSimpleName()+"! Cause: impossible to create an instance of "+typeClass.getName()+".", ex); + } + + // Create a hash key with the XType and the datatype: + final String typeKey = buildTypeKey(typeInstance.getVotDatatype(), typeInstance.getVotXtype().orElse(null)); + if (mapSupportedTypes.containsKey(typeKey)) + throw new IncorrectDataTypeClass("Cannot create a "+this.getClass().getSimpleName()+"! Cause: a similar datatype (i.e. '" + typeKey + "') is already supported!"); + else + mapSupportedTypes.put(typeKey, typeClass); + } + + /** + * Build a key for mapping in a unique way a given data type. + * + * @param datatype A data type. SHOULD NOT BE null. + * @param xtype An extension of the given datatype. MAY BE + * null. + * + * @return The corresponding key. + */ + protected String buildTypeKey(final String datatype, final String xtype){ + return (xtype == null ? "" : normalizeXtype(xtype)) + "#" + normalizeDatatype(datatype); + } + + @Override + public DataType fromVOTable(final String datatype, final String arraysize, String xtype) { + // Search with the xtype and datatype: + ScalarType foundType = getType(datatype, xtype); + + // If not found, search without the xtype, if any is provided: + if (foundType == null && xtype != null){ + foundType = getType(datatype, null); + } + + // If still not found, return an UnknownType: + if (foundType == null){ + return new UnknownType(datatype, arraysize, xtype); + } + // If specified by arraysize, create a vector of this type: + else if (isVector(foundType, arraysize)){ + return new VectorType(foundType, arraysize); + } + // Otherwise, return the found scalar type: + else{ + return foundType; + } + } + + /** + * Search for the exact match for the specified type and return an instance + * of this type. + * + * @param datatype VOTable datatype. SHOULD NOT BE null. + * @param xtype VOTable special type. MAY BE null. + * + * @return The corresponding scalar type, + * or null if no match is found. + */ + protected ScalarType getType(final String datatype, final String xtype){ + // If no datatype, no type to return: + if (datatype == null || datatype.trim().isEmpty()) + return null; + + // Build the mapping key for the specified type: + String typeKey = buildTypeKey(datatype, xtype); + + // Search for a corresponding type: + final Class foundType = mapSupportedTypes.get(typeKey); + + // If found, create and return an instance: + if (foundType != null) { + try { + return foundType.newInstance(); + } catch (Exception t) { + return null; + } + }else + return null; + } + + /** + * Tell whether the given arraysize represents a vector of the given scalar + * type or not. + * + *

+ * Some special types (e.g. timestamp, point) are actually arrays in the + * VOTable representation. In other words, for such type, the VOTable + * attribute "arraysize" is not empty. However, with a multi-dimensional + * arraysize, it is still possible to represent a vector of such special + * scalar type. This function aims to detect simple cases like vector of + * simple scalar types as well as complex cases like a vector of special + * types. + *

+ * + * @param scalarType The scalar type that may be the vector subtype. + * @param arraysize The specified VOTable arraysize. + * + * @return true if the given arraysize represents a vector of + * the given scalar type, + * false if the final type is really just a scalar type. + */ + protected boolean isVector(final ScalarType scalarType, final String arraysize){ + final int arrayDimension = (arraysize != null && !arraysize.trim().isEmpty()) ? arraysize.toLowerCase().split("x").length : 0; + if (arrayDimension > 0) + return (!scalarType.getVotArraysize().isPresent() || arrayDimension > 1); + else + return false; + } + + /** + * Normalize the given VOTable datatype. + * + *

In practice, it means:

+ *
    + *
  • leading and trailing space characters are removed,
  • + *
  • the whole string is lower-cased.
  • + *
+ * + *

+ * Null is returned if the given datatype is + * null or an empty string. + *

+ * + * @param datatype The datatype to normalize. + * + * @return The normalized datatype, + * or null if no datatype provided. + */ + protected String normalizeDatatype(String datatype){ + // Nothing to do, if no xtype: + if (datatype == null) + return null; + + // Remove leading and trailing spaces and put in lower case: + datatype = datatype.trim().toLowerCase(); + + // NULL if nothing to return: + if (datatype.isEmpty()) + return null; + else + return datatype; + } + + /** + * Normalize the given VOTable XType. + * + *

In practice, it means:

+ *
    + *
  • the schema prefix is removed, if any is found + * (e.g. adql:POINT),
  • + *
  • leading and trailing space characters are removed,
  • + *
  • the whole string is lower-cased.
  • + *
+ * + *

+ * Null is returned if the given XType is null + * or an empty string (even after schema prefix removal). + *

+ * + * @param xtype The XType to normalize. + * + * @return The normalized XType, + * or null if no XType provided. + */ + protected String normalizeXtype(String xtype){ + // Nothing to do, if no xtype: + if (xtype == null) + return null; + + // Remove any schema prefix: + final int indSchemaPrefix = xtype.indexOf(':'); + if (indSchemaPrefix >= 0) + xtype = xtype.substring(indSchemaPrefix+1); + + // Remove leading and trailing spaces and put in lower case: + xtype = xtype.trim().toLowerCase(); + + // NULL if nothing to return: + if (xtype.isEmpty()) + return null; + else + return xtype; + } + +} diff --git a/ADQLLib/src/vollt/datatype/ExactNumericType.java b/ADQLLib/src/vollt/datatype/ExactNumericType.java new file mode 100644 index 00000000..7e705a95 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/ExactNumericType.java @@ -0,0 +1,31 @@ +package vollt.datatype; + +/** + * @author Grégory Mantelet (CDS) + * @version (05 / 2023) + */ +public abstract class ExactNumericType extends ScalarType { + @Override + public boolean isNumeric() { return true; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public boolean canMergeWith(final DataType otherDatatype) { + return super.canMergeWith(otherDatatype) + || (otherDatatype instanceof ExactNumericType); + } +} diff --git a/ADQLLib/src/vollt/datatype/FloatingType.java b/ADQLLib/src/vollt/datatype/FloatingType.java new file mode 100644 index 00000000..c681852d --- /dev/null +++ b/ADQLLib/src/vollt/datatype/FloatingType.java @@ -0,0 +1,31 @@ +package vollt.datatype; + +/** + * @author Grégory Mantelet (CDS) + * @version (05 / 2023) + */ +public abstract class FloatingType extends ScalarType { + @Override + public boolean isNumeric() { return true; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public boolean canMergeWith(final DataType otherDatatype) { + return super.canMergeWith(otherDatatype) + || (otherDatatype instanceof FloatingType); + } +} diff --git a/ADQLLib/src/vollt/datatype/GeometryType.java b/ADQLLib/src/vollt/datatype/GeometryType.java new file mode 100644 index 00000000..ab77f298 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/GeometryType.java @@ -0,0 +1,27 @@ +package vollt.datatype; + +public abstract class GeometryType extends ScalarType { + @Override + public boolean isNumeric() { return false; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return true; } + + @Override + public boolean isTime() { return false; } + + @Override + public boolean canMergeWith(final DataType otherDatatype) { + return super.canMergeWith(otherDatatype) + || (otherDatatype instanceof GeometryType); + } +} diff --git a/ADQLLib/src/vollt/datatype/IncorrectDataTypeClass.java b/ADQLLib/src/vollt/datatype/IncorrectDataTypeClass.java new file mode 100644 index 00000000..f1d78060 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/IncorrectDataTypeClass.java @@ -0,0 +1,19 @@ +package vollt.datatype; + +public class IncorrectDataTypeClass extends RuntimeException { + public IncorrectDataTypeClass() { + super(); + } + + public IncorrectDataTypeClass(String s) { + super(s); + } + + public IncorrectDataTypeClass(String s, Throwable throwable) { + super(s, throwable); + } + + public IncorrectDataTypeClass(Throwable throwable) { + super(throwable); + } +} diff --git a/ADQLLib/src/vollt/datatype/ScalarType.java b/ADQLLib/src/vollt/datatype/ScalarType.java new file mode 100644 index 00000000..1cdc809a --- /dev/null +++ b/ADQLLib/src/vollt/datatype/ScalarType.java @@ -0,0 +1,13 @@ +package vollt.datatype; + +import java.util.Optional; + +public abstract class ScalarType extends SimpleType { + @Override + public final boolean isArray() { return false; } + + @Override + public Optional getVotArraysize() { + return Optional.empty(); + } +} diff --git a/ADQLLib/src/vollt/datatype/SimpleType.java b/ADQLLib/src/vollt/datatype/SimpleType.java new file mode 100644 index 00000000..d11f091f --- /dev/null +++ b/ADQLLib/src/vollt/datatype/SimpleType.java @@ -0,0 +1,57 @@ +package vollt.datatype; + +/** + * Default implementation for data type serialization ({@link #toString()}) + * and the type comparison for merging ({@link #canMergeWith(DataType)}). + * + *

String serialization

+ *

+ * In this implementation, a {@link DataType} is serialized in string + * using the VOTable type information. In short, if an + * {@link #getVotXtype() XType} if available, {@link #toString()} returns + * just this piece of information. Otherwise, the + * {@link #getVotDatatype() VOTable datatype} is returned. It is suffixed + * with the VOTable array size between square brackets, if representing an + * array. + *

+ *

+ * Examples: char[*], timestamp, + * double, float[2], int[2x3*]. + *

+ * + *

Merge compatibility

+ *

+ * {@link DataType} extending {@link SimpleType} are declared compatible + * for merge only with a datum of the exact same {@link DataType}. + *

+ * + * @author Grégory Mantelet (CDS) + * @version 1.0 (05/2023) + */ +public abstract class SimpleType implements DataType { + + @Override + public String toString() { + // An XType gives the precise datatype name, so use it if provided: + if (getVotXtype().isPresent()) + return getVotXtype().get(); + // Otherwise... + else { + // ...combine the datatype (mandatory): + final StringBuilder str = new StringBuilder(getVotDatatype()); + // ...with the array size (if available): + if (getVotArraysize().isPresent()) + str.append('[').append(getVotArraysize().get()).append(']'); + return str.toString(); + } + } + + @Override + public boolean canMergeWith(final DataType otherDatatype) { + return (otherDatatype != null) + && (this.getClass().equals(otherDatatype.getClass()) + || this instanceof UnknownType || otherDatatype instanceof UnknownType); + // TODO Review merge condition! + } + +} diff --git a/ADQLLib/src/vollt/datatype/StringType.java b/ADQLLib/src/vollt/datatype/StringType.java new file mode 100644 index 00000000..fcb35063 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/StringType.java @@ -0,0 +1,26 @@ +package vollt.datatype; + +import java.util.Optional; + +public abstract class StringType extends ScalarType { + @Override + public boolean isNumeric() { return false; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return true; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeBit.java b/ADQLLib/src/vollt/datatype/TypeBit.java new file mode 100644 index 00000000..8f6683dd --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeBit.java @@ -0,0 +1,31 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeBit extends ScalarType{ + private static final String VOTABLE_DATATYPE = "bit"; + + @Override + public boolean isNumeric() { return true; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return true; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeBoolean.java b/ADQLLib/src/vollt/datatype/TypeBoolean.java new file mode 100644 index 00000000..b42c33e2 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeBoolean.java @@ -0,0 +1,35 @@ +package vollt.datatype; + +import java.util.Optional; + +/** + * @author Grégory Mantelet (CDS) + * @version (05 / 2023) + */ +public class TypeBoolean extends ScalarType { + private static final String VOTABLE_DATATYPE = "boolean"; + + @Override + public boolean isNumeric() { return true; } + + @Override + public boolean isBoolean() { return true; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeChar.java b/ADQLLib/src/vollt/datatype/TypeChar.java new file mode 100644 index 00000000..c50c3f0f --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeChar.java @@ -0,0 +1,8 @@ +package vollt.datatype; + +public class TypeChar extends StringType { + private static final String VOTABLE_DATATYPE = "char"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeCircleWithDouble.java b/ADQLLib/src/vollt/datatype/TypeCircleWithDouble.java new file mode 100644 index 00000000..345cb421 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeCircleWithDouble.java @@ -0,0 +1,20 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeCircleWithDouble extends GeometryType { + private static final String VOTABLE_DATATYPE = "double"; + + private static final String VOTABLE_ARRAYSIZE = "3"; + + private static final String VOTABLE_XTYPE = "circle"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeCircleWithFloat.java b/ADQLLib/src/vollt/datatype/TypeCircleWithFloat.java new file mode 100644 index 00000000..bc3cd151 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeCircleWithFloat.java @@ -0,0 +1,20 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeCircleWithFloat extends GeometryType { + private static final String VOTABLE_DATATYPE = "float"; + + private static final String VOTABLE_ARRAYSIZE = "3"; + + private static final String VOTABLE_XTYPE = "circle"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeDouble.java b/ADQLLib/src/vollt/datatype/TypeDouble.java new file mode 100644 index 00000000..b92b06a4 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeDouble.java @@ -0,0 +1,13 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeDouble extends FloatingType { + private static final String VOTABLE_DATATYPE = "double"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeFloat.java b/ADQLLib/src/vollt/datatype/TypeFloat.java new file mode 100644 index 00000000..17516e83 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeFloat.java @@ -0,0 +1,13 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeFloat extends FloatingType { + private static final String VOTABLE_DATATYPE = "float"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeInteger.java b/ADQLLib/src/vollt/datatype/TypeInteger.java new file mode 100644 index 00000000..0a122d77 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeInteger.java @@ -0,0 +1,17 @@ +package vollt.datatype; + +import java.util.Optional; + +/** + * @author Grégory Mantelet (CDS) + * @version (05 / 2023) + */ +public class TypeInteger extends ExactNumericType { + private static final String VOTABLE_DATATYPE = "int"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeInterval.java b/ADQLLib/src/vollt/datatype/TypeInterval.java new file mode 100644 index 00000000..f15aae8e --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeInterval.java @@ -0,0 +1,40 @@ +package vollt.datatype; + +import java.util.Optional; + +public abstract class TypeInterval extends ScalarType{ + + private static final String VOTABLE_ARRAYSIZE = "2"; + + private static final String VOTABLE_XTYPE = "interval"; + + @Override + public boolean isNumeric() { return true; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } + + public static TypeInterval fromShort(){ return new TypeIntervalOfShort(); } + public static TypeInterval fromInteger(){ return new TypeIntervalOfInteger(); } + public static TypeInterval fromLong(){ return new TypeIntervalOfLong(); } + public static TypeInterval fromFloat(){ return new TypeIntervalOfFloat(); } + public static TypeInterval fromDouble(){ return new TypeIntervalOfDouble(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeIntervalOfDouble.java b/ADQLLib/src/vollt/datatype/TypeIntervalOfDouble.java new file mode 100644 index 00000000..580339ba --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeIntervalOfDouble.java @@ -0,0 +1,9 @@ +package vollt.datatype; + +public class TypeIntervalOfDouble extends TypeInterval{ + + private static final String VOTABLE_DATATYPE = "double"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeIntervalOfFloat.java b/ADQLLib/src/vollt/datatype/TypeIntervalOfFloat.java new file mode 100644 index 00000000..9f596deb --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeIntervalOfFloat.java @@ -0,0 +1,9 @@ +package vollt.datatype; + +public class TypeIntervalOfFloat extends TypeInterval{ + + private static final String VOTABLE_DATATYPE = "float"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeIntervalOfInteger.java b/ADQLLib/src/vollt/datatype/TypeIntervalOfInteger.java new file mode 100644 index 00000000..616d1599 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeIntervalOfInteger.java @@ -0,0 +1,9 @@ +package vollt.datatype; + +public class TypeIntervalOfInteger extends TypeInterval{ + + private static final String VOTABLE_DATATYPE = "integer"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeIntervalOfLong.java b/ADQLLib/src/vollt/datatype/TypeIntervalOfLong.java new file mode 100644 index 00000000..b5ecdbae --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeIntervalOfLong.java @@ -0,0 +1,9 @@ +package vollt.datatype; + +public class TypeIntervalOfLong extends TypeInterval{ + + private static final String VOTABLE_DATATYPE = "long"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeIntervalOfShort.java b/ADQLLib/src/vollt/datatype/TypeIntervalOfShort.java new file mode 100644 index 00000000..01976d02 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeIntervalOfShort.java @@ -0,0 +1,9 @@ +package vollt.datatype; + +public class TypeIntervalOfShort extends TypeInterval{ + + private static final String VOTABLE_DATATYPE = "short"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeLong.java b/ADQLLib/src/vollt/datatype/TypeLong.java new file mode 100644 index 00000000..bc73ebe2 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeLong.java @@ -0,0 +1,17 @@ +package vollt.datatype; + +import java.util.Optional; + +/** + * @author Grégory Mantelet (CDS) + * @version (05 / 2023) + */ +public class TypeLong extends ExactNumericType { + private static final String VOTABLE_DATATYPE = "long"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeMOC.java b/ADQLLib/src/vollt/datatype/TypeMOC.java new file mode 100644 index 00000000..b8550d4e --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeMOC.java @@ -0,0 +1,39 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeMOC extends ScalarType { + + private static final String VOTABLE_DATATYPE = "char"; + + private static final String VOTABLE_ARRAYSIZE = "*"; + + private static final String VOTABLE_XTYPE = "moc"; + + @Override + public boolean isNumeric() { return false; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return true; } + + @Override + public boolean isTime() { return false; } + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } +} diff --git a/ADQLLib/src/vollt/datatype/TypePoint.java b/ADQLLib/src/vollt/datatype/TypePoint.java new file mode 100644 index 00000000..088ca6de --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypePoint.java @@ -0,0 +1,19 @@ +package vollt.datatype; + +import java.util.Optional; + +public abstract class TypePoint extends GeometryType { + private static final String VOTABLE_ARRAYSIZE = "2"; + + private static final String VOTABLE_XTYPE = "point"; + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } + + public static TypePoint fromFloat(){ return new TypePointWithFloat(); } + + public static TypePoint fromDouble(){ return new TypePointWithDouble(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypePointWithDouble.java b/ADQLLib/src/vollt/datatype/TypePointWithDouble.java new file mode 100644 index 00000000..c1e1bd59 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypePointWithDouble.java @@ -0,0 +1,8 @@ +package vollt.datatype; + +public class TypePointWithDouble extends TypePoint { + private static final String VOTABLE_DATATYPE = "double"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypePointWithFloat.java b/ADQLLib/src/vollt/datatype/TypePointWithFloat.java new file mode 100644 index 00000000..f6fa6fb5 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypePointWithFloat.java @@ -0,0 +1,8 @@ +package vollt.datatype; + +public class TypePointWithFloat extends TypePoint { + private static final String VOTABLE_DATATYPE = "float"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypePolygon.java b/ADQLLib/src/vollt/datatype/TypePolygon.java new file mode 100644 index 00000000..591cefd9 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypePolygon.java @@ -0,0 +1,20 @@ +package vollt.datatype; + +import java.util.Optional; + +public abstract class TypePolygon extends GeometryType { + + private static final String VOTABLE_ARRAYSIZE = "*"; + + private static final String VOTABLE_XTYPE = "polygon"; + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } + + public static TypePolygon fromFloat(){ return new TypePolygonWithFloat(); } + + public static TypePolygon fromDouble(){ return new TypePolygonWithDouble(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypePolygonWithDouble.java b/ADQLLib/src/vollt/datatype/TypePolygonWithDouble.java new file mode 100644 index 00000000..72887ada --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypePolygonWithDouble.java @@ -0,0 +1,8 @@ +package vollt.datatype; + +public class TypePolygonWithDouble extends TypePolygon { + private static final String VOTABLE_DATATYPE = "double"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypePolygonWithFloat.java b/ADQLLib/src/vollt/datatype/TypePolygonWithFloat.java new file mode 100644 index 00000000..449165e2 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypePolygonWithFloat.java @@ -0,0 +1,8 @@ +package vollt.datatype; + +public class TypePolygonWithFloat extends TypePolygon { + private static final String VOTABLE_DATATYPE = "float"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeRegion.java b/ADQLLib/src/vollt/datatype/TypeRegion.java new file mode 100644 index 00000000..ce6d19e8 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeRegion.java @@ -0,0 +1,34 @@ +package vollt.datatype; + +import java.util.Optional; + +/** + * Type used to represent an STC-s geometrical region. + * + *

+ * This type may be deprecated by future version of DALI. Then, it would be + * replaced by {@link TypeShape}. + * TODO - A mapping between a region and a shape should be done. + *

+ * + * @see TypeShape + * + * @author Grégory Mantelet (CDS) + * @version 1.0 (05/2023) + */ +public class TypeRegion extends GeometryType { + private static final String VOTABLE_DATATYPE = "char"; + + private static final String VOTABLE_ARRAYSIZE = "*"; + + private static final String VOTABLE_XTYPE = "region"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeShape.java b/ADQLLib/src/vollt/datatype/TypeShape.java new file mode 100644 index 00000000..cf0d3940 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeShape.java @@ -0,0 +1,39 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeShape extends ScalarType { + + private static final String VOTABLE_DATATYPE = "char"; + + private static final String VOTABLE_ARRAYSIZE = "*"; + + private static final String VOTABLE_XTYPE = "shape"; + + @Override + public boolean isNumeric() { return false; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return true; } + + @Override + public boolean isTime() { return false; } + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeShort.java b/ADQLLib/src/vollt/datatype/TypeShort.java new file mode 100644 index 00000000..fab2e091 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeShort.java @@ -0,0 +1,17 @@ +package vollt.datatype; + +import java.util.Optional; + +/** + * @author Grégory Mantelet (CDS) + * @version (05 / 2023) + */ +public class TypeShort extends ExactNumericType { + private static final String VOTABLE_DATATYPE = "short"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeTimestamp.java b/ADQLLib/src/vollt/datatype/TypeTimestamp.java new file mode 100644 index 00000000..d4fa6249 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeTimestamp.java @@ -0,0 +1,38 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeTimestamp extends ScalarType { + private static final String VOTABLE_DATATYPE = "char"; + + private static final String VOTABLE_ARRAYSIZE = "*"; + + private static final String VOTABLE_XTYPE = "TIMESTAMP"; + + @Override + public boolean isNumeric() { return false; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return true; } + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotArraysize() { return Optional.of(VOTABLE_ARRAYSIZE); } + + @Override + public Optional getVotXtype() { return Optional.of(VOTABLE_XTYPE); } +} diff --git a/ADQLLib/src/vollt/datatype/TypeUnicodeChar.java b/ADQLLib/src/vollt/datatype/TypeUnicodeChar.java new file mode 100644 index 00000000..241efdcc --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeUnicodeChar.java @@ -0,0 +1,8 @@ +package vollt.datatype; + +public class TypeUnicodeChar extends StringType { + private static final String VOTABLE_DATATYPE = "unicodeChar"; + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } +} diff --git a/ADQLLib/src/vollt/datatype/TypeUnsignedByte.java b/ADQLLib/src/vollt/datatype/TypeUnsignedByte.java new file mode 100644 index 00000000..7ae156ea --- /dev/null +++ b/ADQLLib/src/vollt/datatype/TypeUnsignedByte.java @@ -0,0 +1,31 @@ +package vollt.datatype; + +import java.util.Optional; + +public class TypeUnsignedByte extends ScalarType { + private static final String VOTABLE_DATATYPE = "unsignedByte"; + + @Override + public boolean isNumeric() { return false; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return true; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public String getVotDatatype() { return VOTABLE_DATATYPE; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } +} diff --git a/ADQLLib/src/vollt/datatype/UnknownNumericType.java b/ADQLLib/src/vollt/datatype/UnknownNumericType.java new file mode 100644 index 00000000..257a7d49 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/UnknownNumericType.java @@ -0,0 +1,27 @@ +package vollt.datatype; + +public class UnknownNumericType extends UnknownType { + private static final String VOTABLE_DATATYPE = "double"; + + public UnknownNumericType() { + super(VOTABLE_DATATYPE, null, null); + } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public boolean isArray() { return false; } +} diff --git a/ADQLLib/src/vollt/datatype/UnknownType.java b/ADQLLib/src/vollt/datatype/UnknownType.java new file mode 100644 index 00000000..2ace62a6 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/UnknownType.java @@ -0,0 +1,61 @@ +package vollt.datatype; + +import java.util.Optional; + +public class UnknownType extends SimpleType { + private static final String DEFAULT_DATATYPE = "char"; + + private static final String DEFAULT_ARRAYSIZE = "*"; + + private final String votDatatype; + + private final String votArraysize; + + private final String votXtype; + + public UnknownType() { + this(null, null, null); + } + + public UnknownType(final String votDatatype, final String votArraysize, final String votXtype){ + if (votDatatype == null || votDatatype.trim().length() == 0){ + this.votDatatype = DEFAULT_DATATYPE; + this.votArraysize = DEFAULT_ARRAYSIZE; + this.votXtype = null; + } else { + this.votDatatype = votDatatype.trim(); + this.votArraysize = (votArraysize == null || votArraysize.trim().length() == 0) ? null : votArraysize.trim(); + this.votXtype = (votXtype == null || votXtype.trim().length() == 0) ? null : votXtype.trim(); + } + } + + @Override + public boolean isNumeric() { return true; } + + @Override + public boolean isBoolean() { return true; } + + @Override + public boolean isBinary() { return true; } + + @Override + public boolean isString() { return true; } + + @Override + public boolean isGeometry() { return true; } + + @Override + public boolean isTime() { return true; } + + @Override + public boolean isArray() { return true; } + + @Override + public final String getVotDatatype() { return votDatatype; } + + @Override + public final Optional getVotArraysize() { return Optional.ofNullable(votArraysize); } + + @Override + public final Optional getVotXtype() { return Optional.ofNullable(votXtype); } +} diff --git a/ADQLLib/src/vollt/datatype/VectorType.java b/ADQLLib/src/vollt/datatype/VectorType.java new file mode 100644 index 00000000..df4d7ca3 --- /dev/null +++ b/ADQLLib/src/vollt/datatype/VectorType.java @@ -0,0 +1,58 @@ +package vollt.datatype; + +import java.util.Optional; + +public class VectorType extends SimpleType { + protected final ScalarType subType; + + protected final String arraysize; + + public VectorType(final ScalarType subType, final String arraysize) throws NullPointerException, IllegalArgumentException { + if (subType == null) + throw new NullPointerException("Missing vector sub-type!"); + + if (arraysize == null) + throw new NullPointerException("Missing vector size!"); + else if (arraysize.trim().length() == 0) + throw new IllegalArgumentException("Empty vector size!"); + + this.subType = subType; + this.arraysize = arraysize.trim(); + } + + @Override + public boolean isNumeric() { return subType.isNumeric(); } + + @Override + public boolean isBoolean() { return subType.isBoolean(); } + + @Override + public boolean isBinary() { return subType.isBinary(); } + + @Override + public boolean isString() { return subType.isString(); } + + @Override + public boolean isGeometry() { return subType.isGeometry(); } + + @Override + public boolean isTime() { return subType.isTime(); } + + @Override + public boolean isArray() { return true; } + + @Override + public String getVotDatatype() { return subType.getVotDatatype(); } + + @Override + public Optional getVotArraysize() { return Optional.of(arraysize); } + + @Override + public Optional getVotXtype() { return subType.getVotXtype(); } + + @Override + public boolean canMergeWith(final DataType otherDatatype) { + return (otherDatatype instanceof VectorType) + && subType.canMergeWith(((VectorType)otherDatatype).subType); + } +} diff --git a/ADQLLib/test/vollt/datatype/TestDataTypeFactoryImp.java b/ADQLLib/test/vollt/datatype/TestDataTypeFactoryImp.java new file mode 100644 index 00000000..5797f5d9 --- /dev/null +++ b/ADQLLib/test/vollt/datatype/TestDataTypeFactoryImp.java @@ -0,0 +1,275 @@ +package vollt.datatype; + +import org.junit.Test; + +import java.util.Optional; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class TestDataTypeFactoryImp { + + /* ********************************************************************** + * * FROM_VOTABLE * + * ********************************************************************** */ + + @Test + public void testFromVOTable_WithNoDatatype(){ + final DataType type = (new DataTypeFactoryImp()).fromVOTable(null, null, null); + assertNotNull(type); + assertEquals(UnknownType.class, type.getClass()); + assertEquals("char", type.getVotDatatype()); + assertTrue(type.getVotArraysize().isPresent()); + assertEquals("*", type.getVotArraysize().get()); + assertFalse(type.getVotXtype().isPresent()); + } + + @Test + public void testFromVOTable_WithUnknownDatatype(){ + final String UNKNOWN_DATATYPE = "unknown"; + final DataType type = (new DataTypeFactoryImp()).fromVOTable(UNKNOWN_DATATYPE, null, null); + assertNotNull(type); + assertEquals(UnknownType.class, type.getClass()); + assertEquals(UNKNOWN_DATATYPE, type.getVotDatatype()); + assertFalse(type.getVotArraysize().isPresent()); + assertFalse(type.getVotXtype().isPresent()); + } + + @Test + public void testFromVOTable_WithKnownDatatype(){ + final DataType type = (new DataTypeFactoryImp()).fromVOTable("double", null, null); + assertNotNull(type); + assertEquals(TypeDouble.class, type.getClass()); + } + + @Test + public void testFromVOTable_WithKnownXtype(){ + final DataType type = (new DataTypeFactoryImp()).fromVOTable("char", "*", "timestamp"); + assertNotNull(type); + assertEquals(TypeTimestamp.class, type.getClass()); + } + + @Test + public void testFromVOTable_WithUnknownXtypeButKnownDatatype(){ + final String UNKNOWN_XTYPE = "long_text"; + final DataType type = (new DataTypeFactoryImp()).fromVOTable("char", null, UNKNOWN_XTYPE); + assertNotNull(type); + assertEquals(TypeChar.class, type.getClass()); + assertFalse(type.getVotArraysize().isPresent()); + assertFalse(type.getVotXtype().isPresent()); + } + + @Test + public void testFromVOTable_WithKnownXtypeButIncorrectDatatype(){ + final DataType type = (new DataTypeFactoryImp()).fromVOTable("long", null, "timestamp"); + assertNotNull(type); + assertEquals(TypeLong.class, type.getClass()); + assertFalse(type.getVotArraysize().isPresent()); + assertFalse(type.getVotXtype().isPresent()); + } + + @Test + public void testFromVOTable_WithUnknownXtypeAndUnknownDatatype(){ + final String UNKNOWN_DATATYPE = "unknown"; + final String UNKNOWN_XTYPE = "long_text"; + final DataType type = (new DataTypeFactoryImp()).fromVOTable(UNKNOWN_DATATYPE, null, UNKNOWN_XTYPE); + assertNotNull(type); + assertEquals(UnknownType.class, type.getClass()); + assertEquals(UNKNOWN_DATATYPE, type.getVotDatatype()); + assertFalse(type.getVotArraysize().isPresent()); + assertTrue(type.getVotXtype().isPresent()); + assertEquals(UNKNOWN_XTYPE, type.getVotXtype().get()); + } + + @Test + public void testFromVOTable_WithVectorOfSimpleType(){ + final DataType type = (new DataTypeFactoryImp()).fromVOTable("long", "3", null); + assertNotNull(type); + assertEquals(VectorType.class, type.getClass()); + assertEquals(TypeLong.class, ((VectorType)type).subType.getClass()); + assertTrue(type.getVotArraysize().isPresent()); + assertEquals("3", type.getVotArraysize().get()); + assertFalse(type.getVotXtype().isPresent()); + } + + @Test + public void testFromVOTable_WithVectorOfSpecialType(){ + final DataType type = (new DataTypeFactoryImp()).fromVOTable("double", "2x*", " POINT "); + assertNotNull(type); + assertEquals(VectorType.class, type.getClass()); + assertEquals(TypePointWithDouble.class, ((VectorType)type).subType.getClass()); + assertTrue(type.getVotArraysize().isPresent()); + assertEquals("2x*", type.getVotArraysize().get()); + assertTrue(type.getVotXtype().isPresent()); + assertEquals("point", type.getVotXtype().get()); + } + + /* ********************************************************************** + * * GET_TYPE * + * ********************************************************************** */ + + @Test + public void testGetType_WithNoDatatype(){ + assertNull((new DataTypeFactoryImp()).getType(null, null)); + } + + @Test + public void testGetType_WithNoXtype(){ + final DataType type = (new DataTypeFactoryImp()).getType("char", null); + assertNotNull(type); + assertEquals(TypeChar.class, type.getClass()); + } + + @Test + public void testGetType_WithUnknownDatatype(){ + assertNull((new DataTypeFactoryImp()).getType("unknown", null)); + } + + @Test + public void testGetType_WithUnknownXtype(){ + assertNull((new DataTypeFactoryImp()).getType("char", "unknown")); + } + + /* ********************************************************************** + * * IS_VECTOR * + * ********************************************************************** */ + + @Test + public void testIsVector_WithNoType(){ + try{ + (new DataTypeFactoryImp()).isVector(null, null); + }catch(Throwable t){ + assertEquals(NullPointerException.class, t.getClass()); + } + } + + @Test + public void testIsVector_WithNoArraysize(){ + for(String str : new String[]{null, "", " \n "}) + assertFalse((new DataTypeFactoryImp()).isVector(new TypeTimestamp(), str)); + } + + @Test + public void testIsVector_ScalarWithArraysizeButNotAVector(){ + assertFalse((new DataTypeFactoryImp()).isVector(TypePoint.fromDouble(), "*")); + } + + @Test + public void testIsVector_SpecialTypeWithArraysizeAndAVector(){ + assertTrue((new DataTypeFactoryImp()).isVector(TypePoint.fromFloat(), "2x*")); + } + + @Test + public void testIsVector_ScalarWithArraysizeAndAVector(){ + assertTrue((new DataTypeFactoryImp()).isVector(new TypeDouble(), "3")); + } + + /* ********************************************************************** + * * SUPPORT * + * ********************************************************************** */ + + @Test + public void testSupport_WithNull(){ + try{ + new DataTypeFactoryImp(); + }catch(Throwable t){ + assertEquals(NullPointerException.class, t.getClass()); + } + } + + @Test + public void testSupport_WithMissingEmptyConstructor(){ + try{ + (new DataTypeFactoryImp()).support(TypeScalarMock.class); + }catch(Throwable t){ + assertEquals(IncorrectDataTypeClass.class, t.getClass()); + assertEquals("Cannot create a DataTypeFactoryImp! Cause: impossible to create an instance of "+TypeScalarMock.class.getName()+".", t.getMessage()); + } + } + + /* ********************************************************************** + * * DATATYPE NORMALIZATION * + * ********************************************************************** */ + + @Test + public void testNormalizeDatatype_WithNull(){ + assertNull((new DataTypeFactoryImp()).normalizeDatatype(null)); + } + + @Test + public void testNormalizeDatatype_WithEmptyString(){ + for(String str : new String[]{"", " \n "}) + assertNull((new DataTypeFactoryImp()).normalizeDatatype(str)); + } + + @Test + public void testNormalizeDatatype(){ + assertEquals("double", (new DataTypeFactoryImp()).normalizeDatatype(" double ")); + } + + /* ********************************************************************** + * * XTYPE NORMALIZATION * + * ********************************************************************** */ + + @Test + public void testNormalizeXtype_WithNull(){ + assertNull((new DataTypeFactoryImp()).normalizeXtype(null)); + } + + @Test + public void testNormalizeXtype_WithEmptyString(){ + for(String str : new String[]{"", " \n "}) + assertNull((new DataTypeFactoryImp()).normalizeXtype(str)); + } + + @Test + public void testNormalizeXtype_WithJustPrefixSeparator(){ + assertNull((new DataTypeFactoryImp()).normalizeXtype(":")); + } + + @Test + public void testNormalizeXtype_WithPrefix(){ + assertEquals("point", (new DataTypeFactoryImp()).normalizeXtype(" adql : POINT\n")); + } + + @Test + public void testNormalizeXtype_WithNoPrefix(){ + assertEquals("point", (new DataTypeFactoryImp()).normalizeXtype(" POINT ")); + } + + /* ********************************************************************** + * * MOCK TYPE * + * ********************************************************************** */ + + private static class TypeScalarMock extends ScalarType { + public TypeScalarMock(final boolean uselessAttribute){} + + @Override + public boolean isNumeric() { return false; } + + @Override + public boolean isBoolean() { return false; } + + @Override + public boolean isBinary() { return false; } + + @Override + public boolean isString() { return false; } + + @Override + public boolean isGeometry() { return false; } + + @Override + public boolean isTime() { return false; } + + @Override + public String getVotDatatype() { return "mock"; } + + @Override + public Optional getVotXtype() { return Optional.empty(); } + } + +} \ No newline at end of file diff --git a/ADQLLib/test/vollt/datatype/TestSimpleType.java b/ADQLLib/test/vollt/datatype/TestSimpleType.java new file mode 100644 index 00000000..754201db --- /dev/null +++ b/ADQLLib/test/vollt/datatype/TestSimpleType.java @@ -0,0 +1,128 @@ +package vollt.datatype; + +import org.junit.Test; + +import java.util.Optional; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TestSimpleType { + + + /* ********************************************************************** + * * SERIALIZATION * + * ********************************************************************** */ + + @Test + public void testToString_WithXType(){ + final String XTYPE = "timestamp"; + assertEquals(XTYPE, (new SimpleTypeImpl("char", "*", "timestamp")).toString()); + } + + @Test + public void testToString_WithJustDatatype(){ + final String DATATYPE = "double"; + assertEquals(DATATYPE, (new SimpleTypeImpl(DATATYPE, null, null)).toString()); + } + + @Test + public void testToString_ArrayWithNoXtype(){ + final String DATATYPE = "char"; + final String ARRAYSIZE = "80*"; + assertEquals(DATATYPE+"["+ARRAYSIZE+"]", (new SimpleTypeImpl(DATATYPE, ARRAYSIZE, null)).toString()); + } + + + /* ********************************************************************** + * * CAN MERGE WITH * + * ********************************************************************** */ + + @Test + public void testCanMergeWith_Null() { + assertFalse((new SimpleTypeImpl()).canMergeWith(null)); + } + + @Test + public void testCanMergeWith_DifferentType() { + assertFalse((new SimpleTypeImpl()).canMergeWith(new SimpleTypeImpl2())); + } + + @Test + public void testCanMergeWith_SameType() { + assertTrue((new SimpleTypeImpl()).canMergeWith(new SimpleTypeImpl())); + } + + /* ********************************************************************** + * * MOCK TYPES * + * ********************************************************************** */ + + private static class SimpleTypeImpl extends SimpleType { + + private final String datatype; + private final String arraysize; + private final String xtype; + + public SimpleTypeImpl(){ + this(null, null, null); + } + + public SimpleTypeImpl(final String datatype, final String arraysize, final String xtype){ + this.datatype = datatype; + this.arraysize = arraysize; + this.xtype = xtype; + } + + @Override + public boolean isNumeric() { + return false; + } + + @Override + public boolean isBoolean() { + return false; + } + + @Override + public boolean isBinary() { + return false; + } + + @Override + public boolean isString() { + return false; + } + + @Override + public boolean isGeometry() { + return false; + } + + @Override + public boolean isTime() { + return false; + } + + @Override + public boolean isArray() { + return false; + } + + public String getVotDatatype() { return datatype; } + + public Optional getVotArraysize() { return Optional.ofNullable(arraysize); } + + public Optional getVotXtype() { return Optional.ofNullable(xtype); } + } + + /* + * Implementation note: + * This second implementation extends the first one in order to also test + * the case where two types are the same at a higher level. Even in this + * case, they should not be considered as merge-able. + */ + private static class SimpleTypeImpl2 extends SimpleTypeImpl { + } + +} \ No newline at end of file