/* Copyright (c) 2013 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Victor Olaya (Boundless) - initial implementation
*/
package org.locationtech.geogig.storage.text;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.locationtech.geogig.storage.FieldType;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
/**
* A text serializer for attribute values
*
*/
public class TextValueSerializer {
static interface ValueSerializer {
public Object fromString(String in) throws ParseException;
public String toString(Object value);
}
static abstract class DefaultValueSerializer implements ValueSerializer {
@Override
public String toString(Object value) {
return value.toString();
}
}
static abstract class ArraySerializer implements ValueSerializer {
@Override
public String toString(Object value) {
return "[" + Joiner.on(" ").join((Object[]) value) + "]";
}
}
static Map<FieldType, ValueSerializer> serializers = new HashMap<FieldType, ValueSerializer>();
static {
serializers.put(FieldType.NULL, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return null;
}
@Override
public String toString(Object value) {
return "";
}
});
serializers.put(FieldType.BOOLEAN, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new Boolean(in);
}
});
serializers.put(FieldType.BYTE, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new Byte(in);
}
});
serializers.put(FieldType.SHORT, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new Short(in);
}
});
serializers.put(FieldType.INTEGER, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new Integer(in);
}
});
serializers.put(FieldType.LONG, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new Long(in);
}
});
serializers.put(FieldType.FLOAT, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new Float(in);
}
});
serializers.put(FieldType.DOUBLE, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new Double(in);
}
});
serializers.put(FieldType.STRING, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return in;
}
});
serializers.put(FieldType.BOOLEAN_ARRAY, new ArraySerializer() {
@Override
public Object fromString(String in) {
String[] s = in.split(" ");
List<Boolean> list = Lists.newArrayList();
for (String token : s) {
list.add(new Boolean(token));
}
return list.toArray(new Boolean[0]);
}
});
serializers.put(FieldType.BYTE_ARRAY, new ArraySerializer() {
@Override
public Object fromString(String in) {
String[] s = in.split(" ");
List<Byte> list = Lists.newArrayList();
for (String token : s) {
list.add(new Byte(token));
}
return list.toArray(new Byte[0]);
}
});
serializers.put(FieldType.SHORT_ARRAY, new ArraySerializer() {
@Override
public Object fromString(String in) {
String[] s = in.replace("[", "").replace("]", "").split(" ");
List<Short> list = Lists.newArrayList();
for (String token : s) {
list.add(new Short(token));
}
return list.toArray(new Short[0]);
}
});
serializers.put(FieldType.INTEGER_ARRAY, new ArraySerializer() {
@Override
public Object fromString(String in) {
String[] s = in.split(" ");
List<Integer> list = Lists.newArrayList();
for (String token : s) {
list.add(new Integer(token));
}
return list.toArray(new Integer[0]);
}
});
serializers.put(FieldType.LONG_ARRAY, new ArraySerializer() {
@Override
public Object fromString(String in) {
String[] s = in.split(" ");
List<Long> list = Lists.newArrayList();
for (String token : s) {
list.add(new Long(token));
}
return list.toArray(new Long[0]);
}
});
serializers.put(FieldType.FLOAT_ARRAY, new ArraySerializer() {
@Override
public Object fromString(String in) {
String[] s = in.split(" ");
List<Float> list = Lists.newArrayList();
for (String token : s) {
list.add(new Float(token));
}
return list.toArray(new Float[0]);
}
});
serializers.put(FieldType.DOUBLE_ARRAY, new ArraySerializer() {
@Override
public Object fromString(String in) {
String[] s = in.split(" ");
List<Double> list = Lists.newArrayList();
for (String token : s) {
list.add(new Double(token));
}
return list.toArray(new Byte[0]);
}
});
ValueSerializer geometry = new ValueSerializer() {
@Override
public Object fromString(String in) throws ParseException {
return new WKTReader().read(in);
}
@Override
public String toString(Object value) {
return ((Geometry) value).toText();
}
};
serializers.put(FieldType.GEOMETRY, geometry);
serializers.put(FieldType.POINT, geometry);
serializers.put(FieldType.LINESTRING, geometry);
serializers.put(FieldType.POLYGON, geometry);
serializers.put(FieldType.MULTIPOINT, geometry);
serializers.put(FieldType.MULTILINESTRING, geometry);
serializers.put(FieldType.MULTIPOLYGON, geometry);
serializers.put(FieldType.GEOMETRYCOLLECTION, geometry);
serializers.put(FieldType.UUID, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return UUID.fromString(in);
}
});
serializers.put(FieldType.BIG_INTEGER, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new BigInteger(in);
}
});
serializers.put(FieldType.BIG_DECIMAL, new DefaultValueSerializer() {
@Override
public Object fromString(String in) {
return new BigDecimal(in);
}
});
serializers.put(FieldType.DATETIME, new ValueSerializer() {
@Override
public Object fromString(String in) {
return new java.util.Date(Long.parseLong(in));
}
@Override
public String toString(Object value) {
return String.valueOf(((java.util.Date) value).getTime());
}
});
serializers.put(FieldType.DATE, new ValueSerializer() {
@Override
public Object fromString(String in) {
return new java.sql.Date(Long.parseLong(in));
}
@Override
public String toString(Object value) {
return String.valueOf(((java.sql.Date) value).getTime());
}
});
serializers.put(FieldType.TIME, new ValueSerializer() {
@Override
public Object fromString(String in) {
return new java.sql.Time(Long.parseLong(in));
}
@Override
public String toString(Object value) {
return String.valueOf(((java.sql.Time) value).getTime());
}
});
serializers.put(FieldType.TIMESTAMP, new ValueSerializer() {
@Override
public Object fromString(String in) {
String[] millisnanos = in.split(" ");
java.sql.Timestamp ts = new java.sql.Timestamp(Long.parseLong(millisnanos[0]));
ts.setNanos(Integer.parseInt(millisnanos[1]));
return ts;
}
@Override
public String toString(Object value) {
java.sql.Timestamp ts = (java.sql.Timestamp) value;
return new StringBuilder().append(ts.getTime()).append(' ').append(ts.getNanos())
.toString();
}
});
}
/**
* Returns a string representation of the passed field value
*
* @param opt
*/
public static String asString(Optional<Object> opt) {
final FieldType type = FieldType.forValue(opt);
if (serializers.containsKey(type)) {
return serializers.get(type).toString(opt.orNull());
} else {
throw new IllegalArgumentException("The specified type is not supported: " + type);
}
}
/**
* Creates a value object from its string representation
*
* @param type
* @param in
* @return
*/
public static Object fromString(FieldType type, String in) {
if (serializers.containsKey(type)) {
try {
return serializers.get(type).fromString(in);
} catch (ParseException e) {
throw new IllegalArgumentException("Unable to parse wrong value: " + in);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Unable to parse wrong value: " + in);
}
} else {
throw new IllegalArgumentException("The specified type is not supported");
}
}
}