@SuppressWarnings("unchecked")
  private <T> ConcreteEntityDescriptor<T> createConcreteEntityDescriptor(
      Class<?> c, EntityDescriptorStore store, Map<Type, Class<?>> types) throws IOException {
    // parent of the entity
    Class<?> parentClass = c.getSuperclass();
    ConcreteEntityDescriptor<?> parent = null;
    while (parentClass != null) {
      Entity parentAnnotation = parentClass.getAnnotation(Entity.class);
      if (parentAnnotation != null) {
        parent = createConcreteEntityDescriptor(parentClass, store, types);
        break;
      }
      parentClass = parentClass.getSuperclass();
    }

    // @Entity
    Entity annotation = c.getAnnotation(Entity.class);

    InputStream in = null;
    try {
      // bug 1739760
      in = c.getResourceAsStream("/" + c.getName().replace('.', '/') + ".class");
      if (in == null) {
        throw new IllegalArgumentException("cannot find bytecode for " + c);
      }
      ClassReader reader = new ClassReader(in);
      EntityClassVisitor visitor = new EntityClassVisitor(c, store, types);
      reader.accept(visitor, true);
      visitor.verify();

      // getting the descriptor
      EntityDescriptor<?> descriptor = visitor.getDescriptor(parent);

      store.put(c, descriptor);

      // is this entity inlineable?
      if (annotation.inline()) {
        if (!descriptor.isInlineable()) {
          throw new IllegalArgumentException(
              "entity  '"
                  + descriptor.getReturnedClass()
                  + "' is not inlineable."
                  + " An entity is inlineable only if it has one property.");
        }
      }

      return (ConcreteEntityDescriptor<T>) descriptor;
    } finally {
      if (in != null) {
        in.close();
      }
    }
  }