public static void toString(Object value, Text t) { if (value == null) { t.append("null"); } else { final Class<? extends Object> clazz = value.getClass(); final DataType type = getDataType(clazz); if (type == null) { throw new RuntimeException("Invalid type: " + clazz.getName()); } type.toMarkup(value, t); } }
/** * Given this type and another, find the 'broadest' type * * @param rhs The other type. * @return The broadest type * @throws TypeMismatchException Data does not match expected data type. */ public DataType getCommnType(DataType rhs) throws TypeMismatchException { final DataType result; result = ordinal() > rhs.ordinal() ? this : rhs; if (numeric || rhs.numeric) { // One numeric then both must be.. if (result.ordinal() > F.ordinal()) { throw new TypeMismatchException("Either both must be numeric or neither"); } } else { // Neither numeric then both must be the same if (ordinal() != rhs.ordinal()) { throw new TypeMismatchException("Both types must be the same for non-numerics"); } } return result; }
/** * Given the parsing context and what numerical data type is expected convert a string to the * correct type. Note no attempt is made to let the magnitude of the number influence our choice. * * @param string The string to convert to a number. E.g. "123.3e2". If it contains a '.' or an 'e' * then the type must either be f or F. * @param requiredType Either z, Z, f, F or any. * @param tb The source. The cursor will be at the end of the number but any type specifier will * not have been consumed. If there is one then we'll eat it. * @return The derived type. * @throws ParsingException If there is a clash of types. */ private static Object deriveType(String string, DataType requiredType, Text t, int radix) { final Object result; // Figure out the correct type... final DataType derivedType; if (t.isEof()) { if (requiredType == DataType.any) { if (string.indexOf('.') >= 0 || string.indexOf('e') >= 0) { derivedType = DataType.f; } else { derivedType = DataType.z; } } else { derivedType = requiredType; } } else { final char c = t.peek(); if (c == 'z' || c == 'Z' || c == 'f' || c == 'F') { t.consume(c); derivedType = DataType.valueOf(String.valueOf(c)); if (!(requiredType == DataType.any || requiredType == derivedType)) { throw new ParsingException("Incompatible type: " + string + c); } } else { if (requiredType == DataType.any) { if (string.indexOf('.') >= 0 || string.indexOf('e') >= 0) { derivedType = DataType.f; } else { derivedType = DataType.z; } } else { derivedType = requiredType; } } } switch (derivedType) { case z: result = new Long(Long.parseLong(string, radix)); break; case Z: result = new BigInteger(string, radix); break; case f: result = new Double(string); break; case F: result = new BigDecimal(string); break; // $CASES-OMITTED$ default: throw new UnexpectedException("toType: " + derivedType); } return result; }
/** * Return the DataType corresponding to a given Java type. For example 'text' is returned given * String.class. * * @param clazz The class to look up. * @return The associated class or null if not found. */ @Nullable public static DataType getDataType(Class<?> clazz) { /* * This has to be done just-in-time as the javaToDataType is static and * can't be loaded as the enum is created. */ if (javaToDataType.isEmpty()) { for (final DataType dataType : DataType.values()) { javaToDataType.put(dataType.javaClass, dataType); } } return javaToDataType.get(clazz); }
/** * Can't override valueOf() so uUse this method instead as it treats boolean properly. If an error * is detected the Advisory is updated. * * @param key The key to look up. * @return The DataType associated with the given key. */ public static DataType valueOfCorrected(String key) { DataType result; try { if ("boolean".equals(key)) { result = bool; } else { result = DataType.valueOf(key); } } catch (final IllegalArgumentException e) { // todo Perhaps throw the catch when the Locus is known? final Advisory advisory = Context.get(Advisory.class); advisory.error("Invalid data type: " + key); result = any; } return result; }
@SuppressWarnings("unchecked") @Override public <P> Getter<GettableByIndexData, P> newGetter( Type target, DatastaxColumnKey key, ColumnDefinition<?, ?> columnDefinition) { Class<?> targetClass = TypeHelper.toClass(target); if (Date.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxDateGetter(key.getIndex()); } if (boolean.class.equals(targetClass) || Boolean.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxBooleanGetter(key.getIndex()); } if (InetAddress.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxInetAddressGetter(key.getIndex()); } if (TupleValue.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxTupleValueGetter(key.getIndex()); } if (Collection.class.isAssignableFrom(targetClass)) { Type elementType = TypeHelper.getComponentTypeOfListOrArray(target); Class<?> dataTypeClass = Object.class; Class<?> dataTypeElt = null; DataType dtElt = null; if (key.getDataType() != null) { DataType dataType = key.getDataType(); dataTypeClass = dataType.asJavaClass(); if (dataType.isCollection()) { dtElt = key.getDataType().getTypeArguments().get(0); dataTypeElt = dtElt.asJavaClass(); } } else { dataTypeElt = TypeHelper.toClass(elementType); } if (dataTypeElt != null) { if (TypeHelper.areEquals(elementType, dataTypeElt)) { if (Set.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxSetGetter(key.getIndex(), TypeHelper.toClass(elementType)); } } if (List.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxListGetter(key.getIndex(), TypeHelper.toClass(elementType)); } } } else { Converter<?, ?> converter = getConverter(elementType, dataTypeElt, dtElt); if (converter != null) { if (Set.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxSetWithConverterGetter(key.getIndex(), dataTypeElt, converter); } } if (List.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxListWithConverterGetter(key.getIndex(), dataTypeElt, converter); } } } } } } if (Map.class.equals(targetClass)) { Tuple2<Type, Type> keyValueTypeOfMap = TypeHelper.getKeyValueTypeOfMap(target); Class<?> dtKeyType = null; Class<?> dtValueType = null; DataType dtKey = null; DataType dtValue = null; if (key.getDataType() != null) { List<DataType> typeArguments = key.getDataType().getTypeArguments(); if (typeArguments.size() == 2) { dtKey = typeArguments.get(0); dtKeyType = dtKey.asJavaClass(); dtValue = typeArguments.get(1); dtValueType = dtValue.asJavaClass(); } } else { dtKeyType = TypeHelper.toClass(keyValueTypeOfMap.first()); dtValueType = TypeHelper.toClass(keyValueTypeOfMap.second()); } if (dtKeyType != null && dtValueType != null) { if (TypeHelper.areEquals(keyValueTypeOfMap.first(), dtKeyType) && TypeHelper.areEquals(keyValueTypeOfMap.second(), dtValueType)) { return new DatastaxMapGetter( key.getIndex(), TypeHelper.toClass(keyValueTypeOfMap.first()), TypeHelper.toClass(keyValueTypeOfMap.second())); } else { Converter<?, ?> keyConverter = getConverter(keyValueTypeOfMap.first(), dtKeyType, dtKey); Converter<?, ?> valueConverter = getConverter(keyValueTypeOfMap.second(), dtValueType, dtValue); if (keyConverter != null && valueConverter != null) { return new DatastaxMapWithConverterGetter( key.getIndex(), dtKeyType, dtValueType, keyConverter, valueConverter); } } } } if (Tuples.isTuple(target)) { if (key.getDataType() != null && key.getDataType() instanceof TupleType) { TupleType tt = (TupleType) key.getDataType(); List<DataType> typeArguments = tt.getTypeArguments(); TypeVariable<? extends Class<?>>[] typeParameters = targetClass.getTypeParameters(); if (typeArguments.size() <= typeParameters.length) { return (Getter<GettableByIndexData, P>) DatastaxTupleGetter.newInstance(datastaxMapperFactory, target, tt, key.getIndex()); } } } if (TypeHelper.isEnum(target)) { final Getter<GettableByIndexData, ? extends Enum> getter = enumGetter(key, TypeHelper.toClass(target)); if (getter != null) { return (Getter<GettableByIndexData, P>) getter; } } final GetterFactory<GettableByIndexData, DatastaxColumnKey> rowGetterFactory = getterFactories.get(targetClass); if (rowGetterFactory != null) { return rowGetterFactory.newGetter(target, key, columnDefinition); } final Getter<GettableByIndexData, P> getter = jodaTimeGetterFactory.newGetter(target, key, columnDefinition); if (getter != null) { return getter; } if (key.getDataType() != null && key.getDataType() instanceof UserType) { UserType ut = (UserType) key.getDataType(); return (Getter<GettableByIndexData, P>) DatastaxUDTGetter.newInstance(datastaxMapperFactory, target, ut, key.getIndex()); } return null; }