View Javadoc
1   /*
2    * *************************************************************************************************************************************************************
3    *
4    * TheseFoolishThings: Miscellaneous utilities
5    * http://tidalwave.it/projects/thesefoolishthings
6    *
7    * Copyright (C) 2009 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8    *
9    * *************************************************************************************************************************************************************
10   *
11   * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12   * You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * 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
17   * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
18   *
19   * *************************************************************************************************************************************************************
20   *
21   * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22   * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23   *
24   * *************************************************************************************************************************************************************
25   */
26  package it.tidalwave.util;
27  
28  import java.lang.reflect.InvocationTargetException;
29  import jakarta.annotation.Nonnull;
30  import jakarta.annotation.Nullable;
31  import java.util.Arrays;
32  import java.util.List;
33  import lombok.extern.slf4j.Slf4j;
34  import static java.util.stream.Collectors.*;
35  
36  /***************************************************************************************************************************************************************
37   *
38   * A utility that returns short qualified names for class literals and objects.
39   *
40   * @author  Fabrizio Giudici
41   * @since   3.2-ALPHA-17
42   *
43   **************************************************************************************************************************************************************/
44  @Slf4j
45  public class ShortNames
46    {
47      /***********************************************************************************************************************************************************
48       * Returns the short name for a class literal.
49       *
50       * @param     clazz     the class
51       * @return              the short name
52       **********************************************************************************************************************************************************/
53      @Nonnull
54      public static String shortName (@Nonnull final Class<?> clazz)
55        {
56          return shortName(clazz, false);
57        }
58  
59      /***********************************************************************************************************************************************************
60       * Returns the short name for a class literal, eventually adding interface names (but not those in the java.*
61       * package).
62       *
63       * @param     clazz               the class
64       * @param     withInterfaces      whether the interfaces must be listed
65       * @return                        the short name
66       **********************************************************************************************************************************************************/
67      @Nonnull
68      public static String shortName (@Nonnull final Class<?> clazz, final boolean withInterfaces)
69          {
70            var className = clazz.getName();
71            var prefix = "";
72  
73          if (className.contains("EnhancerByMockito"))
74            {
75              prefix = "mock-of-";
76              className = className.replaceAll("\\$\\$EnhancerByMockito.*", "");
77            }
78  
79          final var parts = className.split("\\.");
80          final var s = new StringBuilder();
81  
82          for (var i = 0; i < parts.length; i++)
83            {
84              s.append((i < parts.length - 1) ? parts[i].charAt(0) + "." : parts[i]);
85            }
86  
87          if (withInterfaces)
88            {
89              final var interfaces = clazz.getInterfaces();
90  
91              if (interfaces.length > 0)
92                {
93                  s.append(Arrays.stream(interfaces)
94                                 .filter(i -> !i.getPackage().getName().startsWith("java"))
95                                 .map(ShortNames::shortName).collect(joining(", ", "{", "}")));
96                }
97            }
98  
99          return prefix + s;
100       }
101 
102     /***********************************************************************************************************************************************************
103      * Returns the short name for class literals, eventually adding interface names (but not those in the java.*
104      * package).
105      *
106      * @param     classes   the classes
107      * @return              the short names
108      **********************************************************************************************************************************************************/
109     @Nonnull
110     public static String shortNames (@Nonnull final Iterable<Class<?>> classes)
111       {
112         final var result = new StringBuilder();
113         var separator = "";
114 
115         for (final var clazz : classes)
116           {
117             result.append(separator).append(shortName(clazz));
118             separator = ", ";
119           }
120 
121         return "[" + result + "]";
122       }
123 
124     /***********************************************************************************************************************************************************
125      * Return the short name for an object. If the object contains a method named {@code getId()}, the id is part of
126      * the result.
127      *
128      * @param     object    the object
129      * @return              the short name
130      **********************************************************************************************************************************************************/
131     @Nonnull
132     public static String shortId (@Nullable final Object object)
133       {
134         if (object == null)
135           {
136             return "null";
137           }
138 
139         final var s = new StringBuilder();
140         s.append(String.format("%s@%x", shortName(object.getClass()), System.identityHashCode(object)));
141 
142         try
143           {
144             final var id = object.getClass().getMethod("getId").invoke(object);
145             s.append("/").append(id != null ? id.toString() : "null");
146           }
147         catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored)
148           {
149             // log.trace("While invoking 'getId(): {}", e.toString());
150           }
151 
152         return s.toString();
153       }
154 
155     /***********************************************************************************************************************************************************
156      * Return the short names for some objects.
157      *
158      * @param     objects   the objects
159      * @return              the short names
160      **********************************************************************************************************************************************************/
161     @Nonnull
162     public static String shortIds (@Nonnull final Iterable<?> objects)
163       {
164         final var result = new StringBuilder();
165         var separator = "";
166 
167         for (final var object : objects)
168           {
169             result.append(separator).append(shortId(object));
170             separator = ", ";
171           }
172 
173         return "[" + result + "]";
174       }
175 
176     /***********************************************************************************************************************************************************
177      * Return the short names for some objects.
178      *
179      * @param     objects   the objects
180      * @return              the short names
181      **********************************************************************************************************************************************************/
182     @Nonnull
183     public static String shortIds (@Nonnull final Object... objects)
184       {
185         return shortIds(List.of(objects));
186       }
187   }