001/* 002 * Copyright 2011-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2019 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 061 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 062 * for proprietary functionality or for external specifications that are not 063 * considered stable or mature enough to be guaranteed to work in an 064 * interoperable way with 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<>(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 = new ArrayList<>(attrElements.length); 171 for (final ASN1Element e : attrElements) 172 { 173 attrNames.add(ASN1OctetString.decodeAsOctetString(e).stringValue()); 174 } 175 176 return new IgnoreAttributesChangeSelectionCriteria( 177 ASN1Boolean.decodeAsBoolean(elements[1]).booleanValue(), 178 attrNames); 179 } 180 catch (final Exception e) 181 { 182 Debug.debugException(e); 183 throw new LDAPException(ResultCode.DECODING_ERROR, 184 ERR_IGNORE_ATTRS_CHANGE_SELECTION_CRITERIA_DECODE_ERROR.get( 185 StaticUtils.getExceptionMessage(e)), 186 e); 187 } 188 } 189 190 191 192 /** 193 * Indicates whether to automatically include all operational attributes in 194 * the set of attributes to ignore. 195 * 196 * @return {@code true} if all operational attributes should automatically be 197 * included in the set of attributes to ignore, or {@code false} if 198 * only those operational attributes which are explicitly named 199 * should be ignored. 200 */ 201 public boolean ignoreOperationalAttributes() 202 { 203 return ignoreOperationalAttributes; 204 } 205 206 207 208 /** 209 * Retrieves the names of the target attributes for changes that should be 210 * retrieved. 211 * 212 * @return The names of the target attributes for changes that should be 213 * retrieved. 214 */ 215 public List<String> getAttributeNames() 216 { 217 return attributeNames; 218 } 219 220 221 222 /** 223 * {@inheritDoc} 224 */ 225 @Override() 226 public ASN1Element encodeInnerElement() 227 { 228 final ArrayList<ASN1Element> attrNameElements = 229 new ArrayList<>(attributeNames.size()); 230 for (final String s : attributeNames) 231 { 232 attrNameElements.add(new ASN1OctetString(s)); 233 } 234 235 return new ASN1Sequence(TYPE_SELECTION_CRITERIA_IGNORE_ATTRIBUTES, 236 new ASN1Sequence(attrNameElements), 237 new ASN1Boolean(ignoreOperationalAttributes)); 238 } 239 240 241 242 /** 243 * {@inheritDoc} 244 */ 245 @Override() 246 public void toString(final StringBuilder buffer) 247 { 248 buffer.append("IgnoreAttributesChangeSelectionCriteria(attributeNames={"); 249 250 final Iterator<String> iterator = attributeNames.iterator(); 251 while (iterator.hasNext()) 252 { 253 buffer.append(iterator.next()); 254 if (iterator.hasNext()) 255 { 256 buffer.append(','); 257 } 258 } 259 260 buffer.append("}, ignoreOperationalAttributes="); 261 buffer.append(ignoreOperationalAttributes); 262 buffer.append(')'); 263 } 264}