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.sdk.ComplexValue;
021import com.unboundid.scim.schema.AttributeDescriptor;
022import com.unboundid.scim.sdk.InvalidResourceException;
023import com.unboundid.scim.sdk.SCIMAttribute;
024import com.unboundid.scim.sdk.SCIMAttributeValue;
025import com.unboundid.scim.sdk.SimpleValue;
026
027import java.util.ArrayList;
028import java.util.Date;
029import java.util.List;
030import java.util.Map;
031
032/**
033 * Used to resolve SCIM attribute values to Java instances.
034 *
035 * @param <T> The Java class to resolve.
036 */
037public abstract class AttributeValueResolver<T>
038{
039  /**
040   * Create an instance from the given attribute value.
041   *
042   * @param value The value to create an instance from.
043   * @return The instance created from the attribute value.
044   */
045  public abstract T toInstance(final SCIMAttributeValue value);
046
047  /**
048   * Create a SCIM attribute value from the given instance.
049   *
050   * @param attributeDescriptor The descriptor for the attribute to create.
051   * @param value The instance.
052   * @return The SCIM attribute value created from the instance.
053   * @throws InvalidResourceException if the value violates the schema.
054   */
055  public abstract SCIMAttributeValue fromInstance(
056      final AttributeDescriptor attributeDescriptor, final T value)
057      throws InvalidResourceException;
058
059  /**
060   * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
061   * to/from <code>String</code> instances.
062   */
063  public static final AttributeValueResolver<String> STRING_RESOLVER =
064      new AttributeValueResolver<String>() {
065
066        /**
067         * {@inheritDoc}
068         */
069        public String toInstance(final SCIMAttributeValue value) {
070          return value.getStringValue();
071        }
072
073        /**
074         * {@inheritDoc}
075         */
076        public SCIMAttributeValue fromInstance(
077            final AttributeDescriptor attributeDescriptor, final String value) {
078          return SCIMAttributeValue.createStringValue(value);
079        }
080      };
081
082
083  /**
084   * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
085   * to/from <code>String</code> instances.
086   */
087  public static final AttributeValueResolver<Date> DATE_RESOLVER =
088      new AttributeValueResolver<Date>() {
089        /**
090         * {@inheritDoc}
091         */
092        public Date toInstance(final SCIMAttributeValue value) {
093          return value.getDateValue();
094        }
095
096        /**
097         * {@inheritDoc}
098         */
099        public SCIMAttributeValue fromInstance(
100            final AttributeDescriptor attributeDescriptor, final Date value) {
101          return SCIMAttributeValue.createDateValue(value);
102        }
103      };
104
105  /**
106   * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
107   * to/from <code>Boolean</code> instances.
108   */
109  public static final AttributeValueResolver<Boolean> BOOLEAN_RESOLVER =
110      new AttributeValueResolver<Boolean>() {
111        /**
112         * {@inheritDoc}
113         */
114        public Boolean toInstance(final SCIMAttributeValue value) {
115          return value.getBooleanValue();
116        }
117
118        /**
119         * {@inheritDoc}
120         */
121        public SCIMAttributeValue fromInstance(
122            final AttributeDescriptor attributeDescriptor,
123            final Boolean value) {
124          return SCIMAttributeValue.createBooleanValue(value);
125        }
126      };
127
128  /**
129   * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
130   * to/from <code>byte[]</code> instances.
131   */
132  public static final AttributeValueResolver<byte[]> BINARY_RESOLVER =
133      new AttributeValueResolver<byte[]>() {
134
135        /**
136         * {@inheritDoc}
137         */
138        @Override
139        public byte[] toInstance(final SCIMAttributeValue value) {
140          return value.getBinaryValue();
141        }
142
143        /**
144         * {@inheritDoc}
145         */
146        @Override
147        public SCIMAttributeValue fromInstance(
148            final AttributeDescriptor attributeDescriptor,
149            final byte[] value) {
150          return SCIMAttributeValue.createBinaryValue(value);
151        }
152      };
153
154  /**
155   * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
156   * to/from <code>Decimal</code> instances.
157   */
158  public static final AttributeValueResolver<Double> DECIMAL_RESOLVER =
159      new AttributeValueResolver<Double>() {
160        /**
161         * {@inheritDoc}
162         */
163        public Double toInstance(final SCIMAttributeValue value) {
164          return value.getDecimalValue();
165        }
166
167        /**
168         * {@inheritDoc}
169         */
170        public SCIMAttributeValue fromInstance(
171            final AttributeDescriptor attributeDescriptor,
172            final Double value) {
173          return SCIMAttributeValue.createStringValue(String.valueOf(value));
174        }
175      };
176
177  /**
178   * The <code>AttributeValueResolver</code> that resolves SCIM attribute values
179   * to/from <code>Integer</code> instances.
180   */
181  public static final AttributeValueResolver<Long> INTEGER_RESOLVER =
182      new AttributeValueResolver<Long>() {
183        /**
184         * {@inheritDoc}
185         */
186        public Long toInstance(final SCIMAttributeValue value) {
187          return value.getIntegerValue();
188        }
189
190        /**
191         * {@inheritDoc}
192         */
193        public SCIMAttributeValue fromInstance(
194            final AttributeDescriptor attributeDescriptor,
195            final Long value) {
196          return SCIMAttributeValue.createStringValue(String.valueOf(value));
197        }
198      };
199
200
201  /**
202   * A default <code>AttributeValueResolver</code> for complex SCIM attribute
203   * values. Resolves to/from a <code>ComplexValue</code> instance.
204   */
205  public static final AttributeValueResolver<ComplexValue>
206      COMPLEX_RESOLVER = new AttributeValueResolver<ComplexValue>() {
207
208        /**
209         * {@inheritDoc}
210         */
211        @Override
212        public ComplexValue toInstance(
213            final SCIMAttributeValue value) {
214
215          ComplexValue complex = new ComplexValue();
216          for (Map.Entry<String,SCIMAttribute> subEntry :
217              value.getAttributes().entrySet())
218          {
219            String subAttrName = subEntry.getKey();
220            SCIMAttribute subAttribute = subEntry.getValue();
221            complex.put(subAttrName, subAttribute.getValue().getValue());
222          }
223          return complex;
224        }
225
226        /**
227         * {@inheritDoc}
228         */
229        @Override
230        public SCIMAttributeValue fromInstance(
231            final AttributeDescriptor attributeDescriptor,
232            final ComplexValue complex)
233            throws InvalidResourceException {
234
235          List<SCIMAttribute> subAttributes = new ArrayList<SCIMAttribute>();
236
237          for (Map.Entry<String,SimpleValue> subEntry :
238              complex.entrySet())
239          {
240            String subAttrName = subEntry.getKey();
241            SimpleValue subAttrValue = subEntry.getValue();
242
243            AttributeDescriptor subDescriptor =
244                attributeDescriptor.getSubAttribute(subAttrName);
245
246            subAttributes.add(SCIMAttribute.create(subDescriptor,
247                SCIMAttributeValue.createSimpleValue(subAttrValue)));
248          }
249
250          return SCIMAttributeValue.createComplexValue(subAttributes);
251        }
252      };
253}