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