001/*license*\
002   Codelet: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
003
004   This software is dual-licensed under the:
005   - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
006   - Apache Software License (ASL) version 2.0.
007
008   Either license may be applied at your discretion. More information may be found at
009   - http://en.wikipedia.org/wiki/Multi-licensing.
010
011   The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
012   - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
013   - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
014\*license*/
015package  com.github.aliteralmind.codelet.simplesig;
016   import  com.github.xbn.lang.CrashIfObject;
017   import  com.github.xbn.util.JavaRegexes;
018   import  com.google.common.base.Joiner;
019   import  java.lang.reflect.Member;
020   import  java.util.ArrayList;
021   import  java.util.Collections;
022   import  java.util.List;
023   import  java.util.Objects;
024   import  java.util.regex.Matcher;
025   import  java.util.regex.Pattern;
026/**
027   <p>A method or constructor signature, using only {@linkplain java.lang.Class#getSimpleName() simple} parameter-type names--this can be matched by a {@code SimpleParamSigSearchTerm}. This class is unrelated to {@link SimpleMethodSignature}.</p>
028
029 * @see  SimpleParamSigSearchTerm
030 * @since  0.1.0
031 * @author  Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <a href="http://codelet.aliteralmind.com">{@code http://codelet.aliteralmind.com}</a>, <a href="https://github.com/aliteralmind/codelet">{@code https://github.com/aliteralmind/codelet}</a>
032 **/
033public abstract class SimpleParamNameSignature implements Comparable<SimpleParamNameSignature>  {
034   private static final Matcher IDENTIFIER_MTCHR = Pattern.compile(JavaRegexes.IDENTIFIER).matcher("");
035   private final Member cnstrOrMthd;
036   private final List<String> typeList;
037   private final String noParens;
038   private final String withParens;
039   /**
040      <p>Create a new instance from a constructor or method, and its parameter class types.</p>
041
042    * <p>Equal to
043      <br/> &nbsp; &nbsp; <code>{@link #SimpleParamNameSignature(Member, List) this}(false, cnstr_method,
044      <br/> &nbsp; &nbsp; SimpleParamNameSignature.{@link #getSimpleNameListFromClasses(Class[]) getSimpleNameListFromClasses}(param_types))</code></p>
045    */
046   public SimpleParamNameSignature(Member cnstr_method, Class<?>[] param_types)  {
047      this(false, cnstr_method,
048         SimpleParamNameSignature.getSimpleNameListFromClasses(param_types));
049   }
050   /**
051      <p>Create a new instance from a method or constructor, and an array of its parameter simple names.</p>
052
053      <p>This sets<ol>
054         <li>{@link #getParamNameList() getParamNameList}{@code ()} to an immutable string-list of all parameter type names.</li>
055         <li>{@link #getWithParens() getWithParens}{@code ()} to a comma-delimited string of the each type's {@linkplain java.lang.Class#getSimpleName() simple names}, in the same order as in {@code types}, surrounded by parentheses.</li>
056         <li>{@link #getNoParens() getNoParens}{@code ()} to the same comma-delimited list, with no paretheses.</li>
057      </ol></p>
058
059    * @see  java.lang.Class#getSimpleName()
060    */
061   public SimpleParamNameSignature(Member cnstr_method, List<String> type_list)  {
062      this(false, cnstr_method, type_list);
063      Objects.requireNonNull(cnstr_method, "cnstr_method");
064      try  {
065         for(int i = 0; i < type_list.size(); i++)  {
066            try  {
067               if(!IDENTIFIER_MTCHR.reset(type_list.get(i)).matches())  {
068                  throw  new IllegalArgumentException("type_list.get(" + i + ") (\"" + type_list.get(i) + "\") is not a valid Java identifier.");
069               }
070            }  catch(RuntimeException rx)  {
071               throw  CrashIfObject.nullOrReturnCause(type_list.get(i), "type_list.get(" + i + ")", null, rx);
072            }
073         }
074      }  catch(RuntimeException rx)  {
075         throw  CrashIfObject.nullOrReturnCause(type_list, "type_list", null, rx);
076      }
077   }
078      private SimpleParamNameSignature(boolean ignored, Member cnstr_method, List<String> type_list)  {
079         try  {
080            //Does throw NPX if null:
081            typeList = Collections.unmodifiableList(type_list);
082         }  catch(RuntimeException rx)  {
083            throw  CrashIfObject.nullOrReturnCause(type_list, "type_list", null, rx);
084         }
085         cnstrOrMthd = cnstr_method;
086         noParens = Joiner.on(", ").join(typeList);
087         withParens = "(" + noParens + ")";
088      }
089   /**
090      <p>The method or constructor having these parameters.</p>
091
092    * @return  A non-{@code null} {@linkplain java.lang.reflect.Method method} or {@linkplain java.lang.reflect.Constructor constructor} object.
093    */
094   public Member getMember()  {
095      return  cnstrOrMthd;
096   }
097   /**
098      <p>List of all parameter-type simple names.</p>
099
100    * @return  An immutable list of all parameter-types, in the same order as they exist in the consructor or function. If no parameters, this is an empty list.
101    * @see  #getWithParens()
102    * @see  #SimpleParamNameSignature(Member, List)
103    * @see  java.lang.Class#getSimpleName()
104    */
105   public List<String> getParamNameList()  {
106      return  typeList;
107   }
108   /**
109      <p>Comma-delimited string of all parameter-type simple names, excluding the surrounding parentheses.</p>
110
111    * @return  A non-{@code null}, comma-delimited string of all simple type names, in the same order as declared, with a single space between each comma.
112    * @see  #getWithParens()
113    */
114   public String getNoParens()  {
115      return  noParens;
116   }
117   /**
118      <p>Comma-delimited string of all parameter-type simple names, listed in the same order as declared, including the surrounding parentheses.</p>
119
120    * @return  A non-{@code null}, comma-delimited string of all simple type names, in the same order as declared, with a single space between each comma.
121    * @see  #getParamNameList()
122    * @see  #getNoParens()
123    * @see  #toString()
124    */
125   public String getWithParens()  {
126      return  withParens;
127   }
128   /**
129      <p>If a method: its name, if a constructor: the empty string ({@code ""}).</p>
130    */
131   public abstract String getMethodName();
132   /**
133    * @return   <code>{@link #getMethodName() getMethodName}() + {@link #getWithParens() getWithParens}()</code>
134    */
135   public String toString()  {
136      return  getMethodName() + getWithParens();
137   }
138   /**
139    * @return  <code>{@link #getWithParens() getWithParens}().compareTo(to_compareTo.getWithParens())</code> &nbsp; &nbsp; <i>(This does not need to be overriden to include the constructor/function name. This is only for sorting parameter-lists within each constructor/method.)</i>
140    */
141   public int compareTo(SimpleParamNameSignature to_compareTo)  {
142      return  getWithParens().compareTo(to_compareTo.getWithParens());
143   }
144   /**
145      <p>Create a list of all simple names from a class array.</p>
146
147    * @param  types  May not be {@code null}.
148    * @return  A non-null list having the same length as {@code types}.
149    * @see  #SimpleParamNameSignature(Member, Class[])
150    */
151   public static final List<String> getSimpleNameListFromClasses(Class<?>[] types)  {
152      List<String> typeList = null;
153      try  {
154         typeList = new ArrayList<String>(types.length);
155      }  catch(RuntimeException rx)  {
156         throw  CrashIfObject.nullOrReturnCause(types, "types", null, rx);
157      }
158      for(Class<?> type : types)  {
159         typeList.add(type.getSimpleName());
160      }
161      return  typeList;
162   }
163}