OPENJPA-1115 Base identifier support

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@899738 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jeremy Bauer 2010-01-15 18:05:14 +00:00
parent 5a8c5de491
commit 8e0e9cfbd2
10 changed files with 1523 additions and 0 deletions

View File

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
/**
* Base interface for identifiers.
*/
public interface Identifier extends Comparable<Identifier>, Cloneable {
public String getName();
public void setName(String name);
public int length();
}

View File

@ -0,0 +1,89 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import java.util.Map;
/**
* The IdentifierConfiguration interface. Implementers of this interface supply
* naming configuration information to consumers of names/identifiers.
*/
public interface IdentifierConfiguration {
/**
* Returns the leading delimiter value to use when delimiting a name.
*/
public String getLeadingDelimiter();
/**
* Returns the trailing delimiter value to use when delimiting a name.
*/
public String getTrailingDelimiter();
/**
* Returns true if global name delimiting is enabled.
*/
public boolean delimitAll();
/**
* Returns true if delimiting is supported
*/
public boolean getSupportsDelimitedIdentifiers();
/**
* Returns the value used to concatenate multiple names together.
* For example: "_" used in TABLE1_TABLE2
*/
public String getIdentifierConcatenator();
/**
* Returns the value used to delimit between individual names.
* For example: "." used in MYSCHEMA.MYTABLE
*/
public String getIdentifierDelimiter();
/**
* Gets the default naming rule
*/
public IdentifierRule getDefaultIdentifierRule();
/**
* Returns all naming rules
* @return
*/
public <T> Map<T, IdentifierRule> getIdentifierRules();
/**
* Returns a naming rule or null if the rule is
* not found.
*/
public <T> IdentifierRule getIdentifierRule(T t);
/**
* Returns the case that is used when delimiting.
* @return upper, lower, or preserve
*/
public String getDelimitedCase();
/**
* Returns the case that is used when delimiters are not used.
* @return upper, lower, or preserve
*/
public String getSchemaCase();
}

View File

@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import java.io.Serializable;
/**
* Base identifer implementation.
*/
public class IdentifierImpl implements Identifier, Serializable {
private String _name = null;
protected IdentifierImpl() {}
public IdentifierImpl(String name) {
setName(name);
}
public void setName(String name) {
_name = name;
}
public String getName() {
return _name;
}
public String toString() {
return getName();
}
public int hashCode() {
if (_name == null) {
return super.hashCode();
}
return _name.hashCode();
}
public int length() {
if (getName() == null) {
return 0;
}
return getName().length();
}
public int compareTo(Identifier o) {
if (_name == null && (o == null || o.getName() == null)) {
return 0;
}
if (_name == null)
return 1;
if (o == null || o.getName() == null)
return -1;
return _name.compareTo(o.getName());
}
}

View File

