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.reflect.RTNoSuchMethodException;
017   import  com.github.xbn.lang.reflect.Declared;
018   import  com.github.xbn.lang.CrashIfObject;
019   import  com.github.xbn.list.ImmutableValues;
020   import  com.github.xbn.list.MapUtil;
021   import  com.github.xbn.list.SortListValues;
022   import  java.lang.reflect.Constructor;
023   import  java.lang.reflect.Method;
024   import  java.util.ArrayList;
025   import  java.util.Collections;
026   import  java.util.List;
027   import  java.util.Map;
028   import  java.util.TreeMap;
029   import  static com.github.xbn.lang.XbnConstants.*;
030/**
031   <p>All constructors and methods in a class.</p>
032
033 * @since  0.1.0
034 * @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>
035 **/
036public class AllSimpleParamSignatures  {
037   private final Class<?> containing;
038   private final List<ConstructorSimpleParamSig>  cnstrList;
039   private final Map<String,List<MethodSimpleParamSig>> methodMap;
040   /**
041      <p>Create a new instance from a class.</p>
042
043      <p>Sets<ol>
044         <li>{@link #getConstructorList() getConstructorList}{@code ()} to an {@linkplain java.util.Collections#unmodifiableList(List) immutable} version of
045         <br/> &nbsp; &nbsp; <code>AllSimpleParamSignatures.{@link AllSimpleParamSignatures#newConstructorList(Class, Declared, Sorted) newConstructorList}(containing_cls, declared, {@link Sorted Sorted}.{@link Sorted#YES YES})</code></li>
046         <li>{@link #getMethodMap() getMethodMap}{@code ()} to an {@linkplain java.util.Collections#unmodifiableMap(Map) immutable} version of
047         <br/> &nbsp; &nbsp; <code>AllSimpleParamSignatures.{@link #newMethodMap(Class, Declared, SortListValues, ImmutableValues) newMethodMap}(containing_cls, declared, {@link com.github.xbn.list.SortListValues}.{@link com.github.xbn.list.SortListValues#ORIGINAL ORIGINAL}, {@link com.github.xbn.list.ImmutableValues ImmutableValues}.{@link com.github.xbn.list.ImmutableValues#YES YES})</code></li>
048      </ol></p>
049
050    * @param  containing_cls  The class containing the methods. May not be {@code null} and <i>should</i> be the class whose methods are in {@code map}. Get with {@link #getContainingClass() getContainingClass}{@code ()}. Get with {@link #getMethodMap() getMethodMap}{@code ()}.
051    */
052   public AllSimpleParamSignatures(Class<?> containing_cls, Declared declared)  {
053      containing = containing_cls;
054
055      List<ConstructorSimpleParamSig> cnstrList2 = AllSimpleParamSignatures.
056         newConstructorList(containing_cls, declared, Sorted.YES);
057      Map<String,List<MethodSimpleParamSig>> methodMap2 = AllSimpleParamSignatures.
058         newMethodMap(containing_cls, declared, SortListValues.ORIGINAL, ImmutableValues.YES);
059
060      //Both throw NPX if null (doesn't apply, just FYI)
061      cnstrList = Collections.<ConstructorSimpleParamSig>unmodifiableList(cnstrList2);
062      methodMap = Collections.<String,List<MethodSimpleParamSig>>unmodifiableMap(methodMap2);
063   }
064   /**
065      <p>All constructors.</p>
066
067    * @return  A non-{@code null}, immutable list of all constructors in the {@link #getContainingClass() class}.
068    * @see  #getMethodMap()
069    * @see  #AllSimpleParamSignatures(Class, Declared)
070    */
071   public List<ConstructorSimpleParamSig> getConstructorList()  {
072      return  cnstrList;
073   }
074   /**
075      <p>All methods.</p>
076
077    * @return  A non-{@code null}, immutable map of all methods in the {@link #getContainingClass() class}.
078    * @see  #getConstructorList()
079    * @see  #AllSimpleParamSignatures(Class, Declared)
080    * @see  #getMethodListForNameCrashIfNone(String)
081    */
082   public Map<String,List<MethodSimpleParamSig>> getMethodMap()  {
083      return  methodMap;
084   }
085   /**
086      <p>Get the methods with a name, or crash if no methods have that name.</p>
087
088    * @return  <code>{@link #getMethodMap() getMethodMap}().{@link java.util.Map#get(Object) get}(name)</code>
089    * @exception  RTNoSuchMethodException  If no methods have the name {@code name}.
090    */
091   public List<MethodSimpleParamSig> getMethodListForNameCrashIfNone(String name)  {
092      List<MethodSimpleParamSig> match = getMethodMap().get(name);
093      if(match == null)  {
094         throw  new RTNoSuchMethodException("name=\"" + name + "\"");
095      }
096      return  match;
097   }
098   /**
099      <p>The class containing the constructors and methods.</p>
100
101    * @see  #AllSimpleParamSignatures(Class, Declared)
102    */
103   public Class<?> getContainingClass()  {
104      return  containing;
105   }
106   /**
107    * @return  <code>{@link #appendToString(StringBuilder) appendToString}(new StringBuilder()).toString()</code>
108    */
109   public String toString()  {
110      return  appendToString(new StringBuilder()).toString();
111   }
112   /**
113      <p>A summary of all constructors and functions.</p>
114
115    * @param  to_appendTo May not be {@code null}.
116    * @see  #toString()
117    */
118   public StringBuilder appendToString(StringBuilder to_appendTo)  {
119      try  {
120         to_appendTo.append(getContainingClass().getName()).append(": ").append("constructors=" + getConstructorList().size()).append(", ");
121      }  catch(RuntimeException rx)  {
122         throw  CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
123      }
124
125      int i = 0;
126      int sizeMinus1 = getMethodMap().size() - 1;
127      for (Map.Entry<String,List<MethodSimpleParamSig>> entry : methodMap.entrySet())  {
128         to_appendTo.append(entry.getKey()).append("=").append(entry.getValue().size());
129         if(i < sizeMinus1)  {
130            to_appendTo.append(", ");
131         }
132      }
133
134      return  to_appendTo;
135   }
136   /**
137    * @return  <code>{@link #appendFullToString(StringBuilder) appendFullToString}(new StringBuilder()).toString()</code>
138    */
139   public String fullToString()  {
140      return  appendFullToString(new StringBuilder()).toString();
141   }
142   /**
143      <p>A full listing of all constructors and functions.</p>
144
145    * @param  to_appendTo May not be {@code null}.
146    * @see  #fullToString()
147    */
148   public StringBuilder appendFullToString(StringBuilder to_appendTo)  {
149      try  {
150         to_appendTo.append(getContainingClass().getName()).append(":").append(LINE_SEP).append("Constructors (").append(getConstructorList().size()).append("):").append(LINE_SEP);
151      }  catch(RuntimeException rx)  {
152         throw  CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
153      }
154
155      AllSimpleParamSignatures.appendToStringForAllListsInList(to_appendTo, " - ", getConstructorList(), LINE_SEP);
156
157      to_appendTo.append(LINE_SEP).append("All methods:").append(LINE_SEP);
158
159//              int i = 0;
160//              int sizeMinus1 = getMethodMap().size() - 1;
161      for (Map.Entry<String,List<MethodSimpleParamSig>> entry : methodMap.entrySet())  {
162         List<MethodSimpleParamSig> value = entry.getValue();
163         if(value.size() == 1)  {
164            to_appendTo.append(" - ").append(value.get(0)).append(LINE_SEP);
165
166         }  else  {
167            to_appendTo.append(" - ").append(entry.getKey()).
168               append(" (").append(value.size()).append(")").append(LINE_SEP);
169            AllSimpleParamSignatures.appendToStringForAllListsInList(to_appendTo, "    - ", value, LINE_SEP);
170            to_appendTo.append(LINE_SEP);
171         }
172      }
173      return  to_appendTo;
174   }
175   /**
176      <p>For displaying all parameter-lists in a list.</p>
177
178    * @return  <code>{@link #appendToStringForAllListsInList(StringBuilder, String, List, String) appendToStringForAllListsInArray}((new StringBuilder()), prefix, param_listList, between).toString()</code>
179    */
180   public static final String toStringForAllListsInList(String prefix, List<? extends SimpleParamNameSignature> param_listList, String between)  {
181      return  appendToStringForAllListsInList((new StringBuilder()), prefix, param_listList, between).toString();
182   }
183   /**
184      <p>For displaying all parameter-lists in a list.</p>
185
186    * @return  <code>{@link #appendToStringForAllListsInArray(StringBuilder, String, SimpleParamNameSignature[], String) appendToStringForAllListsInArray}(new StringBuilder(), prefix, methods, between).toString()</code>
187    */
188   public static final StringBuilder appendToStringForAllListsInList(StringBuilder to_appendTo, String prefix, List<? extends SimpleParamNameSignature> param_listList, String between)  {
189      try  {
190         return  appendToStringForAllListsInArray(to_appendTo, prefix,
191            param_listList.toArray(new SimpleParamNameSignature[param_listList.size()]),
192            between);
193      }  catch(RuntimeException rx)  {
194         throw  CrashIfObject.nullOrReturnCause(param_listList, "param_listList", null, rx);
195      }
196   }
197   /**
198      <p>For displaying all parameter-lists in an array.</p>
199
200    * @return  <code>{@link #appendToStringForAllListsInArray(StringBuilder, String, SimpleParamNameSignature[], String) appendToStringForAllListsInArray}(new StringBuilder(), prefix, methods, between).toString()</code>
201    */
202   public static final String toStringForAllListsInArray(String prefix, SimpleParamNameSignature[] param_lists, String between)  {
203      return  appendToStringForAllListsInArray(new StringBuilder(), prefix, param_lists, between).toString();
204   }
205   /**
206      <p>For displaying all parameter-lists in an array.</p>
207
208    * @param  to_appendTo  May not be {@code null}.
209    * @param  prefix  What to print before each method. Setting this to {@code null} is the same as setting it to the empty-string ({@code ""}).
210    * @param  param_lists  May not be {@code null}, and no element may be {@code null}.
211    * @param  between  What to print between each method. <i>Should</i> not be {@code null} or empty.
212    */
213   public static final StringBuilder appendToStringForAllListsInArray(StringBuilder to_appendTo, String prefix, SimpleParamNameSignature[] param_lists, String between)  {
214      int sizeMinus1 = -1;
215      try  {
216         sizeMinus1 = param_lists.length - 1;
217      }  catch(RuntimeException rx)  {
218         throw  CrashIfObject.nullOrReturnCause(param_lists, "param_lists", null, rx);
219      }
220
221      if(prefix == null)  {
222         prefix = "";
223      }
224
225      int i = 0;
226      try  {
227         for(; i < param_lists.length; i++)  {
228            try  {
229               to_appendTo.append(prefix).append(param_lists[i].toString());
230            }  catch(RuntimeException rx)  {
231               throw  CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
232            }
233            if(i < sizeMinus1)  {
234               to_appendTo.append(between);
235            }
236         }
237      }  catch(RuntimeException rx)  {
238         throw  CrashIfObject.nullOrReturnCause(param_lists[i], "param_lists[i]", null, rx);
239      }
240      return  to_appendTo;
241   }
242   /**
243      <p>Create a new list of all constructors in a class.</p>
244
245    * @param  containing_cls  May not be {@code null}.
246    * @param  declared  If {@link com.github.xbn.lang.reflect.Declared Declared}.{@link com.github.xbn.lang.reflect.Declared#YES YES}, then {@linkplain java.lang.Class#getDeclaredMethods() declared} methods are retrieved. If {@link com.github.xbn.lang.reflect.Declared#NO NO}, {@linkplain java.lang.Class#getMethods() non-declared}.
247    * @param  sort  If {@link com.github.xbn.list.SortListValues#ORIGINAL ORIGINAL} or {@link com.github.xbn.list.SortListValues#DUPLICATE DUPLICATE}, then the returned list is sorted.
248    */
249   public static final List<ConstructorSimpleParamSig> newConstructorList(Class<?> containing_cls, Declared declared, Sorted sort)  {
250      Constructor<?>[] cnstrs = null;
251      try  {
252         cnstrs = (declared.isYes() ? containing_cls.getDeclaredConstructors()
253            :  containing_cls.getConstructors());
254      }  catch(RuntimeException rx)  {
255         CrashIfObject.nnull(containing_cls, "containing_cls", null);
256         throw  CrashIfObject.nullOrReturnCause(declared, "declared", null, rx);
257      }
258      List<ConstructorSimpleParamSig> list = new ArrayList<ConstructorSimpleParamSig>(cnstrs.length);
259      for(Constructor<?> cnstr : cnstrs)  {
260         list.add(new ConstructorSimpleParamSig(cnstr));
261      }
262
263      try  {
264         if(sort.isYes())  {
265            Collections.<ConstructorSimpleParamSig>sort(list);
266         }
267
268         return  list;
269      }  catch(RuntimeException rx)  {
270         throw  CrashIfObject.nullOrReturnCause(sort, "sort", null, rx);
271      }
272   }
273   /**
274      <p>Create a new map of all methods in a class.</p>
275
276    * @param  containing_cls  May not be {@code null}.
277    * @param  declared  If {@link com.github.xbn.lang.reflect.Declared Declared}.{@link com.github.xbn.lang.reflect.Declared#YES YES}, then {@linkplain java.lang.Class#getDeclaredMethods() declared} methods are retrieved. If {@link com.github.xbn.lang.reflect.Declared#NO NO}, {@linkplain java.lang.Class#getMethods() non-declared}.
278    * @return  A non-null map containing all methods. This ends by returning
279      <br/> &nbsp; &nbsp; <code>{@link com.github.xbn.list.MapUtil MapUtil}.&lt;MethodSimpleParamSig,String&gt;{@link com.github.xbn.list.MapUtil#getWithModifiedListValues(Map, SortListValues, ImmutableValues) getWithModifiedListValues}(<i>[the-map]</i>, sort_lists, immutable_lists)</code>
280    */
281   public static final Map<String,List<MethodSimpleParamSig>> newMethodMap(Class<?> containing_cls, Declared declared, SortListValues sort_lists, ImmutableValues immutable_lists)  {
282      Method[] methods = null;
283      try  {
284         methods = (declared.isYes() ? containing_cls.getDeclaredMethods()
285            :  containing_cls.getMethods());
286      }  catch(RuntimeException rx)  {
287         CrashIfObject.nnull(containing_cls, "containing_cls", null);
288         throw  CrashIfObject.nullOrReturnCause(declared, "declared", null, rx);
289      }
290      Map<String,List<MethodSimpleParamSig>> map = new TreeMap<String,List<MethodSimpleParamSig>>();
291      for(Method m : methods)  {
292         String name = m.getName();
293         if(!map.containsKey(name))  {
294            List<MethodSimpleParamSig> list = new ArrayList<MethodSimpleParamSig>(3);
295            list.add(new MethodSimpleParamSig(m));
296            map.put(name, list);
297         }  else  {
298            map.get(name).add(new MethodSimpleParamSig(m));
299         }
300      }
301
302      return  MapUtil.<MethodSimpleParamSig,String>getWithModifiedListValues(map, sort_lists, immutable_lists);
303   }
304}