Program: 91930
Project: 91930
Buggy source:
/** 
 * Parses a   {@code "GeodeticCRS"} (WKT 2) element. The syntax is given by<a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#49">WKT 2 specification §8</a>. The legacy WKT 1 specification had two elements for this: {@preformat text}GEOGCS["<name>", <datum>, <prime meridian>, <angular unit>   ,<twin axes>} {,<authority>}] } and  {@preformat text}GEOCCS["<name>", <datum>, <prime meridian>, <linear unit>  ,<axis> ,<axis> ,<axis>} {,<authority>}] }
 * @param mode      {@link #FIRST},   {@link #OPTIONAL} or {@link #MANDATORY}.
 * @param parent    The parent element.
 * @param dimension The minimal number of dimensions (usually 2).
 * @param csType    The default coordinate system type, or {@code null} if unknown.Should be non-null only when parsing a  {@link GeneralDerivedCRS#getBaseCRS()} component.
 * @return The {@code "GeodeticCRS"} element as a {@link GeographicCRS} or {@link GeocentricCRS} object.
 * @throws ParseException if the {@code "GeodeticCRS"} element can not be parsed.
 * @see org.apache.sis.referencing.crs.DefaultGeographicCRS#formatTo(Formatter)
 * @see org.apache.sis.referencing.crs.DefaultGeocentricCRS#formatTo(Formatter)
 */
private SingleCRS parseGeodeticCRS(final int mode,final Element parent,int dimension,String csType) throws ParseException {
  final Element element=parent.pullElement(mode,(csType != null) ? new String[]{WKTKeywords.BaseGeodCRS,WKTKeywords.GeogCS} : new String[]{WKTKeywords.GeodeticCRS,WKTKeywords.GeogCS,WKTKeywords.GeodCRS,WKTKeywords.GeocCS});
  if (element == null) {
    return null;
  }
  final boolean isWKT1;
  Unit<?> csUnit;
  Unit<Angle> angularUnit;
switch (element.getKeywordIndex()) {
default :
{
      isWKT1=false;
      csUnit=parseUnit(element);
      if (Units.isAngular(csUnit)) {
        angularUnit=csUnit.asType(Angle.class);
      }
 else {
        angularUnit=NonSI.DEGREE_ANGLE;
        if (csUnit == null) {
          if (WKTKeywords.ellipsoidal.equals(csType)) {
            csUnit=NonSI.DEGREE_ANGLE;
          }
        }
      }
      break;
    }
case 1:
{
    isWKT1=true;
    csType=WKTKeywords.ellipsoidal;
    angularUnit=parseScaledUnit(element,WKTKeywords.AngleUnit,SI.RADIAN);
    csUnit=angularUnit;
    dimension=2;
    break;
  }
case 3:
{
  isWKT1=true;
  csType=WKTKeywords.Cartesian;
  angularUnit=NonSI.DEGREE_ANGLE;
  csUnit=parseScaledUnit(element,WKTKeywords.LengthUnit,SI.METRE);
  dimension=3;
  break;
}
}
final String name=element.pullString("String_Node_Str");
SingleCRS baseCRS=null;
Conversion fromBase=null;
if (!isWKT1 && csType == null) {
fromBase=parseDerivingConversion(OPTIONAL,element,WKTKeywords.DerivingConversion,csUnit,angularUnit);
if (fromBase != null) {
baseCRS=parseGeodeticCRS(MANDATORY,element,getSourceDimensions(fromBase.getMethod()),WKTKeywords.ellipsoidal);
}
}
final CoordinateSystem cs;
try {
cs=parseCoordinateSystem(element,csType,dimension,isWKT1,csUnit,null);
if (baseCRS != null) {
final Map<String,?> properties=parseMetadataAndClose(element,name,null);
return crsFactory.createDerivedCRS(properties,baseCRS,fromBase,cs);
}
angularUnit=AxisDirections.getAngularUnit(cs,angularUnit);
final PrimeMeridian meridian=parsePrimeMeridian(OPTIONAL,element,isWKT1,angularUnit);
final GeodeticDatum datum=parseDatum(MANDATORY,element,meridian);
final Map<String,?> properties=parseMetadataAndClose(element,name,datum);
if (cs instanceof EllipsoidalCS) {
return crsFactory.createGeographicCRS(properties,datum,(EllipsoidalCS)cs);
}
if (cs instanceof CartesianCS) {
return crsFactory.createGeocentricCRS(properties,datum,referencing.upgradeGeocentricCS((CartesianCS)cs));
}
if (cs instanceof SphericalCS) {
return crsFactory.createGeocentricCRS(properties,datum,(SphericalCS)cs);
}
}
 catch (FactoryException exception) {
throw element.parseFailed(exception);
}
throw element.illegalCS(cs);
}