@ -0,0 +1,209 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
/**
* The standard identifier rule. Rules are used for specific configuration
* of identifier types. For example. A rule could be used to indicate that
* an identifier type should not be delimited or has a max length of 255
* characters.
*
*/
public class IdentifierRule {
public static final Set<String> EMPTY_SET = new HashSet<String>(0);
public static final String DEFAULT_RULE = "default";
public static char UNDERSCORE = '_';
private String _name;
private int _maxLength = 128;
private boolean _nullable = false;
private boolean _allowTruncation = false;
private boolean _allowCompaction = true;
private boolean _canDelimit = true;
private boolean _mustDelimit = false;
private boolean _mustBeginWithLetter = true;
private boolean _onlyLettersDigitsUnderscores = true;
private String _specialCharacters = "";
private Set<String> _reservedWords = null;
private boolean _delimitReservedWords = false;
private String _wildcard = "%";
public void setName(String name) {
_name = name;
}
public String getName() {
return _name;
}
public void setMaxLength(int maxLength) {
_maxLength = maxLength;
}
public int getMaxLength() {
return _maxLength;
}
public void setAllowTruncation(boolean allowTruncation) {
_allowTruncation = allowTruncation;
}
public boolean isAllowTruncation() {
return _allowTruncation;
}
public void setNullable(boolean nullable) {
_nullable = nullable;
}
public boolean isNullable() {
return _nullable;
}
public void setAllowCompaction(boolean allowCompaction) {
_allowCompaction = allowCompaction;
}
public boolean getAllowCompaction() {
return _allowCompaction;
}
public void setCanDelimit(boolean canDelimit) {
_canDelimit = canDelimit;
}
public boolean getCanDelimit() {
return _canDelimit;
}
public void setMustDelimit(boolean mustDelimit) {
_mustDelimit = mustDelimit;
}
public boolean getMustDelimit() {
return _mustDelimit;
}
public void setMustBeginWithLetter(boolean mustBeginWithLetter) {
_mustBeginWithLetter = mustBeginWithLetter;
}
public boolean isMustBeginWithLetter() {
return _mustBeginWithLetter;
}
public void setOnlyLettersDigitsUnderscores(boolean onlyLettersDigitsUnderscores) {
_onlyLettersDigitsUnderscores = onlyLettersDigitsUnderscores;
}
public boolean isOnlyLettersDigitsUnderscores() {
return _onlyLettersDigitsUnderscores;
}
public void setReservedWords(Set<String> reservedWords) {
_reservedWords = reservedWords;
}
public Set<String> getReservedWords() {
if (_reservedWords == null) {
_reservedWords = new HashSet<String>();
}
return _reservedWords;
}
public void setSpecialCharacters(String specialCharacters) {
_specialCharacters = specialCharacters;
}
public String getSpecialCharacters() {
return _specialCharacters;
}
public void setDelimitReservedWords(boolean delimitReservedWords) {
delimitReservedWords = _delimitReservedWords;
}
public boolean getDelimitReservedWords() {
return _delimitReservedWords;
}
/**
* SQL identifier rules:
* 1) Can be up to 128 characters long
* 2) Must begin with a letter
* 3) Can contain letters, digits, and underscores
* 4) Can't contain spaces or special characters such as #, $, &, %, or
* punctuation.
* 5) Can't be reserved words
*/
public boolean requiresDelimiters(String identifier) {
// Do not delimit single valued wildcards or "?" or names that have method-type
// signatures (ex. getValue()). These are considered special values in OpenJPA
// and should not be delimited.
if (_wildcard.equals(identifier) || "?".equals(identifier) ||
identifier.endsWith("()")) {
return false;
}
if (getMustDelimit()) {
return true;
}
// Assert identifier begins with a letter
char[] chars = identifier.toCharArray();
if (isMustBeginWithLetter()) {
if (!CharUtils.isAsciiAlpha(chars[0])) {
return true;
}
}
// Iterate through chars, asserting delimiting rules
for (char ch : chars) {
if (isOnlyLettersDigitsUnderscores()) {
if (!CharUtils.isAsciiAlphanumeric(ch) && !(ch == UNDERSCORE)) {
return true;
}
}
// Look for special characters
if (StringUtils.contains(getSpecialCharacters(), ch)) {
return true;
}
}
// Finally, look for reserved words
if (getDelimitReservedWords()) {
if (isReservedWord(identifier)) {
return true;
}
}
return false;
}
public boolean isReservedWord(String identifier) {
return _reservedWords.contains(identifier);
}
}

View File

