package org.odata4j.edm;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import javax.sql.rowset.serial.SerialBlob;
import org.core4j.Enumerable;
import org.joda.time.DateTime;
import org.joda.time.Instant;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.odata4j.core.Guid;
import org.odata4j.core.UnsignedByte;
/**
* Primitive types in the EDM type system.
* Simple types are exposed as constants and associated with one or more java-types.
*
* @see <a href="http://msdn.microsoft.com/en-us/library/bb399213.aspx">[msdn] Simple Types (EDM)</a>
*/
public class EdmSimpleType<V> extends EdmType {
private static Set<EdmSimpleType<?>> all = new HashSet<EdmSimpleType<?>>();
// http://msdn.microsoft.com/en-us/library/bb399213.aspx
public static final EdmSimpleType<byte[]> BINARY = newSimple("Edm.Binary", byte[].class, Byte[].class);
public static final EdmSimpleType<Blob> STREAM = newSimple("Edm.Stream", Blob.class, Blob.class, SerialBlob.class);
public static final EdmSimpleType<Boolean> BOOLEAN = newSimple("Edm.Boolean", Boolean.class, boolean.class);
public static final EdmSimpleType<UnsignedByte> BYTE = newSimple("Edm.Byte", UnsignedByte.class);
public static final EdmSimpleType<LocalDateTime> DATETIME = newSimple("Edm.DateTime", LocalDateTime.class, Instant.class, Date.class, Calendar.class, Timestamp.class, java.sql.Date.class); // possible, but not default: Time.class
public static final EdmSimpleType<DateTime> DATETIMEOFFSET = newSimple("Edm.DateTimeOffset", DateTime.class);
public static final EdmSimpleType<BigDecimal> DECIMAL = newSimple("Edm.Decimal", BigDecimal.class);
public static final EdmSimpleType<Double> DOUBLE = newSimple("Edm.Double", Double.class, double.class);
public static final EdmSimpleType<Guid> GUID = newSimple("Edm.Guid", Guid.class, UUID.class);
public static final EdmSimpleType<Short> INT16 = newSimple("Edm.Int16", Short.class, short.class);
public static final EdmSimpleType<Integer> INT32 = newSimple("Edm.Int32", Integer.class, int.class);
public static final EdmSimpleType<Long> INT64 = newSimple("Edm.Int64", Long.class, long.class);
public static final EdmSimpleType<Byte> SBYTE = newSimple("Edm.SByte", Byte.class, byte.class);
public static final EdmSimpleType<Float> SINGLE = newSimple("Edm.Single", Float.class, float.class);
public static final EdmSimpleType<String> STRING = newSimple("Edm.String", String.class, char.class, Character.class);
public static final EdmSimpleType<LocalTime> TIME = newSimple("Edm.Time", LocalTime.class, Time.class); // possible, but not default: Date.class, Calendar.class, Timestamp.class
public static final EdmSimpleType<InputStream> INPUTSTREAM = newSimple("Edm.Stream", InputStream.class, InputStream.class);
private static <V> EdmSimpleType<V> newSimple(String typeString, Class<V> canonicalJavaType, Class<?>... alternateJavaTypes) {
EdmSimpleType<V> rt = new EdmSimpleType<V>(typeString, canonicalJavaType, alternateJavaTypes);
all.add(rt);
return rt;
}
/**
* Immutable set of all edm simple types.
*/
public static final Set<EdmSimpleType<?>> ALL = Collections.unmodifiableSet(all);
private final Class<V> canonicalJavaType;
private final Set<Class<?>> javaTypes;
private EdmSimpleType(String fullyQualifiedTypeName, Class<V> canonicalJavaType, Class<?>... alternateJavaTypes) {
super(fullyQualifiedTypeName);
this.canonicalJavaType = canonicalJavaType;
this.javaTypes = Enumerable.<Class<?>> create(canonicalJavaType).concat(alternateJavaTypes).toSet();
}
@Override
public boolean isSimple() {
return true;
}
public Class<V> getCanonicalJavaType() {
return canonicalJavaType;
}
/**
* Gets all java-types associated with this edm-type.
*
* @return the associated java-types.
*/
public Set<Class<?>> getJavaTypes() {
return javaTypes;
}
/**
* Finds the edm simple type for a given java-type.
*
* @param javaType the java-type
* @return the associated edm simple type, else null
*/
@SuppressWarnings("unchecked")
public static <V> EdmSimpleType<V> forJavaType(Class<?> javaType) {
for (EdmSimpleType<?> simple : ALL)
if (simple.getJavaTypes().contains(javaType))
return (EdmSimpleType<V>) simple;
return null;
}
public static EdmType.Builder<?, ?> newBuilder(EdmType type) {
return new Builder(type);
}
private static class Builder extends EdmType.Builder<EdmType, Builder> {
private Builder(EdmType type) {
super(type);
}
@Override
Builder newBuilder(EdmType type, BuilderContext context) {
return new Builder(type);
}
@Override
public EdmType build() {
return (EdmType) _build();
}
@Override
protected EdmType buildImpl() {
// should never get here
return null;
}
}
}