001/* 002 * Copyright 2011-2016 UnboundID Corp. 003 * 004 * This program is free software; you can redistribute it and/or modify 005 * it under the terms of the GNU General Public License (GPLv2 only) 006 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 007 * as published by the Free Software Foundation. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program; if not, see <http://www.gnu.org/licenses>. 016 */ 017 018package com.unboundid.scim.data; 019 020import com.unboundid.scim.schema.AttributeDescriptor; 021import com.unboundid.scim.sdk.InvalidResourceException; 022import com.unboundid.scim.sdk.SCIMAttribute; 023import com.unboundid.scim.sdk.SCIMAttributeValue; 024 025import java.util.ArrayList; 026import java.util.Date; 027import java.util.List; 028 029/** 030 * Represents a standard value of a multi-valued attribute. 031 * 032 * @param <T> The value type. 033 */ 034public final class Entry<T> 035{ 036 /** 037 * The <code>AttributeValueResolver</code> that resolves SCIM attribute values 038 * to/from <code>String</code> valued <code>Entry</code> instances. 039 */ 040 public static final AttributeValueResolver<Entry<String>> 041 STRINGS_RESOLVER = 042 new AttributeValueResolver<Entry<String>>() { 043 /** 044 * {@inheritDoc} 045 */ 046 @Override 047 public Entry<String> toInstance(final SCIMAttributeValue value) { 048 String v = 049 value.getSubAttributeValue("value", STRING_RESOLVER); 050 String t = 051 value.getSubAttributeValue("type", STRING_RESOLVER); 052 Boolean p = 053 value.getSubAttributeValue("primary", BOOLEAN_RESOLVER); 054 String d = 055 value.getSubAttributeValue("display", STRING_RESOLVER); 056 String o = 057 value.getSubAttributeValue("operation", STRING_RESOLVER); 058 059 060 return new Entry<String>(v, t, p == null ? false : p, d, o); 061 } 062 063 /** 064 * {@inheritDoc} 065 */ 066 @Override 067 public SCIMAttributeValue fromInstance( 068 final AttributeDescriptor attributeDescriptor, 069 final Entry<String> value) throws InvalidResourceException { 070 final List<SCIMAttribute> subAttributes = 071 new ArrayList<SCIMAttribute>(5); 072 073 if (value.value != null) 074 { 075 subAttributes.add( 076 SCIMAttribute.create( 077 attributeDescriptor.getSubAttribute("value"), 078 SCIMAttributeValue.createStringValue(value.value))); 079 } 080 081 if (value.primary) 082 { 083 subAttributes.add( 084 SCIMAttribute.create( 085 attributeDescriptor.getSubAttribute("primary"), 086 SCIMAttributeValue.createBooleanValue(value.primary))); 087 } 088 089 if (value.type != null) 090 { 091 subAttributes.add( 092 SCIMAttribute.create( 093 attributeDescriptor.getSubAttribute("type"), 094 SCIMAttributeValue.createStringValue(value.type))); 095 } 096 097 if(value.display != null) 098 { 099 subAttributes.add( 100 SCIMAttribute.create( 101 attributeDescriptor.getSubAttribute("display"), 102 SCIMAttributeValue.createStringValue(value.display))); 103 } 104 105 if(value.operation != null) 106 { 107 subAttributes.add( 108 SCIMAttribute.create( 109 attributeDescriptor.getSubAttribute("operation"), 110 SCIMAttributeValue.createStringValue(value.operation))); 111 } 112 113 return SCIMAttributeValue.createComplexValue(subAttributes); 114 } 115 }; 116 117 /** 118 * The <code>AttributeValueResolver</code> that resolves SCIM attribute values 119 * to/from <code>Boolean</code> valued <code>Entry</code> instances. 120 */ 121 public static final AttributeValueResolver<Entry<Boolean>> 122 BOOLEANS_RESOLVER = 123 new AttributeValueResolver<Entry<Boolean>>() { 124 /** 125 * {@inheritDoc} 126 */ 127 @Override 128 public Entry<Boolean> toInstance(final SCIMAttributeValue value) { 129 Boolean v = 130 value.getSubAttributeValue("value", BOOLEAN_RESOLVER); 131 String t = 132 value.getSubAttributeValue("type", STRING_RESOLVER); 133 Boolean p = 134 value.getSubAttributeValue("primary", BOOLEAN_RESOLVER); 135 String d = 136 value.getSubAttributeValue("display", STRING_RESOLVER); 137 String o = 138 value.getSubAttributeValue("operation", STRING_RESOLVER); 139 140 141 return new Entry<Boolean>(v, t, p == null ? false : p, d, o); 142 } 143 144 /** 145 * {@inheritDoc} 146 */ 147 @Override 148 public SCIMAttributeValue fromInstance( 149 final AttributeDescriptor attributeDescriptor, 150 final Entry<Boolean> value) throws InvalidResourceException { 151 final List<SCIMAttribute> subAttributes = 152 new ArrayList<SCIMAttribute>(5); 153 154 if (value.value != null) 155 { 156 subAttributes.add( 157 SCIMAttribute.create( 158 attributeDescriptor.getSubAttribute("value"), 159 SCIMAttributeValue.createBooleanValue(value.value))); 160 } 161 162 if (value.primary) 163 { 164 subAttributes.add( 165 SCIMAttribute.create( 166 attributeDescriptor.getSubAttribute("primary"), 167 SCIMAttributeValue.createBooleanValue(value.primary))); 168 } 169 170 if (value.type != null) 171 { 172 subAttributes.add( 173 SCIMAttribute.create( 174 attributeDescriptor.getSubAttribute("type"), 175 SCIMAttributeValue.createStringValue(value.type))); 176 } 177 178 if(value.display != null) 179 { 180 subAttributes.add( 181 SCIMAttribute.create( 182 attributeDescriptor.getSubAttribute("display"), 183 SCIMAttributeValue.createStringValue(value.display))); 184 } 185 186 if(value.operation != null) 187 { 188 subAttributes.add( 189 SCIMAttribute.create( 190 attributeDescriptor.getSubAttribute("operation"), 191 SCIMAttributeValue.createStringValue(value.operation))); 192 } 193 194 return SCIMAttributeValue.createComplexValue(subAttributes); 195 } 196 }; 197 198 /** 199 * The <code>AttributeValueResolver</code> that resolves SCIM attribute values 200 * to/from <code>byte[]</code> valued <code>Entry</code> instances. 201 */ 202 public static final AttributeValueResolver<Entry<byte[]>> 203 BINARIES_RESOLVER = 204 new AttributeValueResolver<Entry<byte[]>>() { 205 /** 206 * {@inheritDoc} 207 */ 208 @Override 209 public Entry<byte[]> toInstance(final SCIMAttributeValue value) { 210 byte[] v = 211 value.getSubAttributeValue("value", BINARY_RESOLVER); 212 String t = 213 value.getSubAttributeValue("type", STRING_RESOLVER); 214 Boolean p = 215 value.getSubAttributeValue("primary", BOOLEAN_RESOLVER); 216 String d = 217 value.getSubAttributeValue("display", STRING_RESOLVER); 218 String o = 219 value.getSubAttributeValue("operation", STRING_RESOLVER); 220 221 222 return new Entry<byte[]>(v, t, p == null ? false : p, d, o); 223 } 224 225 /** 226 * {@inheritDoc} 227 */ 228 @Override 229 public SCIMAttributeValue fromInstance( 230 final AttributeDescriptor attributeDescriptor, 231 final Entry<byte[]> value) throws InvalidResourceException { 232 final List<SCIMAttribute> subAttributes = 233 new ArrayList<SCIMAttribute>(5); 234 235 if (value.value != null) 236 { 237 subAttributes.add( 238 SCIMAttribute.create( 239 attributeDescriptor.getSubAttribute("value"), 240 SCIMAttributeValue.createBinaryValue(value.value))); 241 } 242 243 if (value.primary) 244 { 245 subAttributes.add( 246 SCIMAttribute.create( 247 attributeDescriptor.getSubAttribute("primary"), 248 SCIMAttributeValue.createBooleanValue(value.primary))); 249 } 250 251 if (value.type != null) 252 { 253 subAttributes.add( 254 SCIMAttribute.create( 255 attributeDescriptor.getSubAttribute("type"), 256 SCIMAttributeValue.createStringValue(value.type))); 257 } 258 259 if(value.display != null) 260 { 261 subAttributes.add( 262 SCIMAttribute.create( 263 attributeDescriptor.getSubAttribute("display"), 264 SCIMAttributeValue.createStringValue(value.display))); 265 } 266 267 if(value.operation != null) 268 { 269 subAttributes.add( 270 SCIMAttribute.create( 271 attributeDescriptor.getSubAttribute("operation"), 272 SCIMAttributeValue.createStringValue(value.operation))); 273 } 274 275 return SCIMAttributeValue.createComplexValue(subAttributes); 276 } 277 }; 278 279 /** 280 * The <code>AttributeValueResolver</code> that resolves SCIM attribute values 281 * to/from <code>Date</code> valued <code>Entry</code> instances. 282 */ 283 public static final AttributeValueResolver<Entry<Date>> 284 DATES_RESOLVER = 285 new AttributeValueResolver<Entry<Date>>() { 286 /** 287 * {@inheritDoc} 288 */ 289 @Override 290 public Entry<Date> toInstance(final SCIMAttributeValue value) { 291 Date v = 292 value.getSubAttributeValue("value", DATE_RESOLVER); 293 String t = 294 value.getSubAttributeValue("type", STRING_RESOLVER); 295 Boolean p = 296 value.getSubAttributeValue("primary", BOOLEAN_RESOLVER); 297 String d = 298 value.getSubAttributeValue("display", STRING_RESOLVER); 299 String o = 300 value.getSubAttributeValue("operation", STRING_RESOLVER); 301 302 303 return new Entry<Date>(v, t, p == null ? false : p, d, o); 304 } 305 306 /** 307 * {@inheritDoc} 308 */ 309 @Override 310 public SCIMAttributeValue fromInstance( 311 final AttributeDescriptor attributeDescriptor, 312 final Entry<Date> value) throws InvalidResourceException { 313 final List<SCIMAttribute> subAttributes = 314 new ArrayList<SCIMAttribute>(5); 315 316 if (value.value != null) 317 { 318 subAttributes.add( 319 SCIMAttribute.create( 320 attributeDescriptor.getSubAttribute("value"), 321 SCIMAttributeValue.createDateValue(value.value))); 322 } 323 324 if (value.primary) 325 { 326 subAttributes.add( 327 SCIMAttribute.create( 328 attributeDescriptor.getSubAttribute("primary"), 329 SCIMAttributeValue.createBooleanValue(value.primary))); 330 } 331 332 if (value.type != null) 333 { 334 subAttributes.add( 335 SCIMAttribute.create( 336 attributeDescriptor.getSubAttribute("type"), 337 SCIMAttributeValue.createStringValue(value.type))); 338 } 339 340 if(value.display != null) 341 { 342 subAttributes.add( 343 SCIMAttribute.create( 344 attributeDescriptor.getSubAttribute("display"), 345 SCIMAttributeValue.createStringValue(value.display))); 346 } 347 348 if(value.operation != null) 349 { 350 subAttributes.add( 351 SCIMAttribute.create( 352 attributeDescriptor.getSubAttribute("operation"), 353 SCIMAttributeValue.createStringValue(value.operation))); 354 } 355 356 return SCIMAttributeValue.createComplexValue(subAttributes); 357 } 358 }; 359 360 361 private T value; 362 private boolean primary; 363 private String type; 364 private String display; 365 private String operation; 366 367 /** 368 * Constructs an entry instance with the specified information. 369 * 370 * @param value The primary value of this attribute. 371 * @param type The type of attribute for this instance, usually used to 372 * label the preferred function of the given resource. 373 */ 374 public Entry(final T value, final String type) { 375 this(value, type, false, null, null); 376 } 377 378 /** 379 * Constructs an entry instance with the specified information. 380 * 381 * @param value The primary value of this attribute. 382 * @param type The type of attribute for this instance, usually used to 383 * label the preferred function of the given resource. 384 * @param primary A Boolean value indicating whether this instance of the 385 * multi-valued Attribute is the primary or preferred value of 386 * for this attribute. 387 */ 388 public Entry(final T value, final String type, final boolean primary) { 389 this(value, type, primary, null, null); 390 } 391 392 /** 393 * Constructs an entry instance with the specified information. 394 * 395 * @param value The primary value of this attribute. 396 * @param type The type of attribute for this instance, usually used to 397 * label the preferred function of the given resource. 398 * @param primary A Boolean value indicating whether this instance of the 399 * multi-valued Attribute is the primary or preferred value of 400 * for this attribute. 401 * @param display A human readable name, primarily used for display purposes 402 * where the value is an opaque or complex type such as an id. 403 */ 404 public Entry(final T value, final String type, final boolean primary, 405 final String display) { 406 this(value, type, primary, display, null); 407 } 408 409 /** 410 * Constructs an entry instance with the specified information. 411 * 412 * @param value The primary value of this attribute. 413 * @param type The type of attribute for this instance, usually used to 414 * label the preferred function of the given resource. 415 * @param primary A Boolean value indicating whether this instance of the 416 * multi-valued Attribute is the primary or preferred value of 417 * for this attribute. 418 * @param display A human readable name, primarily used for display purposes 419 * where the value is an opaque or complex type such as an id. 420 * @param operation The operation to perform on the multi-valued attribute 421 * during a PATCH request. 422 */ 423 public Entry(final T value, final String type, final boolean primary, 424 final String display, final String operation) { 425 this.value = value; 426 this.type = type; 427 this.primary = primary; 428 this.display = display; 429 this.operation = operation; 430 } 431 432 /** 433 * Whether this instance of the multi-valued Attribute is the primary or 434 * preferred value of for this attribute. 435 * 436 * @return <code>true</code> if this instance of the multi-valued Attribute is 437 * the primary or preferred value of for this attribute or 438 * <code>false</code> otherwise 439 */ 440 public boolean isPrimary() { 441 return primary; 442 } 443 444 /** 445 * Sets whether this instance of the multi-valued Attribute is the primary or 446 * preferred value of for this attribute. 447 * 448 * @param primary <code>true</code> if this instance of the multi-valued 449 * Attribute is the primary or preferred value of for this 450 * attribute or <code>false</code> otherwise. 451 */ 452 public void setPrimary(final boolean primary) { 453 this.primary = primary; 454 } 455 456 /** 457 * Retrieves the type of attribute for this instance, usually used to label 458 * the preferred function of the given resource. 459 * 460 * @return The type of attribute for this instance, usually used to label 461 * the preferred function of the given resource. 462 */ 463 public String getType() { 464 return type; 465 } 466 467 /** 468 * Sets the type of attribute for this instance, usually used to label 469 * the preferred function of the given resource. 470 * 471 * @param type The type of attribute for this instance, usually used to label 472 * the preferred function of the given resource. 473 */ 474 public void setType(final String type) { 475 this.type = type; 476 } 477 478 /** 479 * Retrieves the primary value of this attribute. 480 * 481 * @return The primary value of this attribute. 482 */ 483 public T getValue() { 484 return value; 485 } 486 487 /** 488 * Sets the primary value of this attribute. 489 * 490 * @param value The primary value of this attribute. 491 */ 492 public void setValue(final T value) { 493 this.value = value; 494 } 495 496 /** 497 * Retrieves the human readable name, primarily used for display purposes 498 * where the value is an opaque or complex type such as an id. 499 * 500 * @return The human readable name. 501 */ 502 public String getDisplay() { 503 return this.display; 504 } 505 506 /** 507 * Sets the human readable name, primarily used for display purposes 508 * where the value is an opaque or complex type such as an id. 509 * 510 * @param display The human readable name. 511 */ 512 public void setDisplay(final String display) { 513 this.display = display; 514 } 515 516 517 518 /** 519 * Retrieves the operation to perform on the multi-valued attribute during 520 * a PATCH request. A value of "delete" signifies that this instance should be 521 * removed from the Resource. 522 * 523 * @return The operation to perform on the multi-valued attribute during 524 * a PATCH request. 525 */ 526 public String getOperation() 527 { 528 return operation; 529 } 530 531 532 533 /** 534 * Sets the operation to perform on the multi-valued attribute during a 535 * PATCH request. A value of "delete" signifies that this instance should be 536 * removed from the Resource. 537 * 538 * @param operation The operation to perform on the multi-valued attribute 539 * during a PATCH request. 540 */ 541 public void setOperation(final String operation) 542 { 543 this.operation = operation; 544 } 545 546 547 548 /** 549 * {@inheritDoc} 550 */ 551 @Override 552 public boolean equals(final Object o) { 553 if (this == o) { 554 return true; 555 } 556 if (o == null || getClass() != o.getClass()) { 557 return false; 558 } 559 560 Entry entry = (Entry) o; 561 562 if (primary != entry.primary) { 563 return false; 564 } 565 if (type != null ? !type.equals(entry.type) : entry.type != null) { 566 return false; 567 } 568 if (value != null ? !value.equals(entry.value) : entry.value != null) { 569 return false; 570 } 571 if (display != null ? !display.equals(entry.display) : 572 entry.display != null) { 573 return false; 574 } 575 if (operation != null ? !operation.equals(entry.operation) : 576 entry.operation != null) { 577 return false; 578 } 579 580 return true; 581 } 582 583 /** 584 * {@inheritDoc} 585 */ 586 @Override 587 public int hashCode() { 588 int result = value != null ? value.hashCode() : 0; 589 result = 31 * result + (primary ? 1 : 0); 590 result = 31 * result + (type != null ? type.hashCode() : 0); 591 result = 31 * result + (display != null ? display.hashCode() : 0); 592 result = 31 * result + (operation != null ? operation.hashCode() : 0); 593 return result; 594 } 595 596 /** 597 * {@inheritDoc} 598 */ 599 @Override 600 public String toString() { 601 return "Entry{" + 602 "value=" + value + 603 ", type='" + type + '\'' + 604 ", primary=" + primary + 605 ", display=" + display + 606 ", operation=" + operation + 607 '}'; 608 } 609}