blob: 60986bf5abb8c68b1ed2a8969f863b113b177c63 [file] [log] [blame]
/*
* 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 java.util.Locale;
import org.apache.openjpa.lib.conf.Configurable;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
/**
* 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;
}
@Override
public void setIdentifierConfiguration(IdentifierConfiguration config) {
_config = config;
}
@Override
public IdentifierConfiguration getIdentifierConfiguration() {
return _config;
}
@Override
public String combineNames(String rule, String name1, String name2) {
return combineNames(getNamingRule(rule), name1, name2);
}
@Override
public String combineNames(String rule, String[] names) {
return combineNames(getNamingRule(rule), names);
}
public String combineNames(IdentifierConfiguration config, String rule, String[] names) {
return combineNames(config, getNamingRule(rule), names);
}
@Override
public String combineNames(IdentifierRule rule,
IdentifierRule[] rules, String[] names) {
return combineNames(_config, rule, rules, names);
}
public String combineNames(IdentifierConfiguration config, 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(config, rules[i], name);
}
if (i == 0) {
combined = name;
}
else {
combined = combined + config.getIdentifierConcatenator() + name;
}
}
if (delimited) {
combined = delimit(config, rule, combined);
}
return combined;
}
public String combineNames(IdentifierConfiguration config, IdentifierRule rule, String name1, String name2) {
boolean delimit = false;
if (isDelimited(rule, name1)) {
name1 = removeDelimiters(config, rule, name1);
delimit = true;
}
if (isDelimited(rule, name2)) {
name2 = removeDelimiters(config, rule, name2);
delimit = true;
}
String name = name1 + config.getIdentifierConcatenator() + name2;
return delimit(config, rule, name, delimit);
}
public String combineNames(IdentifierConfiguration config, IdentifierRule namingRule, String[] names) {
boolean delimited = false;
String combined = null;
for (int i = 0; i < names.length; i++) {
String name = names[i];
if (isDelimited(config, namingRule, name)) {
delimited = true;
name = removeDelimiters(config, namingRule, name);
}
if (i == 0) {
combined = name;
}
else {
combined = combined + config.getIdentifierConcatenator() + name;
}
}
if (delimited) {
combined = delimit(config, namingRule, combined);
}
return combined;
}
@Override
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);
}
/**
* Joins multiple names together using the standard delimiting rules
* ex. ( {"s", "t", "c"} --> "s"."t"."c" }
*/
@Override
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();
}
@Override
public String joinNames(String rule, String[] names) {
return joinNames(_config, getNamingRule(rule), names, _config.getIdentifierDelimiter());
}
@Override
public String joinNames(IdentifierRule rule, String[] names) {
return joinNames(_config, rule, names, _config.getIdentifierDelimiter());
}
@Override
public String joinNames(IdentifierRule rule, String[] names, String delimiter) {
return joinNames(_config, rule, names, delimiter);
}
@Override
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
*/
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(IdentifierConfiguration config, IdentifierRule nrule, String name) {
return splitName(nrule, name, config.getIdentifierDelimiter());
}
@Override
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 }
*/
@Override
public String[] splitName(IdentifierRule nrule, String name, String nameDelim) {
if (!canSplit(nrule, name, nameDelim) || StringUtil.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<>(2);
String pname = name;
// for each name
int ndLen = nameDelim.length();
while (!StringUtil.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
*/
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
*/
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(IdentifierConfiguration config, IdentifierRule rule, String name) {
return delimit(config, rule, name, false);
}
@Override
public String delimit(IdentifierRule rule, String name) {
return delimit(_config, rule, name, false);
}
@Override
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() || StringUtil.isEmpty(name)) {
return name;
}
if ((force && !isDelimited(config, rule, name)) || requiresDelimiters(config, rule, name)) {
return config.getLeadingDelimiter() + name + config.getTrailingDelimiter();
}
return name;
}
@Override
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());
}
@Override
public String removeDelimiters(IdentifierConfiguration config, String rule,
String name) {
return removeDelimiters(_config, getNamingRule(rule), name, _config.getLeadingDelimiter(),
_config.getTrailingDelimiter());
}
@Override
public String removeDelimiters(IdentifierRule rule, String name) {
return removeDelimiters(_config, rule, name, _config.getLeadingDelimiter(),
_config.getTrailingDelimiter());
}
public String removeDelimiters(IdentifierConfiguration config, IdentifierRule rule, String name) {
return removeDelimiters(config, rule, name, _config.getLeadingDelimiter(),
_config.getTrailingDelimiter());
}
@Override
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.
*/
@Override
public boolean isReservedWord(IdentifierRule rule, String name) {
if (rule == null) {
throw new IllegalArgumentException("Naming rule is null!");
}
if (rule.getReservedWords() == null) {
return false;
}
if (!isDelimited(rule, name)) {
name = name.toUpperCase(Locale.ENGLISH);
}
return rule.getReservedWords().contains(name);
}
@Override
public boolean isReservedWord(String rule, String name) {
return isReservedWord(_config.getIdentifierRule(rule), name);
}
protected String removeDelimiters(IdentifierConfiguration config, IdentifierRule rule, String name, String leading,
String trailing) {
if (name == null) {
return null;
}
if (isDelimited(config, rule, name)) {
String id = name.substring(leading.length(),
(name.length() - trailing.length()));
return id;
}
return name;
}
@Override
public String combineNames(String rule, String[] rules, String[] names) {
return combineNames(getNamingRule(rule), getNamingRules(rules), names);
}
@Override
public String truncateName(String rule, String name, int length) {
return truncateName(getNamingRule(rule), name, length);
}
@Override
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);
}
return tName;
}
@Override
public String delimit(String rule, String name) {
return delimit(getNamingRule(rule), name);
}
@Override
public String delimit(String rule, String name, boolean force) {
return delimit(getNamingRule(rule), name, force);
}
@Override
public boolean isDelimited(String rule, String name) {
return isDelimited(getNamingRule(rule), name);
}
@Override
public String removeDelimiters(String rule, String name) {
return removeDelimiters(getNamingRule(rule), name);
}
@Override
public boolean requiresDelimiters(String rule, String name) {
return requiresDelimiters(getNamingRule(rule), name);
}
public String[] splitName(IdentifierConfiguration config, String rule, String name) {
return splitName(config, getNamingRule(rule), name);
}
@Override
public String[] splitName(String rule, String name) {
return splitName(_config, getNamingRule(rule), name);
}
@Override
public String joinNames(String[] rules, String[] names) {
return joinNames(getNamingRules(rules), names);
}
private IdentifierRule getNamingRule(String rule) {
return _config.getIdentifierRule(rule);
}
@Override
public String appendNames(String rule, String name1, String name2) {
return appendNames(getNamingRule(rule), name1, name2);
}
@Override
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);
}
return name;
}
@Override
public String removeHungarianNotation(String rule, String name) {
return removeHungarianNotation(getNamingRule(rule), name);
}
@Override
public String[] splitName(String nrule, String name, String nameDelim) {
return splitName(getNamingRule(nrule), name, nameDelim);
}
@Override
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(config, orule, name);
if (delimit) {
name = removeDelimiters(config, orule, name, config.getLeadingDelimiter(),
config.getTrailingDelimiter());
return delimit(getIdentifierConfiguration(), nrule, name, delimit);
}
return name;
}
@Override
public String convertFull(IdentifierConfiguration config, String rule, String fullName) {
if (!needsConversion(config)) {
return fullName;
}
// Split
String[] names = splitName(config, rule, fullName);
// Convert
for (int i = 0; i < names.length; i++) {
names[i] = convert(config, rule, names[i]);
}
// If a single part name, return it.
if (names.length == 1) {
return names[0];
}
// Join if multiple names
return joinNames(getIdentifierConfiguration(), config.getIdentifierRule(rule), names,
getIdentifierConfiguration().getIdentifierDelimiter());
}
public String combineFull(IdentifierConfiguration config, String rule, String fullName) {
if (!needsConversion(config)) {
return fullName;
}
// Split
String[] names = splitName(config, 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());
}
protected boolean needsConversion(IdentifierConfiguration config) {
return (config != getIdentifierConfiguration())
&& !(config.getConversionKey().equals(getIdentifierConfiguration().getConversionKey()));
}
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;
}
@Override
public void endConfiguration() {
}
@Override
public void setConfiguration(Configuration conf) {
}
@Override
public void startConfiguration() {
}
@Override
public boolean canSplit(String rule, String name) {
return canSplit(getNamingRule(rule), name, _config.getIdentifierDelimiter());
}
@Override
public boolean canSplit(IdentifierRule rule, String name) {
return canSplit(rule, name, _config.getIdentifierDelimiter());
}
@Override
public boolean canSplit(String rule, String name, String delim) {
return canSplit(getNamingRule(rule), name);
}
@Override
public boolean canSplit(IdentifierRule rule, String name, String delim) {
if (name == null || name.length() == 0) {
return false;
}
return name.contains(delim);
}
@Override
public String combineNames(IdentifierRule rule, String[] names) {
return combineNames(_config, rule, names);
}
@Override
public String combineNames(IdentifierRule rule, String name1, String name2) {
return combineNames(_config, rule, name1, name2);
}
}