001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2016 ForgeRock AS.
015 */
016package org.forgerock.opendj.rest2ldap;
017
018import org.forgerock.api.models.ApiDescription;
019import org.forgerock.http.ApiProducer;
020import org.forgerock.json.resource.ActionRequest;
021import org.forgerock.json.resource.ActionResponse;
022import org.forgerock.json.resource.CreateRequest;
023import org.forgerock.json.resource.DeleteRequest;
024import org.forgerock.json.resource.PatchRequest;
025import org.forgerock.json.resource.QueryRequest;
026import org.forgerock.json.resource.QueryResourceHandler;
027import org.forgerock.json.resource.QueryResponse;
028import org.forgerock.json.resource.ReadRequest;
029import org.forgerock.json.resource.Request;
030import org.forgerock.json.resource.RequestHandler;
031import org.forgerock.json.resource.ResourceException;
032import org.forgerock.json.resource.ResourceResponse;
033import org.forgerock.json.resource.UpdateRequest;
034import org.forgerock.services.context.Context;
035import org.forgerock.services.descriptor.Describable;
036import org.forgerock.util.Reject;
037import org.forgerock.util.promise.Promise;
038
039/** Decorator for a request handler that can return an api descriptor of the underlying handler. */
040public class DescribableRequestHandler implements RequestHandler, Describable<ApiDescription, Request> {
041    private final RequestHandler delegate;
042    private final Describable<ApiDescription, Request> describableDelegate;
043    private ApiDescription api;
044
045    /**
046     * Builds an object decorating the provided handler.
047     *
048     * @param handler
049     *          the handler to decorate.
050     */
051    @SuppressWarnings("unchecked")
052    public DescribableRequestHandler(final RequestHandler handler) {
053        this.delegate = Reject.checkNotNull(handler);
054        this.describableDelegate = delegate instanceof Describable
055            ? (Describable<ApiDescription, Request>) delegate
056            : null;
057    }
058
059    @Override
060    public Promise<ActionResponse, ResourceException> handleAction(Context context, ActionRequest request) {
061        return delegate.handleAction(wrap(context), request);
062    }
063
064    @Override
065    public Promise<ResourceResponse, ResourceException> handleCreate(Context context, CreateRequest request) {
066        return delegate.handleCreate(wrap(context), request);
067    }
068
069    @Override
070    public Promise<ResourceResponse, ResourceException> handleDelete(Context context, DeleteRequest request) {
071        return delegate.handleDelete(wrap(context), request);
072    }
073
074    @Override
075    public Promise<ResourceResponse, ResourceException> handlePatch(Context context, PatchRequest request) {
076        return delegate.handlePatch(wrap(context), request);
077    }
078
079    @Override
080    public Promise<QueryResponse, ResourceException> handleQuery(
081            Context context, QueryRequest request, QueryResourceHandler handler) {
082        return delegate.handleQuery(wrap(context), request, handler);
083    }
084
085    @Override
086    public Promise<ResourceResponse, ResourceException> handleRead(Context context, ReadRequest request) {
087        return delegate.handleRead(wrap(context), request);
088    }
089
090    @Override
091    public Promise<ResourceResponse, ResourceException> handleUpdate(Context context, UpdateRequest request) {
092        return delegate.handleUpdate(wrap(context), request);
093    }
094
095    /**
096     * Allows sub classes to wrap the provided context and return the wrapping context.
097     *
098     * @param context
099     *          the context to wrap
100     * @return the wrapping context that should be used
101     */
102    protected Context wrap(final Context context) {
103        return context;
104    }
105
106    @Override
107    public ApiDescription api(ApiProducer<ApiDescription> producer) {
108        if (describableDelegate != null) {
109            api = describableDelegate.api(producer);
110        }
111        return api;
112    }
113
114    @Override
115    public ApiDescription handleApiRequest(Context context, Request request) {
116        return api;
117    }
118
119    @Override
120    public void addDescriptorListener(Describable.Listener listener) {
121        if (describableDelegate != null) {
122            describableDelegate.addDescriptorListener(listener);
123        }
124    }
125
126    @Override
127    public void removeDescriptorListener(Describable.Listener listener) {
128        if (describableDelegate != null) {
129            describableDelegate.removeDescriptorListener(listener);
130        }
131    }
132}