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

Matthew Swift
31.01.2013 b0a81eda9a0b2717e90dee49af53adc71f7cc3dc
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
@@ -11,26 +11,29 @@
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2012 ForgeRock AS.
 * Copyright 2012-2013 ForgeRock AS.
 */
package org.forgerock.opendj.rest2ldap;
import static org.forgerock.opendj.rest2ldap.Utils.accumulate;
import static org.forgerock.opendj.rest2ldap.Utils.transform;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
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.json.resource.ResourceException;
import org.forgerock.json.resource.ResultHandler;
import org.forgerock.json.resource.ServerContext;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.Function;
/**
 * An attribute mapper which combines the results of a set of subordinate
@@ -62,9 +65,10 @@
     * {@inheritDoc}
     */
    @Override
    public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) {
    public void getLDAPAttributes(final Context c, final JsonPointer jsonAttribute,
            final Set<String> ldapAttributes) {
        for (final AttributeMapper attribute : attributeMappers) {
            attribute.getLDAPAttributes(jsonAttribute, ldapAttributes);
            attribute.getLDAPAttributes(c, jsonAttribute, ldapAttributes);
        }
    }
@@ -72,49 +76,68 @@
     * {@inheritDoc}
     */
    @Override
    public void toJSON(final ServerContext c, final Entry e,
            final ResultHandler<Map<String, Object>> h) {
        final 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 getLDAPFilter(final Context c, final FilterType type,
            final JsonPointer jsonAttribute, final String operator, final Object valueAssertion,
            final ResultHandler<Filter> h) {
        final ResultHandler<Filter> handler =
                accumulate(attributeMappers.size(), transform(
                        new Function<List<Filter>, Filter, Void>() {
                            @Override
                            public Filter apply(final List<Filter> value, final Void p) {
                                // Remove unmapped filters and combine using logical-OR.
                                final Iterator<Filter> i = value.iterator();
                                while (i.hasNext()) {
                                    final Filter f = i.next();
                                    if (f == null) {
                                        // No mapping so remove.
                                        i.remove();
                                    } else if (f == c.getConfig().getFalseFilter()) {
                                        return c.getConfig().getFalseFilter();
                                    } else if (f == c.getConfig().getTrueFilter()) {
                                        return c.getConfig().getTrueFilter();
                                    }
                                }
                                switch (value.size()) {
                                case 0:
                                    // No mappings found.
                                    return null;
                                case 1:
                                    return value.get(0);
                                default:
                                    return Filter.or(value);
                                }
                            }
                        }, h));
        for (final AttributeMapper subMapper : attributeMappers) {
            subMapper.getLDAPFilter(c, type, jsonAttribute, operator, valueAssertion, handler);
        }
    }
            @Override
            public void handleError(final ResourceException e) {
                // Ensure that handler is only invoked once.
                if (latch.getAndSet(0) > 0) {
                    h.handleError(e);
                }
            }
            @Override
            public void handleResult(final Map<String, Object> result) {
                if (result != null && !result.isEmpty()) {
                    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);
                }
            }
        };
    /**
     * {@inheritDoc}
     */
    @Override
    public void toJSON(final Context c, final Entry e, final ResultHandler<Map<String, Object>> h) {
        final ResultHandler<Map<String, Object>> handler =
                accumulate(attributeMappers.size(), transform(
                        new Function<List<Map<String, Object>>, Map<String, Object>, Void>() {
                            @Override
                            public Map<String, Object> apply(final List<Map<String, Object>> value,
                                    final Void p) {
                                switch (value.size()) {
                                case 0:
                                    return Collections.<String, Object> emptyMap();
                                case 1:
                                    return value.get(0) != null ? value.get(0) : Collections
                                            .<String, Object> emptyMap();
                                default:
                                    return mergeJsonValues(value,
                                            new LinkedHashMap<String, Object>());
                                }
                            }
                        }, h));
        for (final AttributeMapper mapper : attributeMappers) {
            mapper.toJSON(c, e, resultAccumulater);
            mapper.toJSON(c, e, handler);
        }
    }
@@ -122,21 +145,10 @@
     * {@inheritDoc}
     */
    @Override
    public void toLDAP(final ServerContext c, final JsonValue v,
            final ResultHandler<List<Attribute>> h) {
    public void toLDAP(final Context c, final JsonValue v, final ResultHandler<List<Attribute>> h) {
        // TODO Auto-generated method stub
    }
    /**
     * 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(final Map<String, Object> srcValue,
            final Map<String, Object> dstValue) {
@@ -150,8 +162,8 @@
            } 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);
                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
@@ -166,19 +178,13 @@
        }
    }
    /**
     * 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(final List<Map<String, Object>> srcValues,
    private Map<String, Object> mergeJsonValues(final List<Map<String, Object>> srcValues,
            final Map<String, Object> dstValue) {
        for (final Map<String, Object> value : srcValues) {
            mergeJsonValue(value, dstValue);
            if (value != null) {
                mergeJsonValue(value, dstValue);
            }
        }
        return dstValue;
    }
}