public class NameConverter extends java.lang.Object implements MatchPhraseConstants
NameConverter
instance is unaware of the type of symbol
being converted, but it is aware of the type of symbol which must result
from the conversion. The latter is specified during construction using
one of this class' type constants.
Sun-like naming conventions are used to generate Java variable, method, "constant", and class names:
processVariableSyllable(java.lang.String, int)
and
processMethodSyllable(java.lang.String, int)
, respectively, to modify);
processConstantSyllable(java.lang.String, int)
to modify);
processClassSyllable(java.lang.String, int)
to modify).
processDatabaseSyllable(java.lang.String, int)
to modify);
processTableSyllable(java.lang.String, int)
to modify);
processColumnSyllable(java.lang.String, int)
to modify);
processIndexSyllable(java.lang.String, int)
to modify).
Replacement entries can be overridden as a whole via the setReplacements(java.util.Map<java.lang.String, java.lang.String>)
method. Individual replacements can be overridden, and
arbitrary replacements added, via the putReplacement(java.lang.String, java.lang.String)
method.
If more than one substring key matches within a symbol name, the following
precedence rules apply:
Except for the type-specific rules described above, case is generally preserved in the converted symbol name. However, substring matches for the purpose of performing replacements are case-insensitive.
TODO: conversion to Java variable and method names should match the behavior of java.bean.Introspector.decapitalize(). Currently, it does so in 99.9% of cases, but it seems that certain character combinations are handled differently, such as when underscore follows a first, capital letter.
TODO: if the generic replacement functionality in this class is useful in other contexts, this functionality should be abstracted into a parent class (e.g., StringConverter). The key methods which would be moved into this parent would be:
setReplacements(java.util.Map<java.lang.String, java.lang.String>)
- no changes
putReplacement(java.lang.String, java.lang.String)
- no changes
convert(java.lang.String, int)
- no changes
nextToken()
- no changes
processSyllable(java.lang.String, int)
- would return syllable text unmodified by
default; subclasses would override.
prepareCandidates()
- no changes
Modifier and Type | Field and Description |
---|---|
private java.lang.String[] |
candidates
Array of candidates when matching substrings for replacement
|
private static java.lang.String |
currentSchemaName
Currently processed database name
|
private static MatchPhraseDictionary |
defaults
Default substring replacements, indexed by substring to be replaced
|
private static int |
FULL_MATCH
Used when matching substrings within symbol; indicates full match
|
private java.util.Map<java.lang.String,java.lang.String> |
fulltxt
Map of "full text only" replacements.
|
private int |
index
Current position in original name symbol
|
private static java.util.Map<java.lang.String,java.lang.String> |
mappings
Default replacement mappings.
|
private int[] |
matches
Array of match state for each candidate during a match operation
|
private java.lang.String |
name
Original name to be converted
|
private static int |
NO_MATCH
Used when matching substrings within symbol; indicates no match
|
private static int |
PARTIAL_MATCH
Used when matching substrings within symbol; indicates partial match
|
private java.lang.String |
pendingMatch
A substring match detected via lookahead while processing next token
|
private java.util.Stack<java.lang.String> |
pendingStack
A stack of pending replacement syllables detected via lookahead
|
private java.util.Map<java.lang.String,java.lang.String> |
replacements
Map of substring replacements, indexed by substring to be replaced
|
private static java.util.Set<java.lang.String> |
reservedJava
All Java language reserved keywords or named literals
|
private static java.util.Set<java.lang.String> |
reservedSQL
Problematic SQL keywords
|
private java.util.Map<java.lang.String,java.lang.String> |
standards
Map of standard replacements, applied in case of no-replace mode
|
private int |
type
Type of conversion being performed (using this class' constants)
|
ALL, CUSTOM, PRESERVE, STANDARD, TYPE_CLASS, TYPE_COLUMN, TYPE_CONSTANT, TYPE_DATABASE, TYPE_INDEX, TYPE_METHOD, TYPE_PROPERTY, TYPE_SIMPLE, TYPE_TABLE, TYPE_VARIABLE
Constructor and Description |
---|
NameConverter()
Default constructor;
ALL default match phrases from the
project-specific match phrase dictionary are loaded, and replacement
is enabled. |
NameConverter(int phrases,
boolean replace)
Constructor which accepts a code indicating which default matches to
pick up from the project's match phrase dictionary.
|
Modifier and Type | Method and Description |
---|---|
java.lang.String |
convert(java.lang.String name,
int type)
Perform the symbol name conversion and return the converted name.
|
private java.lang.String |
convert(java.lang.String name,
int type,
boolean internal)
Perform the symbol name conversion and return the converted name.
|
static java.lang.String |
convertPackage(java.lang.String pkg)
Lowercase and split the input into individual package names, then ensure that each
one is not a conflict with a Java reserved word.
|
java.lang.String |
describeConversion()
Retrieve a string describing the conversion type performed by this
converter.
|
private java.lang.String |
fullTextReplacement(java.lang.String candidate)
If the given candidate name is marked as a forced full text match (a
match that is only allowed with the full text of the name rather than
as a partial basis), return that replacement.
|
static java.lang.String |
generateBeanName(java.lang.String field,
boolean getter,
boolean bool)
Create a (mostly) Java-bean compatible getter or setter name for a
given field.
|
java.lang.String |
getName()
Get the name being converted.
|
private java.lang.String |
getPendingReplacement()
Get the next pending replacement string, if any, based on a previous
substring match.
|
static void |
load(java.lang.String list,
boolean db)
Load or reload the match phrase dictionary definitions from the given
persisted match list or the default defined for the current project.
|
static void |
main(java.lang.String[] args)
Entry point and test harness for this class.
|
private java.lang.String |
nextToken()
Generate the next token (aka syllable) to be appended to the target
symbol name.
|
private void |
prepareCandidates()
Perform preparation of the data structures used to match candidate
substrings in the
nextToken() method. |
private java.lang.String |
preprocess(java.lang.String name)
Preprocess the given name.
|
protected java.lang.String |
processClassSyllable(java.lang.String text,
int syllable)
Process a syllable for a Java class or interface symbol name.
|
protected java.lang.String |
processColumnSyllable(java.lang.String text,
int syllable)
Process a syllable for an SQL column symbol name.
|
protected java.lang.String |
processConstantSyllable(java.lang.String text,
int syllable)
Process a syllable for a Java "constant" symbol name.
|
protected java.lang.String |
processDatabaseSyllable(java.lang.String text,
int syllable)
Process a syllable for an SQL database symbol name.
|
protected java.lang.String |
processIndexSyllable(java.lang.String text,
int syllable)
Process a syllable for an SQL index symbol name.
|
protected java.lang.String |
processMethodSyllable(java.lang.String text,
int syllable)
Process a syllable for a Java method symbol name.
|
private java.lang.String |
processSql(java.lang.String text,
int syllable)
This is the backing method behind the
processDatabaseSyllable(java.lang.String, int) ,
processTableSyllable(java.lang.String, int) , processColumnSyllable(java.lang.String, int) , and
processIndexSyllable(java.lang.String, int) methods, which all have the same default
behavior. |
protected java.lang.String |
processSyllable(java.lang.String text,
int syllable)
Process each syllable which will become a component of the converted
symbol name.
|
protected java.lang.String |
processTableSyllable(java.lang.String text,
int syllable)
Process a syllable for an SQL table symbol name.
|
protected java.lang.String |
processVariableSyllable(java.lang.String text,
int syllable)
Process a syllable for a Java variable symbol name.
|
private java.lang.String |
processVarMeth(java.lang.String text,
int syllable)
This is the backing method behind the
processVariableSyllable(java.lang.String, int)
and processMethodSyllable(java.lang.String, int) methods, which both have the same
default behavior. |
void |
putReplacement(java.lang.String key,
java.lang.String value)
Override an individual, default substring replacement definition, or
add an arbitrary substring replacement definition to the default
definitions.
|
static void |
resetDialects(java.lang.String schema)
Reset the internal keyword exclusion list for the next schema to be processed.
|
private void |
resetMatchStatus()
Reset the list of potential matches so that each candidate has an
equal starting state of NO_MATCH.
|
private static java.lang.String |
resolvePossibleKeywordConflict(java.lang.String possible,
int type)
Test the given name against the list of Java keywords and resolve any
conflict by adding text to the name to make it different (and thus
javac will compile it).
|
void |
setReplacements(java.util.Map<java.lang.String,java.lang.String> replacements)
Completely override the default substring replacement definitions with
the map specified.
|
private void |
setupPendingStack(java.lang.String key)
Set up the stack of pending replacement words.
|
java.lang.String |
toString()
Get a string representation of this object.
|
private static final int NO_MATCH
private static final int PARTIAL_MATCH
private static final int FULL_MATCH
private static java.util.Map<java.lang.String,java.lang.String> mappings
private static MatchPhraseDictionary defaults
private static final java.util.Set<java.lang.String> reservedJava
private static final java.util.Set<java.lang.String> reservedSQL
private static java.lang.String currentSchemaName
private java.util.Map<java.lang.String,java.lang.String> replacements
private java.util.Map<java.lang.String,java.lang.String> standards
private java.util.Map<java.lang.String,java.lang.String> fulltxt
private java.lang.String[] candidates
private int[] matches
private java.lang.String name
private int type
private int index
private java.lang.String pendingMatch
private java.util.Stack<java.lang.String> pendingStack
public NameConverter()
ALL
default match phrases from the
project-specific match phrase dictionary are loaded, and replacement
is enabled.public NameConverter(int phrases, boolean replace)
phrases
- A bitwise-OR'd combination of MatchPhraseConstants
flags indicating which set of default match phrase entries
to load from the project-specific match phrase dictionary.replace
- If true
, any token from the match phrase entries
defined by phrases
which is found within
name
is replaced with its designated replacement
string. If false
, only tokens from the standard
entries (if phrases
includes the constant
STANDARD
) are replaced. All other tokens are
recognized as separate syllables, but are not replaced.public static void resetDialects(java.lang.String schema)
schema
- The schema to prepare for.public static void load(java.lang.String list, boolean db) throws ConfigurationException
list
- The match list to use or null
to use the default
match list.db
- true
to add the database specific default mappings,
otherwise only add the code mappings.ConfigurationException
- if there is any error with the global configuration or an
error loading the dictionary from persistence. A missing
match list file is not fatal and does not trigger
this exception, but does elicit a warning message to
stderr
.public static java.lang.String generateBeanName(java.lang.String field, boolean getter, boolean bool) throws java.lang.IllegalArgumentException
boolean
and a getter is
requested, then the prefix will be "is", otherwise getters are prefixed
with "get". All setters are prefixed with "set". The name of the
field always has its first character uppercased which is slightly
different than how Sun defines the standard.field
- The name to use as the basis, must be non-null and non-empty.getter
- If true
the resulting bean name will be a
getter.bool
- If getter
is true
and this is
true
then the resulting bean name will prefixed
with "is" instead of "get". Ignored for setters.java.lang.IllegalArgumentException
- If the field name is null
or is the empty string.public java.lang.String getName()
public void setReplacements(java.util.Map<java.lang.String,java.lang.String> replacements)
replacements
- Map of substrings to match and the text which should replace
them in the converted symbol name, as described above.public void putReplacement(java.lang.String key, java.lang.String value)
key
- The substring to be replaced in the original symbol name.
The match against this key is case-insensitive.value
- The text to be substituted in the target symbol name, wherever
key
is found in the original. Case is generally
preserved in the replacement value, though it may be
overridden depending upon the target symbol type.public java.lang.String convert(java.lang.String name, int type)
For example, the symbol test-name
is processed as three
syllables: test
(precedes the replacement of
"-
") and name
(succeeds the replacement of
"-
"). In addition, the empty string which replaces the
hyphen character between these two syllables is itself considered as
the second syllable for processing purposes, even though it does not
appear in the converted result:
testName
testName
TEST_NAME
TestName
test_name
test_name
test_name
test_name
test%name
, the second
syllable would instead be Pct
(using the default set of
replacements).
The processSyllable(java.lang.String, int)
method is called for each syllable
encountered. The string returned from that method is appended to the
target symbol. This occurs until the entire, original symbol name has
been processed.
name
- Name to be converted.type
- One of the type constants defined in this class. Indicates
what type of Java or SQL symbol should result from the
conversion.public static java.lang.String convertPackage(java.lang.String pkg)
pkg
- A candidate Java package name, possibly including multiple period-separated
directories.public java.lang.String describeConversion()
public java.lang.String toString()
toString
in class java.lang.Object
protected java.lang.String processSyllable(java.lang.String text, int syllable)
description
.text
- Text which comprises the current syllable being processed.syllable
- Zero-based index of this syllable in the converted symbol
name.protected java.lang.String processVariableSyllable(java.lang.String text, int syllable)
Default processing is to lowercase the first letter of the first symbol, and uppercase the first letter of all subsequent syllables.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.protected java.lang.String processMethodSyllable(java.lang.String text, int syllable)
Default processing is to lowercase the first letter of the first symbol, and uppercase the first letter of all subsequent syllables.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.protected java.lang.String processConstantSyllable(java.lang.String text, int syllable)
Default processing is to uppercase all letters and prepend an underscore character to each syllable after the first.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.protected java.lang.String processClassSyllable(java.lang.String text, int syllable)
Default processing is to uppercase the first letter of every syllable.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.protected java.lang.String processDatabaseSyllable(java.lang.String text, int syllable)
Default processing is to lowercase all letters and prepend an underscore character to each syllable after the first.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.protected java.lang.String processTableSyllable(java.lang.String text, int syllable)
Default processing is to lowercase all letters and prepend an underscore character to each syllable after the first.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.protected java.lang.String processColumnSyllable(java.lang.String text, int syllable)
Default processing is to lowercase all letters and prepend an underscore character to each syllable after the first.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.protected java.lang.String processIndexSyllable(java.lang.String text, int syllable)
Default processing is to lowercase all letters and prepend an underscore character to each syllable after the first.
text
- Text of current syllable.syllable
- Zero-based index of current syllable.private java.lang.String convert(java.lang.String name, int type, boolean internal)
For example, the symbol test-name
is processed as three
syllables: test
(precedes the replacement of
"-
") and name
(succeeds the replacement of
"-
"). In addition, the empty string which replaces the
hyphen character between these two syllables is itself considered as
the second syllable for processing purposes, even though it does not
appear in the converted result:
testName
testName
TEST_NAME
TestName
test_name
test_name
test_name
test_name
testName
or TName
in certain cases,
where after a lowercase char there is a set of uppercases chars. This is done in
order to match the way Hibernate expectes these property names.
test%name
, the second
syllable would instead be Pct
(using the default set of
replacements).
The processSyllable(java.lang.String, int)
method is called for each syllable
encountered. The string returned from that method is appended to the
target symbol. This occurs until the entire, original symbol name has
been processed.
This method may be invoked as an internal attempt to remove any illegal characters from a converted syllable. In this case, full text only mode is ignored.
name
- Name to be converted.type
- One of the type constants defined in this class. Indicates
what type of Java or SQL symbol should result from the
conversion.internal
- true
if this method is invoked due to internal
housekeeping; false
if invoked as the result of
an external call.private java.lang.String preprocess(java.lang.String name)
name
- Name to be converted.private java.lang.String fullTextReplacement(java.lang.String candidate)
candidate
- The string that is to be tested.null
if this
candidate is not forced into full text mode.private java.lang.String processVarMeth(java.lang.String text, int syllable)
processVariableSyllable(java.lang.String, int)
and processMethodSyllable(java.lang.String, int)
methods, which both have the same
default behavior.text
- Text of current syllable.syllable
- Zero-based index of current syllable.private java.lang.String processSql(java.lang.String text, int syllable)
processDatabaseSyllable(java.lang.String, int)
,
processTableSyllable(java.lang.String, int)
, processColumnSyllable(java.lang.String, int)
, and
processIndexSyllable(java.lang.String, int)
methods, which all have the same default
behavior.text
- Text of current syllable.syllable
- Zero-based index of current syllable.private java.lang.String nextToken()
For example, the symbol this&that
would generate three
tokens (i.e., syllables), using the default replacement map:
this
- not matched for any substring replacement; its
end is determined by the fact that the next character begins a
a run of characters (in this case, one character, actually) which
is matched to replacement key &
;
and
- replacement text for substring
&
;
that
- not matched for any substring replacement; its
end is determined by the end of the original token string.
null
if
we have reached the end of the original symbol string and
we have no new characters to return.private void resetMatchStatus()
private void setupPendingStack(java.lang.String key)
nextToken()
until the stack is empty.key
- A substring which was matched in the original symbol; the
key to a replacement string in the map of replacements.private java.lang.String getPendingReplacement()
null
if
the stack of pending replacements is empty.private void prepareCandidates()
nextToken()
method. This includes setting
each candidate key string into an array, and creating a new array
of integers to track the match status of each candidate key as the
nextToken
method scans characters from the original
symbol.private static java.lang.String resolvePossibleKeywordConflict(java.lang.String possible, int type)
possible
- The name to check for conflicts.type
- The type of name. This is used to ensure that the name is
a Java name (and thus requires conflict resolution).public static void main(java.lang.String[] args)
symbol
(required) - Progress symbol name to be
converted;
type
(required) - type of conversion to apply. Use
the integer equivalents of the TYPE_*
constants
defined by this class;
replace
(required) - true/false. True to replace
substrings as the name is tokenized; false to tokenize syllables
without replacement;
key
(optional) - substring in symbol
to be replaced by the following parameter;
replacement
(required) - replacement text for the
immediately previous parameter.
args
- Command line parameters as described above.