From 58ffacee660a4eb792f49dd311a4e2ddda05afad Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 25 May 2012 22:12:32 +0000
Subject: [PATCH] Checkpoint local changes: add more attribute mapping support.

---
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ComplexAttributeMapper.java   |   33 +---
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java   |   19 ++
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java    |   59 +++++++--
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java                    |   15 +
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPResource.java             |    4 
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java          |   20 --
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java |   14 --
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Example.java                  |    8 +
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java |   60 ++++++++++
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ConstantAttributeMapper.java  |   79 +++++++++++++
 10 files changed, 232 insertions(+), 79 deletions(-)

diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java
index 47acac8..e906357 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java
@@ -32,33 +32,19 @@
 public interface AttributeMapper {
 
     /**
-     * Adds the names of the all the LDAP attributes required by this attribute
-     * mapper to the provided set.
-     * <p>
-     * Implementations should only add the names of attributes found in the LDAP
-     * entry directly associated with the resource.
-     *
-     * @param ldapAttributes
-     *            The set into which the required LDAP attribute names should be
-     *            put.
-     */
-    void getLDAPAttributes(Set<String> ldapAttributes);
-
-    /**
      * Adds the names of the LDAP attributes required by this attribute mapper
      * which are associated with the provided resource attribute to the provided
      * set.
      * <p>
      * Implementations should only add the names of attributes found in the LDAP
      * entry directly associated with the resource.
-     *
+     * @param jsonAttribute
+     *            The name of the resource attribute requested by the client.
      * @param ldapAttributes
      *            The set into which the required LDAP attribute names should be
      *            put.
-     * @param resourceAttribute
-     *            The name of the resource attribute requested by the client.
      */
-    void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute);
+    void getLDAPAttributes(JsonPointer jsonAttribute, Set<String> ldapAttributes);
 
     /**
      * Transforms attributes contained in the provided LDAP entry to JSON
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ComplexAttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ComplexAttributeMapper.java
index fcd9f1b..3120ffc 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ComplexAttributeMapper.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ComplexAttributeMapper.java
@@ -51,35 +51,17 @@
      */
     public ComplexAttributeMapper(String jsonAttributeName, AttributeMapper mapper) {
         this.jsonAttributeName = jsonAttributeName;
-        this.normalizedJsonAttributeName = toLowerCase(jsonAttributeName);
         this.mapper = mapper;
+        this.normalizedJsonAttributeName = toLowerCase(jsonAttributeName);
     }
 
     /**
      * {@inheritDoc}
      */
