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.valueOfUtf8(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, String valueString) 186 { 187 return create(getAttributeTypeOrDefault(attributeName), attributeName, valueString); 188 } 189 190 /** 191 * Creates a new multi-valued attribute with the specified attribute 192 * name and attribute values. 193 * <p> 194 * If the attribute name cannot be found in the schema, a new 195 * attribute type is created using the default attribute syntax. 196 * <p> 197 * <b>NOTE:</b> this method is provided as a convenience and should 198 * typically be reserved for use in unit tests and places where 199 * performance is not an issue. In particular, this method will 200 * construct a temporary array containing the attribute's values. 201 * For performance critical purposes, incrementally construct an 202 * attribute using an {@link AttributeBuilder}. 203 * 204 * @param attributeName 205 * The name or OID of the attribute type for this attribute 206 * (can be mixed case). 207 * @param valueStrings 208 * The string representation of the attribute values. 209 * @return A new attribute with the specified name and values. 210 */ 211 public static Attribute create(String attributeName, String... valueStrings) 212 { 213 if (valueStrings.length == 0) { 214 return empty(attributeName); 215 } 216 AttributeBuilder builder = new AttributeBuilder(attributeName); 217 builder.addAllStrings(Arrays.asList(valueStrings)); 218 return builder.toAttribute(); 219 } 220 221 /** 222 * Creates a new attribute which has the same attribute type and 223 * attribute options as the provided attribute but no attribute 224 * values. 225 * 226 * @param attribute 227 * The attribute to be copied. 228 * @return A new attribute which has the same attribute type and 229 * attribute options as the provided attribute but no 230 * attribute values. 231 */ 232 public static Attribute empty(Attribute attribute) 233 { 234 return new AttributeBuilder(attribute, true).toAttribute(); 235 } 236 237 238 239 /** 240 * Creates a new attribute with the provided attribute type and no 241 * values. 242 * 243 * @param attributeType 244 * The attribute type to use. 245 * @return A new attribute with the provided attribute type and no 246 * values. 247 */ 248 public static Attribute empty(AttributeType attributeType) 249 { 250 return empty(attributeType, attributeType.getNameOrOID()); 251 } 252 253 254 255 /** 256 * Creates a new attribute with the provided attribute type and no 257 * values. 258 * 259 * @param attributeType 260 * The attribute type to use. 261 * @param name 262 * The user-provided name for this attribute. 263 * @return A new attribute with the provided attribute type and no 264 * values. 265 */ 266 public static Attribute empty(AttributeType attributeType, 267 String name) 268 { 269 return AttributeBuilder.create(attributeType, name, Collections 270 .<ByteString> emptySet()); 271 } 272 273 274 275 /** 276 * Creates a new attribute with the specified attribute name and no 277 * attribute values. 278 * <p> 279 * If the attribute name cannot be found in the schema, a new 280 * attribute type is created using the default attribute syntax. 281 * 282 * @param attributeName 283 * The name or OID of the attribute type for this attribute 284 * (can be mixed case). 285 * @return A new attribute with the specified name and no values. 286 */ 287 public static Attribute empty(String attributeName) 288 { 289 return empty(getAttributeTypeOrDefault(attributeName), attributeName); 290 } 291 292 293 294 /** 295 * Creates a new attribute containing all the values from the two 296 * provided attributes. The returned attribute will use the name and 297 * options taken from the first attribute. 298 * <p> 299 * This method is logically equivalent to: 300 * 301 * <pre> 302 * merge(a1, a2, null); 303 * </pre> 304 * 305 * @param a1 306 * The first attribute. 307 * @param a2 308 * The second attribute. 309 * @return A new attribute containing all the values from the two 310 * provided attributes. 311 */ 312 public static Attribute merge(Attribute a1, Attribute a2) 313 { 314 return merge(a1, a2, null); 315 } 316 317 318 319 /** 320 * Creates a new attribute containing all the values from the two 321 * provided attributes and put any duplicate values into the 322 * provided collection. The returned attribute will use the name 323 * and options taken from the first attribute. 324 * 325 * @param a1 326 * The first attribute. 327 * @param a2 328 * The second attribute. 329 * @param duplicateValues 330 * A collection which will be used to store any duplicate 331 * values, or <code>null</code> if duplicate values should 332 * not be stored. 333 * @return A new attribute containing all the values from the two 334 * provided attributes. 335 */ 336 public static Attribute merge(Attribute a1, Attribute a2, 337 Collection<ByteString> duplicateValues) 338 { 339 AttributeBuilder builder = new AttributeBuilder(a1); 340 for (ByteString av : a2) 341 { 342 if (!builder.add(av) && duplicateValues != null) 343 { 344 duplicateValues.add(av); 345 } 346 } 347 return builder.toAttribute(); 348 } 349 350 351 352 /** 353 * Creates a new attribute containing the values from the first 354 * attribute which are not in the second attribute. The returned 355 * attribute will use the name and options taken from the first 356 * attribute. 357 * <p> 358 * This method is logically equivalent to: 359 * 360 * <pre> 361 * subtract(a1, a2, null); 362 * </pre> 363 * 364 * @param a1 365 * The first attribute. 366 * @param a2 367 * The second attribute. 368 * @return A new attribute containing the values from the first 369 * attribute which are not in the second attribute. 370 */ 371 public static Attribute subtract(Attribute a1, Attribute a2) 372 { 373 return subtract(a1, a2, null); 374 } 375 376 377 378 /** 379 * Creates a new attribute containing the values from the first 380 * attribute which are not in the second attribute. Any values which 381 * were present in the second attribute but which were not present 382 * in the first attribute will be put into the provided collection. 383 * The returned attribute will use the name and options taken from 384 * the first attribute. 385 * 386 * @param a1 387 * The first attribute. 388 * @param a2 389 * The second attribute. 390 * @param missingValues 391 * A collection which will be used to store any missing 392 * values, or <code>null</code> if missing values should 393 * not be stored. 394 * @return A new attribute containing the values from the first 395 * attribute which are not in the second attribute. 396 */ 397 public static Attribute subtract(Attribute a1, Attribute a2, 398 Collection<ByteString> missingValues) 399 { 400 AttributeBuilder builder = new AttributeBuilder(a1); 401 for (ByteString av : a2) 402 { 403 if (!builder.remove(av) && missingValues != null) 404 { 405 missingValues.add(av); 406 } 407 } 408 return builder.toAttribute(); 409 } 410 411 private static AttributeType getAttributeTypeOrDefault(String attributeName) 412 { 413 return DirectoryServer.getAttributeTypeOrDefault(toLowerCase(attributeName), attributeName); 414 } 415}