View Javadoc

1   package org.springframework.roo.model;
2   
3   import java.util.regex.Matcher;
4   import java.util.regex.Pattern;
5   
6   import org.springframework.roo.support.util.Assert;
7   import org.springframework.roo.support.util.StringUtils;
8   
9   /**
10   * Immutable representation of a Java field name, method name, or other common legal Java identifier.
11   * 
12   * <p>
13   * Ensures the field is properly formed.
14   * 
15   * @author Ben Alex
16   * @since 1.0
17   *
18   */
19  public final class JavaSymbolName implements Comparable<JavaSymbolName> {
20  	private String symbolName;
21  
22  	/**
23  	 * Construct a Java symbol name.
24  	 * 
25  	 * <p>
26  	 * The name will be enforced as follows:
27  	 * 
28  	 * <ul>
29  	 * <li>The rules listed in {link {@link JavaTypeUtils#assertJavaNameLegal(String)}}
30  	 * </ul>
31       *
32  	 * @param symbolName the name (mandatory)
33  	 */
34  	public JavaSymbolName(String symbolName) {
35  		Assert.hasText(symbolName, "Fully qualified type name required");
36  		assertJavaNameLegal(symbolName);
37  		this.symbolName = symbolName;
38  	}
39  	
40  	/**
41  	 * @return the symbol name (never null or empty)
42  	 */
43  	public String getSymbolName() {
44  		return symbolName;
45  	}
46  	
47  	/**
48  	 * @return the symbol name, capitalising the first letter (never null or empty)
49  	 */
50  	public String getSymbolNameCapitalisedFirstLetter() {
51  		return StringUtils.capitalize(symbolName);
52  	}
53  	
54  	/**
55  	 * 
56  	 * @return the symbol name in human readable form
57  	 */
58  	public String getReadableSymbolName() {
59  		Pattern p = Pattern.compile("[A-Z][^A-Z]*");
60          Matcher m = p.matcher(StringUtils.capitalize(symbolName));
61  		StringBuilder string = new StringBuilder();
62          while (m.find()) {
63              string.append(m.group()).append(" ");
64          }
65  		return string.toString().trim();
66  	}
67  	
68  	public final int hashCode() {
69  		return this.symbolName.hashCode();
70  	}
71  
72  	public final boolean equals(Object obj) {
73  		// NB: Not using the normal convention of delegating to compareTo (for efficiency reasons)
74  		return obj != null && obj instanceof JavaSymbolName && this.symbolName.equals(((JavaSymbolName) obj).symbolName);
75  	}
76  
77  	public final int compareTo(JavaSymbolName o) {
78  		// NB: If adding more fields to this class ensure the equals(Object) method is updated accordingly 
79  		if (o == null) return -1;
80  		return this.symbolName.compareTo(o.symbolName);
81  	}
82  	
83  	public final String toString() {
84  		return symbolName;
85  	}
86  	
87  	/**
88  	 * Verifies the presented name is a valid Java name. Specifically, the following is enforced:
89  	 * 
90  	 * <ul>
91  	 * <li>Textual content must be provided in the name</li>
92  	 * <li>Must not have any slashes in the name</li>
93  	 * <li>Must not start with a number</li>
94  	 * <li>Must not have any spaces or other illegal characters in the name</li>
95  	 * <li>Must not start or end with a period</li>
96  	 * </ul>
97  	 * 
98  	 * @param name to evaluate (required)
99  	 */
100 	public static final void assertJavaNameLegal(String name) {
101 		if (name == null) {
102 			throw new IllegalArgumentException("Name required");
103 		}
104 		// Note regular expression for legal characters found to be x5 slower in profiling than this approach
105 		char[] value = name.toCharArray();
106 		for (int i = 0; i < value.length; i++) {
107 			char c = value[i];
108 			if ('/' == c || ' ' == c || '*' == c || '>' == c || '<' == c || '!' == c || '@' == c || '%' == c || '^' == c ||
109 					'?' == c || '(' == c || ')' == c || '~' == c || '`' == c || '{' == c || '}' == c || '[' == c || ']' == c ||
110 					'|' == c || '\\' == c || '\'' == c || '+' == c)  {
111 				throw new IllegalArgumentException("Illegal name '" + name + "' (illegal character)");
112 			}
113 			if (i == 0) {
114 				if ('1' == c || '2' == c || '3' == c || '4' == c || '5' == c || '6' == c || '7' == c || '8' == c || '9' == c || '0' == c) {
115 					throw new IllegalArgumentException("Illegal name '" + name + "' (cannot start with a number)");
116 				}
117 			}
118 			if (i+1 == value.length || i == 0) {
119 				if ('.' == c) {
120 					throw new IllegalArgumentException("Illegal name '" + name + "' (cannot start or end with a period)");
121 				}
122 			}
123 		}
124 		/*
125 		Assert.notNull(name, "Name required");
126 		Assert.isTrue(!name.contains("/"), "Slashes are prohibited in the name");
127 		Assert.isTrue(!name.contains(" "), "Spaces are prohibited in the name");
128 		Assert.isTrue(!name.contains("*"), "Illegal name");
129 		Assert.isTrue(!name.contains(">"), "Illegal name");
130 		Assert.isTrue(!name.contains("<"), "Illegal name");
131 		Assert.isTrue(!name.contains("!"), "Illegal name");
132 		Assert.isTrue(!name.contains("@"), "Illegal name");
133 		Assert.isTrue(!name.contains("%"), "Illegal name");
134 		Assert.isTrue(!name.contains("^"), "Illegal name");
135 		Assert.isTrue(!name.contains("?"), "Illegal name");
136 		Assert.isTrue(!name.contains("("), "Illegal name");
137 		Assert.isTrue(!name.contains(")"), "Illegal name");
138 		Assert.isTrue(!name.contains("~"), "Illegal name");
139 		Assert.isTrue(!name.contains("`"), "Illegal name");
140 		Assert.isTrue(!name.contains("{"), "Illegal name");
141 		Assert.isTrue(!name.contains("}"), "Illegal name");
142 		Assert.isTrue(!name.contains("["), "Illegal name");
143 		Assert.isTrue(!name.contains("]"), "Illegal name");
144 		Assert.isTrue(!name.contains("|"), "Illegal name");
145 		Assert.isTrue(!name.contains("\""), "Illegal name");
146 		Assert.isTrue(!name.contains("'"), "Illegal name");
147 		Assert.isTrue(!name.contains("+"), "Illegal name");
148 		Assert.isTrue(!name.startsWith("1"), "Illegal name");
149 		Assert.isTrue(!name.startsWith("2"), "Illegal name");
150 		Assert.isTrue(!name.startsWith("3"), "Illegal name");
151 		Assert.isTrue(!name.startsWith("4"), "Illegal name");
152 		Assert.isTrue(!name.startsWith("5"), "Illegal name");
153 		Assert.isTrue(!name.startsWith("6"), "Illegal name");
154 		Assert.isTrue(!name.startsWith("7"), "Illegal name");
155 		Assert.isTrue(!name.startsWith("8"), "Illegal name");
156 		Assert.isTrue(!name.startsWith("9"), "Illegal name");
157 		Assert.isTrue(!name.startsWith("0"), "Illegal name");
158 		Assert.isTrue(!name.startsWith("."), "The name cannot begin with a period");
159 		Assert.isTrue(!name.endsWith("."), "The name cannot end with a period");
160 		*/
161 	}
162 }