Example usage for java.lang.reflect Field getGenericType

List of usage examples for java.lang.reflect Field getGenericType

Introduction

In this page you can find the example usage for java.lang.reflect Field getGenericType.

Prototype

public Type getGenericType() 

Source Link

Document

Returns a Type object that represents the declared type for the field represented by this Field object.

Usage

From source file:org.apache.syncope.client.console.panels.BeanPanel.java

public BeanPanel(final String id, final IModel<T> bean,
        final Map<String, Pair<AbstractFiqlSearchConditionBuilder, List<SearchClause>>> sCondWrapper,
        final String... excluded) {
    super(id, bean);
    setOutputMarkupId(true);/*from w w  w . j a  va 2  s .com*/

    this.sCondWrapper = sCondWrapper;

    this.excluded = new ArrayList<>(Arrays.asList(excluded));
    this.excluded.add("serialVersionUID");
    this.excluded.add("class");

    final LoadableDetachableModel<List<String>> model = new LoadableDetachableModel<List<String>>() {

        private static final long serialVersionUID = 5275935387613157437L;

        @Override
        protected List<String> load() {
            final List<String> result = new ArrayList<>();

            if (BeanPanel.this.getDefaultModelObject() != null) {
                ReflectionUtils.doWithFields(BeanPanel.this.getDefaultModelObject().getClass(),
                        new FieldCallback() {

                            public void doWith(final Field field)
                                    throws IllegalArgumentException, IllegalAccessException {
                                result.add(field.getName());
                            }

                        }, new FieldFilter() {

                            public boolean matches(final Field field) {
                                return !BeanPanel.this.excluded.contains(field.getName());
                            }
                        });
            }
            return result;
        }
    };

    add(new ListView<String>("propView", model) {

        private static final long serialVersionUID = 9101744072914090143L;

        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        protected void populateItem(final ListItem<String> item) {
            final String fieldName = item.getModelObject();

            item.add(new Label("fieldName", new ResourceModel(fieldName, fieldName)));

            Field field = ReflectionUtils.findField(bean.getObject().getClass(), fieldName);

            if (field == null) {
                return;
            }

            final SearchCondition scondAnnot = field.getAnnotation(SearchCondition.class);
            final Schema schemaAnnot = field.getAnnotation(Schema.class);

            BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean.getObject());

            Panel panel;

            if (scondAnnot != null) {
                final String fiql = (String) wrapper.getPropertyValue(fieldName);

                final List<SearchClause> clauses;
                if (StringUtils.isEmpty(fiql)) {
                    clauses = new ArrayList<>();
                } else {
                    clauses = SearchUtils.getSearchClauses(fiql);
                }

                final AbstractFiqlSearchConditionBuilder builder;

                switch (scondAnnot.type()) {
                case "USER":
                    panel = new UserSearchPanel.Builder(new ListModel<>(clauses)).required(false)
                            .build("value");
                    builder = SyncopeClient.getUserSearchConditionBuilder();
                    break;
                case "GROUP":
                    panel = new GroupSearchPanel.Builder(new ListModel<>(clauses)).required(false)
                            .build("value");
                    builder = SyncopeClient.getGroupSearchConditionBuilder();
                    break;
                default:
                    panel = new AnyObjectSearchPanel.Builder(scondAnnot.type(), new ListModel<>(clauses))
                            .required(false).build("value");
                    builder = SyncopeClient.getAnyObjectSearchConditionBuilder(null);
                }

                if (BeanPanel.this.sCondWrapper != null) {
                    BeanPanel.this.sCondWrapper.put(fieldName, Pair.of(builder, clauses));
                }
            } else if (List.class.equals(field.getType())) {
                Class<?> listItemType = String.class;
                if (field.getGenericType() instanceof ParameterizedType) {
                    listItemType = (Class<?>) ((ParameterizedType) field.getGenericType())
                            .getActualTypeArguments()[0];
                }

                if (listItemType.equals(String.class) && schemaAnnot != null) {
                    SchemaRestClient schemaRestClient = new SchemaRestClient();

                    final List<AbstractSchemaTO> choices = new ArrayList<>();

                    for (SchemaType type : schemaAnnot.type()) {
                        switch (type) {
                        case PLAIN:
                            choices.addAll(
                                    schemaRestClient.getSchemas(SchemaType.PLAIN, schemaAnnot.anyTypeKind()));
                            break;

                        case DERIVED:
                            choices.addAll(
                                    schemaRestClient.getSchemas(SchemaType.DERIVED, schemaAnnot.anyTypeKind()));
                            break;

                        case VIRTUAL:
                            choices.addAll(
                                    schemaRestClient.getSchemas(SchemaType.VIRTUAL, schemaAnnot.anyTypeKind()));
                            break;

                        default:
                        }
                    }

                    panel = new AjaxPalettePanel.Builder<>().setName(fieldName)
                            .build("value", new PropertyModel<>(bean.getObject(), fieldName), new ListModel<>(
                                    choices.stream().map(EntityTO::getKey).collect(Collectors.toList())))
                            .hideLabel();
                } else if (listItemType.isEnum()) {
                    panel = new AjaxPalettePanel.Builder<>().setName(fieldName)
                            .build("value", new PropertyModel<>(bean.getObject(), fieldName),
                                    new ListModel(Arrays.asList(listItemType.getEnumConstants())))
                            .hideLabel();
                } else {
                    panel = new MultiFieldPanel.Builder<>(new PropertyModel<>(bean.getObject(), fieldName))
                            .build("value", fieldName,
                                    buildSinglePanel(bean.getObject(), field.getType(), fieldName, "panel"))
                            .hideLabel();
                }
            } else {
                panel = buildSinglePanel(bean.getObject(), field.getType(), fieldName, "value").hideLabel();
            }

            item.add(panel.setRenderBodyOnly(true));
        }

    }.setReuseItems(true).setOutputMarkupId(true));
}