@ -0,0 +1,319 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
/**
* Base IdentifierUtil interface. Defines many operations for operating
* on strings using identifier rules.
*/
public interface IdentifierUtil {
public static final String DOUBLE_QUOTE = "\"";
public static final String DOT = ".";
public static final String UNDERSCORE = "_";
public static final String SPACE = " ";
public static final String BAR = "|";
public static final String EMPTY = "";
public static final String PERCENT = "%";
public static final char DOLLAR_CHAR = '$';
public static final char UNDERSCORE_CHAR = '_';
public static final String CASE_UPPER = "upper";
public static final String CASE_LOWER = "lower";
public static final String CASE_PRESERVE = "preserve";
/**
* Get the naming configuration.
*/
public IdentifierConfiguration getIdentifierConfiguration();
/**
* Set the naming configuration to use for naming operations. A naming
* configuration must be set before calling any other methods.
*/
void setIdentifierConfiguration(IdentifierConfiguration config);
/**
* Delimit the name if it requires delimiters
* @param the rule to use for delimiting
* @param name the name to delimit
* @return the delimited name, if delimiting was necessary.
*/
public String delimit(String rule, String name);
/**
* Delimit the name if it requires delimiters
* @param the rule to use for delimiting
* @param name the name to delimit
* @return the delimited name, if delimiting was necessary.
*/
public String delimit(IdentifierRule rule, String name);
/**
* Delimit the string with the option to force delimiting. If force is
* true, the name will delimited without checking to see if it
* requires delimiters.
* @param the rule to use for delimiting
* @param name the name to delimit
* @param force add delimiters even if delimiting is not required
* @return the delimited name, if delimiting was necessary.
*/
public String delimit(String rule, String name, boolean force);
/**
* Delimit the string with the option to force delimiting. If force is
* true, the name will delimited without checking to see if it
* requires delimiters.
* @param the rule to use for delimiting
* @param name the name to delimit
* @param force add delimiters even if delimiting is not required
* @return the delimited name, if delimiting was necessary.
*/
public String delimit(IdentifierRule rule, String name, boolean force);
/**
* Remove delimiters from a delimited name
* @param the rule to use for removing delimiters
* @param name the name from which to remove delimiters
*/
public String removeDelimiters(String rule, String name);
/**
* Remove delimiters from a delimited name
* @param the rule to use for removing delimiters
* @param name the name from which to remove delimiters
*/
public String removeDelimiters(IdentifierRule rule, String name);
/**
* Determines whether a name is delimited.
* @param the rule to use for removing delimiters
* @param name the name to examine for delimiters
*/
public boolean isDelimited(String rule, String name);
/**
* Determines whether a name is delimited.
* @param the rule to use for removing delimiters
* @param name the name to examine for delimiters
*/
public boolean isDelimited(IdentifierRule rule, String name);
/**
* Determines whether a name requires delimiters based upon:
* <ul>
* <li> The SQL-92 Reference definition of a valid unquoted name</li>
* <li> The naming rule specified</li>
* </ul>
* @param the rule to use for removing delimiters
* @param name the name to examine for delimiting requirements
*/
public boolean requiresDelimiters(String rule, String name);
/**
* Determines whether a name requires delimiters based upon:
* <ul>
* <li> The SQL-92 Reference definition of a valid unquoted name</li>
* <li> The naming rule specified</li>
* </ul>
* @param the rule to use for removing delimiters
* @param name the name to examine for delimiting requirements
*/
public boolean requiresDelimiters(IdentifierRule rule, String name);
/**
* Combines names using delimiting rules and appropriate separators
* @return a combined name
* ex. {"TH IS", THAT} -> "TH IS_THAT"
*/
public String combineNames(String rule, String[] rules, String[] names);
/**
* Combines names using delimiting rules and appropriate separators
* @return a combined name
* ex. {"TH IS", THAT} -> "TH IS_THAT"
*/
public String combineNames(IdentifierRule rule, IdentifierRule[] rules, String[] names);
/**
* Combines names using the specified delimiting rule and appropriate separators
* @return a combined name
* ex. {"TH IS", THAT} -> "TH IS_THAT"
*/
public String combineNames(String rule, String[] names);
/**
* Combines names using the specified delimiting rule and appropriate separators
* @return a combined name
* ex. {"TH IS", THAT} -> "TH IS_THAT"
*/
public String combineNames(IdentifierRule rule, String[] names);
/**
* Combines two names using delimiting rules and appropriate separators
*/
public String combineNames(String rule, String name1, String name2);
/**
* Combines two names using delimiting rules and appropriate separators
*/
public String combineNames(IdentifierRule rule, String name1, String name2);
/**
* Joins several names with different naming rules into a single string
* using appropriate delimiters and separators
*/
public String joinNames(String[] rules, String[] names);
/**
* Joins several names with different naming rules into a single string
* using appropriate delimiters and separators
*/
public String joinNames(IdentifierRule[] rules, String[] names);
/**
* Joins several names with different naming rules into a single string
* using appropriate delimiters and separators
*/
public String joinNames(String rule, String[] names);
/**
* Joins several names with different naming rules into a single string
* using appropriate delimiters and separators
*/
public String joinNames(IdentifierRule rule, String[] names);
/**
* Joins several names with different naming rules into a single string
* using the specified delimiter
*/
public String joinNames(IdentifierRule rule, String[] names, String delimiter);
/**
* Joins several names with different naming rules into a single string
* using the specified delimiter
*/
public String joinNames(String rule, String[] names, String delimiter);
/**
* Splits a combined name name using the provided naming rule
* @param name the multi-value name
* @return individual components of the name
* ex. schema.table --> { schema, table }
*/
public String[] splitName(String rule, String name);
/**
* Splits a combined name name using the provided naming rule
* @param name the multi-value name
* @return individual components of the name
* ex. schema.table --> { schema, table }
*/
public String[] splitName(IdentifierRule rule, String name);
/**
* Splits a combined name name using the provided naming rule and
* delimiter.
* @param name the multi-value name
* @return individual components of the name
* ex. schema.table --> { schema, table }
*/
public String[] splitName(String rule, String name, String delimiter);
/**
* Splits a combined name name using the provided naming rule and
* delimiter.
* @param name the multi-value name
* @return individual components of the name
* ex. schema.table --> { schema, table }
*/
public String[] splitName(IdentifierRule rule, String name, String delimiter);
/**
* Returns whether a name is considered a reserved word
*/
public boolean isReservedWord(String rule, String name);
/**
* Returns whether a name is considered a reserved word
*/
public boolean isReservedWord(IdentifierRule rule, String name);
/**
* Convert the string using this naming configuration to the supplied
* naming configuration.
*/
public String convert(IdentifierConfiguration config, String rule, String name);
/**
* Truncates a name while maintaining delimiters.
*/
public String truncateName(String rule, String name, int length);
/**
* Truncates a name while maintaining delimiters.
*/
public String truncateName(IdentifierRule rule, String name, int length);
/**
* Append the names together while maintaining delimiters.
*/
public String appendNames(IdentifierRule rule, String name1, String name2);
/**
* Append the names together while maintaining delimiters.
*/
public String appendNames(String rule, String name1, String name2);
/**
* Converts a qualified string-based name defined using the base configuration to the
* specified configuration. Returns the converted name.
*/
public String convertFull(IdentifierConfiguration config, String rule, String fullName);
/**
* Removes Hungarian notation from the specified string.
*/
public String removeHungarianNotation(String rule, String name);
/**
* Removes Hungarian notation from the specified string.
*/
public String removeHungarianNotation(IdentifierRule rule, String name);
/**
* Determines whether a name can be split into multiple components.
*/
public boolean canSplit(String rule, String name);
/**
* Determines whether a name can be split into multiple components.
*/
public boolean canSplit(IdentifierRule rule, String name);
/**
* Determines whether a name can be split into multiple components, taking
* into account the specified delimiter.
*/
public boolean canSplit(String rule, String name, String delim);
/**
* Determines whether a name can be split into multiple components, taking
* into account the specified delimiter.
*/
public boolean canSplit(IdentifierRule rule, String name, String delim);
}

