1919
2020package org .elasticsearch .index .seqno ;
2121
22+ import org .elasticsearch .common .ParseField ;
2223import org .elasticsearch .common .io .stream .StreamInput ;
2324import org .elasticsearch .common .io .stream .StreamOutput ;
2425import org .elasticsearch .common .io .stream .Writeable ;
26+ import org .elasticsearch .common .xcontent .ConstructingObjectParser ;
27+ import org .elasticsearch .common .xcontent .ToXContent ;
28+ import org .elasticsearch .common .xcontent .XContentBuilder ;
29+ import org .elasticsearch .common .xcontent .XContentParser ;
2530
2631import java .io .IOException ;
27- import java .util .Arrays ;
28- import java .util .Locale ;
2932import java .util .Objects ;
3033
3134/**
3437 * otherwise merge away operations that have been soft deleted). Each retention lease contains a unique identifier, the retaining sequence
3538 * number, the timestamp of when the lease was created or renewed, and the source of the retention lease (e.g., "ccr").
3639 */
37- public final class RetentionLease implements Writeable {
40+ public final class RetentionLease implements ToXContent , Writeable {
3841
3942 private final String id ;
4043
@@ -94,10 +97,6 @@ public RetentionLease(final String id, final long retainingSequenceNumber, final
9497 if (id .isEmpty ()) {
9598 throw new IllegalArgumentException ("retention lease ID can not be empty" );
9699 }
97- if (id .contains (":" ) || id .contains (";" ) || id .contains ("," )) {
98- // retention lease IDs can not contain these characters because they are used in encoding retention leases
99- throw new IllegalArgumentException ("retention lease ID can not contain any of [:;,] but was [" + id + "]" );
100- }
101100 if (retainingSequenceNumber < 0 ) {
102101 throw new IllegalArgumentException ("retention lease retaining sequence number [" + retainingSequenceNumber + "] out of range" );
103102 }
@@ -108,10 +107,6 @@ public RetentionLease(final String id, final long retainingSequenceNumber, final
108107 if (source .isEmpty ()) {
109108 throw new IllegalArgumentException ("retention lease source can not be empty" );
110109 }
111- if (source .contains (":" ) || source .contains (";" ) || source .contains ("," )) {
112- // retention lease sources can not contain these characters because they are used in encoding retention leases
113- throw new IllegalArgumentException ("retention lease source can not contain any of [:;,] but was [" + source + "]" );
114- }
115110 this .id = id ;
116111 this .retainingSequenceNumber = retainingSequenceNumber ;
117112 this .timestamp = timestamp ;
@@ -145,43 +140,49 @@ public void writeTo(final StreamOutput out) throws IOException {
145140 out .writeString (source );
146141 }
147142
148- /**
149- * Encodes a retention lease as a string. This encoding can be decoded by {@link #decodeRetentionLease(String)}. The retention lease is
150- * encoded in the format <code>id:{id};retaining_seq_no:{retainingSequenecNumber};timestamp:{timestamp};source:{source}</code>.
151- *
152- * @param retentionLease the retention lease
153- * @return the encoding of the retention lease
154- */
155- static String encodeRetentionLease (final RetentionLease retentionLease ) {
156- Objects .requireNonNull (retentionLease );
157- return String .format (
158- Locale .ROOT ,
159- "id:%s;retaining_seq_no:%d;timestamp:%d;source:%s" ,
160- retentionLease .id ,
161- retentionLease .retainingSequenceNumber ,
162- retentionLease .timestamp ,
163- retentionLease .source );
143+ private static final ParseField ID_FIELD = new ParseField ("id" );
144+ private static final ParseField RETAINING_SEQUENCE_NUMBER_FIELD = new ParseField ("retaining_sequence_number" );
145+ private static final ParseField TIMESTAMP_FIELD = new ParseField ("timestamp" );
146+ private static final ParseField SOURCE_FIELD = new ParseField ("source" );
147+
148+ private static ConstructingObjectParser <RetentionLease , Void > PARSER = new ConstructingObjectParser <>(
149+ "retention_leases" ,
150+ (a ) -> new RetentionLease ((String ) a [0 ], (Long ) a [1 ], (Long ) a [2 ], (String ) a [3 ]));
151+
152+ static {
153+ PARSER .declareString (ConstructingObjectParser .constructorArg (), ID_FIELD );
154+ PARSER .declareLong (ConstructingObjectParser .constructorArg (), RETAINING_SEQUENCE_NUMBER_FIELD );
155+ PARSER .declareLong (ConstructingObjectParser .constructorArg (), TIMESTAMP_FIELD );
156+ PARSER .declareString (ConstructingObjectParser .constructorArg (), SOURCE_FIELD );
157+ }
158+
159+ @ Override
160+ public XContentBuilder toXContent (final XContentBuilder builder , final Params params ) throws IOException {
161+ builder .startObject ();
162+ {
163+ builder .field (ID_FIELD .getPreferredName (), id );
164+ builder .field (RETAINING_SEQUENCE_NUMBER_FIELD .getPreferredName (), retainingSequenceNumber );
165+ builder .field (TIMESTAMP_FIELD .getPreferredName (), timestamp );
166+ builder .field (SOURCE_FIELD .getPreferredName (), source );
167+ }
168+ builder .endObject ();
169+ return builder ;
170+ }
171+
172+ @ Override
173+ public boolean isFragment () {
174+ return false ;
164175 }
165176
166177 /**
167- * Decodes a retention lease encoded by {@link #encodeRetentionLease(RetentionLease)}.
178+ * Parses a retention lease from {@link org.elasticsearch.common.xcontent.XContent}. This method assumes that the retention lease was
179+ * converted to {@link org.elasticsearch.common.xcontent.XContent} via {@link #toXContent(XContentBuilder, Params)}.
168180 *
169- * @param encodedRetentionLease an encoded retention lease
170- * @return the decoded retention lease
181+ * @param parser the parser
182+ * @return a retention lease
171183 */
172- static RetentionLease decodeRetentionLease (final String encodedRetentionLease ) {
173- Objects .requireNonNull (encodedRetentionLease );
174- final String [] fields = encodedRetentionLease .split (";" );
175- assert fields .length == 4 : Arrays .toString (fields );
176- assert fields [0 ].matches ("id:[^:;,]+" ) : fields [0 ];
177- final String id = fields [0 ].substring ("id:" .length ());
178- assert fields [1 ].matches ("retaining_seq_no:\\ d+" ) : fields [1 ];
179- final long retainingSequenceNumber = Long .parseLong (fields [1 ].substring ("retaining_seq_no:" .length ()));
180- assert fields [2 ].matches ("timestamp:\\ d+" ) : fields [2 ];
181- final long timestamp = Long .parseLong (fields [2 ].substring ("timestamp:" .length ()));
182- assert fields [3 ].matches ("source:[^:;,]+" ) : fields [3 ];
183- final String source = fields [3 ].substring ("source:" .length ());
184- return new RetentionLease (id , retainingSequenceNumber , timestamp , source );
184+ public static RetentionLease fromXContent (final XContentParser parser ) {
185+ return PARSER .apply (parser , null );
185186 }
186187
187188 @ Override
0 commit comments