/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.isis.viewer.restfulobjects.applib.client; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.google.common.collect.Maps; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.core.BaseClientResponse; import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; import org.apache.isis.viewer.restfulobjects.applib.util.Parser; public final class RestfulRequest { public enum DomainModel { NONE, SIMPLE, FORMAL, SELECTABLE; public static Parser<DomainModel> parser() { return new Parser<RestfulRequest.DomainModel>() { @Override public DomainModel valueOf(final String str) { return DomainModel.valueOf(str.toUpperCase()); } @Override public String asString(final DomainModel t) { return t.name().toLowerCase(); } }; } @Override public String toString() { return name().toLowerCase(); } } public static class RequestParameter<Q> { public static RequestParameter<List<List<String>>> FOLLOW_LINKS = new RequestParameter<List<List<String>>>("x-ro-follow-links", Parser.forListOfListOfStrings(), Collections.<List<String>> emptyList()); public static RequestParameter<Integer> PAGE = new RequestParameter<Integer>("x-ro-page", Parser.forInteger(), 1); public static RequestParameter<Integer> PAGE_SIZE = new RequestParameter<Integer>("x-ro-page-size", Parser.forInteger(), 25); public static RequestParameter<List<String>> SORT_BY = new RequestParameter<List<String>>("x-ro-sort-by", Parser.forListOfStrings(), Collections.<String> emptyList()); public static RequestParameter<DomainModel> DOMAIN_MODEL = new RequestParameter<DomainModel>("x-ro-domain-model", DomainModel.parser(), DomainModel.FORMAL); public static RequestParameter<Boolean> VALIDATE_ONLY = new RequestParameter<Boolean>("x-ro-validate-only", Parser.forBoolean(), false); private final String name; private final Parser<Q> parser; private final Q defaultValue; private RequestParameter(final String name, final Parser<Q> parser, final Q defaultValue) { this.name = name; this.parser = parser; this.defaultValue = defaultValue; } public String getName() { return name; } public Parser<Q> getParser() { return parser; } public Q valueOf(final JsonRepresentation parameterRepresentation) { if (parameterRepresentation == null) { return defaultValue; } if (!parameterRepresentation.isMap()) { return defaultValue; } final Q parsedValue = getParser().valueOf(parameterRepresentation.getRepresentation(getName())); return parsedValue != null ? parsedValue : defaultValue; } public Q getDefault() { return defaultValue; } @Override public String toString() { return getName(); } } public static class Header<X> { public static Header<String> IF_MATCH = new Header<String>("If-Match", Parser.forString()); public static Header<List<MediaType>> ACCEPT = new Header<List<MediaType>>("Accept", Parser.forListOfJaxRsMediaTypes()); private final String name; private final Parser<X> parser; /** * public visibility for testing purposes only. */ public Header(final String name, final Parser<X> parser) { this.name = name; this.parser = parser; } public String getName() { return name; } public Parser<X> getParser() { return parser; } void setHeader(final ClientRequestConfigurer clientRequestConfigurer, final X t) { clientRequestConfigurer.header(getName(), parser.asString(t)); } @Override public String toString() { return getName(); } } private final ClientRequestConfigurer clientRequestConfigurer; private final Map<RequestParameter<?>, Object> args = Maps.newLinkedHashMap(); public RestfulRequest(final ClientRequestConfigurer clientRequestConfigurer) { this.clientRequestConfigurer = clientRequestConfigurer; } public <T> RestfulRequest withHeader(final Header<T> header, final T t) { header.setHeader(clientRequestConfigurer, t); return this; } public <T> RestfulRequest withHeader(final Header<List<T>> header, final T... ts) { header.setHeader(clientRequestConfigurer, Arrays.asList(ts)); return this; } public <Q> RestfulRequest withArg(final RestfulRequest.RequestParameter<Q> queryParam, final String argStrFormat, final Object... args) { final String argStr = String.format(argStrFormat, args); final Q arg = queryParam.getParser().valueOf(argStr); return withArg(queryParam, arg); } public <Q> RestfulRequest withArg(final RestfulRequest.RequestParameter<Q> queryParam, final Q arg) { args.put(queryParam, arg); return this; } public RestfulResponse<JsonRepresentation> execute() { try { if (!args.isEmpty()) { clientRequestConfigurer.configureArgs(args); } final ClientRequest clientRequest = clientRequestConfigurer.getClientRequest(); final Response response = clientRequest.execute(); // this is a bit hacky @SuppressWarnings("unchecked") final BaseClientResponse<String> restEasyResponse = (BaseClientResponse<String>) response; restEasyResponse.setReturnType(String.class); return RestfulResponse.ofT(response); } catch (final Exception ex) { throw new RuntimeException(ex); } } @SuppressWarnings("unchecked") public <T extends JsonRepresentation> RestfulResponse<T> executeT() { final RestfulResponse<JsonRepresentation> restfulResponse = execute(); return (RestfulResponse<T>) restfulResponse; } /** * For testing only. */ ClientRequestConfigurer getClientRequestConfigurer() { return clientRequestConfigurer; } }