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