com.github.cassandra.jdbc.CassandraDataTypeConverters.java Source code

Java tutorial

Introduction

Here is the source code for com.github.cassandra.jdbc.CassandraDataTypeConverters.java

Source

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package com.github.cassandra.jdbc;

import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.*;
import com.google.common.io.ByteStreams;
import com.google.common.io.CharStreams;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Ints;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.pmw.tinylog.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.sql.Blob;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.*;

public class CassandraDataTypeConverters {
    private static final Splitter valueSplitter = Splitter.on(',').trimResults().omitEmptyStrings();

    private static final byte[] emptyByteArray = new byte[0];

    private static final List emptyList = ImmutableList.builder().build();
    private static final Set emptySet = ImmutableSet.builder().build();
    private static final Map emptyMap = ImmutableMap.builder().build();

    static final CassandraDataTypeConverters instance = new CassandraDataTypeConverters();

    private final Map<String, Object> defaultValues = new HashMap<String, Object>();
    private final Map<String, Function> typeMappings = new HashMap<String, Function>();

    protected void init() {
        // use "null" instead of empty string to avoid "InvalidQueryException: Key may not be empty"
        addMapping(String.class, "null", new Function<Object, String>() {
            public String apply(Object input) {
                String result;
                if (input instanceof Readable) {
                    try {
                        result = CharStreams.toString(((Readable) input));
                    } catch (IOException e) {
                        throw new IllegalArgumentException("Failed to read from Readable " + input, e);
                    }
                } else {
                    result = String.valueOf(input);
                }

                return result;
            }
        });
        addMapping(java.util.UUID.class, java.util.UUID.randomUUID(), new Function<Object, UUID>() {
            public UUID apply(Object input) {
                return java.util.UUID.fromString(String.valueOf(input));
            }
        });

        InetAddress defaultAddress = null;
        try {
            defaultAddress = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            Logger.warn(e, "Failed to get local host");
        }
        addMapping(InetAddress.class, defaultAddress, new Function<Object, InetAddress>() {
            public InetAddress apply(Object input) {
                try {
                    return InetAddress.getByName(String.valueOf(input));
                } catch (UnknownHostException e) {
                    throw CassandraErrors.unexpectedException(e);
                }
            }
        });
        addMapping(Blob.class, new CassandraBlob(new byte[0]), new Function<Object, Blob>() {
            public Blob apply(Object input) {
                CassandraBlob blob;

                if (input instanceof ByteBuffer) {
                    blob = new CassandraBlob((ByteBuffer) input);
                } else if (input instanceof byte[]) {
                    blob = new CassandraBlob((byte[]) input);
                } else if (input instanceof InputStream) {
                    try {
                        blob = new CassandraBlob(ByteStreams.toByteArray((InputStream) input));
                    } catch (IOException e) {
                        throw new IllegalArgumentException("Failed to read from input stream " + input, e);
                    }
                } else {
                    blob = new CassandraBlob(String.valueOf(input).getBytes());
                }

                return blob;
            }
        });
        addMapping(byte[].class, emptyByteArray, new Function<Object, byte[]>() {
            public byte[] apply(Object input) {
                byte[] result;

                if (input instanceof ByteBuffer) {
                    result = ((ByteBuffer) input).array();
                } else {
                    result = String.valueOf(input).getBytes();
                }

                return result;
            }
        });
        /*
        addMapping(ByteBuffer.class, ByteBuffer.wrap(new byte[0]), new Function<Object, ByteBuffer>() {
        public ByteBuffer apply(Object input) {
            return ByteBuffer.wrap(input instanceof byte[] ? (byte[]) input : String.valueOf(input).getBytes());
        }
        });
        */
        addMapping(Boolean.class, Boolean.FALSE, new Function<Object, Boolean>() {
            public Boolean apply(Object input) {
                return Boolean.valueOf(String.valueOf(input));
            }
        });
        addMapping(Byte.class, (byte) 0, new Function<Object, Byte>() {
            public Byte apply(Object input) {
                return input instanceof Number ? ((Number) input).byteValue()
                        : Ints.tryParse(String.valueOf(input)).byteValue();
            }
        });
        addMapping(Short.class, (short) 0, new Function<Object, Short>() {
            public Short apply(Object input) {
                return input instanceof Number ? ((Number) input).shortValue()
                        : Ints.tryParse(String.valueOf(input)).shortValue();
            }
        });
        addMapping(Integer.class, 0, new Function<Object, Integer>() {
            public Integer apply(Object input) {
                return input instanceof Number ? ((Number) input).intValue() : Ints.tryParse(String.valueOf(input));
            }
        });
        addMapping(Long.class, 0L, new Function<Object, Long>() {
            public Long apply(Object input) {
                return input instanceof Number ? ((Number) input).longValue()
                        : Long.parseLong(String.valueOf(input));
            }
        });
        addMapping(Float.class, 0.0F, new Function<Object, Float>() {
            public Float apply(Object input) {
                return input instanceof Number ? ((Number) input).floatValue()
                        : Doubles.tryParse(String.valueOf(input)).floatValue();
            }
        });
        addMapping(Double.class, 0.0D, new Function<Object, Double>() {
            public Double apply(Object input) {
                return input instanceof Number ? ((Number) input).doubleValue()
                        : Doubles.tryParse(String.valueOf(input));
            }
        });
        addMapping(BigDecimal.class, BigDecimal.ZERO, new Function<Object, BigDecimal>() {
            public BigDecimal apply(Object input) {
                return new BigDecimal(String.valueOf(input));
            }
        });
        addMapping(BigInteger.class, BigInteger.ZERO, new Function<Object, BigInteger>() {
            public BigInteger apply(Object input) {
                return new BigInteger(String.valueOf(input));
            }
        });

        addMapping(Date.class, new Date(System.currentTimeMillis()), new Function<Object, Date>() {
            public Date apply(Object input) {
                Date result;
                if (input instanceof LocalDate) {
                    result = new Date(((LocalDate) input).toDate().getTime());
                } else if (input instanceof java.util.Date) {
                    result = new Date(((java.util.Date) input).getTime());
                } else {
                    result = new Date(LocalDate.parse(String.valueOf(input)).toDate().getTime());
                }
                return result;
            }
        });
        addMapping(Time.class, new Time(System.currentTimeMillis()), new Function<Object, Time>() {
            public Time apply(Object input) {
                Time result;
                if (input instanceof LocalTime) {
                    result = new Time(((LocalTime) input).toDateTimeToday().getMillis());
                } else if (input instanceof java.util.Date) {
                    result = new Time(((java.util.Date) input).getTime());
                } else {
                    result = new Time(LocalTime.parse(String.valueOf(input)).toDateTimeToday().getMillis());
                }
                return result;
            }
        });
        addMapping(Timestamp.class, new Timestamp(System.currentTimeMillis()), new Function<Object, Timestamp>() {
            public Timestamp apply(Object input) {
                Timestamp result;
                if (input instanceof Instant) {
                    result = new Timestamp(((Instant) input).toDate().getTime());
                } else if (input instanceof java.util.Date) {
                    result = new Timestamp(((java.util.Date) input).getTime());
                } else if (input instanceof Number) {
                    result = new Timestamp(((Number) input).longValue());
                } else {
                    String dateTime = String.valueOf(input);
                    if (dateTime.indexOf(' ') == 10 && dateTime.indexOf('Z') < 0) {
                        StringBuilder builder = new StringBuilder(dateTime).append('Z');
                        builder.setCharAt(10, 'T');
                        dateTime = builder.toString();
                    }

                    result = new Timestamp(Instant.parse(dateTime).toDate().getTime());
                }
                return result;
            }
        });

        // now collections
        addMapping(List.class, emptyList, new Function<Object, List>() {
            public List apply(Object input) {
                List result;
                if (input instanceof Iterable) {
                    result = Lists.newArrayList((Iterable) input);
                } else if (input instanceof Object[]) {
                    result = Lists.newArrayList((Object[]) input);
                } else {
                    result = valueSplitter.splitToList(String.valueOf(input));
                }

                return result;
            }
        });
        addMapping(Set.class, emptySet, new Function<Object, Set>() {
            public Set apply(Object input) {
                Set result;
                if (input instanceof Iterable) {
                    result = Sets.newTreeSet((Iterable) input);
                } else if (input instanceof Object[]) {
                    result = Sets.newHashSet((Object[]) input);
                } else {
                    result = Sets.newTreeSet(valueSplitter.splitToList(String.valueOf(input)));
                }

                return result;
            }
        });
        addMapping(Set.class, emptyMap, new Function<Object, Map>() {
            public Map apply(Object input) {
                return Map.class.cast(input);
            }
        });
    }

    protected void addMapping(Class clazz, Object defaultValue, Function converter) {
        String key = clazz == null ? null : clazz.getName();

        if (defaultValue != null) {
            defaultValues.put(key, defaultValue);
        }

        if (converter != null) {
            typeMappings.put(key, converter);
        }
    }

    protected CassandraDataTypeConverters() {
        init();
    }

    public <T> T defaultValueOf(Class<T> type) {
        return (T) defaultValues.get(type.getName());
    }

    public <T> T convert(Object value, Class<T> type, boolean replaceNullValue) {
        T result;

        String key = type.getName();
        if (value == null) {
            result = replaceNullValue ? (T) defaultValues.get(key) : null;
        } else if (type.isInstance(value)) {
            result = (T) value;
        } else {
            Function<Object, T> func = typeMappings.get(key);
            result = func == null // convert function is not available for this type
                    ? type.cast(value) // this will usually end up with ClassCastException
                    : func.apply(value);
        }

        return result;
    }
}