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 2013-2016 ForgeRock AS. 015 */ 016 017package org.forgerock.json.resource; 018 019import java.util.Collection; 020 021import org.forgerock.api.models.ApiDescription; 022import org.forgerock.http.ApiProducer; 023import org.forgerock.services.context.Context; 024import org.forgerock.services.descriptor.Describable; 025import org.forgerock.util.promise.Promise; 026 027/** 028 * An abstract base class from which connection wrappers may be easily 029 * implemented. The default implementation of each method is to delegate to the 030 * wrapped connection. 031 * 032 * @param <C> 033 * The type of wrapped connection. 034 */ 035public abstract class AbstractConnectionWrapper<C extends Connection> 036 implements Connection, Describable<ApiDescription, Request> { 037 /** 038 * The wrapped connection. 039 */ 040 protected final C connection; 041 042 /** 043 * Creates a new connection wrapper. 044 * 045 * @param connection 046 * The connection to be wrapped. 047 */ 048 protected AbstractConnectionWrapper(final C connection) { 049 this.connection = connection; 050 } 051 052 /** 053 * Optional Context-transformation function if the implementer has 054 * requirements to override the {@link Context} provided in the 055 * {@link Connection}'s method invocations. 056 * <p> 057 * The default implementation is a pass-through no-op. 058 * 059 * @param context 060 * the request context 061 * @return the transformed context 062 */ 063 protected Context transform(Context context) { 064 return context; 065 } 066 067 /** 068 * {@inheritDoc} 069 * <p> 070 * The default implementation is to delegate. 071 */ 072 public ActionResponse action(Context context, ActionRequest request) throws ResourceException { 073 return connection.action(transform(context), request); 074 } 075 076 /** 077 * {@inheritDoc} 078 * <p> 079 * The default implementation is to delegate. 080 */ 081 public Promise<ActionResponse, ResourceException> actionAsync(Context context, ActionRequest request) { 082 return connection.actionAsync(transform(context), request); 083 } 084 085 /** 086 * {@inheritDoc} 087 * <p> 088 * The default implementation is to delegate. 089 */ 090 public void close() { 091 connection.close(); 092 } 093 094 /** 095 * {@inheritDoc} 096 * <p> 097 * The default implementation is to delegate. 098 */ 099 public ResourceResponse create(Context context, CreateRequest request) throws ResourceException { 100 return connection.create(transform(context), request); 101 } 102 103 /** 104 * {@inheritDoc} 105 * <p> 106 * The default implementation is to delegate. 107 */ 108 public Promise<ResourceResponse, ResourceException> createAsync(Context context, CreateRequest request) { 109 return connection.createAsync(transform(context), request); 110 } 111 112 /** 113 * {@inheritDoc} 114 * <p> 115 * The default implementation is to delegate. 116 */ 117 public ResourceResponse delete(Context context, DeleteRequest request) throws ResourceException { 118 return connection.delete(transform(context), request); 119 } 120 121 /** 122 * {@inheritDoc} 123 * <p> 124 * The default implementation is to delegate. 125 */ 126 public Promise<ResourceResponse, ResourceException> deleteAsync(Context context, DeleteRequest request) { 127 return connection.deleteAsync(transform(context), request); 128 } 129 130 /** 131 * {@inheritDoc} 132 * <p> 133 * The default implementation is to delegate. 134 */ 135 public boolean isClosed() { 136 return connection.isClosed(); 137 } 138 139 /** 140 * {@inheritDoc} 141 * <p> 142 * The default implementation is to delegate. 143 */ 144 public boolean isValid() { 145 return connection.isValid(); 146 } 147 148 /** 149 * {@inheritDoc} 150 * <p> 151 * The default implementation is to delegate. 152 */ 153 public ResourceResponse patch(Context context, PatchRequest request) throws ResourceException { 154 return connection.patch(transform(context), request); 155 } 156 157 /** 158 * {@inheritDoc} 159 * <p> 160 * The default implementation is to delegate. 161 */ 162 public Promise<ResourceResponse, ResourceException> patchAsync(Context context, PatchRequest request) { 163 return connection.patchAsync(transform(context), request); 164 } 165 166 /** 167 * {@inheritDoc} 168 * <p> 169 * The default implementation is to delegate. 170 */ 171 public QueryResponse query(Context context, QueryRequest request, QueryResourceHandler handler) 172 throws ResourceException { 173 return connection.query(transform(context), request, handler); 174 } 175 176 /** 177 * {@inheritDoc} 178 * <p> 179 * The default implementation is to delegate. 180 */ 181 public QueryResponse query(Context context, QueryRequest request, 182 Collection<? super ResourceResponse> results) throws ResourceException { 183 return connection.query(transform(context), request, results); 184 } 185 186 /** 187 * {@inheritDoc} 188 * <p> 189 * The default implementation is to delegate. 190 */ 191 public Promise<QueryResponse, ResourceException> queryAsync(Context context, 192 QueryRequest request, QueryResourceHandler handler) { 193 return connection.queryAsync(transform(context), request, handler); 194 } 195 196 /** 197 * {@inheritDoc} 198 * <p> 199 * The default implementation is to delegate. 200 */ 201 public ResourceResponse read(Context context, ReadRequest request) throws ResourceException { 202 return connection.read(transform(context), request); 203 } 204 205 /** 206 * {@inheritDoc} 207 * <p> 208 * The default implementation is to delegate. 209 */ 210 public Promise<ResourceResponse, ResourceException> readAsync(Context context, ReadRequest request) { 211 return connection.readAsync(transform(context), request); 212 } 213 214 /** 215 * {@inheritDoc} 216 * <p> 217 * The default implementation is to delegate. 218 */ 219 public ResourceResponse update(Context context, UpdateRequest request) throws ResourceException { 220 return connection.update(transform(context), request); 221 } 222 223 /** 224 * {@inheritDoc} 225 * <p> 226 * The default implementation is to delegate. 227 */ 228 public Promise<ResourceResponse, ResourceException> updateAsync(Context context, UpdateRequest request) { 229 return connection.updateAsync(transform(context), request); 230 } 231 232 @Override 233 @SuppressWarnings("unchecked") 234 public ApiDescription api(ApiProducer<ApiDescription> producer) { 235 if (connection instanceof Describable) { 236 return ((Describable<ApiDescription, Request>) connection).api(producer); 237 } 238 return null; 239 } 240 241 @Override 242 @SuppressWarnings("unchecked") 243 public ApiDescription handleApiRequest(Context context, Request request) { 244 if (connection instanceof Describable) { 245 return ((Describable<ApiDescription, Request>) connection) 246 .handleApiRequest(context, request); 247 } 248 throw new UnsupportedOperationException("Connection is not describable"); 249 } 250 251 @Override 252 public void addDescriptorListener(Describable.Listener listener) { 253 if (connection instanceof Describable) { 254 ((Describable) connection).addDescriptorListener(listener); 255 } 256 } 257 258 @Override 259 public void removeDescriptorListener(Describable.Listener listener) { 260 if (connection instanceof Describable) { 261 ((Describable) connection).removeDescriptorListener(listener); 262 } 263 } 264}