All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.rest.client.remote.RemoteOperationMeta Maven / Gradle / Ivy

// ***************************************************************************************************************************
// * 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.juneau.rest.client.remote;

import static org.apache.juneau.httppart.HttpPartType.*;
import static org.apache.juneau.common.internal.StringUtils.*;
import static org.apache.juneau.http.remote.RemoteUtils.*;

import java.lang.reflect.*;
import java.util.*;
import java.util.function.*;

import org.apache.juneau.*;
import org.apache.juneau.http.annotation.*;
import org.apache.juneau.http.remote.RemoteOp;
import org.apache.juneau.httppart.*;
import org.apache.juneau.httppart.bean.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.reflect.*;

/**
 * Contains the meta-data about a Java method on a REST proxy class.
 *
 * 

* Captures the information in {@link RemoteOp @RemoteOp} annotations for caching and reuse. * *

See Also:
*/ public class RemoteOperationMeta { private final String httpMethod; private final String fullPath; private final RemoteOperationArg[] pathArgs, queryArgs, headerArgs, formDataArgs; private final RemoteOperationBeanArg[] requestArgs; private final RemoteOperationArg contentArg; private final RemoteOperationReturn methodReturn; private final Class[] exceptions; /** * Constructor. * * @param parentPath The absolute URI of the REST interface backing the interface proxy. * @param m The Java method. * @param defaultMethod The default HTTP method if not specified through annotation. */ public RemoteOperationMeta(final String parentPath, Method m, String defaultMethod) { Builder b = new Builder(parentPath, m, defaultMethod); this.httpMethod = b.httpMethod; this.fullPath = b.fullPath; this.pathArgs = b.pathArgs.toArray(new RemoteOperationArg[b.pathArgs.size()]); this.queryArgs = b.queryArgs.toArray(new RemoteOperationArg[b.queryArgs.size()]); this.formDataArgs = b.formDataArgs.toArray(new RemoteOperationArg[b.formDataArgs.size()]); this.headerArgs = b.headerArgs.toArray(new RemoteOperationArg[b.headerArgs.size()]); this.requestArgs = b.requestArgs.toArray(new RemoteOperationBeanArg[b.requestArgs.size()]); this.contentArg = b.bodyArg; this.methodReturn = b.methodReturn; this.exceptions = m.getExceptionTypes(); } private static final class Builder { String httpMethod, fullPath, path; List pathArgs = new LinkedList<>(), queryArgs = new LinkedList<>(), headerArgs = new LinkedList<>(), formDataArgs = new LinkedList<>(); List requestArgs = new LinkedList<>(); RemoteOperationArg bodyArg; RemoteOperationReturn methodReturn; Builder(String parentPath, Method m, String defaultMethod) { MethodInfo mi = MethodInfo.of(m); AnnotationList al = mi.getAnnotationList(REMOTE_OP_GROUP); if (al.isEmpty()) al = mi.getReturnType().unwrap(Value.class,Optional.class).getAnnotationList(REMOTE_OP_GROUP); Value _httpMethod = Value.empty(), _path = Value.empty(); al.stream().map(x -> x.getName().substring(6).toUpperCase()).filter(x -> ! x.equals("OP")).forEach(x -> _httpMethod.set(x)); al.forEachValue(String.class, "method", NOT_EMPTY, x -> _httpMethod.set(x.trim().toUpperCase())); al.forEachValue(String.class, "path", NOT_EMPTY, x-> _path.set(x.trim())); httpMethod = _httpMethod.orElse("").trim(); path = _path.orElse("").trim(); Value value = Value.empty(); al.forEach(RemoteOp.class, x -> isNotEmpty(x.inner().value().trim()), x -> value.set(x.inner().value().trim())); if (value.isPresent()) { String v = value.get(); int i = v.indexOf(' '); if (i == -1) { httpMethod = v; } else { httpMethod = v.substring(0, i).trim(); path = v.substring(i).trim(); } } else { al.forEach(x -> ! x.isType(RemoteOp.class) && isNotEmpty(x.getValue(String.class, "value", NOT_EMPTY).orElse("").trim()),x -> value.set(x.getValue(String.class, "value", NOT_EMPTY).get().trim())); if (value.isPresent()) path = value.get(); } if (path.isEmpty()) { path = HttpUtils.detectHttpPath(m, nullIfEmpty(httpMethod)); } if (httpMethod.isEmpty()) httpMethod = HttpUtils.detectHttpMethod(m, true, defaultMethod); path = trimSlashes(path); if (! isOneOf(httpMethod, "DELETE", "GET", "POST", "PUT", "OPTIONS", "HEAD", "CONNECT", "TRACE", "PATCH")) throw new RemoteMetadataException(m, "Invalid value specified for @RemoteOp(httpMethod) annotation: '"+httpMethod+"'. Valid values are [DELETE,GET,POST,PUT,OPTIONS,HEAD,CONNECT,TRACE,PATCH]."); methodReturn = new RemoteOperationReturn(mi); fullPath = path.indexOf("://") != -1 ? path : (parentPath.isEmpty() ? urlEncodePath(path) : (trimSlashes(parentPath) + '/' + urlEncodePath(path))); mi.getParams().forEach(x -> { RemoteOperationArg rma = RemoteOperationArg.create(x); if (rma != null) { HttpPartType pt = rma.getPartType(); if (pt == HEADER) headerArgs.add(rma); else if (pt == QUERY) queryArgs.add(rma); else if (pt == FORMDATA) formDataArgs.add(rma); else if (pt == PATH) pathArgs.add(rma); else bodyArg = rma; } RequestBeanMeta rmba = RequestBeanMeta.create(x, AnnotationWorkList.create()); if (rmba != null) { requestArgs.add(new RemoteOperationBeanArg(x.getIndex(), rmba)); } }); } } /** * Returns the value of the {@link RemoteOp#method() @RemoteOp(method)} annotation on this Java method. * * @return The value of the annotation, never null. */ public String getHttpMethod() { return httpMethod; } /** * Returns the absolute URI of the REST interface invoked by this Java method. * * @return The absolute URI of the REST interface, never null. */ public String getFullPath() { return fullPath; } /** * Performs an action on the {@link Path @Path} annotated arguments on this Java method. * * @param action The action to perform. * @return This object. */ public RemoteOperationMeta forEachPathArg(Consumer action) { for (RemoteOperationArg a : pathArgs) action.accept(a); return this; } /** * Performs an action on the {@link Query @Query} annotated arguments on this Java method. * * @param action The action to perform. * @return This object. */ public RemoteOperationMeta forEachQueryArg(Consumer action) { for (RemoteOperationArg a : queryArgs) action.accept(a); return this; } /** * Performs an action on the {@link FormData @FormData} annotated arguments on this Java method. * * @param action The action to perform. * @return This object. */ public RemoteOperationMeta forEachFormDataArg(Consumer action) { for (RemoteOperationArg a : formDataArgs) action.accept(a); return this; } /** * Performs an action on the {@link Header @Header} annotated arguments on this Java method. * * @param action The action to perform. * @return This object. */ public RemoteOperationMeta forEachHeaderArg(Consumer action) { for (RemoteOperationArg a : headerArgs) action.accept(a); return this; } /** * Performs an action on the {@link Request @Request} annotated arguments on this Java method. * * @param action The action to perform. * @return This object. */ public RemoteOperationMeta forEachRequestArg(Consumer action) { for (RemoteOperationBeanArg a : requestArgs) action.accept(a); return this; } /** * Returns the argument annotated with {@link Content @Content}. * * @return A index of the argument with the {@link Content @Content} annotation, or null if no argument exists. */ public RemoteOperationArg getContentArg() { return contentArg; } /** * Returns whether the method returns the HTTP response body or status code. * * @return Whether the method returns the HTTP response body or status code. */ public RemoteOperationReturn getReturns() { return methodReturn; } /** * Performs an action on the exceptions thrown by this method. * * @param action The action to perform. * @return This object. */ public RemoteOperationMeta forEachException(Consumer> action) { for (Class e : exceptions) action.accept(e); return this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy