001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.client.classic.remote;
018
019import static org.apache.juneau.commons.httppart.HttpPartType.*;
020
021import java.util.*;
022
023import org.apache.juneau.commons.httppart.*;
024import org.apache.juneau.commons.inject.*;
025import org.apache.juneau.commons.reflect.*;
026import org.apache.juneau.http.*;
027import org.apache.juneau.marshall.httppart.*;
028
029/**
030 * Represents the metadata about an annotated argument of a method on a REST proxy class.
031 *
032 * <h5 class='section'>See Also:</h5><ul>
033 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxies">REST Proxies</a>
034 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestClient">juneau-rest-client-classic</a>
035 * </ul>
036 */
037@SuppressWarnings({
038   "unchecked" // Type erasure on reflective/generic cast; element type is verified at call site
039})
040public class RemoteOperationArg {
041
042   private static final AnnotationProvider AP = AnnotationProvider.INSTANCE;
043
044   static RemoteOperationArg create(ParameterInfo mpi) {
045      int i = mpi.getIndex();
046      if (AP.has(Header.class, mpi)) {
047         return new RemoteOperationArg(i, HEADER, HttpPartSchema.create(Header.class, mpi));
048      } else if (AP.has(Query.class, mpi)) {
049         return new RemoteOperationArg(i, QUERY, HttpPartSchema.create(Query.class, mpi));
050      } else if (AP.has(FormData.class, mpi)) {
051         return new RemoteOperationArg(i, FORMDATA, HttpPartSchema.create(FormData.class, mpi));
052      } else if (AP.has(PathRemainder.class, mpi)) {
053         // PathRemainder is equivalent to @Path("/*")
054         // Create with schema properties but override name to "/*"
055         var schema = HttpPartSchema.create(PathRemainder.class, mpi);
056         return new RemoteOperationArg(i, PATH, schema, "/*");
057      } else if (AP.has(Path.class, mpi)) {
058         return new RemoteOperationArg(i, PATH, HttpPartSchema.create(Path.class, mpi));
059      } else if (AP.has(Content.class, mpi)) {
060         return new RemoteOperationArg(i, BODY, HttpPartSchema.create(Content.class, mpi));
061      }
062      return null;
063   }
064
065   private final int index;
066   private final HttpPartType partType;
067   private final Optional<HttpPartSerializer> serializer;
068
069   private final HttpPartSchema schema;
070
071   RemoteOperationArg(int index, HttpPartType partType, HttpPartSchema schema) {
072      this.index = index;
073      this.partType = partType;
074      this.serializer = BeanInstantiator.optionalOf((Class<HttpPartSerializer>) schema.getSerializer());
075      this.schema = schema;
076   }
077
078   RemoteOperationArg(int index, HttpPartType partType, HttpPartSchema schema, String overrideName) {
079      this.index = index;
080      this.partType = partType;
081      this.serializer = BeanInstantiator.optionalOf((Class<HttpPartSerializer>) schema.getSerializer());
082      // Create a new schema with the overridden name
083      this.schema = HttpPartSchema.create().name(overrideName).build();
084   }
085
086   /**
087    * Returns the method argument index.
088    *
089    * @return The method argument index.
090    */
091   public int getIndex() { return index; }
092
093   /**
094    * Returns the name of the HTTP part.
095    *
096    * @return The name of the HTTP part.
097    */
098   public String getName() { return schema.getName(); }
099
100   /**
101    * Returns the HTTP part type.
102    *
103    * @return The HTTP part type.  Never <jk>null</jk>.
104    */
105   public HttpPartType getPartType() { return partType; }
106
107   /**
108    * Returns the HTTP part schema information about this part.
109    *
110    * @return The HTTP part schema information, or <jk>null</jk> if not found.
111    */
112   public HttpPartSchema getSchema() { return schema; }
113
114   /**
115    * Returns the HTTP part serializer to use for serializing this part.
116    *
117    * @return The HTTP part serializer, or an empty {@link Optional} if not specified.
118    */
119   public Optional<HttpPartSerializer> getSerializer() { return serializer; }
120
121   /**
122    * Returns whether the <c>skipIfEmpty</c> flag was found in the schema.
123    *
124    * @return <jk>true</jk> if the <c>skipIfEmpty</c> flag was found in the schema.
125    */
126   public boolean isSkipIfEmpty() { return schema.isSkipIfEmpty(); }
127}