1919import static com .google .cloud .spanner .connection .ReadOnlyStalenessUtil .parseTimeUnit ;
2020import static com .google .cloud .spanner .connection .ReadOnlyStalenessUtil .toChronoUnit ;
2121
22+ import com .google .api .gax .core .CredentialsProvider ;
23+ import com .google .cloud .spanner .Dialect ;
2224import com .google .cloud .spanner .ErrorCode ;
2325import com .google .cloud .spanner .Options .RpcPriority ;
2426import com .google .cloud .spanner .SpannerException ;
3133import com .google .common .base .Preconditions ;
3234import com .google .common .base .Strings ;
3335import com .google .spanner .v1 .DirectedReadOptions ;
36+ import java .lang .reflect .Constructor ;
37+ import java .lang .reflect .InvocationTargetException ;
3438import java .time .Duration ;
3539import java .time .temporal .ChronoUnit ;
3640import java .util .Base64 ;
@@ -73,7 +77,11 @@ private E get(String value) {
7377
7478 /** Converter from string to {@link Boolean} */
7579 static class BooleanConverter implements ClientSideStatementValueConverter <Boolean > {
80+ static final BooleanConverter INSTANCE = new BooleanConverter ();
7681
82+ private BooleanConverter () {}
83+
84+ /** Constructor that is needed for reflection. */
7785 public BooleanConverter (String allowedValues ) {}
7886
7987 @ Override
@@ -142,7 +150,11 @@ public Boolean convert(String value) {
142150
143151 /** Converter from string to a non-negative integer. */
144152 static class NonNegativeIntegerConverter implements ClientSideStatementValueConverter <Integer > {
153+ static final NonNegativeIntegerConverter INSTANCE = new NonNegativeIntegerConverter ();
154+
155+ private NonNegativeIntegerConverter () {}
145156
157+ /** Constructor needed for reflection. */
146158 public NonNegativeIntegerConverter (String allowedValues ) {}
147159
148160 @ Override
@@ -167,6 +179,9 @@ public Integer convert(String value) {
167179
168180 /** Converter from string to {@link Duration}. */
169181 static class DurationConverter implements ClientSideStatementValueConverter <Duration > {
182+ static final DurationConverter INSTANCE =
183+ new DurationConverter ("('(\\ d{1,19})(s|ms|us|ns)'|\\ d{1,19}|NULL)" );
184+
170185 private final String resetValue ;
171186
172187 private final Pattern allowedValues ;
@@ -227,6 +242,10 @@ public PgDurationConverter(String allowedValues) {
227242 /** Converter from string to possible values for read only staleness ({@link TimestampBound}). */
228243 static class ReadOnlyStalenessConverter
229244 implements ClientSideStatementValueConverter <TimestampBound > {
245+ static final ReadOnlyStalenessConverter INSTANCE =
246+ new ReadOnlyStalenessConverter (
247+ "'((STRONG)|(MIN_READ_TIMESTAMP)[\\ t ]+((\\ d{4})-(\\ d{2})-(\\ d{2})([Tt](\\ d{2}):(\\ d{2}):(\\ d{2})(\\ .\\ d{1,9})?)([Zz]|([+-])(\\ d{2}):(\\ d{2})))|(READ_TIMESTAMP)[\\ t ]+((\\ d{4})-(\\ d{2})-(\\ d{2})([Tt](\\ d{2}):(\\ d{2}):(\\ d{2})(\\ .\\ d{1,9})?)([Zz]|([+-])(\\ d{2}):(\\ d{2})))|(MAX_STALENESS)[\\ t ]+((\\ d{1,19})(s|ms|us|ns))|(EXACT_STALENESS)[\\ t ]+((\\ d{1,19})(s|ms|us|ns)))'" );
248+
230249 private final Pattern allowedValues ;
231250 private final CaseInsensitiveEnumMap <Mode > values = new CaseInsensitiveEnumMap <>(Mode .class );
232251
@@ -337,9 +356,14 @@ public DirectedReadOptions convert(String value) {
337356 /** Converter for converting strings to {@link AutocommitDmlMode} values. */
338357 static class AutocommitDmlModeConverter
339358 implements ClientSideStatementValueConverter <AutocommitDmlMode > {
359+ static final AutocommitDmlModeConverter INSTANCE = new AutocommitDmlModeConverter ();
360+
340361 private final CaseInsensitiveEnumMap <AutocommitDmlMode > values =
341362 new CaseInsensitiveEnumMap <>(AutocommitDmlMode .class );
342363
364+ private AutocommitDmlModeConverter () {}
365+
366+ /** Constructor needed for reflection. */
343367 public AutocommitDmlModeConverter (String allowedValues ) {}
344368
345369 @ Override
@@ -353,7 +377,35 @@ public AutocommitDmlMode convert(String value) {
353377 }
354378 }
355379
380+ static class ConnectionStateTypeConverter
381+ implements ClientSideStatementValueConverter <ConnectionState .Type > {
382+ static final ConnectionStateTypeConverter INSTANCE = new ConnectionStateTypeConverter ();
383+
384+ private final CaseInsensitiveEnumMap <ConnectionState .Type > values =
385+ new CaseInsensitiveEnumMap <>(ConnectionState .Type .class );
386+
387+ private ConnectionStateTypeConverter () {}
388+
389+ /** Constructor that is needed for reflection. */
390+ public ConnectionStateTypeConverter (String allowedValues ) {}
391+
392+ @ Override
393+ public Class <ConnectionState .Type > getParameterClass () {
394+ return ConnectionState .Type .class ;
395+ }
396+
397+ @ Override
398+ public ConnectionState .Type convert (String value ) {
399+ return values .get (value );
400+ }
401+ }
402+
356403 static class StringValueConverter implements ClientSideStatementValueConverter <String > {
404+ static final StringValueConverter INSTANCE = new StringValueConverter ();
405+
406+ private StringValueConverter () {}
407+
408+ /** Constructor needed for reflection. */
357409 public StringValueConverter (String allowedValues ) {}
358410
359411 @ Override
@@ -481,6 +533,8 @@ public PgTransactionMode convert(String value) {
481533
482534 /** Converter for converting strings to {@link RpcPriority} values. */
483535 static class RpcPriorityConverter implements ClientSideStatementValueConverter <RpcPriority > {
536+ static final RpcPriorityConverter INSTANCE = new RpcPriorityConverter ("(HIGH|MEDIUM|LOW|NULL)" );
537+
484538 private final CaseInsensitiveEnumMap <RpcPriority > values =
485539 new CaseInsensitiveEnumMap <>(RpcPriority .class );
486540 private final Pattern allowedValues ;
@@ -512,9 +566,14 @@ public RpcPriority convert(String value) {
512566 /** Converter for converting strings to {@link SavepointSupport} values. */
513567 static class SavepointSupportConverter
514568 implements ClientSideStatementValueConverter <SavepointSupport > {
569+ static final SavepointSupportConverter INSTANCE = new SavepointSupportConverter ();
570+
515571 private final CaseInsensitiveEnumMap <SavepointSupport > values =
516572 new CaseInsensitiveEnumMap <>(SavepointSupport .class );
517573
574+ private SavepointSupportConverter () {}
575+
576+ /** Constructor needed for reflection. */
518577 public SavepointSupportConverter (String allowedValues ) {}
519578
520579 @ Override
@@ -528,6 +587,30 @@ public SavepointSupport convert(String value) {
528587 }
529588 }
530589
590+ /** Converter for converting strings to {@link DdlInTransactionMode} values. */
591+ static class DdlInTransactionModeConverter
592+ implements ClientSideStatementValueConverter <DdlInTransactionMode > {
593+ static final DdlInTransactionModeConverter INSTANCE = new DdlInTransactionModeConverter ();
594+
595+ private final CaseInsensitiveEnumMap <DdlInTransactionMode > values =
596+ new CaseInsensitiveEnumMap <>(DdlInTransactionMode .class );
597+
598+ private DdlInTransactionModeConverter () {}
599+
600+ /** Constructor needed for reflection. */
601+ public DdlInTransactionModeConverter (String allowedValues ) {}
602+
603+ @ Override
604+ public Class <DdlInTransactionMode > getParameterClass () {
605+ return DdlInTransactionMode .class ;
606+ }
607+
608+ @ Override
609+ public DdlInTransactionMode convert (String value ) {
610+ return values .get (value );
611+ }
612+ }
613+
531614 static class ExplainCommandConverter implements ClientSideStatementValueConverter <String > {
532615 @ Override
533616 public Class <String > getParameterClass () {
@@ -588,4 +671,71 @@ public String convert(String filePath) {
588671 return filePath ;
589672 }
590673 }
674+
675+ static class CredentialsProviderConverter
676+ implements ClientSideStatementValueConverter <CredentialsProvider > {
677+ static final CredentialsProviderConverter INSTANCE = new CredentialsProviderConverter ();
678+
679+ private CredentialsProviderConverter () {}
680+
681+ @ Override
682+ public Class <CredentialsProvider > getParameterClass () {
683+ return CredentialsProvider .class ;
684+ }
685+
686+ @ Override
687+ public CredentialsProvider convert (String credentialsProviderName ) {
688+ if (!Strings .isNullOrEmpty (credentialsProviderName )) {
689+ try {
690+ Class <? extends CredentialsProvider > clazz =
691+ (Class <? extends CredentialsProvider >) Class .forName (credentialsProviderName );
692+ Constructor <? extends CredentialsProvider > constructor = clazz .getDeclaredConstructor ();
693+ return constructor .newInstance ();
694+ } catch (ClassNotFoundException classNotFoundException ) {
695+ throw SpannerExceptionFactory .newSpannerException (
696+ ErrorCode .INVALID_ARGUMENT ,
697+ "Unknown or invalid CredentialsProvider class name: " + credentialsProviderName ,
698+ classNotFoundException );
699+ } catch (NoSuchMethodException noSuchMethodException ) {
700+ throw SpannerExceptionFactory .newSpannerException (
701+ ErrorCode .INVALID_ARGUMENT ,
702+ "Credentials provider "
703+ + credentialsProviderName
704+ + " does not have a public no-arg constructor." ,
705+ noSuchMethodException );
706+ } catch (InvocationTargetException
707+ | InstantiationException
708+ | IllegalAccessException exception ) {
709+ throw SpannerExceptionFactory .newSpannerException (
710+ ErrorCode .INVALID_ARGUMENT ,
711+ "Failed to create an instance of "
712+ + credentialsProviderName
713+ + ": "
714+ + exception .getMessage (),
715+ exception );
716+ }
717+ }
718+ return null ;
719+ }
720+ }
721+
722+ /** Converter for converting strings to {@link Dialect} values. */
723+ static class DialectConverter implements ClientSideStatementValueConverter <Dialect > {
724+ static final DialectConverter INSTANCE = new DialectConverter ();
725+
726+ private final CaseInsensitiveEnumMap <Dialect > values =
727+ new CaseInsensitiveEnumMap <>(Dialect .class );
728+
729+ private DialectConverter () {}
730+
731+ @ Override
732+ public Class <Dialect > getParameterClass () {
733+ return Dialect .class ;
734+ }
735+
736+ @ Override
737+ public Dialect convert (String value ) {
738+ return values .get (value );
739+ }
740+ }
591741}
0 commit comments