class AbstractAttribute implements Attribute<O, A> {

    static <O> Class<O> readGenericObjectType(Class<?> attributeClass, String attributeName) {
        try {
            ParameterizedType superclass = (ParameterizedType) attributeClass.getGenericSuperclass();
            @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
            Type actualType = superclass.getActualTypeArguments()[0];
            Class<O> cls;
            if (actualType instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType)actualType;
                @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
                Class<O> actualClass = (Class<O>) parameterizedType.getRawType();
                cls = actualClass;
            }
            else {
                @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
                Class<O> actualClass = (Class<O>) actualType;
                cls = actualClass;
            }
            return cls;
        }
        catch (Exception e) {
            String attributeClassStr = attributeName.startsWith("<Unnamed attribute, class ") ? "" : " (" + attributeClass + ")";
            throw new IllegalStateException("Attribute '" + attributeName + "'" + attributeClassStr + " is invalid, cannot read generic type information from it. Attributes should typically EITHER be declared in code with generic type information as a (possibly anonymous) subclass of one of the provided attribute types, OR you can use a constructor of the attribute which allows the types to be specified manually.");
        }
    }

    public  AbstractAttribute();
    public  AbstractAttribute(String attributeName);
    protected  AbstractAttribute(Class<O> objectType, Class<A> attributeType);
    protected  AbstractAttribute(Class<O> objectType, Class<A> attributeType, String attributeName);

}