001    /*
002     * Copyright 2011-2012 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    
018    package com.unboundid.scim.data;
019    
020    import com.unboundid.scim.schema.AttributeDescriptor;
021    import com.unboundid.scim.sdk.InvalidResourceException;
022    import com.unboundid.scim.sdk.SCIMAttribute;
023    import com.unboundid.scim.sdk.SCIMAttributeValue;
024    
025    import java.util.ArrayList;
026    import java.util.Date;
027    import java.util.List;
028    
029    /**
030     * Represents a standard value of a multi-valued attribute.
031     *
032     * @param <T> The value type.
033     */
034    public 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    
057    
058              return new Entry<String>(v, t, p == null ? false : p, d);
059            }
060    
061            /**
062             * {@inheritDoc}
063             */
064            @Override
065            public SCIMAttributeValue fromInstance(
066                final AttributeDescriptor attributeDescriptor,
067                final Entry<String> value) throws InvalidResourceException {
068              final List<SCIMAttribute> subAttributes =
069                  new ArrayList<SCIMAttribute>(4);
070    
071              if (value.value != null)
072              {
073                subAttributes.add(
074                    SCIMAttribute.create(
075                        attributeDescriptor.getSubAttribute("value"),
076                        SCIMAttributeValue.createStringValue(value.value)));
077              }
078    
079              if (value.primary)
080              {
081                subAttributes.add(
082                    SCIMAttribute.create(
083                        attributeDescriptor.getSubAttribute("primary"),
084                        SCIMAttributeValue.createBooleanValue(value.primary)));
085              }
086    
087              if (value.type != null)
088              {
089                subAttributes.add(
090                    SCIMAttribute.create(
091                        attributeDescriptor.getSubAttribute("type"),
092                        SCIMAttributeValue.createStringValue(value.type)));
093              }
094    
095              if(value.display != null)
096              {
097                subAttributes.add(
098                    SCIMAttribute.create(
099                        attributeDescriptor.getSubAttribute("display"),
100                        SCIMAttributeValue.createStringValue(value.display)));
101              }
102    
103              return SCIMAttributeValue.createComplexValue(subAttributes);
104            }
105          };
106    
107      /**
108       * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
109       * to/from <code>Boolean</code> valued <code>Entry</code> instances.
110       */
111      public static final AttributeValueResolver<Entry<Boolean>>
112          BOOLEANS_RESOLVER =
113          new AttributeValueResolver<Entry<Boolean>>() {
114            /**
115             * {@inheritDoc}
116             */
117            @Override
118            public Entry<Boolean> toInstance(final SCIMAttributeValue value) {
119              Boolean v =
120                  value.getSubAttributeValue("value", BOOLEAN_RESOLVER);
121              String t =
122                  value.getSubAttributeValue("type", STRING_RESOLVER);
123              Boolean p =
124                  value.getSubAttributeValue("primary", BOOLEAN_RESOLVER);
125              String d =
126                  value.getSubAttributeValue("display", STRING_RESOLVER);
127    
128    
129              return new Entry<Boolean>(v, t, p == null ? false : p, d);
130            }
131    
132            /**
133             * {@inheritDoc}
134             */
135            @Override
136            public SCIMAttributeValue fromInstance(
137                final AttributeDescriptor attributeDescriptor,
138                final Entry<Boolean> value) throws InvalidResourceException {
139              final List<SCIMAttribute> subAttributes =
140                  new ArrayList<SCIMAttribute>(4);
141    
142              if (value.value != null)
143              {
144                subAttributes.add(
145                    SCIMAttribute.create(
146                        attributeDescriptor.getSubAttribute("value"),
147                        SCIMAttributeValue.createBooleanValue(value.value)));
148              }
149    
150              if (value.primary)
151              {
152                subAttributes.add(
153                    SCIMAttribute.create(
154                        attributeDescriptor.getSubAttribute("primary"),
155                        SCIMAttributeValue.createBooleanValue(value.primary)));
156              }
157    
158              if (value.type != null)
159              {
160                subAttributes.add(
161                    SCIMAttribute.create(
162                        attributeDescriptor.getSubAttribute("type"),
163                        SCIMAttributeValue.createStringValue(value.type)));
164              }
165    
166              if(value.display != null)
167              {
168                subAttributes.add(
169                    SCIMAttribute.create(
170                        attributeDescriptor.getSubAttribute("display"),
171                        SCIMAttributeValue.createStringValue(value.display)));
172              }
173    
174              return SCIMAttributeValue.createComplexValue(subAttributes);
175            }
176          };
177    
178      /**
179       * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
180       * to/from <code>byte[]</code> valued <code>Entry</code> instances.
181       */
182      public static final AttributeValueResolver<Entry<byte[]>>
183          BINARIES_RESOLVER =
184          new AttributeValueResolver<Entry<byte[]>>() {
185            /**
186             * {@inheritDoc}
187             */
188            @Override
189            public Entry<byte[]> toInstance(final SCIMAttributeValue value) {
190              byte[] v =
191                  value.getSubAttributeValue("value", BINARY_RESOLVER);
192              String t =
193                  value.getSubAttributeValue("type", STRING_RESOLVER);
194              Boolean p =
195                  value.getSubAttributeValue("primary", BOOLEAN_RESOLVER);
196              String d =
197                  value.getSubAttributeValue("display", STRING_RESOLVER);
198    
199    
200              return new Entry<byte[]>(v, t, p == null ? false : p, d);
201            }
202    
203            /**
204             * {@inheritDoc}
205             */
206            @Override
207            public SCIMAttributeValue fromInstance(
208                final AttributeDescriptor attributeDescriptor,
209                final Entry<byte[]> value) throws InvalidResourceException {
210              final List<SCIMAttribute> subAttributes =
211                  new ArrayList<SCIMAttribute>(4);
212    
213              if (value.value != null)
214              {
215                subAttributes.add(
216                    SCIMAttribute.create(
217                        attributeDescriptor.getSubAttribute("value"),
218                        SCIMAttributeValue.createBinaryValue(value.value)));
219              }
220    
221              if (value.primary)
222              {
223                subAttributes.add(
224                    SCIMAttribute.create(
225                        attributeDescriptor.getSubAttribute("primary"),
226                        SCIMAttributeValue.createBooleanValue(value.primary)));
227              }
228    
229              if (value.type != null)
230              {
231                subAttributes.add(
232                    SCIMAttribute.create(
233                        attributeDescriptor.getSubAttribute("type"),
234                        SCIMAttributeValue.createStringValue(value.type)));
235              }
236    
237              if(value.display != null)
238              {
239                subAttributes.add(
240                    SCIMAttribute.create(
241                        attributeDescriptor.getSubAttribute("display"),
242                        SCIMAttributeValue.createStringValue(value.display)));
243              }
244    
245              return SCIMAttributeValue.createComplexValue(subAttributes);
246            }
247          };
248    
249      /**
250       * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
251       * to/from <code>Date</code> valued <code>Entry</code> instances.
252       */
253      public static final AttributeValueResolver<Entry<Date>>
254          DATES_RESOLVER =
255          new AttributeValueResolver<Entry<Date>>() {
256            /**
257             * {@inheritDoc}
258             */
259            @Override
260            public Entry<Date> toInstance(final SCIMAttributeValue value) {
261              Date v =
262                  value.getSubAttributeValue("value", DATE_RESOLVER);
263              String t =
264                  value.getSubAttributeValue("type", STRING_RESOLVER);
265              Boolean p =
266                  value.getSubAttributeValue("primary", BOOLEAN_RESOLVER);
267              String d =
268                  value.getSubAttributeValue("display", STRING_RESOLVER);
269    
270    
271              return new Entry<Date>(v, t, p == null ? false : p, d);
272            }
273    
274            /**
275             * {@inheritDoc}
276             */
277            @Override
278            public SCIMAttributeValue fromInstance(
279                final AttributeDescriptor attributeDescriptor,
280                final Entry<Date> value) throws InvalidResourceException {
281              final List<SCIMAttribute> subAttributes =
282                  new ArrayList<SCIMAttribute>(4);
283    
284              if (value.value != null)
285              {
286                subAttributes.add(
287                    SCIMAttribute.create(
288                        attributeDescriptor.getSubAttribute("value"),
289                        SCIMAttributeValue.createDateValue(value.value)));
290              }
291    
292              if (value.primary)
293              {
294                subAttributes.add(
295                    SCIMAttribute.create(
296                        attributeDescriptor.getSubAttribute("primary"),
297                        SCIMAttributeValue.createBooleanValue(value.primary)));
298              }
299    
300              if (value.type != null)
301              {
302                subAttributes.add(
303                    SCIMAttribute.create(
304                        attributeDescriptor.getSubAttribute("type"),
305                        SCIMAttributeValue.createStringValue(value.type)));
306              }
307    
308              if(value.display != null)
309              {
310                subAttributes.add(
311                    SCIMAttribute.create(
312                        attributeDescriptor.getSubAttribute("display"),
313                        SCIMAttributeValue.createStringValue(value.display)));
314              }
315    
316              return SCIMAttributeValue.createComplexValue(subAttributes);
317            }
318          };
319    
320    
321      private T value;
322      private boolean primary;
323      private String type;
324      private String display;
325    
326      /**
327       * Constructs an entry instance with the specified information.
328       *
329       * @param value The primary value of this attribute.
330       * @param type The type of attribute for this instance, usually used to
331       *             label the preferred function of the given resource.
332       */
333      public Entry(final T value, final String type) {
334        this(value, type, false);
335      }
336    
337      /**
338       * Constructs an entry instance with the specified information.
339       *
340       * @param value The primary value of this attribute.
341       * @param type The type of attribute for this instance, usually used to
342       *             label the preferred function of the given resource.
343       * @param primary A Boolean value indicating whether this instance of the
344       *                multi-valued Attribute is the primary or preferred value of
345       *                for this attribute.
346       */
347      public Entry(final T value, final String type, final boolean primary) {
348        this.value = value;
349        this.type = type;
350        this.primary = primary;
351      }
352    
353      /**
354       * Constructs an entry instance with the specified information.
355       *
356       * @param value The primary value of this attribute.
357       * @param type The type of attribute for this instance, usually used to
358       *             label the preferred function of the given resource.
359       * @param primary A Boolean value indicating whether this instance of the
360       *                multi-valued Attribute is the primary or preferred value of
361       *                for this attribute.
362       * @param display A human readable name, primarily used for display purposes
363       *                where the value is an opaque or complex type such as an id.
364       */
365      public Entry(final T value, final String type, final boolean primary,
366                   final String display) {
367        this.value = value;
368        this.type = type;
369        this.primary = primary;
370        this.display = display;
371      }
372    
373      /**
374       * Whether this instance of the multi-valued Attribute is the primary or
375       * preferred value of for this attribute.
376       *
377       * @return <code>true</code> if this instance of the multi-valued Attribute is
378       *         the primary or preferred value of for this attribute or
379       *         <code>false</code> otherwise
380       */
381      public boolean isPrimary() {
382        return primary;
383      }
384    
385      /**
386       * Sets whether this instance of the multi-valued Attribute is the primary or
387       * preferred value of for this attribute.
388       *
389       * @param primary <code>true</code> if this instance of the multi-valued
390       *                Attribute is the primary or preferred value of for this
391       *                attribute or <code>false</code> otherwise.
392       */
393      public void setPrimary(final boolean primary) {
394        this.primary = primary;
395      }
396    
397      /**
398       * Retrieves the type of attribute for this instance, usually used to label
399       * the preferred function of the given resource.
400       *
401       * @return The type of attribute for this instance, usually used to label
402       *         the preferred function of the given resource.
403       */
404      public String getType() {
405        return type;
406      }
407    
408      /**
409       * Sets the type of attribute for this instance, usually used to label
410       * the preferred function of the given resource.
411       *
412       * @param type The type of attribute for this instance, usually used to label
413       * the preferred function of the given resource.
414       */
415      public void setType(final String type) {
416        this.type = type;
417      }
418    
419      /**
420       * Retrieves the primary value of this attribute.
421       *
422       * @return The primary value of this attribute.
423       */
424      public T getValue() {
425        return value;
426      }
427    
428      /**
429       * Sets the primary value of this attribute.
430       *
431       * @param value The primary value of this attribute.
432       */
433      public void setValue(final T value) {
434        this.value = value;
435      }
436    
437      /**
438       * Retrieves the human readable name, primarily used for display purposes
439       * where the value is an opaque or complex type such as an id.
440       *
441       * @return The human readable name.
442       */
443      public String getDisplay() {
444        return this.display;
445      }
446    
447      /**
448       * Sets the human readable name, primarily used for display purposes
449       * where the value is an opaque or complex type such as an id.
450       *
451       * @param display The human readable name.
452       */
453      public void setDisplay(final String display) {
454        this.display = display;
455      }
456    
457      /**
458       * {@inheritDoc}
459       */
460      @Override
461      public boolean equals(final Object o) {
462        if (this == o) {
463          return true;
464        }
465        if (o == null || getClass() != o.getClass()) {
466          return false;
467        }
468    
469        Entry entry = (Entry) o;
470    
471        if (primary != entry.primary) {
472          return false;
473        }
474        if (type != null ? !type.equals(entry.type) : entry.type != null) {
475          return false;
476        }
477        if (value != null ? !value.equals(entry.value) : entry.value != null) {
478          return false;
479        }
480        if (display != null ? !display.equals(entry.display) :
481            entry.display != null) {
482          return false;
483        }
484    
485        return true;
486      }
487    
488      /**
489       * {@inheritDoc}
490       */
491      @Override
492      public int hashCode() {
493        int result = value != null ? value.hashCode() : 0;
494        result = 31 * result + (primary ? 1 : 0);
495        result = 31 * result + (type != null ? type.hashCode() : 0);
496        result = 31 * result + (display != null ? display.hashCode() : 0);
497        return result;
498      }
499    
500      /**
501       * {@inheritDoc}
502       */
503      @Override
504      public String toString() {
505        return "Entry{" +
506            "value=" + value +
507            ", type='" + type + '\'' +
508            ", primary=" + primary +
509            ", display=" + display +
510            '}';
511      }
512    }