protected ClassDescriptor createClassDescriptor(final ClassMapping classMapping)
      throws MappingException {
    // If there is no SQL information for class, ignore it.
    if ((classMapping.getMapTo() == null) || (classMapping.getMapTo().getTable() == null)) {
      LOG.info(Messages.format("mapping.ignoringMapping", classMapping.getName()));
      return null;
    }

    // Create the class descriptor, and register the JDO nature with it.
    ClassDescriptorImpl clsDesc = new ClassDescriptorImpl();
    clsDesc.addNature(ClassDescriptorJDONature.class.getName());
    ClassDescriptorJDONature jdoNature = new ClassDescriptorJDONature(clsDesc);

    // Obtain the Java class.
    Class<?> javaClass = resolveType(classMapping.getName());
    if (!Types.isConstructable(javaClass, true)) {
      throw new MappingException("mapping.classNotConstructable", javaClass.getName());
    }
    clsDesc.setJavaClass(javaClass);

    // If this class extends another class, we need to obtain the extended
    // class and make sure this class indeed extends it.
    ClassDescriptor extDesc = getExtended(classMapping, javaClass);
    if (extDesc != null) {
      if (!(extDesc.hasNature(ClassDescriptorJDONature.class.getName()))) {
        throw new IllegalArgumentException("Extended class does not have a JDO descriptor");
      }

      new ClassDescriptorJDONature(extDesc).addExtended(clsDesc);
    }
    clsDesc.setExtends(extDesc);

    // If this class depends on another class, obtain the class it depends upon.
    clsDesc.setDepends(getDepended(classMapping, javaClass));

    // Create all field descriptors.
    FieldDescriptorImpl[] allFields = createFieldDescriptors(classMapping, javaClass);

    // Make sure there are no two fields with the same name.
    checkFieldNameDuplicates(allFields, javaClass);

    // Set class descriptor containing the field
    for (int i = 0; i < allFields.length; i++) {
      allFields[i].setContainingClassDescriptor(clsDesc);
    }

    // Identify identity and normal fields. Note that order must be preserved.
    List<FieldDescriptor> fieldList = new ArrayList<FieldDescriptor>(allFields.length);
    List<FieldDescriptor> idList = new ArrayList<FieldDescriptor>();
    if (extDesc == null) {
      // Sort fields into 2 lists based on identity definition of field.
      for (int i = 0; i < allFields.length; i++) {
        if (!allFields[i].isIdentity()) {
          fieldList.add(allFields[i]);
        } else {
          idList.add(allFields[i]);
        }
      }

      if (idList.size() == 0) {
        // Found no identities based on identity definition of field.
        // Try to find identities based on identity definition on class.
        String[] idNames = classMapping.getIdentity();
        if ((idNames == null) || (idNames.length == 0)) {
          // There are also no identity definitions on class.
          throw new MappingException("mapping.noIdentity", javaClass.getName());
        }

        FieldDescriptor identity;
        for (int i = 0; i < idNames.length; i++) {
          identity = findIdentityByName(fieldList, idNames[i], javaClass);
          if (identity != null) {
            idList.add(identity);
          } else {
            throw new MappingException("mapping.identityMissing", idNames[i], javaClass.getName());
          }
        }
      }
    } else {
      // Add all fields of extending class to field list.
      for (int i = 0; i < allFields.length; i++) {
        fieldList.add(allFields[i]);
      }

      // Add all identities of extended class to identity list.
      FieldDescriptor[] extIds = ((ClassDescriptorImpl) extDesc).getIdentities();
      for (int i = 0; i < extIds.length; i++) {
        idList.add(extIds[i]);
      }

      // Search redefined identities in extending class.
      FieldDescriptor identity;
      for (int i = 0; i < idList.size(); i++) {
        String idName = (idList.get(i)).getFieldName();
        identity = findIdentityByName(fieldList, idName, javaClass);
        if (identity != null) {
          idList.set(i, identity);
        }
      }
    }

    // Set identities on class descriptor.
    FieldDescriptor[] ids = new FieldDescriptor[idList.size()];
    clsDesc.setIdentities(idList.toArray(ids));

    // Set fields on class descriptor.
    FieldDescriptor[] fields = new FieldDescriptor[fieldList.size()];
    clsDesc.setFields(fieldList.toArray(fields));

    jdoNature.setTableName(classMapping.getMapTo().getTable());

    // Set the field name used for object modification checks.
    jdoNature.setVersionField(classMapping.getVersion());

    extractAndSetAccessMode(jdoNature, classMapping);
    extractAndAddCacheParams(jdoNature, classMapping, javaClass);
    extractAndAddNamedQueries(jdoNature, classMapping);
    extractAndAddNamedNativeQueries(jdoNature, classMapping);
    extractAndSetKeyGeneratorDescriptor(jdoNature, classMapping.getKeyGenerator());

    return clsDesc;
  }