11package org .rcsb .cif .model ;
22
33import java .util .List ;
4+ import java .util .Objects ;
45
56/**
67 * A builder instance for {@link StrColumn} instances.
@@ -27,4 +28,72 @@ public interface StrColumnBuilder<P extends CategoryBuilder<PP, PPP>, PP extends
2728 * @return this builder instance
2829 */
2930 StrColumnBuilder <P , PP , PPP > add (String ... values );
31+
32+ /**
33+ * Add new values with fine-grained control.
34+ * <p>
35+ * For {@link ValueKind#PRESENT}, the corresponding entry from {@code values} is appended.
36+ * For {@link ValueKind#NOT_PRESENT} and {@link ValueKind#UNKNOWN}, this method delegates to
37+ * {@link #markNextNotPresent()} and {@link #markNextUnknown()} respectively.
38+ * </p>
39+ * @param values array of String values
40+ * @param mask array of {@link ValueKind}, must be the same length as {@code values}
41+ * @return this builder instance
42+ * @throws IllegalArgumentException if arrays differ in size
43+ * @throws NullPointerException if {@code values}, {@code mask}, or any {@code mask[i]} is null
44+ */
45+ default StrColumnBuilder <P ,PP ,PPP > addMasked (String [] values , ValueKind [] mask ) {
46+ Objects .requireNonNull (values , "values" );
47+ Objects .requireNonNull (mask , "mask" );
48+ if (values .length != mask .length ) {
49+ throw new IllegalArgumentException ("values.length (" + values .length + ") must equal mask.length (" + mask .length + ")" );
50+ }
51+
52+ for (int i = 0 ; i < values .length ; i ++) {
53+ ValueKind k = Objects .requireNonNull (mask [i ], "mask[" + i + "]" );
54+ if (k == ValueKind .PRESENT && (values [i ] == null || ValueKind .isValueKindToken (values [i ]))) {
55+ throw new IllegalArgumentException ("PRESENT value must not be null, '.' or '?': values[" + i + "]" );
56+ }
57+ switch (k ) {
58+ case PRESENT :
59+ add (values [i ]);
60+ break ;
61+ case NOT_PRESENT :
62+ markNextNotPresent ();
63+ break ;
64+ case UNKNOWN :
65+ markNextUnknown ();
66+ break ;
67+ default :
68+ throw new IllegalStateException ("Unhandled ValueKind: " + k );
69+ }
70+ }
71+ return this ;
72+ }
73+
74+ /**
75+ * Add values from an Iterable.
76+ * @param values String values, null is mapped to NOT_PRESENT ("."); "." and "?" are interpreted as CIF tokens.
77+ * @return this builder instance
78+ */
79+ default StrColumnBuilder <P ,PP ,PPP > addNullable (Iterable <String > values ) {
80+ Objects .requireNonNull (values , "values" );
81+ for (String v : values ) {
82+ ValueKind valueKind = ValueKind .fromCifToken (v );
83+ switch (valueKind ) {
84+ case PRESENT :
85+ add (v );
86+ break ;
87+ case NOT_PRESENT :
88+ markNextNotPresent ();
89+ break ;
90+ case UNKNOWN :
91+ markNextUnknown ();
92+ break ;
93+ default :
94+ throw new IllegalStateException ("Unhandled ValueKind: " + valueKind );
95+ }
96+ }
97+ return this ;
98+ }
3099}
0 commit comments