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}