View File

@ -0,0 +1,548 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import java.util.ArrayList;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.lib.conf.Configurable;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.util.Localizer;
/**
* Implementation class for the base identifier impl.
*
*/
public class IdentifierUtilImpl implements IdentifierUtil, Configurable {
private static final Localizer _loc = Localizer.forPackage
(IdentifierUtilImpl.class);
private IdentifierConfiguration _config = null;
public IdentifierUtilImpl() {
}
public IdentifierUtilImpl(IdentifierConfiguration config) {
_config = config;
}
public void setIdentifierConfiguration(IdentifierConfiguration config) {
_config = config;
}
public IdentifierConfiguration getIdentifierConfiguration() {
return _config;
}
public String combineNames(IdentifierRule rule, IdentifierRule[] rules, String[] names) {
boolean delimited = false;
String combined = null;
for (int i = 0; i < names.length; i++) {
String name = names[i];
if (isDelimited(rules[i], name)) {
delimited = true;
name = removeDelimiters(rules[i], name);
}
if (i == 0) {
combined = name;
}
else {
combined = combined + _config.getIdentifierConcatenator() + name;
}
}
if (delimited) {
combined = delimit(rule, combined.toString()).toString();
}
return combined;
}
public String combineNames(IdentifierRule rule, String name1, String name2) {
boolean delimit = false;
if (isDelimited(rule, name1)) {
name1 = removeDelimiters(rule, name1);
delimit = true;
}
if (isDelimited(rule, name2)) {
name2 = removeDelimiters(rule, name2);
delimit = true;
}
String name = name1 + _config.getIdentifierConcatenator() + name2;
return delimit(rule, name, delimit).toString();
}
public String combineNames(IdentifierRule namingRule, String[] names) {
boolean delimited = false;
String combined = null;
for (int i = 0; i < names.length; i++) {
String name = names[i];
if (isDelimited(namingRule, name)) {
delimited = true;
name = removeDelimiters(namingRule, name);
}
if (i == 0) {
combined = name;
}
else {
combined = combined + _config.getIdentifierConcatenator() + name;
}
}
if (delimited) {
combined = delimit(namingRule, combined.toString()).toString();
}
return combined;
}
public String appendNames(IdentifierRule rule, String name1, String name2) {
if (isDelimited(rule, name1)) {
name1 = removeDelimiters(rule, name1);
}
if (isDelimited(rule, name2)) {
name2 = removeDelimiters(rule, name2);
}
if (name1 == null) {
name1 = IdentifierUtil.EMPTY;
}
if (name2 == null) {
name2 = IdentifierUtil.EMPTY;
}
String name = name1 + name2;
return delimit(rule, name).toString();
}
/**
* Joins multiple names together using the standard delimiting rules
* ex. ( {"s", "t", "c"} --> "s"."t"."c" }
*/
public String joinNames(IdentifierRule[] rules, String[] names) {
if (names == null || names.length == 0) {
return null;
}
StringBuilder combinedName = new StringBuilder();
for (int i = 0; i < names.length; i++) {
combinedName.append(delimit(rules[i], names[i]));
if (i < (names.length -1)) {
combinedName.append(_config.getIdentifierDelimiter());
}
}
return combinedName.toString();
}
public String joinNames(String rule, String[] names) {
return joinNames(_config, getNamingRule(rule), names, _config.getIdentifierDelimiter());
}
public String joinNames(IdentifierRule rule, String[] names) {
return joinNames(_config, rule, names, _config.getIdentifierDelimiter());
}
public String joinNames(IdentifierRule rule, String[] names, String delimiter) {
return joinNames(_config, rule, names, delimiter);
}
public String joinNames(String rule, String[] names, String delimiter) {
return joinNames(_config, getNamingRule(rule), names, delimiter);
}
/**
* Join names using a single naming rule and specified delimiter
* @param rule
* @param names
* @return
*/
public String joinNames(IdentifierConfiguration config, IdentifierRule rule, String[] names, String delimiter) {
if (names == null || names.length == 0) {
return null;
}
StringBuilder combinedName = new StringBuilder();
for (int i = 0; i < names.length; i++) {
if (names[i] != null) {
combinedName.append(delimit(config, rule, names[i], false));
if (i < (names.length -1)) {
combinedName.append(delimiter);
}
}
}
return combinedName.toString();
}
public String[] splitName(IdentifierRule nrule, String name) {
return splitName(nrule, name, _config.getIdentifierDelimiter());
}
/**
* Splits names using single naming rule and appropriate separators
* @param name the multi-value name
* @return individual components of the name
* ex. schema.table --> { schema, table }
*/
public String[] splitName(IdentifierRule nrule, String name, String nameDelim) {
if (!canSplit(nrule, name, nameDelim) || StringUtils.isEmpty(name)) {
return new String[] {name};
}
// "schema"."table"
// "sch.ma"."table"
// "sch""ma".table
// Split names by object delimiter not between name delimiters
ArrayList<String> names = new ArrayList<String>(2);
String pname = name;
// for each name
int ndLen = nameDelim.length();
while (!StringUtils.isEmpty(name)) {
pname = splitNameCharDelimiters(name, nameDelim);
names.add(pname);
if ((pname.length() + ndLen) >= name.length()) {
break;
}
name = name.substring(pname.length() + ndLen);
}
return names.toArray(new String[names.size()]);
}
/**
* Gets the first part of a name when single character delimiters are
* in use.
* @param pname
* @return
*/
private String splitNameCharDelimiters(String name, String nameDelim) {
StringBuilder sname = new StringBuilder("");
char ld = _config.getLeadingDelimiter().charAt(0);
char td = _config.getTrailingDelimiter().charAt(0);
char nd = nameDelim.charAt(0);
int dlvl = 0;
boolean wasLd = false;
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (c == ld) {
// Handle case where delimiters are the same
if (td == ld && wasLd) {
dlvl--;
wasLd = false;
} else {
wasLd = true;
dlvl++;
}
} else if (c == td) {
dlvl--;
} else if (c == nd) {
if (dlvl == 0 && sname.length() > 0) {
return sname.toString();
}
}
sname.append(c);
}
return sname.toString();
}
/**
* Returns whether a name is double quoted
* @return
*/
public static boolean isDoubleQuoted(String name) {
if (name == null || name.length() < 3) {
return false;
}
return name.startsWith(DOUBLE_QUOTE) &&
name.endsWith(DOUBLE_QUOTE);
}
public String delimit(IdentifierRule rule, String name) {
return delimit(_config, rule, name, false);
}
public String delimit(IdentifierRule rule, String name, boolean force) {
return delimit(_config, rule, name, force);
}
public String delimit(IdentifierConfiguration config, IdentifierRule rule, String name, boolean force) {
if (!rule.getCanDelimit() || StringUtils.isEmpty(name)) {
return name;
}
if ((force && !isDelimited(config, rule, name)) || requiresDelimiters(config, rule, name)) {
return config.getLeadingDelimiter() + name + config.getTrailingDelimiter();
}
return name;
}
public boolean isDelimited(IdentifierRule rule, String name) {
return isDelimited(_config, rule, name);
}
public boolean isDelimited(IdentifierConfiguration config, IdentifierRule rule, String name) {
if (name == null || name.length() <= 3) {
return false;
}
return name.startsWith(config.getLeadingDelimiter()) &&
name.endsWith(config.getTrailingDelimiter());
}
public String removeDelimiters(IdentifierRule rule, String name) {
return removeDelimiters(rule, name, _config.getLeadingDelimiter(),
_config.getTrailingDelimiter());
}
public boolean requiresDelimiters(IdentifierRule rule, String name) {
return requiresDelimiters(_config, rule, name);
}
public boolean requiresDelimiters(IdentifierConfiguration config, IdentifierRule rule, String name) {
if (rule == null) {
throw new IllegalArgumentException(_loc.get("no-rules-provided").getMessage());
}
if (rule.getCanDelimit() && !isDelimited(config, rule, name) && rule.requiresDelimiters(name)) {
return true;
}
return false;
}
/**
* Returns whether a name is considered a reserved word.
*/
public boolean isReservedWord(IdentifierRule rule, String name) {
if (rule == null) {
System.out.println("NAmingConfig: " + _config.getClass().getName());
throw new IllegalArgumentException("Naming rule is null!");
}
if (rule.getReservedWords() == null) {
return false;
}
if (!isDelimited(rule, name)) {
name = name.toUpperCase();
}
return rule.getReservedWords().contains(name);
}
public boolean isReservedWord(String rule, String name) {
return isReservedWord(_config.getIdentifierRule(rule), name);
}
protected String removeDelimiters(IdentifierRule rule, String name, String leading,
String trailing) {
if (name == null) {
return null;
}
if (isDelimited(rule, name)) {
String id = name.substring(leading.length(),
(name.length() - trailing.length()));
return id;
}
return name;
}
public String combineNames(String rule, String[] rules, String[] names) {
return combineNames(getNamingRule(rule), getNamingRules(rules), names);
}
public String truncateName(String rule, String name, int length) {
return truncateName(getNamingRule(rule), name, length);
}
public String truncateName(IdentifierRule namingRule, String name, int length) {
String tName = name;
boolean delimited = isDelimited(namingRule, name);
if (delimited) {
tName = removeDelimiters(namingRule, name);
}
if (tName.length() <= length) {
return name;
}
tName = tName.substring(0, tName.length() - length);
if (delimited) {
tName = delimit(namingRule, tName).toString();
}
return tName;
}
public String delimit(String rule, String name) {
return delimit(getNamingRule(rule), name);
}
public String delimit(String rule, String name, boolean force) {
return delimit(getNamingRule(rule), name, force);
}
public boolean isDelimited(String rule, String name) {
return isDelimited(getNamingRule(rule), name);
}
public String removeDelimiters(String rule, String name) {
return removeDelimiters(getNamingRule(rule), name);
}
public boolean requiresDelimiters(String rule, String name) {
return requiresDelimiters(getNamingRule(rule), name);
}
public String[] splitName(String rule, String name) {
return splitName(getNamingRule(rule), name);
}
public String joinNames(String[] rules, String[] names) {
return joinNames(getNamingRules(rules), names);
}
private IdentifierRule getNamingRule(String rule) {
return _config.getIdentifierRule(rule);
}
public String combineNames(String rule, String name1, String name2) {
return combineNames(getNamingRule(rule), name1, name2);
}
public String combineNames(String rule, String[] names) {
return combineNames(getNamingRule(rule), names);
}
public String appendNames(String rule, String name1, String name2) {
return appendNames(getNamingRule(rule), name1, name2);
}
public String removeHungarianNotation(IdentifierRule rule, String name) {
boolean delimited = isDelimited(rule, name);
if (delimited) {
name = removeDelimiters(rule, name);
}
char[] chname = name.toCharArray();
int newStart = 0;
for (int i = 0; i < chname.length; i++) {
if (Character.isUpperCase(chname[i]))
{
newStart = i;
break;
}
}
name = name.substring(newStart);
if (delimited) {
name = delimit(rule, name).toString();
}
return name;
}
public String removeHungarianNotation(String rule, String name) {
return removeHungarianNotation(getNamingRule(rule), name);
}
public String[] splitName(String nrule, String name, String nameDelim) {
return splitName(getNamingRule(nrule), name, nameDelim);
}
public String convert(IdentifierConfiguration config, String rule, String name) {
// Already using same delimiter, no need to convert
if (!needsConversion(config)) {
return name;
}
// Otherwise, remove delimiters and add appropriate delimiters
IdentifierRule orule = getIdentifierConfiguration().getIdentifierRule(rule);
IdentifierRule nrule = config.getIdentifierRule(rule);
boolean delimit = isDelimited(orule, name);
if (delimit) {
name = removeDelimiters(orule, name, config.getLeadingDelimiter(),
config.getTrailingDelimiter());
return delimit(config, nrule, name, delimit).toString();
}
return name;
}
public String convertFull(IdentifierConfiguration config, String rule, String fullName) {
if (!needsConversion(config)) {
return fullName;
}
// Split
String[] names = splitName(rule, fullName);
// Convert
for (int i = 0; i < names.length; i++) {
names[i] = convert(config, rule, names[i]);
}
// Join
return joinNames(config, config.getIdentifierRule(rule), names, config.getIdentifierDelimiter());
}
public String combineFull(IdentifierConfiguration config, String rule, String fullName) {
if (!needsConversion(config)) {
return fullName;
}
// Split
String[] names = splitName(rule, fullName);
// Convert
for (int i = 0; i < names.length; i++) {
names[i] = convert(config, rule, names[i]);
}
// Join
return joinNames(config, config.getIdentifierRule(rule), names, config.getIdentifierDelimiter());
}
private boolean needsConversion(IdentifierConfiguration config) {
return !(config.getLeadingDelimiter().equals(getIdentifierConfiguration().getLeadingDelimiter()) &&
config.getTrailingDelimiter().equals(getIdentifierConfiguration().getTrailingDelimiter()) &&
config.getIdentifierDelimiter().equals(getIdentifierConfiguration().getIdentifierDelimiter()));
}
private IdentifierRule[] getNamingRules(String[] rules) {
IdentifierRule[] nrules = new IdentifierRule[rules.length];
for (int i = 0; i < rules.length; i++) {
nrules[i] = _config.getIdentifierRule(rules[i]);
}
return nrules;
}
public void endConfiguration() {
}
public void setConfiguration(Configuration conf) {
}
public void startConfiguration() {
}
public boolean canSplit(String rule, String name) {
return canSplit(getNamingRule(rule), name, _config.getIdentifierDelimiter());
}
public boolean canSplit(IdentifierRule rule, String name) {
return canSplit(rule, name, _config.getIdentifierDelimiter());
}
public boolean canSplit(String rule, String name, String delim) {
return canSplit(getNamingRule(rule), name);
}
public boolean canSplit(IdentifierRule rule, String name, String delim) {
if (name == null || name.length() == 0) {
return false;
}
return name.contains(delim);
}
}