Fixed version (ground truth):
/** 
 * Parses a   {@code "GeodeticCRS"} (WKT 2) element. The syntax is given by<a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#49">WKT 2 specification §8</a>. The legacy WKT 1 specification had two elements for this: {@preformat wkt}GEOGCS["<name>", <datum>, <prime meridian>, <angular unit>   ,<twin axes>} {,<authority>}] } and  {@preformat wkt}GEOCCS["<name>", <datum>, <prime meridian>, <linear unit>  ,<axis> ,<axis> ,<axis>} {,<authority>}] }
 * @param mode      {@link #FIRST},   {@link #OPTIONAL} or {@link #MANDATORY}.
 * @param parent    The parent element.
 * @param dimension The minimal number of dimensions (usually 2).
 * @param csType    The default coordinate system type, or {@code null} if unknown.Should be non-null only when parsing a  {@link GeneralDerivedCRS#getBaseCRS()} component.
 * @return The {@code "GeodeticCRS"} element as a {@link GeographicCRS} or {@link GeocentricCRS} object.
 * @throws ParseException if the {@code "GeodeticCRS"} element can not be parsed.
 * @see org.apache.sis.referencing.crs.DefaultGeographicCRS#formatTo(Formatter)
 * @see org.apache.sis.referencing.crs.DefaultGeocentricCRS#formatTo(Formatter)
 */
private SingleCRS parseGeodeticCRS(final int mode,final Element parent,int dimension,String csType) throws ParseException {
  final Element element=parent.pullElement(mode,(csType != null) ? new String[]{WKTKeywords.BaseGeodCRS,WKTKeywords.GeogCS} : new String[]{WKTKeywords.GeodeticCRS,WKTKeywords.GeogCS,WKTKeywords.GeodCRS,WKTKeywords.GeocCS});
  if (element == null) {
    return null;
  }
  final boolean isWKT1;
  Unit<?> csUnit;
  Unit<Angle> angularUnit;
switch (element.getKeywordIndex()) {
default :
{
      isWKT1=false;
      csUnit=parseUnit(element);
      if (Units.isAngular(csUnit)) {
        angularUnit=csUnit.asType(Angle.class);
      }
 else {
        angularUnit=NonSI.DEGREE_ANGLE;
        if (csUnit == null) {
          if (WKTKeywords.ellipsoidal.equals(csType)) {
            csUnit=NonSI.DEGREE_ANGLE;
          }
        }
      }
      break;
    }
case 1:
{
    isWKT1=true;
    csType=WKTKeywords.ellipsoidal;
    angularUnit=parseScaledUnit(element,WKTKeywords.AngleUnit,SI.RADIAN);
    csUnit=angularUnit;
    dimension=2;
    break;
  }
case 3:
{
  isWKT1=true;
  csType=WKTKeywords.Cartesian;
  angularUnit=NonSI.DEGREE_ANGLE;
  csUnit=parseScaledUnit(element,WKTKeywords.LengthUnit,SI.METRE);
  dimension=3;
  break;
}
}
final String name=element.pullString("String_Node_Str");
SingleCRS baseCRS=null;
Conversion fromBase=null;
if (!isWKT1 && csType == null) {
fromBase=parseDerivingConversion(OPTIONAL,element,WKTKeywords.DerivingConversion,csUnit,angularUnit);
if (fromBase != null) {
baseCRS=parseGeodeticCRS(MANDATORY,element,getSourceDimensions(fromBase.getMethod()),WKTKeywords.ellipsoidal);
}
}
final CoordinateSystem cs;
try {
cs=parseCoordinateSystem(element,csType,dimension,isWKT1,csUnit,null);
if (baseCRS != null) {
final Map<String,?> properties=parseMetadataAndClose(element,name,null);
return crsFactory.createDerivedCRS(properties,baseCRS,fromBase,cs);
}
angularUnit=AxisDirections.getAngularUnit(cs,angularUnit);
final PrimeMeridian meridian=parsePrimeMeridian(OPTIONAL,element,isWKT1,angularUnit);
final GeodeticDatum datum=parseDatum(MANDATORY,element,meridian);
final Map<String,?> properties=parseMetadataAndClose(element,name,datum);
if (cs instanceof EllipsoidalCS) {
return crsFactory.createGeographicCRS(properties,datum,(EllipsoidalCS)cs);
}
if (cs instanceof CartesianCS) {
return crsFactory.createGeocentricCRS(properties,datum,referencing.upgradeGeocentricCS((CartesianCS)cs));
}
if (cs instanceof SphericalCS) {
return crsFactory.createGeocentricCRS(properties,datum,(SphericalCS)cs);
}
}
 catch (FactoryException exception) {
throw element.parseFailed(exception);
}
throw element.illegalCS(cs);
}