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}