001/*
002 * Copyright 2011-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.extensions;
022
023
024
025import java.util.ArrayList;
026import java.util.Collection;
027import java.util.Collections;
028import java.util.Iterator;
029import java.util.List;
030
031import com.unboundid.asn1.ASN1Boolean;
032import com.unboundid.asn1.ASN1Element;
033import com.unboundid.asn1.ASN1OctetString;
034import com.unboundid.asn1.ASN1Sequence;
035import com.unboundid.ldap.sdk.LDAPException;
036import com.unboundid.ldap.sdk.ResultCode;
037import com.unboundid.util.Debug;
038import com.unboundid.util.NotMutable;
039import com.unboundid.util.StaticUtils;
040import com.unboundid.util.ThreadSafety;
041import com.unboundid.util.ThreadSafetyLevel;
042import com.unboundid.util.Validator;
043
044import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
045
046
047
048/**
049 * This class provides an implementation of a get changelog batch change
050 * selection criteria value that indicates that the server should not return
051 * changes which target only the specified attributes.  This can be useful for
052 * ignoring changes to attributes which are changed frequently but not of
053 * interest to the client.  Note that changes returned may include changes to
054 * these attributes, but only if the change targets other attributes that should
055 * not be ignored.
056 * <BR>
057 * <BLOCKQUOTE>
058 *   <B>NOTE:</B>  This class, and other classes within the
059 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
060 *   supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661
061 *   server products.  These classes provide support for proprietary
062 *   functionality or for external specifications that are not considered stable
063 *   or mature enough to be guaranteed to work in an interoperable way with
064 *   other types of LDAP servers.
065 * </BLOCKQUOTE>
066 */
067@NotMutable()
068@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
069public final class IgnoreAttributesChangeSelectionCriteria
070       extends ChangelogBatchChangeSelectionCriteria
071{
072  /**
073   * The inner BER type that should be used for encoded elements that represent
074   * an ignore attributes get changelog batch selection criteria value.
075   */
076  static final byte TYPE_SELECTION_CRITERIA_IGNORE_ATTRIBUTES = (byte) 0xA3;
077
078
079
080  // Indicates whether to automatically consider all operational attributes in
081  // the ignore list.
082  private final boolean ignoreOperationalAttributes;
083
084  // The names of the attributes to ignore.
085  private final List<String> attributeNames;
086
087
088
089  /**
090   * Creates a new ignore attributes change selection criteria value with the
091   * provided information.
092   *
093   * @param  ignoreOperationalAttributes  Indicates whether to automatically
094   *                                      include all operational attributes in
095   *                                      the set of attributes to ignore.
096   * @param  attributeNames               The names of the attributes to ignore.
097   *                                      It may be {@code null} or empty only
098   *                                      if
099   *                                      {@code ignoreOperationalAttributes}
100   *                                      is {@code true} and no user attributes
101   *                                      changes should be ignored.
102   */
103  public IgnoreAttributesChangeSelectionCriteria(
104              final boolean ignoreOperationalAttributes,
105              final String... attributeNames)
106  {
107    this(ignoreOperationalAttributes, StaticUtils.toList(attributeNames));
108  }
109
110
111
112  /**
113   * Creates a new ignore attributes change selection criteria value with the
114   * provided information.
115   *
116   * @param  ignoreOperationalAttributes  Indicates whether to automatically
117   *                                      include all operational attributes in
118   *                                      the set of attributes to ignore.
119   * @param  attributeNames               The names of the attributes to ignore.
120   *                                      It may be {@code null} or empty only
121   *                                      if
122   *                                      {@code ignoreOperationalAttributes}
123   *                                      is {@code true} and no user attributes
124   *                                      changes should be ignored.
125   */
126  public IgnoreAttributesChangeSelectionCriteria(
127              final boolean ignoreOperationalAttributes,
128              final Collection<String> attributeNames)
129  {
130    if ((attributeNames == null) || attributeNames.isEmpty())
131    {
132      Validator.ensureTrue(ignoreOperationalAttributes);
133      this.attributeNames = Collections.emptyList();
134    }
135    else
136    {
137      this.attributeNames =
138           Collections.unmodifiableList(new ArrayList<String>(attributeNames));
139    }
140
141    this.ignoreOperationalAttributes = ignoreOperationalAttributes;
142  }
143
144
145
146  /**
147   * Decodes the provided ASN.1 element, which is the inner element of a
148   * changelog batch change selection criteria element, as an all attributes
149   * change selection criteria value.
150   *
151   * @param  innerElement  The inner element of a changelog batch change
152   *                       selection criteria element to be decoded.
153   *
154   * @return  The decoded all attributes change selection criteria value.
155   *
156   * @throws  LDAPException  If a problem is encountered while trying to decode
157   *                         the provided element as the inner element of an all
158   *                         attributes change selection criteria value.
159   */
160  static IgnoreAttributesChangeSelectionCriteria decodeInnerElement(
161              final ASN1Element innerElement)
162         throws LDAPException
163  {
164    try
165    {
166      final ASN1Element[] elements =
167           ASN1Sequence.decodeAsSequence(innerElement).elements();
168      final ASN1Element[] attrElements =
169           ASN1Sequence.decodeAsSequence(elements[0]).elements();
170      final ArrayList<String> attrNames =
171           new ArrayList<String>(attrElements.length);
172      for (final ASN1Element e : attrElements)
173      {
174        attrNames.add(ASN1OctetString.decodeAsOctetString(e).stringValue());
175      }
176
177      return new IgnoreAttributesChangeSelectionCriteria(
178           ASN1Boolean.decodeAsBoolean(elements[1]).booleanValue(),
179           attrNames);
180    }
181    catch (final Exception e)
182    {
183      Debug.debugException(e);
184      throw new LDAPException(ResultCode.DECODING_ERROR,
185           ERR_IGNORE_ATTRS_CHANGE_SELECTION_CRITERIA_DECODE_ERROR.get(
186                StaticUtils.getExceptionMessage(e)),
187           e);
188    }
189  }
190
191
192
193  /**
194   * Indicates whether to automatically include all operational attributes in
195   * the set of attributes to ignore.
196   *
197   * @return  {@code true} if all operational attributes should automatically be
198   *          included in the set of attributes to ignore, or {@code false} if
199   *          only those operational attributes which are explicitly named
200   *          should be ignored.
201   */
202  public boolean ignoreOperationalAttributes()
203  {
204    return ignoreOperationalAttributes;
205  }
206
207
208
209  /**
210   * Retrieves the names of the target attributes for changes that should be
211   * retrieved.
212   *
213   * @return  The names of the target attributes for changes that should be
214   *          retrieved.
215   */
216  public List<String> getAttributeNames()
217  {
218    return attributeNames;
219  }
220
221
222
223  /**
224   * {@inheritDoc}
225   */
226  @Override()
227  public ASN1Element encodeInnerElement()
228  {
229    final ArrayList<ASN1Element> attrNameElements =
230         new ArrayList<ASN1Element>(attributeNames.size());
231    for (final String s : attributeNames)
232    {
233      attrNameElements.add(new ASN1OctetString(s));
234    }
235
236    return new ASN1Sequence(TYPE_SELECTION_CRITERIA_IGNORE_ATTRIBUTES,
237         new ASN1Sequence(attrNameElements),
238         new ASN1Boolean(ignoreOperationalAttributes));
239  }
240
241
242
243  /**
244   * {@inheritDoc}
245   */
246  @Override()
247  public void toString(final StringBuilder buffer)
248  {
249    buffer.append("IgnoreAttributesChangeSelectionCriteria(attributeNames={");
250
251    final Iterator<String> iterator = attributeNames.iterator();
252    while (iterator.hasNext())
253    {
254      buffer.append(iterator.next());
255      if (iterator.hasNext())
256      {
257        buffer.append(',');
258      }
259    }
260
261    buffer.append("}, ignoreOperationalAttributes=");
262    buffer.append(ignoreOperationalAttributes);
263    buffer.append(')');
264  }
265}