@Override
 public boolean canCreate(
     PropertyDescriptor propertyDescriptor,
     Type attributeType,
     SessionFactoryImplementor sessionFactoryImplementor) {
   // TODO also check that key attribute is primitive
   return attributeType instanceof MapType
       && propertyDescriptor.getAnnotation(MapKey.class) != null;
 }
 @Override
 public boolean canCreate(
     final PropertyDescriptor propertyDescriptor,
     final Type attributeType,
     final SessionFactoryImplementor sessionFactoryImplementor) {
   PrimitiveType primitiveType =
       primitiveTypeFactory.getPrimitiveType(propertyDescriptor.getPropertyType());
   return primitiveType != null;
 }
 @Override
 public Attribute create(
     final ValidationMetaData validationMetaData,
     final EntityType entityType,
     final HibernateEntityTypeCreationContext ctx,
     final PropertyDescriptor propertyDescriptor,
     final Type attributeType,
     final SessionFactoryImplementor sessionFactoryImplementor) {
   PrimitiveType primitiveType =
       primitiveTypeFactory.getPrimitiveType(propertyDescriptor.getPropertyType());
   PrimitiveAttributeImpl<?> attribute = new PrimitiveAttributeImpl();
   attribute.setAccessor(
       new HibernateAccessor(
           propertyDescriptor.getField(),
           propertyDescriptor.getReadMethod(),
           propertyDescriptor.getWriteMethod()));
   setStandardProperties(entityType, propertyDescriptor, attribute);
   attribute.setTargetType(primitiveType);
   attribute.setRequired(propertyDescriptor.getPropertyType().isPrimitive());
   return attribute;
 }
  @Override
  public Attribute create(
      ValidationMetaData validationMetaData,
      EntityType entityType,
      HibernateEntityTypeCreationContext ctx,
      PropertyDescriptor propertyDescriptor,
      Type attributeType,
      SessionFactoryImplementor sessionFactoryImplementor) {
    MapType mapType = (MapType) attributeType;
    Association association = propertyDescriptor.getAnnotation(Association.class);
    final MapAttributeImpl mapAssociationAttributeImpl = beanCreator.create(MapAttributeImpl.class);
    mapAssociationAttributeImpl.setAccessor(
        new HibernateAccessor(
            propertyDescriptor.getField(),
            propertyDescriptor.getReadMethod(),
            propertyDescriptor.getWriteMethod()));
    mapAssociationAttributeImpl.setCode(propertyDescriptor.getName());
    mapAssociationAttributeImpl.setEntityType(entityType);

    final String targeTypeName = mapType.getElementType(sessionFactoryImplementor).getName();
    final EntityType targetType = ctx.getEntityTypeReference(targeTypeName);
    mapAssociationAttributeImpl.setTargetType(targetType);
    MapKey jpaMapKey = propertyDescriptor.getAnnotation(MapKey.class);
    final String mapKeyPropertyName = jpaMapKey.name();

    ctx.addListener(
        new EntityTypeRepositoryListener() {
          @Override
          public void onEvent(PhaseEvent event) {
            if (event.getPhase() == Phase.ENTITY_TYPES_INITIALIZED) {
              final Attribute keyAttribute = targetType.getAttribute(mapKeyPropertyName);
              mapAssociationAttributeImpl.setKeyType(keyAttribute.getTargetType());
            }
          }
        });
    // TODO add subtypes here
    mapAssociationAttributeImpl.setWriteable(true);
    return mapAssociationAttributeImpl;
  }