View File

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import org.apache.openjpa.lib.identifier.IdentifierRule;
public class DefaultTestIdRule extends IdentifierRule {
}

View File

@ -0,0 +1,87 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import java.util.HashMap;
import java.util.Map;
import org.apache.openjpa.lib.identifier.IdentifierConfiguration;
import org.apache.openjpa.lib.identifier.IdentifierRule;
import org.apache.openjpa.lib.identifier.IdentifierUtil;
public class IdConfigurationTestImpl implements IdentifierConfiguration {
Map<String, IdentifierRule> _rules = new HashMap<String, IdentifierRule>();
public IdConfigurationTestImpl() {
_rules.put("DEFAULT", _defRule);
}
private IdentifierRule _defRule = new IdentifierRule();
public boolean delimitAll() {
return false;
}
public IdentifierRule getDefaultIdentifierRule() {
return _defRule;
}
public String getDelimitedCase() {
return IdentifierUtil.CASE_PRESERVE;
}
public String getLeadingDelimiter() {
return "`";
}
public String getIdentifierDelimiter() {
return ":";
}
public String getIdentifierConcatenator() {
return "-";
}
public <T> IdentifierRule getIdentifierRule(T t) {
IdentifierRule r = _rules.get(t);
if (r == null) {
return getDefaultIdentifierRule();
}
return r;
}
@SuppressWarnings("unchecked")
public <T> Map<T, IdentifierRule> getIdentifierRules() {
return (Map<T, IdentifierRule>) _rules;
}
public String getTrailingDelimiter() {
return "`";
}
public String getSchemaCase() {
return IdentifierUtil.CASE_UPPER;
}
public boolean getSupportsDelimitedIdentifiers() {
return true;
}
}

