From b0a81eda9a0b2717e90dee49af53adc71f7cc3dc Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 31 Jan 2013 18:01:23 +0000
Subject: [PATCH] Fix OPENDJ-690: Rest2LDAP - Implement basic search support

---
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java |  149 ++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 127 insertions(+), 22 deletions(-)

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 9d83322..9a66c9c 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
@@ -11,7 +11,7 @@
  * 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;
 
@@ -21,13 +21,18 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.xml.bind.DatatypeConverter;
 
+import org.forgerock.json.resource.ResourceException;
+import org.forgerock.json.resource.ResultHandler;
 import org.forgerock.opendj.ldap.Attribute;
 import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.Filter;
 import org.forgerock.opendj.ldap.Function;
 import org.forgerock.opendj.ldap.Functions;
 import org.forgerock.opendj.ldap.schema.Syntax;
@@ -36,37 +41,85 @@
  * Internal utility methods.
  */
 final class Utils {
+    /**
+     * Implementation class for {@link #accumulate}.
+     *
+     * @param <V>
+     *            The type of result.
+     */
+    private static final class AccumulatingResultHandler<V> implements ResultHandler<V> {
+        private final ResultHandler<List<V>> handler;
+        private final AtomicInteger latch;
+        private final List<V> results;
+
+        private AccumulatingResultHandler(final int size, final ResultHandler<List<V>> handler) {
+            this.latch = new AtomicInteger(size);
+            this.results = new ArrayList<V>(size);
+            this.handler = handler;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void handleError(final ResourceException e) {
+            // Ensure that handler is only invoked once.
+            if (latch.getAndSet(0) > 0) {
+                handler.handleError(e);
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void handleResult(final V result) {
+            synchronized (results) {
+                results.add(result);
+            }
+            if (latch.decrementAndGet() == 0) {
+                handler.handleResult(results);
+            }
+        }
+
+    }
 
     // @Checkstyle:off
     private static final Function<ByteString, Object, Attribute> BYTESTRING_TO_JSON =
             new Function<ByteString, Object, Attribute>() {
-        @Override
-        public Object apply(final ByteString value, final Attribute a) {
-            final Syntax syntax = a.getAttributeDescription().getAttributeType().getSyntax();
-            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());
-            }
-        }
-    };
-    // @Checkstyle:on
+                @Override
+                public Object apply(final ByteString value, final Attribute a) {
+                    final Syntax syntax =
+                            a.getAttributeDescription().getAttributeType().getSyntax();
+                    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());
+                    }
+                }
+            };
+
+    static <V> ResultHandler<V> accumulate(final int size, final ResultHandler<List<V>> handler) {
+        return new AccumulatingResultHandler<V>(size, handler);
+    }
 
     static Object attributeToJson(final Attribute a) {
         final Function<ByteString, Object, Void> f = Functions.fixedFunction(BYTESTRING_TO_JSON, a);
-        final boolean isSingleValued = a.getAttributeDescription().getAttributeType()
-                .isSingleValue();
+        final boolean isSingleValued =
+                a.getAttributeDescription().getAttributeType().isSingleValue();
         return isSingleValued ? a.parse().as(f) : asList(a.parse().asSetOf(f));
     }
 
+    // @Checkstyle:on
+
     static Function<ByteString, Object, Attribute> byteStringToJson() {
         return BYTESTRING_TO_JSON;
     }
@@ -89,10 +142,62 @@
         return a.getAttributeDescription().withoutOption("binary").toString();
     }
 
+    static Filter toFilter(final Context c, final FilterType type, final String ldapAttribute,
+            final Object valueAssertion) {
+        final String v = String.valueOf(valueAssertion);
+        final Filter filter;
+        switch (type) {
+        case CONTAINS:
+            filter = Filter.substrings(ldapAttribute, null, Collections.singleton(v), null);
+            break;
+        case STARTS_WITH:
+            filter = Filter.substrings(ldapAttribute, v, null, null);
+            break;
+        case EQUAL_TO:
+            filter = Filter.equality(ldapAttribute, v);
+            break;
+        case GREATER_THAN:
+            filter = Filter.greaterThan(ldapAttribute, v);
+            break;
+        case GREATER_THAN_OR_EQUAL_TO:
+            filter = Filter.greaterOrEqual(ldapAttribute, v);
+            break;
+        case LESS_THAN:
+            filter = Filter.lessThan(ldapAttribute, v);
+            break;
+        case LESS_THAN_OR_EQUAL_TO:
+            filter = Filter.lessOrEqual(ldapAttribute, v);
+            break;
+        case PRESENT:
+            filter = Filter.present(ldapAttribute);
+            break;
+        case EXTENDED:
+        default:
+            filter = c.getConfig().getFalseFilter(); // Not supported.
+            break;
+        }
+        return filter;
+    }
+
     static String toLowerCase(final String s) {
         return s != null ? s.toLowerCase(Locale.ENGLISH) : null;
     }
 
+    static <M, N> ResultHandler<M> transform(final Function<M, N, Void> f,
+            final ResultHandler<N> handler) {
+        return new ResultHandler<M>() {
+            @Override
+            public void handleError(final ResourceException error) {
+                handler.handleError(error);
+            }
+
+            @Override
+            public void handleResult(final M result) {
+                handler.handleResult(f.apply(result, null));
+            }
+        };
+    }
+
     private static <T> List<T> asList(final Collection<T> c) {
         if (c instanceof List) {
             return (List<T>) c;

--
Gitblit v1.10.0