Program: 92111
Project: 92111
Buggy source:
/** 
 * Parses an   {@code "AXIS"} element.This element has the following pattern: {@preformat textAXIS["<name>", NORTH | SOUTH | EAST | WEST | UP | DOWN | OTHER]}<div class="note"><b>Note:</b> There is no AUTHORITY element for AXIS element in WKT 1 specification. However, we accept it anyway in order to make the parser more tolerant to non-100% compliant WKT. Note that AXIS is really the only element without such AUTHORITY clause and the EPSG database provides authority code for all axis.</div>
 * @param parent The parent element.
 * @param unit The contextual unit, usually {@code SI.METRE} or {@code SI.RADIAN}.
 * @param mandatory {@code true} if the axis is mandatory, or {@code false} if it is optional.
 * @return The {@code "AXIS"} element as a {@link CoordinateSystemAxis} object, or {@code null}if the axis was not required and there is no axis object.
 * @throws ParseException if the {@code "AXIS"} element can not be parsed.
 */
private CoordinateSystemAxis parseAxis(final Element parent,final Unit<?> unit,final boolean mandatory) throws ParseException {
  final Element element;
  if (mandatory) {
    element=parent.pullElement(WKTKeywords.Axis);
  }
 else {
    element=parent.pullOptionalElement(WKTKeywords.Axis);
    if (element == null) {
      return null;
    }
  }
  final String name=element.pullString("String_Node_Str");
  final Element orientation=element.pullVoidElement("String_Node_Str");
  final AxisDirection direction=Types.forCodeName(AxisDirection.class,orientation.keyword,mandatory);
  try {
    return csFactory.createCoordinateSystemAxis(parseAuthorityAndClose(element,name),name,direction,unit);
  }
 catch (  FactoryException exception) {
    throw element.parseFailed(exception);
  }
}

Fixed version (ground truth):
/** 
 * Parses an   {@code "AXIS"} element.This element has the following pattern: {@preformat textAXIS["<name>", NORTH | SOUTH | EAST | WEST | UP | DOWN | OTHER]}<div class="note"><b>Note:</b> There is no AUTHORITY element for AXIS element in WKT 1 specification. However, we accept it anyway in order to make the parser more tolerant to non-100% compliant WKT. Note that AXIS is really the only element without such AUTHORITY clause and the EPSG database provides authority code for all axis.</div>
 * @param parent       The parent element.
 * @param isGeographic {@code true} if the parent element is a geodetic CRS having an ellipsoidal coordinate system.
 * @param unit         The contextual unit, usually {@code SI.METRE} or {@code SI.RADIAN}.
 * @param mandatory    {@code true} if the axis is mandatory, or {@code false} if it is optional.
 * @return The {@code "AXIS"} element as a {@link CoordinateSystemAxis} object, or {@code null}if the axis was not required and there is no axis object.
 * @throws ParseException if the {@code "AXIS"} element can not be parsed.
 */
private CoordinateSystemAxis parseAxis(final Element parent,final boolean isGeographic,final Unit<?> unit,final boolean mandatory) throws ParseException {
  final Element element;
  if (mandatory) {
    element=parent.pullElement(WKTKeywords.Axis);
  }
 else {
    element=parent.pullOptionalElement(WKTKeywords.Axis);
    if (element == null) {
      return null;
    }
  }
  String name=CharSequences.trimWhitespaces(element.pullString("String_Node_Str"));
  if (isGeographic) {
    if (name.equalsIgnoreCase(AxisNames.LATITUDE) || name.equalsIgnoreCase("String_Node_Str")) {
      name=AxisNames.GEODETIC_LATITUDE;
    }
 else     if (name.equalsIgnoreCase(AxisNames.LONGITUDE) || name.equalsIgnoreCase("String_Node_Str") || name.equalsIgnoreCase("String_Node_Str")) {
      name=AxisNames.GEODETIC_LONGITUDE;
    }
  }
  final Element orientation=element.pullVoidElement("String_Node_Str");
  final AxisDirection direction=Types.forCodeName(AxisDirection.class,orientation.keyword,mandatory);
  final String abbreviation;
  final int start, end=name.length() - 1;
  if (end > 1 && name.charAt(end) == ')' && (start=name.lastIndexOf('(',end - 1)) >= 0) {
    abbreviation=CharSequences.trimWhitespaces(name.substring(start + 1,end));
    name=CharSequences.trimWhitespaces(name.substring(0,start));
    if (name.isEmpty()) {
      name=abbreviation;
    }
  }
 else {
    abbreviation=referencing.suggestAbbreviation(name,direction,unit);
  }
  try {
    return csFactory.createCoordinateSystemAxis(parseAuthorityAndClose(element,name),abbreviation,direction,unit);
  }
 catch (  FactoryException exception) {
    throw element.parseFailed(exception);
  }
}