class LocationReferencePointDecoder {

    LocationReferencePoint decode(openlr.proto.schema.LocationReferencePoint data, int sequenceNumber, boolean isLast) throws OpenLRProtoException {
        if (!data.hasCoordinates()) {
            throw new OpenLRProtoException(OpenLRProtoStatusCode.INVALID_LOCATION_REFERENCE);
        }

        Coordinates coordinates = data.getCoordinates();
        double longitudeDeg = coordinates.getLongitude();
        double latitudeDeg = coordinates.getLatitude();

        if (!data.hasLineAttributes()) {
            throw new OpenLRProtoException(OpenLRProtoStatusCode.INVALID_LOCATION_REFERENCE);
        }

        LineAttributes lineAttributes = data.getLineAttributes();
        int bearing = lineAttributes.getBearing();
        FunctionalRoadClass frc = decode(lineAttributes.getFrc());
        FormOfWay fow = decode(lineAttributes.getFow());

        if (isLast) {
            return new LocationReferencePointProtoImpl(
                    sequenceNumber,
                    longitudeDeg,
                    latitudeDeg,
                    bearing,
                    frc,
                    fow);
        } else {
            if (!data.hasPathAttributes()) {
                throw new OpenLRProtoException(OpenLRProtoStatusCode.INVALID_LOCATION_REFERENCE);
            }

            PathAttributes pathAttributes = data.getPathAttributes();
            int distanceToNext = pathAttributes.getDistanceToNext();
            FunctionalRoadClass lfrc = decode(pathAttributes.getLowestFrcAlongPath());

            return new LocationReferencePointProtoImpl(
                    sequenceNumber,
                    longitudeDeg,
                    latitudeDeg,
                    bearing,
                    frc,
                    fow,
                    distanceToNext,
                    lfrc);
        }
    }

}