View File

@ -0,0 +1,87 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import java.util.HashMap;
import java.util.Map;
import org.apache.openjpa.lib.identifier.IdentifierConfiguration;
import org.apache.openjpa.lib.identifier.IdentifierRule;
import org.apache.openjpa.lib.identifier.IdentifierUtil;
public class NewIdConfigurationTestImpl implements IdentifierConfiguration {
Map<String, IdentifierRule> _rules = new HashMap<String, IdentifierRule>();
public NewIdConfigurationTestImpl() {
_rules.put("DEFAULT", _defRule);
}
private IdentifierRule _defRule = new IdentifierRule();
public boolean delimitAll() {
return false;
}
public IdentifierRule getDefaultIdentifierRule() {
return _defRule;
}
public String getDelimitedCase() {
return IdentifierUtil.CASE_PRESERVE;
}
public String getLeadingDelimiter() {
return "\"";
}
public String getIdentifierDelimiter() {
return ".";
}
public String getIdentifierConcatenator() {
return "_";
}
public <T> IdentifierRule getIdentifierRule(T t) {
IdentifierRule r = _rules.get(t);
if (r == null) {
return getDefaultIdentifierRule();
}
return r;
}
@SuppressWarnings("unchecked")
public <T> Map<T, IdentifierRule> getIdentifierRules() {
return (Map<T, IdentifierRule>) _rules;
}
public String getTrailingDelimiter() {
return "\"";
}
public String getSchemaCase() {
return IdentifierUtil.CASE_UPPER;
}
public boolean getSupportsDelimitedIdentifiers() {
return true;
}
}

