mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
15.16.2012 eda03abb06f41962772d6439f14a3395ca99bd5e
Checkpoint dev.
4 files added
3 files modified
561 ■■■■ changed files
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java 39 ●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java 178 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/EntryContainer.java 4 ●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/EtagStrategy.java 26 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/IdentityAttributeMapper.java 112 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPResource.java 113 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java 89 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java
@@ -18,6 +18,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.forgerock.json.fluent.JsonPointer;
@@ -33,30 +34,30 @@
public interface AttributeMapper {
    /**
     * Returns an unmodifiable set containing the names of the LDAP attributes
     * required by this attribute mapper. The returned set should only contain
     * the names of attributes found in the LDAP entry directly associated with
     * the resource.
     * Returns an unmodifiable collection containing the names of the LDAP
     * attributes required by this attribute mapper. The returned collection
     * should only contain the names of attributes found in the LDAP entry
     * directly associated with the resource.
     *
     * @return An unmodifiable set containing the names of the LDAP attributes
     *         required by this attribute mapper.
     * @return An unmodifiable collection containing the names of the LDAP
     *         attributes required by this attribute mapper.
     */
    Set<String> getAllLDAPAttributes();
    Collection<String> getAllLDAPAttributes();
    /**
     * Returns an unmodifiable collection containing the names of the LDAP
     * attributes required by this attribute mapper and which are associated
     * with the provided resource attribute. The returned set should only
     * contain the names of attributes found in the LDAP entry directly
     * associated with the resource.
     * Adds the names of the LDAP attributes required by this attribute mapper
     * which are associated with the provided resource attribute.
     * <p>
     * Implementations should only add the names of attributes found in the LDAP
     * entry directly associated with the resource.
     *
     * @param resourceAttribute
     *            The name of the resource attribute requested by the client.
     * @return An unmodifiable collection containing the names of the LDAP
     *         attributes required by this attribute mapper and which are
     *         associated with the provided resource attribute.
     * @param ldapAttributes
     *            The set into which the required LDAP attribute names should be
     *            put.
     */
    Collection<String> getLDAPAttributesFor(JsonPointer resourceAttribute);
    void getLDAPAttributesFor(JsonPointer resourceAttribute, Set<String> ldapAttributes);
    /**
     * Transforms attributes contained in the provided LDAP entry to JSON
@@ -69,10 +70,9 @@
     *
     * @param c
     * @param e
     * @param v
     * @param h
     */
    void toJson(Context c, Entry e, JsonValue v, ResultHandler<JsonValue> h);
    void toJson(Context c, Entry e, ResultHandler<Map<String, Object>> h);
    /**
     * Transforms JSON content in the provided JSON value to LDAP attributes,
@@ -84,10 +84,9 @@
     *
     * @param c
     * @param v
     * @param a
     * @param h
     */
    void toLDAP(Context c, JsonValue v, List<Attribute> a, ResultHandler<Entry> h);
    void toLDAP(Context c, JsonValue v, ResultHandler<List<Attribute>> h);
    // TODO: methods for obtaining schema information (e.g. name, description,
    // type information).
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
New file
@@ -0,0 +1,178 @@
/*
 * 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.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
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.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.ResultHandler;
import org.forgerock.resource.provider.Context;
/**
 *
 */
public final class CompositeAttributeMapper implements AttributeMapper {
    private final Set<String> allLDAPAttributes;
    private final List<AttributeMapper> attributeMappers;
    /**
     * Creates a new composite attribute mapper.
     *
     * @param attributeMappers
     *            The list of attribute mappers.
     */
    public CompositeAttributeMapper(final List<AttributeMapper> attributeMappers) {
        this.attributeMappers = new ArrayList<AttributeMapper>(attributeMappers);
        Set<String> tmp = new LinkedHashSet<String>(attributeMappers.size());
        for (final AttributeMapper mapper : attributeMappers) {
            tmp.addAll(mapper.getAllLDAPAttributes());
        }
        allLDAPAttributes = Collections.unmodifiableSet(tmp);
    }
    /**
     * {@inheritDoc}
     */
    public Set<String> getAllLDAPAttributes() {
        return allLDAPAttributes;
    }
    /**
     * {@inheritDoc}
     */
    public void getLDAPAttributesFor(JsonPointer resourceAttribute, Set<String> ldapAttributes) {
        for (AttributeMapper attribute : attributeMappers) {
            attribute.getLDAPAttributesFor(resourceAttribute, ldapAttributes);
        }
    }
    /**
     * {@inheritDoc}
     */
    public void toJson(Context c, Entry e, final ResultHandler<Map<String, Object>> h) {
        ResultHandler<Map<String, Object>> resultAccumulater =
                new ResultHandler<Map<String, Object>>() {
                    private final AtomicInteger latch = new AtomicInteger(attributeMappers.size());
                    private final List<Map<String, Object>> results =
                            new ArrayList<Map<String, Object>>(latch.get());
                    public void handleErrorResult(ErrorResultException error) {
                        // Ensure that handler is only invoked once.
                        if (latch.getAndSet(0) > 0) {
                            h.handleErrorResult(error);
                        }
                    }
                    public void handleResult(Map<String, Object> result) {
                        synchronized (this) {
                            results.add(result);
                        }
                        if (latch.decrementAndGet() == 0) {
                            final Map<String, Object> mergeResult;
                            switch (results.size()) {
                            case 0:
                                mergeResult = Collections.<String, Object> emptyMap();
                                break;
                            case 1:
                                mergeResult = results.get(0);
                                break;
                            default:
                                mergeResult = new LinkedHashMap<String, Object>();
                                mergeJsonValues(results, mergeResult);
                                break;
                            }
                            h.handleResult(mergeResult);
                        }
                    }
                };
        for (AttributeMapper mapper : attributeMappers) {
            mapper.toJson(c, e, resultAccumulater);
        }
    }
    /**
     * {@inheritDoc}
     */
    public void toLDAP(Context c, JsonValue v, ResultHandler<List<Attribute>> h) {
        // TODO Auto-generated method stub
    }
    /**
     * Merge the provided list of JSON values into a single value.
     *
     * @param srcValues
     *            The source values.
     * @param dstValue
     *            The destination value, into which which the values should be
     *            merged.
     */
    private void mergeJsonValues(List<Map<String, Object>> srcValues, Map<String, Object> dstValue) {
        for (Map<String, Object> value : srcValues) {
            mergeJsonValue(value, dstValue);
        }
    }
    /**
     * Merge one JSON value into another.
     *
     * @param srcValue
     *            The source value.
     * @param dstValue
     *            The destination value, into which which the value should be
     *            merged.
     */
    @SuppressWarnings("unchecked")
    private void mergeJsonValue(Map<String, Object> srcValue, Map<String, Object> dstValue) {
        for (Map.Entry<String, Object> record : srcValue.entrySet()) {
            String key = record.getKey();
            Object newValue = record.getValue();
            Object existingValue = dstValue.get(key);
            if (existingValue == null) {
                // Value is new, so just add it.
                dstValue.put(key, newValue);
            } else if (existingValue instanceof Map && newValue instanceof Map) {
                // Merge two maps - create a new Map, in case the existing one
                // is unmodifiable.
                existingValue =
                        new LinkedHashMap<String, Object>((Map<String, Object>) existingValue);
                mergeJsonValue((Map<String, Object>) newValue, (Map<String, Object>) existingValue);
            } else if (existingValue instanceof List && newValue instanceof List) {
                // Merge two lists- create a new List, in case the existing one
                // is unmodifiable.
                List<Object> tmp = new ArrayList<Object>((List<Object>) existingValue);
                tmp.addAll((List<Object>) newValue);
                existingValue = tmp;
            }
            // Replace the existing value.
            dstValue.put(key, newValue);
        }
    }
}
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/EntryContainer.java
@@ -16,7 +16,7 @@
package org.forgerock.opendj.rest2ldap;
import java.util.Set;
import java.util.Collection;
import org.forgerock.opendj.ldap.ResultHandler;
import org.forgerock.opendj.ldap.SearchResultHandler;
@@ -58,7 +58,7 @@
     * @param h
     *            The result handler.
     */
    public void readEntry(final Context c, final String id, final Set<String> attributes,
    public void readEntry(final Context c, final String id, final Collection<String> attributes,
            final ResultHandler<SearchResultEntry> h) {
        // TODO Auto-generated method stub
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/EtagStrategy.java
New file
@@ -0,0 +1,26 @@
/*
 * 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 org.forgerock.opendj.ldap.Entry;
/**
 *
 */
public interface EtagStrategy {
    String getEtagFromEntry(final Entry entry);
}
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/IdentityAttributeMapper.java
New file
@@ -0,0 +1,112 @@
/*
 * 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 static org.forgerock.opendj.rest2ldap.Utils.getAttributeName;
import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
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.opendj.ldap.ResultHandler;
import org.forgerock.resource.provider.Context;
/**
 *
 */
public final class IdentityAttributeMapper implements AttributeMapper {
    // All user attributes by default.
    private final Map<String, String> includedAttributes = new LinkedHashMap<String, String>();
    private final Map<String, String> excludedAttributes = new LinkedHashMap<String, String>();
    public IdentityAttributeMapper() {
        // No implementation required.
    }
    public IdentityAttributeMapper includeAttribute(String... attributes) {
        for (String attribute : attributes) {
            includedAttributes.put(toLowerCase(attribute), attribute);
        }
        return this;
    }
    public IdentityAttributeMapper excludeAttribute(String... attributes) {
        for (String attribute : attributes) {
            excludedAttributes.put(toLowerCase(attribute), attribute);
        }
        return this;
    }
    public Collection<String> getAllLDAPAttributes() {
        if (!includedAttributes.isEmpty()) {
            return includedAttributes.values();
        } else {
            // All user attributes.
            return Collections.emptySet();
        }
    }
    public void getLDAPAttributesFor(JsonPointer resourceAttribute, Set<String> ldapAttributes) {
        String name = resourceAttribute.leaf();
        if (name != null) {
            if (isIncludedAttribute(name)) {
                ldapAttributes.add(name);
            } else {
                // FIXME: log something or return a ResourceException?
            }
        }
    }
    public void toJson(Context c, Entry e, ResultHandler<Map<String, Object>> h) {
        Map<String, Object> result = new LinkedHashMap<String, Object>(e.getAttributeCount());
        for (Attribute a : e.getAllAttributes()) {
            String name = getAttributeName(a);
            if (isIncludedAttribute(name)) {
                result.put(name, Utils.attributeToJson(a));
            }
        }
    }
    private boolean isIncludedAttribute(String name) {
        String lowerName = toLowerCase(name);
        // Ignore the requested attribute if it has been excluded.
        if (excludedAttributes.containsKey(lowerName)) {
            return false;
        }
        // Include all attributes by default.
        if (includedAttributes.isEmpty() || includedAttributes.containsKey(lowerName)) {
            return true;
        }
        return false;
    }
    public void toLDAP(Context c, JsonValue v, ResultHandler<List<Attribute>> h) {
        // TODO:
    }
}
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPResource.java
@@ -17,16 +17,24 @@
package org.forgerock.opendj.rest2ldap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
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.Entry;
import org.forgerock.opendj.ldap.AssertionFailureException;
import org.forgerock.opendj.ldap.AuthenticationException;
import org.forgerock.opendj.ldap.AuthorizationException;
import org.forgerock.opendj.ldap.ConnectionException;
import org.forgerock.opendj.ldap.EntryNotFoundException;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.MultipleEntriesFoundException;
import org.forgerock.opendj.ldap.ResultHandler;
import org.forgerock.opendj.ldap.SearchResultHandler;
import org.forgerock.opendj.ldap.TimeoutResultException;
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.responses.SearchResultReference;
@@ -53,23 +61,27 @@
 *
 */
public class LDAPResource implements Resource {
    private Set<String> allLDAPAttributes;
    private final EntryContainer container;
    private final List<AttributeMapper> mappers;
    private final EntryContainer entryContainer;
    private final AttributeMapper attributeMapper;
    private final EtagStrategy etagStrategy;
    /**
     * Creates a new LDAP resource.
     * 
     * @param container
     * @param entryContainer
     *            The entry container which will be used to interact with the
     *            LDAP server.
     * @param mappers
     *            The list of attribute mappers.
     * @param etagStrategy
     *            The algorithm which should be used to obtain a resource's etag
     *            from an entry.
     * @param attributeMapper
     *            The attribute mapper.
     */
    public LDAPResource(final EntryContainer container, final List<AttributeMapper> mappers) {
        this.container = container;
        this.mappers = mappers;
        cacheAllLDAPAttributes();
    public LDAPResource(final EntryContainer entryContainer, final EtagStrategy etagStrategy,
            final AttributeMapper attributeMapper) {
        this.entryContainer = entryContainer;
        this.etagStrategy = etagStrategy;
        this.attributeMapper = attributeMapper;
    }
    /**
@@ -125,7 +137,7 @@
                public boolean handleEntry(final SearchResultEntry entry) {
                    // TODO: should the resource or the container define the ID
                    // mapping?
                    resourceIDs.add(container.getIDFromEntry(entry));
                    resourceIDs.add(entryContainer.getIDFromEntry(entry));
                    return true;
                }
@@ -135,7 +147,7 @@
                public boolean handleReference(final SearchResultReference reference) {
                    // TODO: should this be classed as an error since rest2ldap
                    // assumes entries are all colocated.
                    // assumes entries are all colocated?
                    return true;
                }
@@ -143,13 +155,13 @@
                    out.setResult(id, null, new JsonValue(resourceIDs));
                }
            };
            container.listEntries(context, handler);
            entryContainer.listEntries(context, handler);
        } else {
            // Read a single entry.
            // TODO: Determine the set of LDAP attributes that need to be read.
            final Set<JsonPointer> requestedAttributes = new LinkedHashSet<JsonPointer>();
            final Set<String> requestedLDAPAttributes =
            final Collection<String> requestedLDAPAttributes =
                    getRequestedLDAPAttributes(requestedAttributes);
            final ResultHandler<SearchResultEntry> handler =
@@ -159,23 +171,22 @@
                        }
                        public void handleResult(final SearchResultEntry entry) {
                            final String revision = getRevisionFromEntry(entry);
                            final ResultHandler<JsonValue> mapHandler =
                                    new ResultHandler<JsonValue>() {
                            final String revision = etagStrategy.getEtagFromEntry(entry);
                            final ResultHandler<Map<String, Object>> mapHandler =
                                    new ResultHandler<Map<String, Object>>() {
                                        public void handleErrorResult(
                                                final ErrorResultException error) {
                                            out.setFailure(adaptErrorResult(error));
                                        }
                                        public void handleResult(final JsonValue result) {
                                            out.setResult(id, revision, result);
                                        public void handleResult(final Map<String, Object> result) {
                                            out.setResult(id, revision, new JsonValue(result));
                                        }
                                    };
                            mapEntryToJson(context, requestedAttributes, entry, mapHandler);
                            attributeMapper.toJson(context, entry, mapHandler);
                        }
                    };
            container.readEntry(context, id, requestedLDAPAttributes, handler);
            entryContainer.readEntry(context, id, requestedLDAPAttributes, handler);
        }
    }
@@ -187,20 +198,35 @@
        out.setFailure(new NotSupportedException("Not yet implemented"));
    }
    private ResourceException adaptErrorResult(final ErrorResultException error) {
        // TODO Auto-generated method stub
        return null;
    }
    /**
     * Caches the set of LDAP attributes associated with all of this resource's
     * mappers.
     * Adapts an LDAP result code to a resource exception.
     *
     * @param error
     *            The LDAP error that should be adapted.
     * @return The equivalent resource exception.
     */
    private void cacheAllLDAPAttributes() {
        allLDAPAttributes = new LinkedHashSet<String>(mappers.size());
        for (final AttributeMapper mapper : mappers) {
            allLDAPAttributes.addAll(mapper.getAllLDAPAttributes());
    private ResourceException adaptErrorResult(final ErrorResultException error) {
        int resourceResultCode;
        try {
            throw error;
        } catch (AssertionFailureException e) {
            resourceResultCode = ResourceException.VERSION_MISMATCH;
        } catch (AuthenticationException e) {
            resourceResultCode = 401;
        } catch (AuthorizationException e) {
            resourceResultCode = ResourceException.FORBIDDEN;
        } catch (ConnectionException e) {
            resourceResultCode = ResourceException.UNAVAILABLE;
        } catch (EntryNotFoundException e) {
            resourceResultCode = ResourceException.NOT_FOUND;
        } catch (MultipleEntriesFoundException e) {
            resourceResultCode = ResourceException.INTERNAL_ERROR;
        } catch (TimeoutResultException e) {
            resourceResultCode = 408;
        } catch (ErrorResultException e) {
            resourceResultCode = ResourceException.INTERNAL_ERROR;
        }
        return ResourceException.getException(resourceResultCode, null, error.getMessage(), error);
    }
    /**
@@ -212,31 +238,18 @@
     * @return The set of LDAP attributes associated with the resource
     *         attributes.
     */
    private Set<String> getRequestedLDAPAttributes(final Set<JsonPointer> requestedAttributes) {
    private Collection<String> getRequestedLDAPAttributes(final Set<JsonPointer> requestedAttributes) {
        if (requestedAttributes.isEmpty()) {
            // Full read.
            return allLDAPAttributes;
            return attributeMapper.getAllLDAPAttributes();
        } else {
            // Partial read.
            final Set<String> requestedLDAPAttributes =
                    new LinkedHashSet<String>(requestedAttributes.size());
            for (final JsonPointer requestedAttribute : requestedAttributes) {
                for (final AttributeMapper mapper : mappers) {
                    requestedLDAPAttributes.addAll(mapper.getLDAPAttributesFor(requestedAttribute));
                }
                attributeMapper.getLDAPAttributesFor(requestedAttribute, requestedLDAPAttributes);
            }
            return requestedLDAPAttributes;
        }
    }
    private String getRevisionFromEntry(final SearchResultEntry entry) {
        // TODO Auto-generated method stub
        return null;
    }
    private void mapEntryToJson(final Context c, final Set<JsonPointer> requestedAttributes,
            final Entry result, final ResultHandler<JsonValue> h) {
        // TODO Auto-generated method stub
    }
}
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
New file
@@ -0,0 +1,89 @@
/*
 * 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 static org.forgerock.opendj.ldap.schema.CoreSchema.getBooleanSyntax;
import static org.forgerock.opendj.ldap.schema.CoreSchema.getGeneralizedTimeSyntax;
import static org.forgerock.opendj.ldap.schema.CoreSchema.getIntegerSyntax;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import javax.xml.bind.DatatypeConverter;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.Function;
import org.forgerock.opendj.ldap.Functions;
import org.forgerock.opendj.ldap.schema.Syntax;
/**
 *
 */
public 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) {
                    if (syntax.equals(getBooleanSyntax())) {
                        return Functions.byteStringToBoolean().apply(value, null);
                    } else if (syntax.equals(getIntegerSyntax())) {
                        return Functions.byteStringToLong().apply(value, null);
                    } else if (syntax.equals(getGeneralizedTimeSyntax())) {
                        return DatatypeConverter.printDateTime(Functions
                                .byteStringToGeneralizedTime().apply(value, null).toCalendar());
                    } else if (syntax.isHumanReadable()) {
                        return Functions.byteStringToString().apply(value, null);
                    } else {
                        // Base 64 encoded binary.
                        return DatatypeConverter.printBase64Binary(value.toByteArray());
                    }
                }
            };
    // Prevent instantiation.
    private Utils() {
        // No implementation required.
    }
    private static <T> List<T> asList(Collection<T> c) {
        if (c instanceof List) {
            return (List<T>) c;
        } else {
            List<T> result = new ArrayList<T>(c.size());
            result.addAll(c);
            return result;
        }
    }
    public static Object attributeToJson(Attribute a) {
        Syntax syntax = a.getAttributeDescription().getAttributeType().getSyntax();
        Function<ByteString, Object, Void> f = Functions.fixedFunction(BYTESTRING_TO_JSON, syntax);
        boolean isSingleValued = a.getAttributeDescription().getAttributeType().isSingleValue();
        return isSingleValued ? a.parse().as(f) : asList(a.parse().asSetOf(f));
    }
    public static String getAttributeName(Attribute a) {
        return a.getAttributeDescription().withoutOption("binary").toString();
    }
    public static String toLowerCase(String s) {
        return s != null ? s.toLowerCase(Locale.ENGLISH) : null;
    }
}