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 }