001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * docs/licenses/cddl.txt.  If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 *      Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 *      Copyright 2010-2021 Ping Identity Corporation
026 */
027package com.unboundid.directory.sdk.sync.types;
028
029import java.io.Serializable;
030import java.util.Date;
031
032/**
033 * Used to identify how to set the starting point for synchronization (beginning
034 * of changelog, end of changelog, based on a change sequence number, etc).
035 * Different startpoint types require different supporting values; for example
036 * if the type is RESUME_AT_CHANGE_NUMBER, the value must be a <code>long</code>
037 * that represents a change number to start at. Some of the startpoint types
038 * require a server name to be specified as well.
039 * <p>
040 * These objects will be constructed by the <code>realtime-sync</code> CLI and
041 * passed down into the SetStartpointTask, which will then delegate to the
042 * specific Sync Pipe and finally the Sync Source implementation for that pipe.
043 * Not all Sync Source implementations will support all the startpoint types. If
044 * an unsupported type is specified, the underlying implementation is free to
045 * throw a {@link RuntimeException} stating that the startpoint type is
046 * unsupported.
047 */
048public final class SetStartpointOptions
049{
050
051  /**
052   * The possible startpoint types.
053   */
054  public enum StartpointType
055  {
056    /**
057     * Set the startpoint to a specific change sequence number in the change
058     * log.
059     * Note: This type is specific to directory servers.
060     */
061    RESUME_AT_CSN,
062    /**
063     * Set the startpoint to a specific change number in the change log.
064     */
065    RESUME_AT_CHANGE_NUMBER,
066    /**
067     * Set the startpoint to a specific time in the past.
068     */
069    RESUME_AT_CHANGE_TIME,
070    /**
071     * Set the startpoint using a user-defined Serializable object.
072     */
073    RESUME_AT_SERIALIZABLE,
074    /**
075     * Set the startpoint to the very beginning of the change log.
076     */
077    BEGINNING_OF_CHANGELOG,
078    /**
079     * Set the startpoint to the very end of the change log.
080     */
081    END_OF_CHANGELOG;
082  }
083
084  // the startpoint type
085  private final StartpointType startpointType;
086
087  // the possible startpoint values
088  private String csnValue;
089  private long changeNumber;
090  private Date changeTime;
091  private Serializable serializableValue;
092
093  // the external server name, if one is required (change number, and change
094  // time)
095  private String serverName;
096
097  /**
098   * Constructor.
099   * @param startpointType
100   *          indicates the startpoint type (beginning of changelog, change
101   *          time, etc)
102   */
103  private SetStartpointOptions(final StartpointType startpointType)
104  {
105    if(startpointType == null)
106    {
107      throw new NullPointerException(
108              "The startpointType parameter cannot be null.");
109    }
110    this.startpointType = startpointType;
111  }
112
113  /**
114   * Creates a SetStartpointOptions instance with the
115   * <code>BEGINNING_OF_CHANGELOG</code> startpoint type.
116   * @return a immutable instance of this class with only the startpoint type
117   *         populated
118   */
119  public static SetStartpointOptions createBeginningOfChangelogOptions()
120  {
121    SetStartpointOptions options =
122            new SetStartpointOptions(StartpointType.BEGINNING_OF_CHANGELOG);
123    return options;
124  }
125
126  /**
127   * Creates a SetStartpointOptions instance with the
128   * <code>END_OF_CHANGELOG</code> startpoint type.
129   * @return a immutable instance of this class with only the startpoint type
130   *         populated
131   */
132  public static SetStartpointOptions createEndOfChangelogOptions()
133  {
134    SetStartpointOptions options =
135            new SetStartpointOptions(StartpointType.END_OF_CHANGELOG);
136    return options;
137  }
138
139  /**
140   * Creates a SetStartpointOptions instance with the <code>RESUME_AT_CSN</code>
141   * startpoint type.
142   * @param csn
143   *          the change sequence number of the first change to synchronize
144   * @return a immutable instance of this class with the CSN value populated
145   */
146  public static SetStartpointOptions createResumeAtCSNOptions(final String csn)
147  {
148    if(csn == null)
149    {
150      throw new NullPointerException("The CSN parameter cannot be null");
151    }
152    SetStartpointOptions options =
153            new SetStartpointOptions(StartpointType.RESUME_AT_CSN);
154    options.csnValue = csn;
155    return options;
156  }
157
158  /**
159   * Creates a SetStartpointOptions instance with the
160   * <code>RESUME_AT_CHANGE_NUMBER</code> startpoint type.
161   * @param changeNumber
162   *          the change number of the first change to synchronize
163   * @param serverName
164   *          the name of the External Server to which the change number
165   *          applies. The CLI
166   *          requires this parameter to be non-null, because a given change
167   *          number may
168   *          correspond to different changes on different replicas.
169   * @return a immutable instance of this class with the change number and
170   *         server name populated
171   */
172  public static SetStartpointOptions createResumeAtChangeNumberOptions(
173          final long changeNumber, final String serverName)
174  {
175    if(serverName == null)
176    {
177      throw new NullPointerException("The serverName parameter cannot be null");
178    }
179    SetStartpointOptions options =
180            new SetStartpointOptions(StartpointType.RESUME_AT_CHANGE_NUMBER);
181    options.changeNumber = changeNumber;
182    options.serverName = serverName;
183    return options;
184  }
185
186  /**
187   * Creates a SetStartpointOptions instance with the
188   * <code>RESUME_AT_CHANGE_TIME</code> startpoint type. Changes
189   * made prior to the specified change time will be ignored.
190   * @param changeTime
191   *          the cut-off time at which synchronization will resume
192   * @param serverName
193   *          the name of the External Server to which the change time applies.
194   *          The CLI allows
195   *          this parameter to be null, but some underlying sync source
196   *          implementations
197   *          may require it (such as DSEESyncSource).
198   * @return a immutable instance of this class with the change time and server
199   *         name populated
200   */
201  public static SetStartpointOptions createResumeAtChangeTimeOptions(
202          final Date changeTime, final String serverName)
203  {
204    if(changeTime == null)
205    {
206      throw new NullPointerException("The changeTime parameter cannot be null");
207    }
208    SetStartpointOptions options =
209            new SetStartpointOptions(StartpointType.RESUME_AT_CHANGE_TIME);
210    options.changeTime = changeTime;
211    options.serverName = serverName;
212    return options;
213  }
214
215  /**
216   * Creates a SetStartpointOptions instance with the
217   * <code>RESUME_AT_SERIALIZABLE</code> startpoint type. Changes made prior to
218   * the specified state will be ignored.
219   * @param startpointValue
220   *          a Serializable object which can be passed to the sync source as a
221   *          valid
222   *          indicator of where to start synchronization
223   * @return a immutable instance of this class with the generic startpoint
224   *         value populated
225   */
226  public static SetStartpointOptions createResumeAtSerializableOptions(
227          final Serializable startpointValue)
228  {
229    SetStartpointOptions options =
230            new SetStartpointOptions(StartpointType.RESUME_AT_SERIALIZABLE);
231    options.serializableValue = startpointValue;
232    return options;
233  }
234
235  /**
236   * Gets the startpointType (i.e. RESUME_AT_CHANGE_NUMBER, END_OF_CHANGELOG,
237   * etc)
238   * @return a {@link StartpointType} instance
239   */
240  public StartpointType getStartpointType()
241  {
242    return this.startpointType;
243  }
244
245  /**
246   * Gets the CSN value if one was specified.
247   * @return a change sequence number, or null if the startpoint type is not
248   *         <code>RESUME_AT_CSN</code>
249   */
250  public String getCSN()
251  {
252    return this.csnValue;
253  }
254
255  /**
256   * Gets the change number value if one was specified.
257   * @return a change number, or null if the startpoint type is not
258   *         <code>RESUME_AT_CHANGE_NUMBER</code>
259   */
260  public long getChangeNumber()
261  {
262    return this.changeNumber;
263  }
264
265  /**
266   * Gets the change time value if one was specified.
267   * @return a {@link Date}, or null if the startpoint type is not
268   *         <code>RESUME_AT_CHANGE_TIME</code>
269   */
270  public Date getChangeTime()
271  {
272    return this.changeTime;
273  }
274
275  /**
276   * Gets the generic (serializable) startpoint value if one was specified.
277   * @return a {@link Serializable} instance, or null if the startpoint type is
278   *         not <code>RESUME_AT_SERIALIZABLE</code>
279   */
280  public Serializable getSerializableValue()
281  {
282    return this.serializableValue;
283  }
284
285  /**
286   * Gets the server name if one was specified, representing the External Server
287   * at which to
288   * set the start point.
289   * @return an External Server name, or null if one was not specified
290   */
291  public String getServerName()
292  {
293    return this.serverName;
294  }
295}