From source file:au.com.addstar.cellblock.configuration.AutoConfig.java

@SuppressWarnings("unchecked")
public boolean load() {
    FileConfiguration yml = new YamlConfiguration();
    try {/*from  ww w  .  java2  s.  c o  m*/
        if (mFile.getParentFile().exists() || mFile.getParentFile().mkdirs()) {// Make sure the file exists
            if (mFile.exists() || mFile.createNewFile()) {
                // Parse the config
                yml.load(mFile);
                for (Field field : getClass().getDeclaredFields()) {
                    ConfigField configField = field.getAnnotation(ConfigField.class);
                    if (configField == null)
                        continue;

                    String optionName = configField.name();
                    if (optionName.isEmpty())
                        optionName = field.getName();

                    field.setAccessible(true);

                    String path = (configField.category().isEmpty() ? "" : configField.category() + ".") //$NON-NLS-2$
                            + optionName;
                    if (!yml.contains(path)) {
                        if (field.get(this) == null)
                            throw new InvalidConfigurationException(
                                    path + " is required to be set! Info:\n" + configField.comment());
                    } else {
                        // Parse the value

                        if (field.getType().isArray()) {
                            // Integer
                            if (field.getType().getComponentType().equals(Integer.TYPE))
                                field.set(this, yml.getIntegerList(path).toArray(new Integer[0]));

                            // Float
                            else if (field.getType().getComponentType().equals(Float.TYPE))
                                field.set(this, yml.getFloatList(path).toArray(new Float[0]));

                            // Double
                            else if (field.getType().getComponentType().equals(Double.TYPE))
                                field.set(this, yml.getDoubleList(path).toArray(new Double[0]));

                            // Long
                            else if (field.getType().getComponentType().equals(Long.TYPE))
                                field.set(this, yml.getLongList(path).toArray(new Long[0]));

                            // Short
                            else if (field.getType().getComponentType().equals(Short.TYPE))
                                field.set(this, yml.getShortList(path).toArray(new Short[0]));

                            // Boolean
                            else if (field.getType().getComponentType().equals(Boolean.TYPE))
                                field.set(this, yml.getBooleanList(path).toArray(new Boolean[0]));

                            // String
                            else if (field.getType().getComponentType().equals(String.class)) {
                                field.set(this, yml.getStringList(path).toArray(new String[0]));
                            } else
                                throw new IllegalArgumentException("Cannot use type "
                                        + field.getType().getSimpleName() + " for AutoConfiguration"); //$NON-NLS-1$
                        } else if (List.class.isAssignableFrom(field.getType())) {
                            if (field.getGenericType() == null)
                                throw new IllegalArgumentException(
                                        "Cannot use type List without specifying generic type for AutoConfiguration");

                            Type type = ((ParameterizedType) field.getGenericType())
                                    .getActualTypeArguments()[0];

                            if (type.equals(Integer.class))
                                field.set(this, newList((Class<? extends List<Integer>>) field.getType(),
                                        yml.getIntegerList(path)));
                            else if (type.equals(Float.class))
                                field.set(this, newList((Class<? extends List<Float>>) field.getType(),
                                        yml.getFloatList(path)));
                            else if (type.equals(Double.class))
                                field.set(this, newList((Class<? extends List<Double>>) field.getType(),
                                        yml.getDoubleList(path)));
                            else if (type.equals(Long.class))
                                field.set(this, newList((Class<? extends List<Long>>) field.getType(),
                                        yml.getLongList(path)));
                            else if (type.equals(Short.class))
                                field.set(this, newList((Class<? extends List<Short>>) field.getType(),
                                        yml.getShortList(path)));
                            else if (type.equals(Boolean.class))
                                field.set(this, newList((Class<? extends List<Boolean>>) field.getType(),
                                        yml.getBooleanList(path)));
                            else if (type.equals(String.class))
                                field.set(this, newList((Class<? extends List<String>>) field.getType(),
                                        yml.getStringList(path)));
                            else
                                throw new IllegalArgumentException(
                                        "Cannot use type " + field.getType().getSimpleName() + "<" //$NON-NLS-2$
                                                + type.toString() + "> for AutoConfiguration");
                        } else if (Set.class.isAssignableFrom(field.getType())) {
                            if (field.getGenericType() == null)
                                throw new IllegalArgumentException(
                                        "Cannot use type set without specifying generic type for AytoConfiguration");

                            Type type = ((ParameterizedType) field.getGenericType())
                                    .getActualTypeArguments()[0];

                            if (type.equals(Integer.class))
                                field.set(this, newSet((Class<? extends Set<Integer>>) field.getType(),
                                        yml.getIntegerList(path)));
                            else if (type.equals(Float.class))
                                field.set(this, newSet((Class<? extends Set<Float>>) field.getType(),
                                        yml.getFloatList(path)));
                            else if (type.equals(Double.class))
                                field.set(this, newSet((Class<? extends Set<Double>>) field.getType(),
                                        yml.getDoubleList(path)));
                            else if (type.equals(Long.class))
                                field.set(this, newSet((Class<? extends Set<Long>>) field.getType(),
                                        yml.getLongList(path)));
                            else if (type.equals(Short.class))
                                field.set(this, newSet((Class<? extends Set<Short>>) field.getType(),
                                        yml.getShortList(path)));
                            else if (type.equals(Boolean.class))
                                field.set(this, newSet((Class<? extends Set<Boolean>>) field.getType(),
                                        yml.getBooleanList(path)));
                            else if (type.equals(String.class))
                                field.set(this, newSet((Class<? extends Set<String>>) field.getType(),
                                        yml.getStringList(path)));
                            else
                                throw new IllegalArgumentException(
                                        "Cannot use type " + field.getType().getSimpleName() + "<" //$NON-NLS-2$
                                                + type.toString() + "> for AutoConfiguration");
                        } else {
                            // Integer
                            if (field.getType().equals(Integer.TYPE))
                                field.setInt(this, yml.getInt(path));

                            // Float
                            else if (field.getType().equals(Float.TYPE))
                                field.setFloat(this, (float) yml.getDouble(path));

                            // Double
                            else if (field.getType().equals(Double.TYPE))
                                field.setDouble(this, yml.getDouble(path));

                            // Long
                            else if (field.getType().equals(Long.TYPE))
                                field.setLong(this, yml.getLong(path));

                            // Short
                            else if (field.getType().equals(Short.TYPE))
                                field.setShort(this, (short) yml.getInt(path));

                            // Boolean
                            else if (field.getType().equals(Boolean.TYPE))
                                field.setBoolean(this, yml.getBoolean(path));

                            // ItemStack
                            else if (field.getType().equals(ItemStack.class))
                                field.set(this, yml.getItemStack(path));

                            // String
                            else if (field.getType().equals(String.class))
                                field.set(this, yml.getString(path));
                            else
                                throw new IllegalArgumentException("Cannot use type "
                                        + field.getType().getSimpleName() + " for AutoConfiguration"); //$NON-NLS-1$
                        }
                    }
                }

                onPostLoad();
            } else {
                Bukkit.getLogger().log(Level.INFO, "Unable to create file: " + mFile.toString());
            }
        } else {
            Bukkit.getLogger().log(Level.INFO, "Unable to create file: " + mFile.getParentFile().toString());
        }
        return true;
    } catch (IOException | InvalidConfigurationException | IllegalAccessException
            | IllegalArgumentException e) {
        e.printStackTrace();
        return false;
    }
}

