ObjectClassDefinition constructObjectClass(
      final String name, final String sup, final ObjectClassType type, final OIDAllocator a) {
    final TreeMap<String, String> requiredAttrs = new TreeMap<String, String>();
    final TreeMap<String, String> optionalAttrs = new TreeMap<String, String>();

    for (final FieldInfo i : fieldMap.values()) {
      boolean found = false;
      for (final String s : i.getObjectClasses()) {
        if (name.equalsIgnoreCase(s)) {
          found = true;
          break;
        }
      }

      if (!found) {
        continue;
      }

      final String attrName = i.getAttributeName();
      final String lowerName = toLowerCase(attrName);
      if (i.includeInRDN() || (i.isRequiredForDecode() && i.isRequiredForEncode())) {
        requiredAttrs.put(lowerName, attrName);
      } else {
        optionalAttrs.put(lowerName, attrName);
      }
    }

    for (final GetterInfo i : getterMap.values()) {
      boolean found = false;
      for (final String s : i.getObjectClasses()) {
        if (name.equalsIgnoreCase(s)) {
          found = true;
          break;
        }
      }

      if (!found) {
        continue;
      }

      final String attrName = i.getAttributeName();
      final String lowerName = toLowerCase(attrName);
      if (i.includeInRDN()) {
        requiredAttrs.put(lowerName, attrName);
      } else {
        optionalAttrs.put(lowerName, attrName);
      }
    }

    if (name.equalsIgnoreCase(structuralClass)) {
      for (final SetterInfo i : setterMap.values()) {
        final String attrName = i.getAttributeName();
        final String lowerName = toLowerCase(attrName);
        if (requiredAttrs.containsKey(lowerName) || optionalAttrs.containsKey(lowerName)) {
          continue;
        }

        optionalAttrs.put(lowerName, attrName);
      }
    }

    final String[] reqArray = new String[requiredAttrs.size()];
    requiredAttrs.values().toArray(reqArray);

    final String[] optArray = new String[optionalAttrs.size()];
    optionalAttrs.values().toArray(optArray);

    return new ObjectClassDefinition(
        a.allocateObjectClassOID(name),
        new String[] {name},
        null,
        false,
        new String[] {sup},
        type,
        reqArray,
        optArray,
        null);
  }