001/*
002 * Copyright 2013-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.unboundidds.tasks;
022
023
024
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Collections;
028import java.util.Date;
029import java.util.LinkedHashMap;
030import java.util.List;
031import java.util.Map;
032
033import com.unboundid.ldap.sdk.Attribute;
034import com.unboundid.ldap.sdk.Entry;
035import com.unboundid.util.NotMutable;
036import com.unboundid.util.ThreadSafety;
037import com.unboundid.util.ThreadSafetyLevel;
038import com.unboundid.util.Validator;
039
040import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
041
042
043
044/**
045 * This class defines a Directory Server task that can be used to cause entries
046 * contained in a local DB backend to be re-encoded, which may be used to
047 * apply any configuration changes that affect the encoding of that entry (e.g.,
048 * if the entry should be encrypted, hashed, compressed, or fully or partially
049 * uncached; or if these settings should be reverted).
050 * <BR>
051 * <BLOCKQUOTE>
052 *   <B>NOTE:</B>  This class, and other classes within the
053 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
054 *   supported for use against Ping Identity, UnboundID, and
055 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
056 *   for proprietary functionality or for external specifications that are not
057 *   considered stable or mature enough to be guaranteed to work in an
058 *   interoperable way with other types of LDAP servers.
059 * </BLOCKQUOTE>
060 * <BR>
061 * The properties that are available for use with this type of task include:
062 * <UL>
063 *   <LI>The backend ID of the backend in which entries should be re-encoded.
064 *       This must be provided.</LI>
065 *   <LI>The base DN of a branch of entries to include in the re-encode
066 *       processing.</LI>
067 *   <LI>The base DN of a branch of entries to exclude from the re-encode
068 *       processing.</LI>
069 *   <LI>A filter to use to identify entries to include in the re-encode
070 *       processing.</LI>
071 *   <LI>A filter to use to identify entries to exclude from the re-encode
072 *       processing.</LI>
073 *   <LI>The maximum rate at which to re-encode entries, in number of entries
074 *       per second.</LI>
075 *   <LI>An indication as to whether to skip entries that are fully
076 *       uncached.</LI>
077 *   <LI>An indication as to whether to skip entries that are partially
078 *       uncached.</LI>
079 * </UL>
080 */
081@NotMutable()
082@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
083public final class ReEncodeEntriesTask
084       extends Task
085{
086  /**
087   * The fully-qualified name of the Java class that is used for the re-encode
088   * entries task.
089   */
090  static final String RE_ENCODE_ENTRIES_TASK_CLASS =
091       "com.unboundid.directory.server.tasks.ReEncodeEntriesTask";
092
093
094  /**
095   * The name of the attribute used to specify the backend ID containing the
096   * entries to re-encode.
097   */
098  private static final String ATTR_BACKEND_ID = "ds-task-reencode-backend-id";
099
100
101  /**
102   * The name of the attribute used to specify the include branch(es).
103   */
104  private static final String ATTR_INCLUDE_BRANCH =
105       "ds-task-reencode-include-branch";
106
107
108  /**
109   * The name of the attribute used to specify the exclude branch(es).
110   */
111  private static final String ATTR_EXCLUDE_BRANCH =
112       "ds-task-reencode-exclude-branch";
113
114
115  /**
116   * The name of the attribute used to specify the include filter(s).
117   */
118  private static final String ATTR_INCLUDE_FILTER =
119       "ds-task-reencode-include-filter";
120
121
122  /**
123   * The name of the attribute used to specify the exclude filter(s).
124   */
125  private static final String ATTR_EXCLUDE_FILTER =
126       "ds-task-reencode-exclude-filter";
127
128
129  /**
130   * The name of the attribute used to specify the maximum re-encode rate in
131   * entries per second.
132   */
133  private static final String ATTR_MAX_ENTRIES_PER_SECOND =
134       "ds-task-reencode-max-entries-per-second";
135
136
137  /**
138   * The name of the attribute used to specify whether to skip fully uncached
139   * entries.
140   */
141  private static final String ATTR_SKIP_FULLY_UNCACHED =
142       "ds-task-reencode-skip-fully-uncached-entries";
143
144
145  /**
146   * The name of the attribute used to specify whether to skip partially
147   * uncached entries.
148   */
149  private static final String ATTR_SKIP_PARTIALLY_UNCACHED =
150       "ds-task-reencode-skip-partially-uncached-entries";
151
152
153  /**
154   * The name of the object class used in re-encode entries task entries.
155   */
156  private static final String OC_REENCODE_ENTRIES_TASK =
157       "ds-task-reencode";
158
159
160  /**
161   * The task property that will be used for the backend ID.
162   */
163  static final TaskProperty PROPERTY_BACKEND_ID =
164       new TaskProperty(ATTR_BACKEND_ID,
165            INFO_DISPLAY_NAME_REENCODE_BACKEND_ID.get(),
166            INFO_DESCRIPTION_REENCODE_BACKEND_ID.get(),
167          String.class, true, false, false);
168
169
170
171  /**
172   * The task property that will be used for the include branch(es).
173   */
174  private static final TaskProperty PROPERTY_INCLUDE_BRANCH =
175     new TaskProperty(ATTR_INCLUDE_BRANCH,
176          INFO_DISPLAY_NAME_REENCODE_INCLUDE_BRANCH.get(),
177          INFO_DESCRIPTION_REENCODE_INCLUDE_BRANCH.get(),
178          String.class, false, true, false);
179
180
181
182  /**
183   * The task property that will be used for the exclude branch(es).
184   */
185  private static final TaskProperty PROPERTY_EXCLUDE_BRANCH =
186     new TaskProperty(ATTR_EXCLUDE_BRANCH,
187          INFO_DISPLAY_NAME_REENCODE_EXCLUDE_BRANCH.get(),
188          INFO_DESCRIPTION_REENCODE_EXCLUDE_BRANCH.get(),
189          String.class, false, true, false);
190
191
192
193  /**
194   * The task property that will be used for the include filter(s).
195   */
196  private static final TaskProperty PROPERTY_INCLUDE_FILTER =
197     new TaskProperty(ATTR_INCLUDE_FILTER,
198          INFO_DISPLAY_NAME_REENCODE_INCLUDE_FILTER.get(),
199          INFO_DESCRIPTION_REENCODE_INCLUDE_FILTER.get(),
200          String.class, false, true, false);
201
202
203
204  /**
205   * The task property that will be used for the exclude filter(s).
206   */
207  private static final TaskProperty PROPERTY_EXCLUDE_FILTER =
208     new TaskProperty(ATTR_EXCLUDE_FILTER,
209          INFO_DISPLAY_NAME_REENCODE_EXCLUDE_FILTER.get(),
210          INFO_DESCRIPTION_REENCODE_EXCLUDE_FILTER.get(),
211          String.class, false, true, false);
212
213
214
215  /**
216   * The task property that will be used for the maximum reencode rate.
217   */
218  private static final TaskProperty PROPERTY_MAX_ENTRIES_PER_SECOND =
219     new TaskProperty(ATTR_MAX_ENTRIES_PER_SECOND,
220          INFO_DISPLAY_NAME_REENCODE_MAX_ENTRIES_PER_SECOND.get(),
221          INFO_DESCRIPTION_REENCODE_MAX_ENTRIES_PER_SECOND.get(),
222          Long.class, false, false, false);
223
224
225
226  /**
227   * The task property that will be used to indicate whether to skip fully
228   * uncached entries.
229   */
230  private static final TaskProperty PROPERTY_SKIP_FULLY_UNCACHED =
231     new TaskProperty(ATTR_SKIP_FULLY_UNCACHED,
232          INFO_DISPLAY_NAME_REENCODE_SKIP_FULLY_UNCACHED.get(),
233          INFO_DESCRIPTION_REENCODE_SKIP_FULLY_UNCACHED.get(),
234          Boolean.class, false, false, false);
235
236
237
238  /**
239   * The task property that will be used to indicate whether to skip partially
240   * uncached entries.
241   */
242  private static final TaskProperty PROPERTY_SKIP_PARTIALLY_UNCACHED =
243     new TaskProperty(ATTR_SKIP_PARTIALLY_UNCACHED,
244          INFO_DISPLAY_NAME_REENCODE_SKIP_PARTIALLY_UNCACHED.get(),
245          INFO_DESCRIPTION_REENCODE_SKIP_PARTIALLY_UNCACHED.get(),
246          Boolean.class, false, false, false);
247
248
249
250  /**
251   * The serial version UID for this serializable class.
252   */
253  private static final long serialVersionUID = 1804218099237094046L;
254
255
256
257  // Indicates whether to skip fully-uncached entries.
258  private final boolean skipFullyUncachedEntries;
259
260  // Indicates whether to skip partially-uncached entries.
261  private final boolean skipPartiallyUncachedEntries;
262
263  // The maximum number of entries to re-encode per second.
264  private final Long maxEntriesPerSecond;
265
266  // The list of exclude branch DNs.
267  private final List<String> excludeBranches;
268
269  // The list of exclude filters.
270  private final List<String> excludeFilters;
271
272  // The list of include branch DNs.
273  private final List<String> includeBranches;
274
275  // The list of include filters.
276  private final List<String> includeFilters;
277
278  // The backend ID for the backend containing entries to re-encode.
279  private final String backendID;
280
281
282
283  /**
284   * Creates a new uninitialized re-encode entries task instance which should
285   * only be used for obtaining general information about this task, including
286   * the task name, description, and supported properties.  Attempts to use a
287   * task created with this constructor for any other reason will likely fail.
288   */
289  public ReEncodeEntriesTask()
290  {
291    skipFullyUncachedEntries     = false;
292    skipPartiallyUncachedEntries = false;
293    maxEntriesPerSecond          = null;
294    excludeBranches              = null;
295    excludeFilters               = null;
296    includeBranches              = null;
297    includeFilters               = null;
298    backendID                    = null;
299  }
300
301
302
303  /**
304   * Creates a new re-encode entries task with the provided information.
305   *
306   * @param  taskID                        The task ID to use for this task.  If
307   *                                       it is {@code null} then a UUID will
308   *                                       be generated for use as the task ID.
309   * @param  backendID                     The backend ID of the backend
310   *                                       containing the entries to re-encode.
311   *                                       It must not be {@code null}.
312   * @param  includeBranches               A list containing the base DNs of
313   *                                       branches to include in re-encode
314   *                                       processing.  It may be {@code null}
315   *                                       or empty if there should not be any
316   *                                       include branches.
317   * @param  excludeBranches               A list containing the base DNs of
318   *                                       branches to exclude from re-encode
319   *                                       processing.  It may be {@code null}
320   *                                       or empty if there should not be any
321   *                                       exclude branches.
322   * @param  includeFilters                A list containing filters to use to
323   *                                       identify entries to include in
324   *                                       re-encode processing.  It may be
325   *                                       {@code null} or empty if there should
326   *                                       not be any include filters.
327   * @param  excludeFilters                A list containing filters to use to
328   *                                       identify entries to exclude from
329   *                                       re-encode processing.  It may be
330   *                                       {@code null} or empty if there should
331   *                                       not be any exclude filters.
332   * @param  maxEntriesPerSecond           The maximum number of entries to
333   *                                       re-encode per second.  It may be
334   *                                       {@code null} to indicate that no
335   *                                       limit should be imposed.
336   * @param  skipFullyUncachedEntries      Indicates whether to skip re-encode
337   *                                       processing for entries that are fully
338   *                                       uncached.
339   * @param  skipPartiallyUncachedEntries  Indicates whether to skip re-encode
340   *                                       processing for entries that contain
341   *                                       a mix of cached and uncached
342   *                                       attributes.
343   */
344  public ReEncodeEntriesTask(final String taskID,
345                             final String backendID,
346                             final List<String> includeBranches,
347                             final List<String> excludeBranches,
348                             final List<String> includeFilters,
349                             final List<String> excludeFilters,
350                             final Long maxEntriesPerSecond,
351                             final boolean skipFullyUncachedEntries,
352                             final boolean skipPartiallyUncachedEntries)
353  {
354    this(taskID, backendID, includeBranches, excludeBranches, includeFilters,
355         excludeFilters, maxEntriesPerSecond, skipFullyUncachedEntries,
356         skipPartiallyUncachedEntries, null, null, null, null, null);
357  }
358
359
360
361  /**
362   * Creates a new re-encode entries task with the provided information.
363   *
364   * @param  taskID                        The task ID to use for this task.  If
365   *                                       it is {@code null} then a UUID will
366   *                                       be generated for use as the task ID.
367   * @param  backendID                     The backend ID of the backend
368   *                                       containing the entries to re-encode.
369   *                                       It must not be {@code null}.
370   * @param  includeBranches               A list containing the base DNs of
371   *                                       branches to include in re-encode
372   *                                       processing.  It may be {@code null}
373   *                                       or empty if there should not be any
374   *                                       include branches.
375   * @param  excludeBranches               A list containing the base DNs of
376   *                                       branches to exclude from re-encode
377   *                                       processing.  It may be {@code null}
378   *                                       or empty if there should not be any
379   *                                       exclude branches.
380   * @param  includeFilters                A list containing filters to use to
381   *                                       identify entries to include in
382   *                                       re-encode processing.  It may be
383   *                                       {@code null} or empty if there should
384   *                                       not be any include filters.
385   * @param  excludeFilters                A list containing filters to use to
386   *                                       identify entries to exclude from
387   *                                       re-encode processing.  It may be
388   *                                       {@code null} or empty if there should
389   *                                       not be any exclude filters.
390   * @param  maxEntriesPerSecond           The maximum number of entries to
391   *                                       re-encode per second.  It may be
392   *                                       {@code null} to indicate that no
393   *                                       limit should be imposed.
394   * @param  skipFullyUncachedEntries      Indicates whether to skip re-encode
395   *                                       processing for entries that are fully
396   *                                       uncached.
397   * @param  skipPartiallyUncachedEntries  Indicates whether to skip re-encode
398   *                                       processing for entries that contain
399   *                                       a mix of cached and uncached
400   *                                       attributes.
401   * @param  scheduledStartTime            The time that this task should start
402   *                                       running.
403   * @param  dependencyIDs                 The list of task IDs that will be
404   *                                       required to complete before this task
405   *                                       will be eligible to start.
406   * @param  failedDependencyAction        Indicates what action should be taken
407   *                                       if any of the dependencies for this
408   *                                       task do not complete successfully.
409   * @param  notifyOnCompletion            The list of e-mail addresses of
410   *                                       individuals that should be notified
411   *                                       when this task completes.
412   * @param  notifyOnError                 The list of e-mail addresses of
413   *                                       individuals that should be notified
414   *                                       if this task does not complete
415   *                                       successfully.
416   */
417  public ReEncodeEntriesTask(final String taskID, final String backendID,
418              final List<String> includeBranches,
419              final List<String> excludeBranches,
420              final List<String> includeFilters,
421              final List<String> excludeFilters,
422              final Long maxEntriesPerSecond,
423              final boolean skipFullyUncachedEntries,
424              final boolean skipPartiallyUncachedEntries,
425              final Date scheduledStartTime,
426              final List<String> dependencyIDs,
427              final FailedDependencyAction failedDependencyAction,
428              final List<String> notifyOnCompletion,
429              final List<String> notifyOnError)
430  {
431    this(taskID, backendID, includeBranches, excludeBranches, includeFilters,
432         excludeFilters, maxEntriesPerSecond, skipFullyUncachedEntries,
433         skipPartiallyUncachedEntries, scheduledStartTime, dependencyIDs,
434         failedDependencyAction, null, notifyOnCompletion, null,
435         notifyOnError, null, null, null);
436  }
437
438
439
440  /**
441   * Creates a new re-encode entries task with the provided information.
442   *
443   * @param  taskID                        The task ID to use for this task.  If
444   *                                       it is {@code null} then a UUID will
445   *                                       be generated for use as the task ID.
446   * @param  backendID                     The backend ID of the backend
447   *                                       containing the entries to re-encode.
448   *                                       It must not be {@code null}.
449   * @param  includeBranches               A list containing the base DNs of
450   *                                       branches to include in re-encode
451   *                                       processing.  It may be {@code null}
452   *                                       or empty if there should not be any
453   *                                       include branches.
454   * @param  excludeBranches               A list containing the base DNs of
455   *                                       branches to exclude from re-encode
456   *                                       processing.  It may be {@code null}
457   *                                       or empty if there should not be any
458   *                                       exclude branches.
459   * @param  includeFilters                A list containing filters to use to
460   *                                       identify entries to include in
461   *                                       re-encode processing.  It may be
462   *                                       {@code null} or empty if there should
463   *                                       not be any include filters.
464   * @param  excludeFilters                A list containing filters to use to
465   *                                       identify entries to exclude from
466   *                                       re-encode processing.  It may be
467   *                                       {@code null} or empty if there should
468   *                                       not be any exclude filters.
469   * @param  maxEntriesPerSecond           The maximum number of entries to
470   *                                       re-encode per second.  It may be
471   *                                       {@code null} to indicate that no
472   *                                       limit should be imposed.
473   * @param  skipFullyUncachedEntries      Indicates whether to skip re-encode
474   *                                       processing for entries that are fully
475   *                                       uncached.
476   * @param  skipPartiallyUncachedEntries  Indicates whether to skip re-encode
477   *                                       processing for entries that contain
478   *                                       a mix of cached and uncached
479   *                                       attributes.
480   * @param  scheduledStartTime            The time that this task should start
481   *                                       running.
482   * @param  dependencyIDs                 The list of task IDs that will be
483   *                                       required to complete before this task
484   *                                       will be eligible to start.
485   * @param  failedDependencyAction        Indicates what action should be taken
486   *                                       if any of the dependencies for this
487   *                                       task do not complete successfully.
488   * @param  notifyOnStart                 The list of e-mail addresses of
489   *                                       individuals that should be notified
490   *                                       when this task starts running.
491   * @param  notifyOnCompletion            The list of e-mail addresses of
492   *                                       individuals that should be notified
493   *                                       when this task completes.
494   * @param  notifyOnSuccess               The list of e-mail addresses of
495   *                                       individuals that should be notified
496   *                                       if this task completes successfully.
497   * @param  notifyOnError                 The list of e-mail addresses of
498   *                                       individuals that should be notified
499   *                                       if this task does not complete
500   *                                       successfully.
501   * @param  alertOnStart                  Indicates whether the server should
502   *                                       send an alert notification when this
503   *                                       task starts.
504   * @param  alertOnSuccess                Indicates whether the server should
505   *                                       send an alert notification if this
506   *                                       task completes successfully.
507   * @param  alertOnError                  Indicates whether the server should
508   *                                       send an alert notification if this
509   *                                       task fails to complete successfully.
510   */
511  public ReEncodeEntriesTask(final String taskID, final String backendID,
512              final List<String> includeBranches,
513              final List<String> excludeBranches,
514              final List<String> includeFilters,
515              final List<String> excludeFilters,
516              final Long maxEntriesPerSecond,
517              final boolean skipFullyUncachedEntries,
518              final boolean skipPartiallyUncachedEntries,
519              final Date scheduledStartTime,
520              final List<String> dependencyIDs,
521              final FailedDependencyAction failedDependencyAction,
522              final List<String> notifyOnStart,
523              final List<String> notifyOnCompletion,
524              final List<String> notifyOnSuccess,
525              final List<String> notifyOnError, final Boolean alertOnStart,
526              final Boolean alertOnSuccess, final Boolean alertOnError)
527  {
528    super(taskID, RE_ENCODE_ENTRIES_TASK_CLASS, scheduledStartTime,
529         dependencyIDs, failedDependencyAction, notifyOnStart,
530         notifyOnCompletion, notifyOnSuccess, notifyOnError, alertOnStart,
531         alertOnSuccess, alertOnError);
532
533    Validator.ensureNotNull(backendID);
534
535    this.backendID                    = backendID;
536    this.maxEntriesPerSecond          = maxEntriesPerSecond;
537    this.skipFullyUncachedEntries     = skipFullyUncachedEntries;
538    this.skipPartiallyUncachedEntries = skipPartiallyUncachedEntries;
539
540    if ((includeBranches == null) || includeBranches.isEmpty())
541    {
542      this.includeBranches = Collections.emptyList();
543    }
544    else
545    {
546      this.includeBranches = Collections.unmodifiableList(includeBranches);
547    }
548
549    if ((excludeBranches == null) || excludeBranches.isEmpty())
550    {
551      this.excludeBranches = Collections.emptyList();
552    }
553    else
554    {
555      this.excludeBranches = Collections.unmodifiableList(excludeBranches);
556    }
557
558    if ((includeFilters == null) || includeFilters.isEmpty())
559    {
560      this.includeFilters = Collections.emptyList();
561    }
562    else
563    {
564      this.includeFilters = Collections.unmodifiableList(includeFilters);
565    }
566
567    if ((excludeFilters == null) || excludeFilters.isEmpty())
568    {
569      this.excludeFilters = Collections.emptyList();
570    }
571    else
572    {
573      this.excludeFilters = Collections.unmodifiableList(excludeFilters);
574    }
575  }
576
577
578
579  /**
580   * Creates a new re-encode entries task from the provided entry.
581   *
582   * @param  entry  The entry to use to create this re-encode entries task.
583   *
584   * @throws  TaskException  If the provided entry cannot be parsed as a
585   *                         re-encode entries task entry.
586   */
587  public ReEncodeEntriesTask(final Entry entry)
588         throws TaskException
589  {
590    super(entry);
591
592
593    // Get the backend ID.  It must be present.
594    backendID = entry.getAttributeValue(ATTR_BACKEND_ID);
595    if (backendID == null)
596    {
597      throw new TaskException(ERR_REENCODE_TASK_MISSING_REQUIRED_ATTR.get(
598           entry.getDN(), ATTR_BACKEND_ID));
599    }
600
601    // Get the set of include branches.
602    final String[] iBranches = entry.getAttributeValues(ATTR_INCLUDE_BRANCH);
603    if (iBranches == null)
604    {
605      includeBranches = Collections.emptyList();
606    }
607    else
608    {
609      includeBranches = Collections.unmodifiableList(Arrays.asList(iBranches));
610    }
611
612    // Get the set of exclude branches.
613    final String[] eBranches = entry.getAttributeValues(ATTR_EXCLUDE_BRANCH);
614    if (eBranches == null)
615    {
616      excludeBranches = Collections.emptyList();
617    }
618    else
619    {
620      excludeBranches = Collections.unmodifiableList(Arrays.asList(eBranches));
621    }
622
623    // Get the set of include filters.
624    final String[] iFilters = entry.getAttributeValues(ATTR_INCLUDE_FILTER);
625    if (iFilters == null)
626    {
627      includeFilters = Collections.emptyList();
628    }
629    else
630    {
631      includeFilters = Collections.unmodifiableList(Arrays.asList(iFilters));
632    }
633
634    // Get the set of exclude filters.
635    final String[] eFilters = entry.getAttributeValues(ATTR_EXCLUDE_FILTER);
636    if (eFilters == null)
637    {
638      excludeFilters = Collections.emptyList();
639    }
640    else
641    {
642      excludeFilters = Collections.unmodifiableList(Arrays.asList(eFilters));
643    }
644
645    // Get the max entry rate.
646    maxEntriesPerSecond =
647         entry.getAttributeValueAsLong(ATTR_MAX_ENTRIES_PER_SECOND);
648
649    // Determine whether to skip fully uncached entries.
650    final Boolean skipFullyUncached =
651         entry.getAttributeValueAsBoolean(ATTR_SKIP_FULLY_UNCACHED);
652    if (skipFullyUncached == null)
653    {
654      skipFullyUncachedEntries = false;
655    }
656    else
657    {
658      skipFullyUncachedEntries = skipFullyUncached;
659    }
660
661    // Determine whether to skip partially uncached entries.
662    final Boolean skipPartiallyUncached =
663         entry.getAttributeValueAsBoolean(ATTR_SKIP_PARTIALLY_UNCACHED);
664    if (skipPartiallyUncached == null)
665    {
666      skipPartiallyUncachedEntries = false;
667    }
668    else
669    {
670      skipPartiallyUncachedEntries = skipPartiallyUncached;
671    }
672  }
673
674
675
676  /**
677   * Creates a new re-encode entries task from the provided set of task
678   * properties.
679   *
680   * @param  properties  The set of task properties and their corresponding
681   *                     values to use for the task.  It must not be
682   *                     {@code null}.
683   *
684   * @throws  TaskException  If the provided set of properties cannot be used to
685   *                         create a valid re-encode entries task.
686   */
687  public ReEncodeEntriesTask(final Map<TaskProperty,List<Object>> properties)
688         throws TaskException
689  {
690    super(RE_ENCODE_ENTRIES_TASK_CLASS, properties);
691
692    boolean      skipFullyUncached     = false;
693    boolean      skipPartiallyUncached = false;
694    Long         maxRate               = null;
695    List<String> eBranches             = Collections.emptyList();
696    List<String> eFilters              = Collections.emptyList();
697    List<String> iBranches             = Collections.emptyList();
698    List<String> iFilters              = Collections.emptyList();
699    String       id                    = null;
700
701    for (final Map.Entry<TaskProperty,List<Object>> e : properties.entrySet())
702    {
703      final TaskProperty p = e.getKey();
704      final String attrName = p.getAttributeName();
705      final List<Object> values = e.getValue();
706
707      if (attrName.equalsIgnoreCase(ATTR_BACKEND_ID))
708      {
709        id = parseString(p, values, null);
710      }
711      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_BRANCH))
712      {
713        final String[] branches = parseStrings(p, values, null);
714        if (branches != null)
715        {
716          iBranches = Collections.unmodifiableList(Arrays.asList(branches));
717        }
718      }
719      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_BRANCH))
720      {
721        final String[] branches = parseStrings(p, values, null);
722        if (branches != null)
723        {
724          eBranches = Collections.unmodifiableList(Arrays.asList(branches));
725        }
726      }
727      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_FILTER))
728      {
729        final String[] filters = parseStrings(p, values, null);
730        if (filters != null)
731        {
732          iFilters = Collections.unmodifiableList(Arrays.asList(filters));
733        }
734      }
735      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_FILTER))
736      {
737        final String[] filters = parseStrings(p, values, null);
738        if (filters != null)
739        {
740          eFilters = Collections.unmodifiableList(Arrays.asList(filters));
741        }
742      }
743      else if (attrName.equalsIgnoreCase(ATTR_MAX_ENTRIES_PER_SECOND))
744      {
745        maxRate = parseLong(p, values, null);
746      }
747      else if (attrName.equalsIgnoreCase(ATTR_SKIP_FULLY_UNCACHED))
748      {
749        skipFullyUncached = parseBoolean(p, values, false);
750      }
751      else if (attrName.equalsIgnoreCase(ATTR_SKIP_PARTIALLY_UNCACHED))
752      {
753        skipPartiallyUncached = parseBoolean(p, values, false);
754      }
755    }
756
757    if (id == null)
758    {
759      throw new TaskException(ERR_REENCODE_TASK_MISSING_REQUIRED_PROPERTY.get(
760           ATTR_BACKEND_ID));
761    }
762
763    backendID                    = id;
764    includeBranches              = iBranches;
765    excludeBranches              = eBranches;
766    includeFilters               = iFilters;
767    excludeFilters               = eFilters;
768    maxEntriesPerSecond          = maxRate;
769    skipFullyUncachedEntries     = skipFullyUncached;
770    skipPartiallyUncachedEntries = skipPartiallyUncached;
771  }
772
773
774
775  /**
776   * {@inheritDoc}
777   */
778  @Override()
779  public String getTaskName()
780  {
781    return INFO_TASK_NAME_REENCODE_ENTRIES.get();
782  }
783
784
785
786  /**
787   * {@inheritDoc}
788   */
789  @Override()
790  public String getTaskDescription()
791  {
792    return INFO_TASK_DESCRIPTION_REENCODE_ENTRIES.get();
793  }
794
795
796
797  /**
798   * Retrieves the backend ID for the backend containing the entries to
799   * re-encode.
800   *
801   * @return  The backend ID for the backend containing the entries to
802   *          re-encode.
803   */
804  public String getBackendID()
805  {
806    return backendID;
807  }
808
809
810
811  /**
812   * Retrieves the base DNs of the branches to include in re-encode processing,
813   * if defined.
814   *
815   * @return  The base DNs of the branches to include in re-encode processing,
816   *          or an empty list if there should not be any include branches.
817   */
818  public List<String> getIncludeBranches()
819  {
820    return includeBranches;
821  }
822
823
824
825  /**
826   * Retrieves the base DNs of the branches to exclude from re-encode
827   * processing, if defined.
828   *
829   * @return  The base DNs of the branches to exclude from re-encode processing,
830   *          or an empty list if there should not be any exclude branches.
831   */
832  public List<String> getExcludeBranches()
833  {
834    return excludeBranches;
835  }
836
837
838
839  /**
840   * Retrieves a set of filters to use to identify entries to include in
841   * re-encode processing, if defined.
842   *
843   * @return  A set of filters to use to identify entries to include in
844   *          re-encode processing, or an empty list if there should not be any
845   *          include filters.
846   */
847  public List<String> getIncludeFilters()
848  {
849    return includeFilters;
850  }
851
852
853
854  /**
855   * Retrieves a set of filters to use to identify entries to exclude from
856   * re-encode processing, if defined.
857   *
858   * @return  A set of filters to use to identify entries to exclude from
859   *          re-encode processing, or an empty list if there should not be any
860   *          exclude filters.
861   */
862  public List<String> getExcludeFilters()
863  {
864    return excludeFilters;
865  }
866
867
868
869  /**
870   * Retrieves the maximum number of entries that should be re-encoded per
871   * second, if defined.
872   *
873   * @return  The maximum number of entries that should be re-encoded per
874   *          second, or {@code null} if no rate limit should be imposed.
875   */
876  public Long getMaxEntriesPerSecond()
877  {
878    return maxEntriesPerSecond;
879  }
880
881
882
883  /**
884   * Indicates whether to skip re-encode processing for entries that are stored
885   * as fully uncached.
886   *
887   * @return  {@code true} if fully uncached entries should be skipped, or
888   *          {@code false} if not.
889   */
890  public boolean skipFullyUncachedEntries()
891  {
892    return skipFullyUncachedEntries;
893  }
894
895
896
897  /**
898   * Indicates whether to skip re-encode processing for entries that have a
899   * mix of cached and uncached attributes.
900   *
901   * @return  {@code true} if partially uncached entries should be skipped, or
902   *          {@code false} if not.
903   */
904  public boolean skipPartiallyUncachedEntries()
905  {
906    return skipPartiallyUncachedEntries;
907  }
908
909
910
911  /**
912   * {@inheritDoc}
913   */
914  @Override()
915  protected List<String> getAdditionalObjectClasses()
916  {
917    return Collections.singletonList(OC_REENCODE_ENTRIES_TASK);
918  }
919
920
921
922  /**
923   * {@inheritDoc}
924   */
925  @Override()
926  protected List<Attribute> getAdditionalAttributes()
927  {
928    final ArrayList<Attribute> attrList = new ArrayList<>(7);
929    attrList.add(new Attribute(ATTR_BACKEND_ID, backendID));
930    attrList.add(new Attribute(ATTR_SKIP_FULLY_UNCACHED,
931         String.valueOf(skipFullyUncachedEntries)));
932    attrList.add(new Attribute(ATTR_SKIP_PARTIALLY_UNCACHED,
933         String.valueOf(skipPartiallyUncachedEntries)));
934
935    if (! includeBranches.isEmpty())
936    {
937      attrList.add(new Attribute(ATTR_INCLUDE_BRANCH, includeBranches));
938    }
939
940    if (! excludeBranches.isEmpty())
941    {
942      attrList.add(new Attribute(ATTR_EXCLUDE_BRANCH, excludeBranches));
943    }
944
945    if (! includeFilters.isEmpty())
946    {
947      attrList.add(new Attribute(ATTR_INCLUDE_FILTER, includeFilters));
948    }
949
950    if (! excludeFilters.isEmpty())
951    {
952      attrList.add(new Attribute(ATTR_EXCLUDE_FILTER, excludeFilters));
953    }
954
955    if (maxEntriesPerSecond != null)
956    {
957      attrList.add(new Attribute(ATTR_MAX_ENTRIES_PER_SECOND,
958           String.valueOf(maxEntriesPerSecond)));
959    }
960
961    return attrList;
962  }
963
964
965
966  /**
967   * {@inheritDoc}
968   */
969  @Override()
970  public List<TaskProperty> getTaskSpecificProperties()
971  {
972    return Collections.unmodifiableList(Arrays.asList(
973         PROPERTY_BACKEND_ID,
974         PROPERTY_INCLUDE_BRANCH,
975         PROPERTY_EXCLUDE_BRANCH,
976         PROPERTY_INCLUDE_FILTER,
977         PROPERTY_EXCLUDE_FILTER,
978         PROPERTY_MAX_ENTRIES_PER_SECOND,
979         PROPERTY_SKIP_FULLY_UNCACHED,
980         PROPERTY_SKIP_PARTIALLY_UNCACHED));
981  }
982
983
984
985  /**
986   * {@inheritDoc}
987   */
988  @Override()
989  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
990  {
991    final LinkedHashMap<TaskProperty,List<Object>> props =
992         new LinkedHashMap<>(15);
993
994    props.put(PROPERTY_BACKEND_ID,
995         Collections.<Object>singletonList(backendID));
996    props.put(PROPERTY_INCLUDE_BRANCH,
997         Collections.<Object>unmodifiableList(includeBranches));
998    props.put(PROPERTY_EXCLUDE_BRANCH,
999         Collections.<Object>unmodifiableList(excludeBranches));
1000    props.put(PROPERTY_INCLUDE_FILTER,
1001         Collections.<Object>unmodifiableList(includeFilters));
1002    props.put(PROPERTY_EXCLUDE_FILTER,
1003         Collections.<Object>unmodifiableList(excludeFilters));
1004
1005    if (maxEntriesPerSecond == null)
1006    {
1007      props.put(PROPERTY_MAX_ENTRIES_PER_SECOND,
1008           Collections.emptyList());
1009    }
1010    else
1011    {
1012      props.put(PROPERTY_MAX_ENTRIES_PER_SECOND,
1013           Collections.<Object>singletonList(maxEntriesPerSecond));
1014    }
1015
1016    props.put(PROPERTY_SKIP_FULLY_UNCACHED,
1017         Collections.<Object>singletonList(skipFullyUncachedEntries));
1018    props.put(PROPERTY_SKIP_PARTIALLY_UNCACHED,
1019         Collections.<Object>singletonList(skipPartiallyUncachedEntries));
1020
1021    props.putAll(super.getTaskPropertyValues());
1022    return Collections.unmodifiableMap(props);
1023  }
1024}