View File

@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.identifier;
import org.apache.openjpa.lib.identifier.IdentifierConfiguration;
import org.apache.openjpa.lib.identifier.IdentifierUtil;
import org.apache.openjpa.lib.identifier.IdentifierUtilImpl;
import org.apache.openjpa.lib.test.AbstractTestCase;
public class TestIdentifiers extends AbstractTestCase {
public void testIdentifierConversion() {
// Create a naming configs used for testing.
IdentifierConfiguration defConfig = new IdConfigurationTestImpl();
IdentifierConfiguration newConfig = new NewIdConfigurationTestImpl();
IdentifierUtil nu = new IdentifierUtilImpl(defConfig);
// Test basic name conversion with single name converter
String n0 = "`TABLE`";
String cn0 = nu.convert(newConfig, "DEFAULT", n0);
assertEquals("\"TABLE\"", cn0);
// Test basic name conversion with single name converter - no
// conversion
String n1 = "TABLE";
String cn1 = nu.convert(newConfig, "DEFAULT", n1);
assertEquals("TABLE", cn1);
// Test basic name separator conversion with compound name converter
String n2 = "TABLE:SCHEMA";
String cn2 = nu.convertFull(newConfig, "DEFAULT", n2);
assertEquals("TABLE.SCHEMA", cn2);
String n3 = "`TABLE`:`SCHEMA`";
String cn3 = nu.convertFull(newConfig, "DEFAULT", n3);
assertEquals("\"TABLE\".\"SCHEMA\"", cn3);
}
}