class DhisFhirResourceId implements Serializable {

    @Nonnull
    public static DhisFhirResourceId parse( @Nonnull String value ) throws IllegalArgumentException
    {
        final int firstIndex = value.indexOf( '-' );

        if ( firstIndex < 0 )
        {
            return new DhisFhirResourceId( value );
        }

        if ( firstIndex == 0 )
        {
            throw new IllegalArgumentException( "Invalid DHIS FHIR ID: " + value );
        }

        final int secondIndex = value.indexOf( '-', firstIndex + 1 );

        if ( secondIndex < 0 )
        {
            throw new IllegalArgumentException( "Invalid DHIS FHIR ID: " + value );
        }

        final DhisResourceType type = DhisResourceType.getByAbbreviation( value.substring( 0, firstIndex ) );

        if ( type == null )
        {
            throw new IllegalArgumentException( "Invalid DHIS FHIR ID: " + value );
        }

        final String id = value.substring( firstIndex + 1, secondIndex );

        if ( StringUtils.isBlank( id ) || !StringUtils.isAlphanumeric( id ) )
        {
            throw new IllegalArgumentException( "Invalid DHIS FHIR ID: " + value );
        }

        final UUID ruleId;
        try
        {
            final Matcher matcher = UUID_PATTERN.matcher( value.substring( secondIndex + 1 ) );

            if ( !matcher.matches() )
            {
                throw new IllegalArgumentException( "Invalid DHIS FHIR ID: " + value );
            }

            ruleId = UUID.fromString( matcher.replaceAll( "$1-$2-$3-$4-$5" ) );
        }
        catch ( IllegalArgumentException e )
        {
            throw new IllegalArgumentException( "Invalid DHIS FHIR ID: " + value );
        }

        return new DhisFhirResourceId( type, id, ruleId );
    }

    public  DhisFhirResourceId( @Nullable DhisResourceType type, @Nonnull String id, @Nullable UUID ruleId );
    public  DhisFhirResourceId( @Nonnull String id );

}