001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.isis.viewer.restfulobjects.applib.client; 020 021import java.util.Map; 022 023import javax.ws.rs.core.MediaType; 024import javax.ws.rs.core.MultivaluedMap; 025import javax.ws.rs.core.UriBuilder; 026 027import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; 028import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation; 029import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod; 030import org.apache.isis.viewer.restfulobjects.applib.client.RestfulRequest.RequestParameter; 031import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils; 032import org.jboss.resteasy.client.ClientExecutor; 033import org.jboss.resteasy.client.ClientRequest; 034import org.jboss.resteasy.specimpl.UriBuilderImpl; 035 036/** 037 * Configures the body, query string etc of a {@link ClientRequest}. 038 * 039 * <p> 040 * Needed because, unfortunately, {@link ClientRequest} does not seem to allow 041 * the query string to be set directly (only 042 * {@link ClientRequest#getQueryParameters() query parameters}). Instead, it is 043 * necessary to {@link UriBuilderImpl#replaceQuery(String) use} its underlying 044 * {@link UriBuilderImpl}. 045 */ 046public class ClientRequestConfigurer { 047 048 public static ClientRequestConfigurer create(final ClientExecutor executor, final String uriTemplate) { 049 final UriBuilder uriBuilder = new UriBuilderImpl().uriTemplate(uriTemplate); 050 final ClientRequest clientRequest = executor.createRequest(uriBuilder); 051 return new ClientRequestConfigurer(clientRequest, uriBuilder); 052 } 053 054 private final ClientRequest clientRequest; 055 private final UriBuilder uriBuilder; 056 057 ClientRequestConfigurer(final ClientRequest clientRequest, final UriBuilder uriBuilder) { 058 this.clientRequest = clientRequest; 059 this.uriBuilder = uriBuilder; 060 } 061 062 public ClientRequestConfigurer accept(final MediaType mediaType) { 063 clientRequest.accept(mediaType); 064 return this; 065 } 066 067 public ClientRequestConfigurer header(final String name, final String value) { 068 clientRequest.header(name, value); 069 return this; 070 } 071 072 /** 073 * Prerequisite to {@link #configureArgs(JsonRepresentation)} or 074 * {@link #configureArgs(Map)}. 075 */ 076 public ClientRequestConfigurer setHttpMethod(final RestfulHttpMethod httpMethod) { 077 clientRequest.setHttpMethod(httpMethod.getJavaxRsMethod()); 078 return this; 079 } 080 081 /** 082 * Used when creating a request with arguments to execute. 083 * 084 * <p> 085 * Typical flow is: 086 * <ul> 087 * <li> {@link RestfulClient#createRequest(RestfulHttpMethod, String)} 088 * <li> {@link RestfulRequest#withArg(RequestParameter, Object)} for each arg 089 * <li> {@link RestfulRequest#execute()} - which calls this method. 090 * </ul> 091 */ 092 public ClientRequestConfigurer configureArgs(final Map<RequestParameter<?>, Object> args) { 093 if (clientRequest.getHttpMethod() == null) { 094 throw new IllegalStateException("Must set up http method first"); 095 } 096 097 final JsonRepresentation argsAsMap = JsonRepresentation.newMap(); 098 for (final RequestParameter<?> requestParam : args.keySet()) { 099 put(args, requestParam, argsAsMap); 100 } 101 getHttpMethod().setUpArgs(this, argsAsMap); 102 return this; 103 } 104 105 private <P> void put(final Map<RequestParameter<?>, Object> args, final RequestParameter<P> requestParam, final JsonRepresentation argsAsMap) { 106 @SuppressWarnings("unchecked") 107 final P value = (P) args.get(requestParam); 108 final String valueStr = requestParam.getParser().asString(value); 109 argsAsMap.mapPut(requestParam.getName(), valueStr); 110 } 111 112 /** 113 * Used when following links ( 114 * {@link RestfulClient#follow(LinkRepresentation)}). 115 */ 116 public ClientRequestConfigurer configureArgs(final JsonRepresentation requestArgs) { 117 if (clientRequest.getHttpMethod() == null) { 118 throw new IllegalStateException("Must set up http method first"); 119 } 120 121 getHttpMethod().setUpArgs(this, requestArgs); 122 return this; 123 } 124 125 /** 126 * Called back from 127 * {@link RestfulHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)} 128 */ 129 public ClientRequestConfigurer body(final JsonRepresentation requestArgs) { 130 clientRequest.body(MediaType.APPLICATION_JSON_TYPE, requestArgs.toString()); 131 return this; 132 } 133 134 /** 135 * Called back from 136 * {@link RestfulHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)} 137 */ 138 public ClientRequestConfigurer queryString(final JsonRepresentation requestArgs) { 139 if (requestArgs.size() == 0) { 140 return this; 141 } 142 final String queryString = UrlEncodingUtils.urlEncode(requestArgs.toString()); 143 uriBuilder.replaceQuery(queryString); 144 return this; 145 } 146 147 /** 148 * Called back from 149 * {@link RestfulHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)} 150 */ 151 public ClientRequestConfigurer queryArgs(final JsonRepresentation requestArgs) { 152 final MultivaluedMap<String, String> queryParameters = clientRequest.getQueryParameters(); 153 for (final Map.Entry<String, JsonRepresentation> entry : requestArgs.mapIterable()) { 154 final String param = entry.getKey(); 155 final JsonRepresentation argRepr = entry.getValue(); 156 final String arg = UrlEncodingUtils.urlEncode(argRepr.asArg()); 157 queryParameters.add(param, arg); 158 } 159 return this; 160 } 161 162 /** 163 * For testing. 164 */ 165 ClientRequest getClientRequest() { 166 return clientRequest; 167 } 168 169 RestfulHttpMethod getHttpMethod() { 170 final String httpMethod = clientRequest.getHttpMethod(); 171 return RestfulHttpMethod.valueOf(httpMethod); 172 } 173 174}