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.http.classic.remote;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020import static org.apache.juneau.commons.utils.StringUtils.*;
021
022import java.lang.reflect.*;
023
024import org.apache.juneau.commons.reflect.*;
025import org.apache.juneau.http.remote.*;
026
027/**
028 * Contains the meta-data about a Java method on a remote class.
029 *
030 * <p>
031 * Captures the information in {@link Remote @Remote} annotations for caching and reuse.
032 *
033 * <h5 class='section'>See Also:</h5><ul>
034 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
035 * </ul>
036 */
037public class RrpcInterfaceMethodMeta {
038
039   /**
040    * Given a Java method, returns the arguments signature.
041    *
042    * @param m The Java method.
043    * @return The arguments signature for the specified method.
044    */
045   private static String getMethodArgsSignature(Method m) {
046      var sb = new StringBuilder(128);
047      Class<?>[] pt = m.getParameterTypes();
048      if (pt.length == 0)
049         return "";
050      sb.append('(');
051      for (var i = 0; i < pt.length; i++) {
052         var pti = ClassInfo.of(pt[i]);
053         if (i > 0)
054            sb.append(',');
055         pti.appendNameFormatted(sb, ClassNameFormat.FULL, true, '$', ClassArrayFormat.BRACKETS);
056      }
057      sb.append(')');
058      return sb.toString();
059   }
060
061   private final String url;
062   private final String path;
063
064   private final Method method;
065
066   /**
067    * Constructor.
068    *
069    * @param restUrl The absolute URL of the REST interface backing the interface proxy.  Can be <jk>null</jk> (the resulting method URL is then prefixed with the literal text <js>"null"</js>).
070    * @param m The Java method.  Must not be <jk>null</jk>.
071    */
072   public RrpcInterfaceMethodMeta(String restUrl, Method m) {
073      this.method = m;
074      this.path = m.getName() + '/' + getMethodArgsSignature(m);
075      this.url = trimSlashes(restUrl) + '/' + urlEncode(path);
076   }
077
078   /**
079    * Returns the underlying Java method that this metadata is about.
080    *
081    * @return
082    *    The underlying Java method that this metadata is about.
083    *    <br>Never <jk>null</jk>.
084    */
085   public Method getJavaMethod() { return method; }
086
087   /**
088    * Returns the HTTP path of this method.
089    *
090    * @return
091    *    The HTTP path of this method relative to the parent interface.
092    *    <br>Never <jk>null</jk>.
093    *    <br>Never has leading or trailing slashes.
094    */
095   public String getPath() { return path; }
096
097   /**
098    * Returns the absolute URL of the REST interface invoked by this Java method.
099    *
100    * @return The absolute URL of the REST interface, never <jk>null</jk>.
101    */
102   public String getUri() { return url; }
103
104   @Override
105   public boolean equals(Object o) {
106      return o instanceof RrpcInterfaceMethodMeta other && eq(this, other, (x, y) -> x.method.equals(y.method));
107   }
108
109   @Override
110   public int hashCode() {
111      return method.hashCode();
112   }
113}