Program: 91920
Project: 91920
Buggy source:
/** 
 * Parses an   {@code "AXIS"} element.This element has the following pattern (simplified): {@preformat textAXIS["<name (abbr.)>", NORTH | SOUTH | EAST | WEST | UP | DOWN | OTHER, ORDER[n], UNIT[…], ID[…]]}
 * @param mode        {@link #FIRST},   {@link #OPTIONAL} or {@link #MANDATORY}.
 * @param parent      The parent element.
 * @param csType      The coordinate system type (Cartesian | ellipsoidal | vertical | etc…), or null if unknown.
 * @param defaultUnit The contextual unit (usually {@code SI.METRE} or {@code SI.RADIAN}), or   {@code null} if unknown.
 * @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 int mode,final Element parent,final String csType,final Unit<?> defaultUnit) throws ParseException {
  final Element element=parent.pullElement(mode,WKTKeywords.Axis);
  if (element == null) {
    return null;
  }
  String name=element.pullString("String_Node_Str");
  final Element orientation=element.pullVoidElement("String_Node_Str");
  Unit<?> unit=parseUnit(element);
  if (unit == null) {
    if (defaultUnit == null) {
      throw element.missingComponent(WKTKeywords.Unit);
    }
    unit=defaultUnit;
  }
  AxisDirection direction=Types.forCodeName(AxisDirection.class,orientation.keyword,true);
  final Element meridian=element.pullElement(OPTIONAL,WKTKeywords.Meridian);
  if (meridian != null) {
    double angle=meridian.pullDouble("String_Node_Str");
    final Unit<Angle> m=parseScaledUnit(meridian,WKTKeywords.AngleUnit,SI.RADIAN);
    meridian.close(ignoredElements);
    if (m != null) {
      angle=m.getConverterTo(NonSI.DEGREE_ANGLE).convert(angle);
    }
    direction=referencing.directionAlongMeridian(direction,angle);
  }
  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=AxisDirections.suggestAbbreviation(name,direction,unit);
  }
  name=transliterator.toLongAxisName(csType,direction,name);
  abbreviation=transliterator.toUnicodeAbbreviation(csType,direction,abbreviation);
  final Element order=element.pullElement(OPTIONAL,WKTKeywords.Order);
  Integer n=null;
  if (order != null) {
    n=order.pullInteger("String_Node_Str");
    order.close(ignoredElements);
  }
  final CoordinateSystemAxis axis;
  try {
    axis=csFactory.createCoordinateSystemAxis(parseMetadataAndClose(element,name,null),abbreviation,direction,unit);
  }
 catch (  FactoryException exception) {
    throw element.parseFailed(exception);
  }
  if (axisOrder.put(axis,n) != null) {
    throw new LocalizedParseException(errorLocale,Errors.Keys.DuplicatedElement_1,new Object[]{WKTKeywords.Axis + "String_Node_Str" + name+ "String_Node_Str"},element.offset);
  }
  return axis;
}

Fixed version (ground truth):
/** 
 * Parses an   {@code "AXIS"} element.This element has the following pattern (simplified): {@preformat wktAXIS["<name (abbr.)>", NORTH | SOUTH | EAST | WEST | UP | DOWN | OTHER, ORDER[n], UNIT[…], ID[…]]}Abbreviation may be specified between parenthesis. Nested parenthesis are possible, as for example:  {@preformat wktAXIS["Easting (E(X))", EAST]}
 * @param mode        {@link #FIRST},   {@link #OPTIONAL} or {@link #MANDATORY}.
 * @param parent      The parent element.
 * @param csType      The coordinate system type (Cartesian | ellipsoidal | vertical | etc…), or null if unknown.
 * @param defaultUnit The contextual unit (usually {@code SI.METRE} or {@code SI.RADIAN}), or   {@code null} if unknown.
 * @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 int mode,final Element parent,final String csType,final Unit<?> defaultUnit) throws ParseException {
  final Element element=parent.pullElement(mode,WKTKeywords.Axis);
  if (element == null) {
    return null;
  }
  String name=element.pullString("String_Node_Str");
  final Element orientation=element.pullVoidElement("String_Node_Str");
  Unit<?> unit=parseUnit(element);
  if (unit == null) {
    if (defaultUnit == null) {
      throw element.missingComponent(WKTKeywords.Unit);
    }
    unit=defaultUnit;
  }
  AxisDirection direction=Types.forCodeName(AxisDirection.class,orientation.keyword,true);
  final Element meridian=element.pullElement(OPTIONAL,WKTKeywords.Meridian);
  if (meridian != null) {
    double angle=meridian.pullDouble("String_Node_Str");
    final Unit<Angle> m=parseScaledUnit(meridian,WKTKeywords.AngleUnit,SI.RADIAN);
    meridian.close(ignoredElements);
    if (m != null) {
      angle=m.getConverterTo(NonSI.DEGREE_ANGLE).convert(angle);
    }
    direction=referencing.directionAlongMeridian(direction,angle);
  }
  String abbreviation;
  int start, end=name.length() - 1;
  if (end > 1 && name.charAt(end) == ')' && (start=name.lastIndexOf('(',end - 1)) >= 0) {
    for (int np=end; (--np >= 0) && name.charAt(np) == ')'; ) {
      final int c=name.lastIndexOf('(',start - 1);
      if (c < 0) {
        warning(parent,element,Errors.formatInternational(Errors.Keys.NonEquilibratedParenthesis_2,'(',name),null);
        break;
      }
      start=c;
    }
    abbreviation=CharSequences.trimWhitespaces(name.substring(start + 1,end));
    name=CharSequences.trimWhitespaces(name.substring(0,start));
    if (name.isEmpty()) {
      name=abbreviation;
    }
  }
 else {
    abbreviation=AxisDirections.suggestAbbreviation(name,direction,unit);
  }
  name=transliterator.toLongAxisName(csType,direction,name);
  abbreviation=transliterator.toUnicodeAbbreviation(csType,direction,abbreviation);
  final Element order=element.pullElement(OPTIONAL,WKTKeywords.Order);
  Integer n=null;
  if (order != null) {
    n=order.pullInteger("String_Node_Str");
    order.close(ignoredElements);
  }
  final CoordinateSystemAxis axis;
  try {
    axis=csFactory.createCoordinateSystemAxis(parseMetadataAndClose(element,name,null),abbreviation,direction,unit);
  }
 catch (  FactoryException exception) {
    throw element.parseFailed(exception);
  }
  if (axisOrder.put(axis,n) != null) {
    throw new LocalizedParseException(errorLocale,Errors.Keys.DuplicatedElement_1,new Object[]{WKTKeywords.Axis + "String_Node_Str" + name+ "String_Node_Str"},element.offset);
  }
  return axis;
}