001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.server.types; 018 019import static org.opends.server.core.DirectoryServer.*; 020import static org.opends.server.util.CollectionUtils.*; 021 022import java.util.Arrays; 023import java.util.Collection; 024import java.util.Collections; 025import java.util.List; 026 027import org.forgerock.opendj.ldap.ByteString; 028import org.forgerock.opendj.ldap.schema.AttributeType; 029import org.opends.server.types.Attribute.RemoveOnceSwitchingAttributes; 030 031/** 032 * This class contains various methods for manipulating 033 * {@link Attribute}s as well as static factory methods for 034 * facilitating common {@link Attribute} construction use-cases. 035 * <p> 036 * Of particular interest are the following three factory methods: 037 * 038 * <pre> 039 * empty(String); 040 * 041 * create(String, String); 042 * 043 * create(String, String, String...); 044 * </pre> 045 * 046 * These are provided in order to facilitate construction of empty, 047 * single-valued, and multi-valued attributes respectively, for 048 * example, in unit tests. The last factory method is not designed for 049 * performance critical functionality and, instead, an 050 * {@link AttributeBuilder} should be used in order to incrementally 051 * construct multi-valued attributes. 052 */ 053@RemoveOnceSwitchingAttributes 054public final class Attributes 055{ 056 057 /** 058 * Creates a new single-valued attribute with the specified attribute type and value. 059 * 060 * @param attributeType 061 * The attribute type to use. 062 * @param value 063 * The attribute value. 064 * @return A new attribute with the attribute type and value. 065 */ 066 public static Attribute create(AttributeType attributeType, ByteString value) 067 { 068 return create(attributeType, attributeType.getNameOrOID(), value); 069 } 070 071 /** 072 * Creates a new List with a single-valued attribute with the specified attribute type and value. 073 * 074 * @param attributeType 075 * The attribute type to use. 076 * @param value 077 * The attribute value. 078 * @return A new List with a single-valued attribute with the attribute type and value. 079 */ 080 public static List<Attribute> createAsList(AttributeType attributeType, ByteString value) 081 { 082 return newArrayList(create(attributeType, value)); 083 } 084 085 /** 086 * Creates a new single-valued attribute with the specified name and value. 087 * 088 * @param attributeType 089 * The attribute type to use. 090 * @param valueString 091 * The String representation of the attribute value. 092 * @return A new attribute with the specified name and value. 093 */ 094 public static Attribute create(AttributeType attributeType, String valueString) 095 { 096 return create(attributeType, attributeType.getNameOrOID(), valueString); 097 } 098 099 /** 100 * Creates a new List with a single-valued attribute with the specified name and value. 101 * 102 * @param attributeType 103 * The attribute type to use. 104 * @param valueString 105 * The String representation of the attribute value. 106 * @return A new List with a attribute with the specified name and value. 107 */ 108 public static List<Attribute> createAsList(AttributeType attributeType, String valueString) 109 { 110 return newArrayList(create(attributeType, valueString)); 111 } 112 113 /** 114 * Creates a new single-valued attribute with the specified 115 * attribute type and value. 116 * 117 * @param attributeType 118 * The attribute type to use. 119 * @param name 120 * The user-provided name for this attribute. 121 * @param value 122 * The attribute value. 123 * @return A new attribute with the attribute type and value. 124 */ 125 public static Attribute create(AttributeType attributeType, String name, ByteString value) 126 { 127 return AttributeBuilder.create(attributeType, name, Collections.singleton(value)); 128 } 129 130 /** 131 * Creates a new single-valued attribute with the attribute type and value. 132 * 133 * @param attributeType 134 * The attribute type to use. 135 * @param name 136 * The user-provided name for this attribute. 137 * @param valueString 138 * The String representation of the attribute value. 139 * @return A new attribute with the attribute type and value. 140 */ 141 public static Attribute create(AttributeType attributeType, String name, String valueString) 142 { 143 return create(attributeType, name, ByteString.valueOfUtf8(valueString)); 144 } 145 146 /** 147 * Creates a new List with a single-valued attribute with the attribute type and value. 148 * 149 * @param attributeType 150 * The attribute type to use. 151 * @param name 152 * The user-provided name for this attribute. 153 * @param valueString 154 * The String representation of the attribute value. 155 * @return A new List with a single-valued attribute with the attribute type and value. 156 */ 157 158 public static List<Attribute> createAsList(AttributeType attributeType, String name, String valueString) 159 { 160 return newArrayList(create(attributeType, name, valueString)); 161 } 162 163 /** 164 * Creates a new single-valued attribute with the specified 165 * attribute name and attribute value. 166 * <p> 167 * If the attribute name cannot be found in the schema, a new 168 * attribute type is created using the default attribute syntax. 169 * 170 * @param attributeName 171 * The name or OID of the attribute type for this attribute 172 * (can be mixed case). 173 * @param valueString 174 * The String representation of the attribute value. 175 * @return A new attribute with the specified name and value. 176 */ 177 public static Attribute create(String attributeName, String valueString) 178 { 179 return create(getSchema().getAttributeType(attributeName), attributeName, valueString); 180 } 181 182 /** 183 * Creates a new multi-valued attribute with the specified attribute 184 * name and attribute values. 185 * <p> 186 * If the attribute name cannot be found in the schema, a new 187 * attribute type is created using the default attribute syntax. 188 * <p> 189 * <b>NOTE:</b> this method is provided as a convenience and should 190 * typically be reserved for use in unit tests and places where 191 * performance is not an issue. In particular, this method will 192 * construct a temporary array containing the attribute's values. 193 * For performance critical purposes, incrementally construct an 194 * attribute using an {@link AttributeBuilder}. 195 * 196 * @param attributeName 197 * The name or OID of the attribute type for this attribute 198 * (can be mixed case). 199 * @param valueStrings 200 * The string representation of the attribute values. 201 * @return A new attribute with the specified name and values. 202 */ 203 public static Attribute create(String attributeName, String... valueStrings) 204 { 205 if (valueStrings.length == 0) { 206 return empty(attributeName); 207 } 208 AttributeBuilder builder = new AttributeBuilder(attributeName); 209 builder.addAllStrings(Arrays.asList(valueStrings)); 210 return builder.toAttribute(); 211 } 212 213 /** 214 * Creates a new attribute which has the same attribute type and 215 * attribute options as the provided attribute but no attribute 216 * values. 217 * 218 * @param attribute 219 * The attribute to be copied. 220 * @return A new attribute which has the same attribute type and 221 * attribute options as the provided attribute but no 222 * attribute values. 223 */ 224 public static Attribute empty(Attribute attribute) 225 { 226 return new AttributeBuilder(attribute.getAttributeDescription()).toAttribute(); 227 } 228 229 230 231 /** 232 * Creates a new attribute with the provided attribute type and no 233 * values. 234 * 235 * @param attributeType 236 * The attribute type to use. 237 * @return A new attribute with the provided attribute type and no 238 * values. 239 */ 240 public static Attribute empty(AttributeType attributeType) 241 { 242 return empty(attributeType, attributeType.getNameOrOID()); 243 } 244 245 246 247 /** 248 * Creates a new attribute with the provided attribute type and no 249 * values. 250 * 251 * @param attributeType 252 * The attribute type to use. 253 * @param name 254 * The user-provided name for this attribute. 255 * @return A new attribute with the provided attribute type and no 256 * values. 257 */ 258 public static Attribute empty(AttributeType attributeType, 259 String name) 260 { 261 return AttributeBuilder.create(attributeType, name, Collections 262 .<ByteString> emptySet()); 263 } 264 265 266 267 /** 268 * Creates a new attribute with the specified attribute name and no 269 * attribute values. 270 * <p> 271 * If the attribute name cannot be found in the schema, a new 272 * attribute type is created using the default attribute syntax. 273 * 274 * @param attributeName 275 * The name or OID of the attribute type for this attribute 276 * (can be mixed case). 277 * @return A new attribute with the specified name and no values. 278 */ 279 public static Attribute empty(String attributeName) 280 { 281 return empty(getSchema().getAttributeType(attributeName), attributeName); 282 } 283 284 285 286 /** 287 * Creates a new attribute containing all the values from the two 288 * provided attributes. The returned attribute will use the name and 289 * options taken from the first attribute. 290 * <p> 291 * This method is logically equivalent to: 292 * 293 * <pre> 294 * merge(a1, a2, null); 295 * </pre> 296 * 297 * @param a1 298 * The first attribute. 299 * @param a2 300 * The second attribute. 301 * @return A new attribute containing all the values from the two 302 * provided attributes. 303 */ 304 public static Attribute merge(Attribute a1, Attribute a2) 305 { 306 return merge(a1, a2, null); 307 } 308 309 310 311 /** 312 * Creates a new attribute containing all the values from the two 313 * provided attributes and put any duplicate values into the 314 * provided collection. The returned attribute will use the name 315 * and options taken from the first attribute. 316 * 317 * @param a1 318 * The first attribute. 319 * @param a2 320 * The second attribute. 321 * @param duplicateValues 322 * A collection which will be used to store any duplicate 323 * values, or <code>null</code> if duplicate values should 324 * not be stored. 325 * @return A new attribute containing all the values from the two 326 * provided attributes. 327 */ 328 public static Attribute merge(Attribute a1, Attribute a2, 329 Collection<ByteString> duplicateValues) 330 { 331 AttributeBuilder builder = new AttributeBuilder(a1); 332 for (ByteString av : a2) 333 { 334 if (!builder.add(av) && duplicateValues != null) 335 { 336 duplicateValues.add(av); 337 } 338 } 339 return builder.toAttribute(); 340 } 341 342 343 344 /** 345 * Creates a new attribute containing the values from the first 346 * attribute which are not in the second attribute. The returned 347 * attribute will use the name and options taken from the first 348 * attribute. 349 * <p> 350 * This method is logically equivalent to: 351 * 352 * <pre> 353 * subtract(a1, a2, null); 354 * </pre> 355 * 356 * @param a1 357 * The first attribute. 358 * @param a2 359 * The second attribute. 360 * @return A new attribute containing the values from the first 361 * attribute which are not in the second attribute. 362 */ 363 public static Attribute subtract(Attribute a1, Attribute a2) 364 { 365 return subtract(a1, a2, null); 366 } 367 368 369 370 /** 371 * Creates a new attribute containing the values from the first 372 * attribute which are not in the second attribute. Any values which 373 * were present in the second attribute but which were not present 374 * in the first attribute will be put into the provided collection. 375 * The returned attribute will use the name and options taken from 376 * the first attribute. 377 * 378 * @param a1 379 * The first attribute. 380 * @param a2 381 * The second attribute. 382 * @param missingValues 383 * A collection which will be used to store any missing 384 * values, or <code>null</code> if missing values should 385 * not be stored. 386 * @return A new attribute containing the values from the first 387 * attribute which are not in the second attribute. 388 */ 389 public static Attribute subtract(Attribute a1, Attribute a2, 390 Collection<ByteString> missingValues) 391 { 392 AttributeBuilder builder = new AttributeBuilder(a1); 393 for (ByteString av : a2) 394 { 395 if (!builder.remove(av) && missingValues != null) 396 { 397 missingValues.add(av); 398 } 399 } 400 return builder.toAttribute(); 401 } 402}