@@ -50,10 +50,13 @@ public class VCFHeaderLine implements Comparable, Serializable {
5050 * @param key the key for this header line
5151 * @param value the value for this header line
5252 */
53- public VCFHeaderLine (String key , String value ) {
53+ public VCFHeaderLine (final String key , final String value ) {
54+ final Optional <String > validationFailure = validateAttributeName (key , "header line key" );
55+ if (validationFailure .isPresent ()) {
56+ throw new TribbleException (validationFailure .get ());
57+ }
5458 mKey = key ;
5559 mValue = value ;
56- validate ();
5760 }
5861
5962 /**
@@ -86,15 +89,20 @@ public String getValue() {
8689 public String getID () { return null ; }
8790
8891 /**
89- * Validates this header line against {@code vcfTargetVersion}.
90- * Subclasses can override this to provide line type-specific version validation, and the
91- * overrides should also call super.getValidationFailure to allow each class in the class hierarchy
92- * to do class-level validation.
92+ * Validates this header line against {@code vcfTargetVersion} and returns a {@link VCFValidationFailure}
93+ * describing the reaon for the failure, if one exists. This method is used to report the reason for a
94+ * version upgrade failure.
95+ *
96+ * Subclasses can override this to provide line type-specific version validation. Overrides should
97+ * call super.validateForVersion to allow each class in the hierarchy to do class-level validation.
9398 *
99+ * @param vcfTargetVersion
94100 * @return Optional containing a {@link VCFValidationFailure} describing validation failure if this
95101 * line fails validation, otherwise Optional.empty().
96102 */
97- public Optional <VCFValidationFailure <VCFHeaderLine >> getValidationFailure (final VCFHeaderVersion vcfTargetVersion ) {
103+ public Optional <VCFValidationFailure <VCFHeaderLine >> validateForVersion (final VCFHeaderVersion vcfTargetVersion ) {
104+ ValidationUtils .nonNull (vcfTargetVersion );
105+
98106 // If this header line is itself a fileformat/version line,
99107 // make sure it doesn't clash with the requested vcfTargetVersion.
100108 if (VCFHeaderVersion .isFormatString (getKey ())) {
@@ -124,33 +132,42 @@ public Optional<VCFValidationFailure<VCFHeaderLine>> getValidationFailure(final
124132 }
125133
126134 /**
127- * Validate that the header line conforms to {@code vcfTargetVersion.
128- * @param vcfTargetVersion
135+ * Validate that the header line conforms to {@code vcfTargetVersion. throws if the line fails to
136+ * validate for the target version.
137+ *
138+ * @param vcfTargetVersion the version agint which to validate the line
129139 * @throws {@link TribbleException.VersionValidationFailure} if this header line fails to conform
130140 */
131- public void validateForVersion (final VCFHeaderVersion vcfTargetVersion ) {
132- final Optional <VCFValidationFailure <VCFHeaderLine >> error = getValidationFailure (vcfTargetVersion );
133- if (error .isPresent ()) {
134- throw new TribbleException .VersionValidationFailure (error .get ().getSourceMessage ());
141+ public void validateForVersionOrThrow (final VCFHeaderVersion vcfTargetVersion ) {
142+ ValidationUtils .nonNull (vcfTargetVersion );
143+ final Optional <VCFValidationFailure <VCFHeaderLine >> versionValidationFailure = validateForVersion (vcfTargetVersion );
144+ if (versionValidationFailure .isPresent ()) {
145+ throw new TribbleException .VersionValidationFailure (versionValidationFailure .get ().getSourceMessage ());
135146 }
136147 }
137148
138149 /**
139- * Validate a string that is to be used as a unique id or key field.
150+ * Validate a string that is to be used as a unique id or key field, and return an Optional String describing
151+ * the validation failure.
152+ *
153+ * @param targetString the string to validate
154+ * @param targetContext the context for which the {@code targetString} is used. Used when reporting validation
155+ * failures. May not be null.
156+ * @return an Optional String containing an error message
140157 */
141- protected static void validateKeyOrID (final String keyString , final String sourceName ) {
142- ValidationUtils .nonNull (sourceName );
143- if ( keyString == null ) {
144- throw new TribbleException (
145- String .format ("VCFHeaderLine: %s cannot be null or empty " , sourceName ));
146- }
147- if ( keyString . contains ( "<" ) || keyString . contains ( ">" ) ) {
148- throw new TribbleException (
149- String .format ("VCFHeaderLine: %s cannot contain angle brackets" , sourceName ));
150- }
151- if ( keyString . contains ( "=" ) ) {
152- throw new TribbleException (
153- String . format ( "VCFHeaderLine: %s cannot contain an equals sign" , sourceName ) );
158+ protected static Optional < String > validateAttributeName (final String targetString , final String targetContext ) {
159+ ValidationUtils .nonNull (targetContext );
160+
161+ if ( targetString == null ) {
162+ return Optional . of ( String .format ("VCFHeaderLine: %s is null" , targetContext ));
163+ } else if ( targetString . length () < 1 ) {
164+ return Optional . of ( String . format ( "VCFHeaderLine: %s has zero length" , targetContext ));
165+ } else if ( targetString . contains ( "<" ) || targetString . contains ( ">" ) ) {
166+ return Optional . of ( String .format ("VCFHeaderLine: angle brackets not allowed in \" %s \" value" , targetContext ));
167+ } else if ( targetString . contains ( "=" ) ) {
168+ return Optional . of ( String . format ( "VCFHeaderLine: equals sign not allowed in %s value \" %s \" " , targetContext , targetString ));
169+ } else {
170+ return Optional . empty ( );
154171 }
155172 }
156173
@@ -239,13 +256,6 @@ public static String toStringEncoding(Map<String, ? extends Object> keyValues) {
239256 return builder .toString ();
240257 }
241258
242- /**
243- * Validate the state of this header line. Require the key be valid as an "id".
244- */
245- private void validate () {
246- validateKeyOrID (mKey , "key" );
247- }
248-
249259 private static String escapeQuotes (final String value ) {
250260 // java escaping in a string literal makes this harder to read than it should be
251261 // without string literal escaping and quoting the regex would be: replaceAll( ([^\])" , $1\" )
0 commit comments