-    public void getLDAPAttributes(Set<String> ldapAttributes) {
-        mapper.getLDAPAttributes(ldapAttributes);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute) {
-        if (resourceAttribute.size() > 0) {
-            String rootName = resourceAttribute.get(0);
-            if (toLowerCase(rootName).equals(normalizedJsonAttributeName)) {
-                JsonPointer relativePointer = resourceAttribute.relativePointer();
-                if (relativePointer == null) {
-                    // User requested the entire contents of this complex
-                    // attribute.
-                    mapper.getLDAPAttributes(ldapAttributes);
-                } else {
-                    // User requested partial contents of this complex
-                    // attribute.
-                    mapper.getLDAPAttributes(ldapAttributes, relativePointer);
-                }
-            }
+    public void getLDAPAttributes(JsonPointer jsonAttribute, Set<String> ldapAttributes) {
+        if (attributeMatchesPointer(jsonAttribute)) {
+            JsonPointer relativePointer = jsonAttribute.relativePointer();
+            mapper.getLDAPAttributes(relativePointer, ldapAttributes);
         }
     }
 
@@ -112,4 +94,9 @@
 
     }
 
+    private boolean attributeMatchesPointer(JsonPointer resourceAttribute) {
+        return resourceAttribute.isEmpty()
+                || toLowerCase(resourceAttribute.get(0)).equals(normalizedJsonAttributeName);
+    }
+
 }
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
index f62c6f1..2d53f3e 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
@@ -19,7 +19,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -37,7 +36,6 @@
  *
  */
 public final class CompositeAttributeMapper implements AttributeMapper {
-    private final Set<String> allLDAPAttributes = new LinkedHashSet<String>();
     private final List<AttributeMapper> attributeMappers = new LinkedList<AttributeMapper>();
 
     /**
@@ -50,23 +48,15 @@
 
     public CompositeAttributeMapper addMapper(AttributeMapper mapper) {
         attributeMappers.add(mapper);
-        mapper.getLDAPAttributes(allLDAPAttributes);
         return this;
     }
 
     /**
      * {@inheritDoc}
      */
-    public void getLDAPAttributes(Set<String> ldapAttributes) {
-        ldapAttributes.addAll(allLDAPAttributes);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute) {
+    public void getLDAPAttributes(JsonPointer jsonAttribute, Set<String> ldapAttributes) {
         for (AttributeMapper attribute : attributeMappers) {
-            attribute.getLDAPAttributes(ldapAttributes, resourceAttribute);
+            attribute.getLDAPAttributes(jsonAttribute, ldapAttributes);
         }
     }
 
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ConstantAttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ConstantAttributeMapper.java
new file mode 100644
index 0000000..2d29263
--- /dev/null
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ConstantAttributeMapper.java
@@ -0,0 +1,79 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyrighted [year] [name of copyright owner]".
+ *
+ * Copyright 2012 ForgeRock AS. All rights reserved.
+ */
+
+package org.forgerock.opendj.rest2ldap;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.forgerock.json.fluent.JsonPointer;
+import org.forgerock.json.fluent.JsonValue;
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.resource.provider.Context;
+
+/**
+ *
+ */
+public class ConstantAttributeMapper implements AttributeMapper {
+
+    private final String jsonAttributeName;
+    private final Object jsonAttributeValue;
+
+    /**
+     * Creates a new constant attribute mapper which maps a single LDAP
+     * attribute to a fixed value.
+     *
+     * @param attributeName
+     *            The name of the simple JSON attribute.
+     * @param attributeValue
+     *            The value of the simple JSON attribute.
+     */
+    public ConstantAttributeMapper(String attributeName, Object attributeValue) {
+        this.jsonAttributeName = attributeName;
+        this.jsonAttributeValue = attributeValue;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void getLDAPAttributes(JsonPointer jsonAttribute, Set<String> ldapAttributes) {
+        // Nothing to do.
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void toJson(Context c, Entry e,
+            final AttributeMapperCompletionHandler<Map<String, Object>> h) {
+        // FIXME: how do we know if the user requested it???
+        Map<String, Object> result =
+                Collections.singletonMap(jsonAttributeName, jsonAttributeValue);
+        h.onSuccess(result);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void toLDAP(Context c, JsonValue v, AttributeMapperCompletionHandler<List<Attribute>> h) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java
index 6b363b7..45f5ead 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java
@@ -67,14 +67,23 @@
         }
     }
 
-    public void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute) {
-        String name = resourceAttribute.leaf();
-        if (name != null) {
+    public void getLDAPAttributes(JsonPointer jsonAttribute, Set<String> ldapAttributes) {
+        switch (jsonAttribute.size()) {
+        case 0:
+            // Requested everything.
+            if (!includedAttributes.isEmpty()) {
+                ldapAttributes.addAll(includedAttributes.values());
+            } else {
+                // All user attributes.
+                ldapAttributes.add("*");
+            }
+            break;
+        default:
+            String name = jsonAttribute.get(0);
             if (isIncludedAttribute(name)) {
                 ldapAttributes.add(name);
-            } else {
-                // FIXME: log something or return a ResourceException?
             }
+            break;
         }
     }
 
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Example.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Example.java
index 651c38d..e807869 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Example.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Example.java
@@ -20,6 +20,7 @@
 import org.forgerock.opendj.ldap.ConnectionFactory;
 import org.forgerock.opendj.ldap.Connections;
 import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Functions;
 import org.forgerock.opendj.ldap.LDAPConnectionFactory;
 import org.forgerock.opendj.ldap.requests.Requests;
 import org.forgerock.resource.framework.JsonResourceProvider;
@@ -68,8 +69,11 @@
                                 .includeAttribute("cn", "sn", "givenName"))).addMapper(
                         new ComplexAttributeMapper("contactInformation",
                                 new CompositeAttributeMapper().addMapper(
-                                        new SimpleAttributeMapper("telephoneNumber")).addMapper(
-                                        new SimpleAttributeMapper("emailAddress", "mail"))));
+                                        new SimpleAttributeMapper("telephoneNumber").withDecoder(
+                                                Functions.byteStringToString()).forceSingleValued(
+                                                true)).addMapper(
+                                        new SimpleAttributeMapper("emailAddress", "mail")
+                                                .forceSingleValued(true))));
         LDAPResource userResource = new LDAPResource(userContainer, userMapper);
         ResourceInvoker userResourceInvoker = new ResourceInvoker();
         userResourceInvoker.resource = userResource; // FIXME: Yuk!
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPResource.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPResource.java
index a0fe6f0..890fb00 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPResource.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPResource.java
@@ -230,12 +230,12 @@
         if (requestedAttributes.isEmpty()) {
             // Full read.
             requestedLDAPAttributes = new LinkedHashSet<String>();
-            attributeMapper.getLDAPAttributes(requestedLDAPAttributes);
+            attributeMapper.getLDAPAttributes(new JsonPointer(), requestedLDAPAttributes);
         } else {
             // Partial read.
             requestedLDAPAttributes = new LinkedHashSet<String>(requestedAttributes.size());
             for (final JsonPointer requestedAttribute : requestedAttributes) {
-                attributeMapper.getLDAPAttributes(requestedLDAPAttributes, requestedAttribute);
+                attributeMapper.getLDAPAttributes(requestedAttribute, requestedLDAPAttributes);
             }
         }
         return requestedLDAPAttributes;
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java
new file mode 100644
index 0000000..9e1dcac
--- /dev/null
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java
@@ -0,0 +1,60 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyrighted [year] [name of copyright owner]".
+ *
+ * Copyright 2012 ForgeRock AS. All rights reserved.
+ */
+
+package org.forgerock.opendj.rest2ldap;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.forgerock.json.fluent.JsonPointer;
+import org.forgerock.json.fluent.JsonValue;
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.resource.provider.Context;
+
+/**
+ *
+ */
+public class ReferenceAttributeMapper implements AttributeMapper {
+
+    // private final EntryContainer referencedContainer;
+
+    /**
+     * {@inheritDoc}
+     */
+    public void getLDAPAttributes(JsonPointer jsonAttribute, Set<String> ldapAttributes) {
+        // TODO Auto-generated method stub
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void toJson(Context c, Entry e, AttributeMapperCompletionHandler<Map<String, Object>> h) {
+        // TODO Auto-generated method stub
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void toLDAP(Context c, JsonValue v, AttributeMapperCompletionHandler<List<Attribute>> h) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
index 3d3b5bf..0c92b63 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
@@ -16,7 +16,7 @@
 
 package org.forgerock.opendj.rest2ldap;
 
-import static org.forgerock.opendj.rest2ldap.Utils.attributeToJson;
+import static org.forgerock.opendj.rest2ldap.Utils.byteStringToJson;
 import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
 
 import java.util.Collections;
@@ -27,7 +27,10 @@
 import org.forgerock.json.fluent.JsonPointer;
 import org.forgerock.json.fluent.JsonValue;
 import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.Function;
+import org.forgerock.opendj.ldap.Functions;
 import org.forgerock.resource.provider.Context;
 
 /**
@@ -39,6 +42,11 @@
     private final String jsonAttributeName;
     private final String normalizedJsonAttributeName;
 
+    private boolean forceSingleValued = false;
+    private Object defaultValue = null;
+    private boolean isReadOnly = false;
+    private Function<ByteString, ?, Void> decoder = null;
+
     /**
      * Creates a new simple attribute mapper which maps a single LDAP attribute
      * to an entry.
@@ -61,26 +69,44 @@
      */
     public SimpleAttributeMapper(String jsonAttributeName, String ldapAttributeName) {
         this.jsonAttributeName = jsonAttributeName;
-        this.normalizedJsonAttributeName = toLowerCase(jsonAttributeName);
         this.ldapAttributeName = ldapAttributeName;
+        this.normalizedJsonAttributeName = toLowerCase(jsonAttributeName);
+    }
+
+    public SimpleAttributeMapper withDefaultValue(Object defaultValue) {
+        this.defaultValue = defaultValue;
+        return this;
+    }
+
+    public SimpleAttributeMapper isReadOnly(boolean readOnly) {
+        this.isReadOnly = readOnly;
+        return this;
+    }
+
+    public SimpleAttributeMapper forceSingleValued(boolean singleValued) {
+        this.forceSingleValued = singleValued;
+        return this;
+    }
+
+    public SimpleAttributeMapper withDecoder(Function<ByteString, ?, Void> f) {
+        this.decoder = f;
+        return this;
     }
 
     /**
      * {@inheritDoc}
      */
-    public void getLDAPAttributes(Set<String> ldapAttributes) {
-        ldapAttributes.add(ldapAttributeName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute) {
-        if (toLowerCase(resourceAttribute.leaf()).equals(normalizedJsonAttributeName)) {
+    public void getLDAPAttributes(JsonPointer jsonAttribute, Set<String> ldapAttributes) {
+        if (attributeMatchesPointer(jsonAttribute)) {
             ldapAttributes.add(ldapAttributeName);
         }
     }
 
+    private boolean attributeMatchesPointer(JsonPointer resourceAttribute) {
+        return resourceAttribute.isEmpty()
+                || toLowerCase(resourceAttribute.get(0)).equals(normalizedJsonAttributeName);
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -88,8 +114,15 @@
             final AttributeMapperCompletionHandler<Map<String, Object>> h) {
         Attribute a = e.getAttribute(ldapAttributeName);
         if (a != null) {
-            Map<String, Object> result =
-                    Collections.singletonMap(jsonAttributeName, attributeToJson(a));
+            Function<ByteString, ?, Void> f =
+                    decoder == null ? Functions.fixedFunction(byteStringToJson(), a) : decoder;
+            final Object value;
+            if (forceSingleValued || a.getAttributeDescription().getAttributeType().isSingleValue()) {
+                value = a.parse().as(f, defaultValue);
+            } else {
+                value = a.parse().asSetOf(f, defaultValue);
+            }
+            Map<String, Object> result = Collections.singletonMap(jsonAttributeName, value);
             h.onSuccess(result);
         }
     }
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
index e0cdf90..2446095 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
@@ -38,9 +38,10 @@
  */
 final class Utils {
 
-    private static final Function<ByteString, Object, Syntax> BYTESTRING_TO_JSON =
-            new Function<ByteString, Object, Syntax>() {
-                public Object apply(final ByteString value, final Syntax syntax) {
+    private static final Function<ByteString, Object, Attribute> BYTESTRING_TO_JSON =
+            new Function<ByteString, Object, Attribute>() {
+                public Object apply(final ByteString value, final Attribute a) {
+                    Syntax syntax = a.getAttributeDescription().getAttributeType().getSyntax();
                     if (syntax.equals(getBooleanSyntax())) {
                         return Functions.byteStringToBoolean().apply(value, null);
                     } else if (syntax.equals(getIntegerSyntax())) {
@@ -72,9 +73,12 @@
         }
     }
 
+    static Function<ByteString, Object, Attribute> byteStringToJson() {
+        return BYTESTRING_TO_JSON;
+    }
+
     static Object attributeToJson(Attribute a) {
-        Syntax syntax = a.getAttributeDescription().getAttributeType().getSyntax();
-        Function<ByteString, Object, Void> f = Functions.fixedFunction(BYTESTRING_TO_JSON, syntax);
+        Function<ByteString, Object, Void> f = Functions.fixedFunction(BYTESTRING_TO_JSON, a);
         boolean isSingleValued = a.getAttributeDescription().getAttributeType().isSingleValue();
         return isSingleValued ? a.parse().as(f) : asList(a.parse().asSetOf(f));
     }
@@ -100,4 +104,5 @@
         }
         return object;
     }
+
 }

--
Gitblit v1.10.0