package org.hibernate.jpa.internal.metamodel;
import java.io.Serializable;
import java.lang.reflect.Member;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.metamodel.CollectionAttribute;
import javax.persistence.metamodel.ListAttribute;
import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.Type;
import org.hibernate.mapping.Property;
public abstract class PluralAttributeImpl<X, C, E>
extends AbstractAttribute<X,C>
implements PluralAttribute<X, C, E>, Serializable {
private final Type<E> elementType;
private PluralAttributeImpl(Builder<X,C,E,?> builder) {
super(
builder.property.getName(),
builder.collectionClass,
builder.type,
builder.member,
builder.persistentAttributeType
);
this.elementType = builder.attributeType;
}
public static class Builder<X, C, E, K> {
private final Type<E> attributeType;
private final AbstractManagedType<X> type;
private Member member;
private PersistentAttributeType persistentAttributeType;
private Property property;
private Class<C> collectionClass;
private Type<K> keyType;
private Builder(AbstractManagedType<X> ownerType, Type<E> attrType, Class<C> collectionClass, Type<K> keyType) {
this.type = ownerType;
this.attributeType = attrType;
this.collectionClass = collectionClass;
this.keyType = keyType;
}
public Builder<X,C,E,K> member(Member member) {
this.member = member;
return this;
}
public Builder<X,C,E,K> property(Property property) {
this.property = property;
return this;
}
public Builder<X,C,E,K> persistentAttributeType(PersistentAttributeType attrType) {
this.persistentAttributeType = attrType;
return this;
}
@SuppressWarnings( "unchecked" )
public <K> PluralAttributeImpl<X,C,E> build() {
if ( Map.class.equals( collectionClass ) ) {
final Builder<X,Map<K,E>,E,K> builder = (Builder<X,Map<K,E>,E,K>) this;
return ( PluralAttributeImpl<X, C, E> ) new MapAttributeImpl<X,K,E>(
builder
);
}
else if ( Set.class.equals( collectionClass ) ) {
final Builder<X,Set<E>, E,?> builder = (Builder<X, Set<E>, E,?>) this;
return ( PluralAttributeImpl<X, C, E> ) new SetAttributeImpl<X,E>(
builder
);
}
else if ( List.class.equals( collectionClass ) ) {
final Builder<X, List<E>, E,?> builder = (Builder<X, List<E>, E,?>) this;
return ( PluralAttributeImpl<X, C, E> ) new ListAttributeImpl<X,E>(
builder
);
}
else if ( Collection.class.equals( collectionClass ) ) {
final Builder<X, Collection<E>,E,?> builder = (Builder<X, Collection<E>, E,?>) this;
return ( PluralAttributeImpl<X, C, E> ) new CollectionAttributeImpl<X, E>(
builder
);
}
if ( Map.class.isAssignableFrom( collectionClass ) ) {
final Builder<X,Map<K,E>,E,K> builder = (Builder<X,Map<K,E>,E,K>) this;
return ( PluralAttributeImpl<X, C, E> ) new MapAttributeImpl<X,K,E>(
builder
);
}
else if ( Set.class.isAssignableFrom( collectionClass ) ) {
final Builder<X,Set<E>, E,?> builder = (Builder<X, Set<E>, E,?>) this;
return ( PluralAttributeImpl<X, C, E> ) new SetAttributeImpl<X,E>(
builder
);
}
else if ( List.class.isAssignableFrom( collectionClass ) ) {
final Builder<X, List<E>, E,?> builder = (Builder<X, List<E>, E,?>) this;
return ( PluralAttributeImpl<X, C, E> ) new ListAttributeImpl<X,E>(
builder
);
}
else if ( Collection.class.isAssignableFrom( collectionClass ) ) {
final Builder<X, Collection<E>,E,?> builder = (Builder<X, Collection<E>, E,?>) this;
return ( PluralAttributeImpl<X, C, E> ) new CollectionAttributeImpl<X, E>(
builder
);
}
throw new UnsupportedOperationException( "Unkown collection: " + collectionClass );
}
}
public static <X,C,E,K> Builder<X,C,E,K> create(
AbstractManagedType<X> ownerType,
Type<E> attrType,
Class<C> collectionClass,
Type<K> keyType) {
return new Builder<X,C,E,K>(ownerType, attrType, collectionClass, keyType);
}
@Override
public Type<E> getElementType() {
return elementType;
}
@Override
public boolean isAssociation() {
return true;
}
@Override
public boolean isCollection() {
return true;
}
@Override
public BindableType getBindableType() {
return BindableType.PLURAL_ATTRIBUTE;
}
@Override
public Class<E> getBindableJavaType() {
return elementType.getJavaType();
}
static class SetAttributeImpl<X,E> extends PluralAttributeImpl<X,Set<E>,E> implements SetAttribute<X,E> {
SetAttributeImpl(Builder<X,Set<E>,E,?> xceBuilder) {
super( xceBuilder );
}
@Override
public CollectionType getCollectionType() {
return CollectionType.SET;
}
}
static class CollectionAttributeImpl<X,E> extends PluralAttributeImpl<X,Collection<E>,E> implements CollectionAttribute<X,E> {
CollectionAttributeImpl(Builder<X, Collection<E>,E,?> xceBuilder) {
super( xceBuilder );
}
@Override
public CollectionType getCollectionType() {
return CollectionType.COLLECTION;
}
}
static class ListAttributeImpl<X,E> extends PluralAttributeImpl<X,List<E>,E> implements ListAttribute<X,E> {
ListAttributeImpl(Builder<X,List<E>,E,?> xceBuilder) {
super( xceBuilder );
}
@Override
public CollectionType getCollectionType() {
return CollectionType.LIST;
}
}
static class MapAttributeImpl<X,K,V> extends PluralAttributeImpl<X,Map<K,V>,V> implements MapAttribute<X,K,V> {
private final Type<K> keyType;
MapAttributeImpl(Builder<X,Map<K,V>,V,K> xceBuilder) {
super( xceBuilder );
this.keyType = xceBuilder.keyType;
}
@Override
public CollectionType getCollectionType() {
return CollectionType.MAP;
}
@Override
public Class<K> getKeyJavaType() {
return keyType.getJavaType();
}
@Override
public Type<K> getKeyType() {
return keyType;
}
}
}