1010package net .sf .jsqlparser .statement .create .table ;
1111
1212import java .io .Serializable ;
13+ import java .util .ArrayList ;
1314import java .util .Arrays ;
1415import java .util .Collections ;
1516import java .util .List ;
@@ -268,9 +269,10 @@ public ConstraintKind getConstraintKind() {
268269 }
269270 }
270271
272+ /** Creates an opaque option with its own copy of the supplied tokens, without parsing them. */
271273 public static ColumnOption raw (List <String > tokens ) {
272274 ColumnOption option = new ColumnOption ();
273- option .tokens = tokens ;
275+ option .setTokens ( tokens ) ;
274276 return option ;
275277 }
276278
@@ -295,33 +297,60 @@ public Kind getKind() {
295297 return kind ;
296298 }
297299
300+ /**
301+ * Returns an unmodifiable, detached token snapshot for both raw and structured options. An
302+ * unset raw option returns null; an explicitly empty raw option returns an empty snapshot. Use
303+ * {@link #setTokens(List)} to edit an opaque option, or the typed setters and mutable child
304+ * nodes to edit structured options. Later changes to the option do not change this snapshot.
305+ */
298306 public List <String > getTokens () {
299307 switch (kind ) {
300308 case DEFAULT :
301- return Arrays .asList ("DEFAULT" , String .valueOf (defaultExpression ));
309+ return Collections .unmodifiableList (
310+ Arrays .asList ("DEFAULT" , String .valueOf (defaultExpression )));
302311 case NULLABILITY :
303- return nullable ? Collections .singletonList ("NULL" ) : Arrays .asList ("NOT" , "NULL" );
312+ return nullable ? Collections .singletonList ("NULL" )
313+ : Collections .unmodifiableList (Arrays .asList ("NOT" , "NULL" ));
304314 case COLLATE :
305- return Arrays .asList ("COLLATE" , collation );
315+ return Collections . unmodifiableList ( Arrays .asList ("COLLATE" , collation ) );
306316 case COMMENT :
307- return Arrays .asList ("COMMENT" , comment .toString ());
317+ return Collections . unmodifiableList ( Arrays .asList ("COMMENT" , comment .toString () ));
308318 case ON_UPDATE :
309- return Arrays .asList ("ON" , "UPDATE" , onUpdateExpression .toString ());
319+ return Collections .unmodifiableList (
320+ Arrays .asList ("ON" , "UPDATE" , onUpdateExpression .toString ()));
310321 case GENERATED :
311322 return generatedDefinition .getTokens ();
312323 case CONSTRAINT :
313324 if ("PRIMARY KEY" .equals (constraint .toString ())) {
314- return Arrays .asList ("PRIMARY" , "KEY" );
325+ return Collections . unmodifiableList ( Arrays .asList ("PRIMARY" , "KEY" ) );
315326 }
316327 return Collections .singletonList (toString ());
317328 case OTHER :
318329 case SERIAL_DEFAULT_VALUE :
319- return tokens ;
330+ return tokens == null ? null
331+ : Collections .unmodifiableList (new ArrayList <>(tokens ));
320332 default :
321333 return Collections .singletonList (toString ());
322334 }
323335 }
324336
337+ /**
338+ * Replaces the tokens of an opaque {@link Kind#OTHER} option with a copy of the supplied list.
339+ * Null unsets the tokens; an empty list retains an explicitly empty option. Tokens are never
340+ * parsed or classified. To replace a structured option, including SERIAL DEFAULT VALUE, with
341+ * raw text, replace its node in {@link ColumnDefinition#getColumnOptions()} using
342+ * {@link #raw(List)} instead.
343+ *
344+ * @throws IllegalStateException if this is a structured option
345+ */
346+ public void setTokens (List <String > tokens ) {
347+ if (kind != Kind .OTHER ) {
348+ throw new IllegalStateException (
349+ "Only opaque options accept tokens; use typed setters or replace the option" );
350+ }
351+ this .tokens = tokens == null ? null : new ArrayList <>(tokens );
352+ }
353+
325354 public ForeignKeyReference getForeignKeyReference () {
326355 return foreignKeyReference ;
327356 }
0 commit comments