1 /*
   2  * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.beans;
  26 
  27 import java.util.HashMap;
  28 import java.util.IdentityHashMap;
  29 import java.util.Map;
  30 
  31 import static java.util.Locale.ENGLISH;
  32 
  33 /**
  34  * A utility class which generates unique names for object instances.
  35  * The name will be a concatenation of the unqualified class name
  36  * and an instance number.
  37  * <p>
  38  * For example, if the first object instance javax.swing.JButton
  39  * is passed into <code>instanceName</code> then the returned
  40  * string identifier will be &quot;JButton0&quot;.
  41  *
  42  * @author Philip Milne
  43  */
  44 class NameGenerator {
  45 
  46     private Map<Object, String> valueToName;
  47     private Map<String, Integer> nameToCount;
  48 
  49     public NameGenerator() {
  50         valueToName = new IdentityHashMap<>();
  51         nameToCount = new HashMap<>();
  52     }
  53 
  54     /**
  55      * Clears the name cache. Should be called to near the end of
  56      * the encoding cycle.
  57      */
  58     public void clear() {
  59         valueToName.clear();
  60         nameToCount.clear();
  61     }
  62 
  63     /**
  64      * Returns the root name of the class.
  65      */
  66     @SuppressWarnings("rawtypes")
  67     public static String unqualifiedClassName(Class type) {
  68         if (type.isArray()) {
  69             return unqualifiedClassName(type.getComponentType())+"Array";
  70         }
  71         String name = type.getName();
  72         return name.substring(name.lastIndexOf('.')+1);
  73     }
  74 
  75     /**
  76      * Returns a String which capitalizes the first letter of the string.
  77      */
  78     public static String capitalize(String name) {
  79         if (name == null || name.length() == 0) {
  80             return name;
  81         }
  82         return name.substring(0, 1).toUpperCase(ENGLISH) + name.substring(1);
  83     }
  84 
  85     /**
  86      * Returns a unique string which identifies the object instance.
  87      * Invocations are cached so that if an object has been previously
  88      * passed into this method then the same identifier is returned.
  89      *
  90      * @param instance object used to generate string
  91      * @return a unique string representing the object
  92      */
  93     public String instanceName(Object instance) {
  94         if (instance == null) {
  95             return "null";
  96         }
  97         if (instance instanceof Class) {
  98             return unqualifiedClassName((Class)instance);
  99         }
 100         else {
 101             String result = valueToName.get(instance);
 102             if (result != null) {
 103                 return result;
 104             }
 105             Class<?> type = instance.getClass();
 106             String className = unqualifiedClassName(type);
 107 
 108             Integer size = nameToCount.get(className);
 109             int instanceNumber = (size == null) ? 0 : (size).intValue() + 1;
 110             nameToCount.put(className, instanceNumber);
 111 
 112             result = className + instanceNumber;
 113             valueToName.put(instance, result);
 114             return result;
 115         }
 116     }
 117 }