From source file:org.kuali.rice.core.framework.persistence.jpa.metadata.MetadataManager.java

private static void extractFieldMetadata(Class clazz, EntityDescriptor entityDescriptor) {
    // Don't want to get parent fields if overridden in children since we are walking the tree from child to parent
    Set<String> cachedFields = new HashSet<String>();
    do {/* w w w  .j  a  va2s . co m*/
        for (Field field : clazz.getDeclaredFields()) {
            if (cachedFields.contains(field.getName())) {
                continue;
            }
            cachedFields.add(field.getName());

            int mods = field.getModifiers();
            if (Modifier.isFinal(mods) || Modifier.isStatic(mods) || Modifier.isTransient(mods)
                    || field.isAnnotationPresent(Transient.class)) {
                continue;
            }

            // Basic Fields
            FieldDescriptor fieldDescriptor = new FieldDescriptor();
            fieldDescriptor.setClazz(field.getType());
            fieldDescriptor.setTargetClazz(field.getType());
            fieldDescriptor.setName(field.getName());

            if (field.isAnnotationPresent(Id.class)) {
                fieldDescriptor.setId(true);

                if (entityDescriptor.getIdClass() != null) {
                    // pull the column from IdClass
                    try {
                        Field idClassField = entityDescriptor.getIdClass().getDeclaredField(field.getName());
                        idClassField.setAccessible(true);
                        addColumnInformationToFieldDescriptor(fieldDescriptor, idClassField);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            if (field.isAnnotationPresent(Column.class)) {

                if (!field.isAnnotationPresent(Id.class) || entityDescriptor.getIdClass() == null) {
                    // only populate if we haven't populated already
                    addColumnInformationToFieldDescriptor(fieldDescriptor, field);
                }
            } else if (!field.isAnnotationPresent(Id.class) || entityDescriptor.getIdClass() == null) {
                fieldDescriptor.setColumn(field.getName());
            }
            if (field.isAnnotationPresent(Version.class)) {
                fieldDescriptor.setVersion(true);
            }
            if (field.isAnnotationPresent(Lob.class)) {
                fieldDescriptor.setLob(true);
            }
            if (field.isAnnotationPresent(Temporal.class)) {
                fieldDescriptor.setTemporal(true);
                fieldDescriptor.setTemporalType(field.getAnnotation(Temporal.class).value());
            }

            // Relationships
            if (field.isAnnotationPresent(OneToOne.class)) {
                OneToOneDescriptor descriptor = new OneToOneDescriptor();
                OneToOne relation = field.getAnnotation(OneToOne.class);
                descriptor.setAttributeName(field.getName());
                if (relation.targetEntity().equals(void.class)) {
                    descriptor.setTargetEntity(field.getType());
                } else {
                    descriptor.setTargetEntity(relation.targetEntity());
                    fieldDescriptor.setTargetClazz(relation.targetEntity());
                }

                descriptor.setCascade(relation.cascade());
                descriptor.setFetch(relation.fetch());
                descriptor.setMappedBy(relation.mappedBy());
                descriptor.setOptional(relation.optional());
                if (field.isAnnotationPresent(JoinColumn.class)) {
                    JoinColumn jc = field.getAnnotation(JoinColumn.class);
                    descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                    FieldDescriptor jcFkField = entityDescriptor.getFieldByColumnName(jc.name());
                    if (jcFkField != null) {
                        descriptor.addFkField(jcFkField.getName());
                    } else {
                        //check to see if foreign key is in an AttributeOverride annotation
                        if (clazz.isAnnotationPresent(AttributeOverrides.class)) {
                            for (AttributeOverride override : ((AttributeOverrides) clazz
                                    .getAnnotation(AttributeOverrides.class)).value()) {
                                if (jc.name().equals(override.column().name())) {
                                    entityDescriptor.getFieldByName(override.name())
                                            .setColumn(override.column().name());
                                    jcFkField = entityDescriptor.getFieldByName(override.name());
                                    if (jcFkField != null) {
                                        descriptor.addFkField(jcFkField.getName());
                                    }
                                }
                            }
                        }
                        if (clazz.isAnnotationPresent(AttributeOverride.class)) {
                            AttributeOverride override = (AttributeOverride) clazz
                                    .getAnnotation(AttributeOverride.class);
                            if (jc.name().equals(override.column().name())) {
                                entityDescriptor.getFieldByName(override.name())
                                        .setColumn(override.column().name());
                                jcFkField = entityDescriptor.getFieldByName(override.name());
                                if (jcFkField != null) {
                                    descriptor.addFkField(jcFkField.getName());
                                }
                            }
                        }
                    }
                    //descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                    descriptor.setInsertable(jc.insertable());
                    descriptor.setUpdateable(jc.updatable());
                }
                if (field.isAnnotationPresent(JoinColumns.class)) {
                    JoinColumns jcs = field.getAnnotation(JoinColumns.class);
                    for (JoinColumn jc : jcs.value()) {
                        descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                        descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                    }
                }
                entityDescriptor.add(descriptor);
            }

            if (field.isAnnotationPresent(OneToMany.class)) {
                OneToManyDescriptor descriptor = new OneToManyDescriptor();
                OneToMany relation = field.getAnnotation(OneToMany.class);
                descriptor.setAttributeName(field.getName());
                if (relation.targetEntity().equals(void.class)) {
                    descriptor.setTargetEntity(
                            (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
                } else {
                    descriptor.setTargetEntity(relation.targetEntity());
                    fieldDescriptor.setTargetClazz(relation.targetEntity());
                }
                descriptor.setCascade(relation.cascade());
                descriptor.setFetch(relation.fetch());
                descriptor.setMappedBy(relation.mappedBy());
                EntityDescriptor mappedBy = (entityDescriptor.getClazz().equals(descriptor.getTargetEntity()))
                        ? entityDescriptor
                        : MetadataManager.getEntityDescriptor(descriptor.getTargetEntity());
                ObjectDescriptor od = mappedBy.getObjectDescriptorByName(descriptor.getMappedBy());
                if (od != null) {
                    for (String fk : od.getForeignKeyFields()) {
                        descriptor.addFkField(fk);
                    }
                }
                if (field.isAnnotationPresent(JoinTable.class)) {
                    JoinTable jt = field.getAnnotation(JoinTable.class);
                    for (JoinColumn jc : jt.joinColumns()) {
                        descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                        descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                    }
                    for (JoinColumn jc : jt.inverseJoinColumns()) {
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                        descriptor.addInverseJoinColumnDescriptor(constructJoinDescriptor(jc));
                    }
                } else {
                    if (field.isAnnotationPresent(JoinColumn.class)) {
                        JoinColumn jc = field.getAnnotation(JoinColumn.class);
                        FieldDescriptor jcFkField = entityDescriptor.getFieldByColumnName(jc.name());
                        if (jcFkField != null) {
                            descriptor.addFkField(jcFkField.getName());
                        }
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                        descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                    }
                    if (field.isAnnotationPresent(JoinColumns.class)) {
                        JoinColumns jcs = field.getAnnotation(JoinColumns.class);
                        for (JoinColumn jc : jcs.value()) {
                            descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                            descriptor.setInsertable(jc.insertable());
                            descriptor.setUpdateable(jc.updatable());
                            descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                        }
                    }
                }
                entityDescriptor.add(descriptor);
            }

            if (field.isAnnotationPresent(ManyToOne.class)) {
                ManyToOne relation = field.getAnnotation(ManyToOne.class);
                ManyToOneDescriptor descriptor = new ManyToOneDescriptor();
                descriptor.setAttributeName(field.getName());
                if (relation.targetEntity().equals(void.class)) {
                    descriptor.setTargetEntity(field.getType());
                } else {
                    descriptor.setTargetEntity(relation.targetEntity());
                    fieldDescriptor.setTargetClazz(relation.targetEntity());
                }
                descriptor.setCascade(relation.cascade());
                descriptor.setFetch(relation.fetch());
                descriptor.setOptional(relation.optional());
                if (field.isAnnotationPresent(JoinColumn.class)) {
                    JoinColumn jc = field.getAnnotation(JoinColumn.class);
                    descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                    FieldDescriptor jcFkField = entityDescriptor.getFieldByColumnName(jc.name());
                    if (jcFkField != null) {
                        descriptor.addFkField(jcFkField.getName());
                    }
                    //descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                    //descriptor.addFkField(entitesByClass.get(field.getType()).getFieldByColumnName(jc.name()).getName());
                    descriptor.setInsertable(jc.insertable());
                    descriptor.setUpdateable(jc.updatable());
                }
                if (field.isAnnotationPresent(JoinColumns.class)) {
                    JoinColumns jcs = field.getAnnotation(JoinColumns.class);
                    for (JoinColumn jc : jcs.value()) {
                        descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                        descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                    }
                }
                entityDescriptor.add(descriptor);
            }

            if (field.isAnnotationPresent(ManyToMany.class)) {
                ManyToManyDescriptor descriptor = new ManyToManyDescriptor();
                ManyToMany relation = field.getAnnotation(ManyToMany.class);
                descriptor.setAttributeName(field.getName());
                if (relation.targetEntity().equals(void.class)) {
                    descriptor.setTargetEntity(
                            (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
                } else {
                    descriptor.setTargetEntity(relation.targetEntity());
                    fieldDescriptor.setTargetClazz(relation.targetEntity());
                }
                descriptor.setCascade(relation.cascade());
                descriptor.setFetch(relation.fetch());
                descriptor.setMappedBy(relation.mappedBy());
                if (field.isAnnotationPresent(JoinTable.class)) {
                    JoinTable jt = field.getAnnotation(JoinTable.class);
                    descriptor.setJoinTableName(jt.name());
                    for (JoinColumn jc : jt.joinColumns()) {
                        descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                        descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                    }
                    for (JoinColumn jc : jt.inverseJoinColumns()) {
                        descriptor.addInverseJoinColumnDescriptor(constructJoinDescriptor(jc));
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                        // TODO: Should we add inverse join columns?
                    }
                } else {
                    if (field.isAnnotationPresent(JoinColumn.class)) {
                        JoinColumn jc = field.getAnnotation(JoinColumn.class);
                        FieldDescriptor jcFkField = entityDescriptor.getFieldByColumnName(jc.name());
                        if (jcFkField != null) {
                            descriptor.addFkField(jcFkField.getName());
                        }
                        descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                        descriptor.setInsertable(jc.insertable());
                        descriptor.setUpdateable(jc.updatable());
                    }
                    if (field.isAnnotationPresent(JoinColumns.class)) {
                        JoinColumns jcs = field.getAnnotation(JoinColumns.class);
                        for (JoinColumn jc : jcs.value()) {
                            descriptor.addJoinColumnDescriptor(constructJoinDescriptor(jc));
                            descriptor.addFkField(entityDescriptor.getFieldByColumnName(jc.name()).getName());
                            descriptor.setInsertable(jc.insertable());
                            descriptor.setUpdateable(jc.updatable());
                        }
                    }
                }
                entityDescriptor.add(descriptor);
            }

            // Add the field to the entity
            entityDescriptor.add(fieldDescriptor);
        }
        clazz = clazz.getSuperclass();
    } while (clazz != null && !(clazz.equals(Object.class)));
}