org.openrdf.repository.object.compiler.JavaNameResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of alibaba-composition-object Show documentation
Show all versions of alibaba-composition-object Show documentation
The Object Composition library merges multiple Java objects into a single multi-subject object.
/*
* Copyright (c) 2008-2009, Zepheira All rights reserved.
* Copyright (c) 2011 Talis Inc., Some rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the openrdf.org nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
package org.openrdf.repository.object.compiler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.openrdf.annotations.Iri;
import org.openrdf.annotations.Prefix;
import org.openrdf.model.Model;
import org.openrdf.model.Resource;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.repository.object.exceptions.ObjectStoreConfigException;
import org.openrdf.repository.object.managers.LiteralManager;
import org.openrdf.repository.object.managers.RoleMapper;
/**
* Resolves appropriate Java names from URIs.
*
* @author James Leigh
*
*/
public class JavaNameResolver {
private static final Set KEYWORDS_SENSITIVE = new HashSet(
Arrays.asList(new String[] { "abstract", "continue", "for", "new",
"switch", "assert", "default", "goto", "package",
"synchronized", "boolean", "do", "if", "private", "this",
"break", "double", "implements", "protected", "throw",
"byte", "else", "import", "public", "throws", "case",
"enum", "instanceof", "return", "transient", "catch",
"extends", "int", "short", "try", "char", "final",
"interface", "static", "void", "class", "finally", "long",
"strictfp", "volatile", "const", "float", "native",
"super", "while" }));
private static final Set KEYWORDS_INSENSITIVE = new HashSet(
Arrays.asList(new String[] { "CON", "PRN", "AUX", "CLOCK$",
"NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6",
"COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4",
"LPT5", "LPT6", "LPT7", "LPT8", "LPT9" }));
/** namespace -> package */
private Map packages = new HashMap();
/** namespace -> prefix */
private Map prefixes = new HashMap();
private Map aliases = new HashMap();
private Map implNames = new HashMap();
private Set ignore = new HashSet();
private Model model;
private RoleMapper roles;
private LiteralManager literals;
private ClassLoaderPackages cl;
private Set nouns;
private static class ClassLoaderPackages extends ClassLoader {
private Set namespacePackages;
public ClassLoaderPackages(ClassLoader parent) {
super(parent);
namespacePackages = new HashSet();
for (Package pkg : getPackages()) {
if (pkg.isAnnotationPresent(Iri.class)) {
namespacePackages.add(pkg);
}
}
}
public Set getNamespacePackages() {
return namespacePackages;
}
}
public JavaNameResolver() {
this(Thread.currentThread().getContextClassLoader());
}
public JavaNameResolver(ClassLoader cl) {
this.cl = new ClassLoaderPackages(cl);
for (Package pkg : this.cl.getNamespacePackages()) {
if (pkg.isAnnotationPresent(Prefix.class)) {
String prefix = pkg.getAnnotation(Prefix.class).value();
String ns = pkg.getAnnotation(Iri.class).value();
bindPrefixToNamespace(prefix, ns);
}
}
}
/**
* If an attempt is made to convert Set property names to their plural form.
*/
public boolean isPluralForms() {
return nouns != null;
}
public void setPluralForms(boolean enabled) {
if (enabled && nouns == null) {
nouns = new HashSet();
} else if (!enabled) {
nouns = null;
}
}
public void setLiteralManager(LiteralManager literals) {
this.literals = literals;
}
public void setRoleMapper(RoleMapper roles) {
this.roles = roles;
}
public void setModel(Model model) {
this.model = model;
if (nouns != null) {
Set localNames = new HashSet();
for (Resource subj : model.filter(null, RDF.TYPE, null).subjects()) {
if (subj instanceof URI) {
localNames.add(((URI) subj).getLocalName());
}
}
for (String name : localNames) {
if (name.matches("^[a-zA-Z][a-z]+$")) {
nouns.add(name.toLowerCase());
}
}
}
}
public void setImplNames(Map implNames) {
this.implNames.putAll(implNames);
}
public void assignAlias(URI name, URI alias) {
aliases.put(name, alias);
}
public void assignAnonymous(URI name) {
aliases.put(name, null);
}
public void ignoreExistingClass(URI name) {
ignore.add(name);
}
public void bindPackageToNamespace(String packageName, String namespace) {
packages.put(namespace, packageName(packageName));
}
public void bindPrefixToNamespace(String prefix, String namespace) {
if (prefix == null || prefix.length() == 0) {
prefixes.remove(namespace);
} else {
prefixes.put(namespace, prefix);
}
}
public Collection getRootPackages() {
Set set = new HashSet();
for (String pkg : packages.values()) {
if (pkg.contains(".")) {
set.add(pkg.substring(0, pkg.indexOf('.')));
} else {
set.add(pkg);
}
}
return set;
}
public URI getType(URI name) {
if (aliases.containsKey(name))
return aliases.get(name);
return name;
}
public boolean isAnonymous(URI name) {
return getType(name) == null;
}
public boolean isJavaClass(String className) {
try {
synchronized (cl) {
return Class.forName(className, true, cl) != null;
}
} catch (ClassNotFoundException e) {
return false;
}
}
public String getClassName(URI name) throws ObjectStoreConfigException {
if (name == null)
return Object.class.getName();
if (!ignore.contains(name)) {
Class javaClass = findJavaClass(name);
if (javaClass != null) {
// TODO support n-dimension arrays
if (javaClass.isArray())
return javaClass.getComponentType().getName() + "[]";
if (javaClass.getPackage() != null)
return javaClass.getName();
}
}
if (!packages.containsKey(name.getNamespace()))
throw new ObjectStoreConfigException("Unknown type: " + name);
String pkg = getPackageName(name);
String simple = word(name.getLocalName());
if (pkg == null)
return simple;
return pkg + '.' + simple;
}
public String getAnnotationAttributeName(URI uri) throws ObjectStoreConfigException {
if (!ignore.contains(uri)) {
Method m = roles.findAnnotationMethod(uri);
if (m != null)
return m.getName();
}
return "value";
}
public boolean isCompiledAnnotation(URI name) {
return roles.isRecordedAnnotation(name);
}
public boolean isCompiledAnnotationFunctional(URI name) {
Method ann = roles.findAnnotationMethod(name);
if (ann == null)
return false;
return !ann.getReturnType().isArray();
}
public boolean isAnnotationOfClasses(URI name) {
Method m = roles.findAnnotationMethod(name);
if (m == null)
return false;
Class> type = m.getReturnType();
return type.equals(Class.class) || type.getComponentType() != null
&& type.getComponentType().equals(Class.class);
}
public String getMethodName(URI name) {
String ns = name.getNamespace();
String localPart = name.getLocalName();
if (prefixes.containsKey(ns))
return word(getMemberPrefix(ns) + initcap(localPart));
return word(localPart);
}
public String getBoundPackageName(String namespace) {
return packages.get(namespace);
}
public String getPackageName(URI uri) {
if (packages.containsKey(uri.getNamespace()))
return packages.get(uri.getNamespace());
Class javaClass = findJavaClass(uri);
if (javaClass == null || javaClass.getPackage() == null)
return null;
return javaClass.getPackage().getName();
}
public String getSinglePropertyName(URI name) {
return getMemberName(name);
}
public String getSingleParameterName(URI name) {
return word(name.getLocalName());
}
public String getPluralParameterName(URI name) {
String ns = name.getNamespace();
String localPart = name.getLocalName();
String plural = plural(localPart);
if (model.contains(new URIImpl(ns + plural), null, null)) {
plural = localPart;
}
return word(plural);
}
public String getMemberPrefix(String ns) {
if (prefixes.containsKey(ns))
return enc(prefixes.get(ns));
return "";
}
public String getPluralPropertyName(URI name) {
String ns = name.getNamespace();
String localPart = name.getLocalName();
String plural = plural(localPart);
if (model.contains(new URIImpl(ns + plural), null, null)) {
plural = localPart;
}
if (prefixes.containsKey(ns))
return getMemberPrefix(ns) + initcap(plural);
return enc(plural);
}
public String getSimpleName(URI name) {
if ("".equals(name.getLocalName())) {
String ns = name.getNamespace();
if (ns.indexOf(':') == ns.length() - 1) {
return word(ns.substring(0, ns.length() - 1));
}
return getSimpleName(new URIImpl(ns.substring(0, ns.length() - 1)));
}
return word(name.getLocalName());
}
private String getMemberName(URI name) {
String ns = name.getNamespace();
String localPart = name.getLocalName();
if (prefixes.containsKey(ns))
return getMemberPrefix(ns) + initcap(localPart);
return enc(localPart);
}
private String packageName(String pkgName) {
StringBuilder sb = new StringBuilder();
String[] dots = pkgName.split("\\.");
for (int i=0;i0) {
sb.append('.');
}
sb.append(word(dots[i]));
}
return sb.toString();
}
private String word(String str) {
String enc = enc(str);
if (KEYWORDS_SENSITIVE.contains(enc))
return "_" + enc;
if (KEYWORDS_INSENSITIVE.contains(enc.toUpperCase()))
return "_" + enc;
char first = enc.charAt(0);
if (!Character.isLetter(first) && '_' != first && '$' != first)
return "_" + enc;
return enc;
}
private String enc(String str) {
if (str.length() == 0)
return "_";
char[] name = str.toCharArray();
StringBuffer sb = new StringBuffer(name.length);
for (int i = 0; i < name.length; i++) {
if ('A' <= name[i] && name[i] <= 'Z') {
sb.append(name[i]);
} else if ('a' <= name[i] && name[i] <= 'z') {
sb.append(name[i]);
} else if ('0' <= name[i] && name[i] <= '9') {
sb.append(name[i]);
} else if ('$' == name[i]) {
sb.append(name[i]);
} else if ('*' == name[i]) {
sb.append("Star");
} else if ('#' == name[i]) {
sb.append("Hash");
} else {
sb.append('_');
}
}
return sb.toString();
}
private Class findJavaClass(URI uri) {
if (uri.equals(RDF.XMLLITERAL))
return literals.findClass(uri);
Class klass = roles.findConcept(uri, cl);
if (klass != null)
return klass;
klass = findLoadedMethod(uri);
if (klass != null)
return klass;
Method m = roles.findAnnotationMethod(uri);
if (m != null)
return m.getDeclaringClass();
return literals.findClass(uri);
}
private Class findLoadedMethod(URI URI) {
if (cl == null)
return null;
String sn = getSimpleName(URI);
for (Package pkg : cl.getNamespacePackages()) {
String namespace = pkg.getAnnotation(Iri.class).value();
if (URI.getNamespace().equals(namespace)) {
try {
synchronized (cl) {
return Class.forName(pkg.getName() + '.' + sn, true, cl);
}
} catch (ClassNotFoundException e) {
continue;
}
}
}
return null;
}
private String plural(String singular) {
if (nouns == null) {
return singular;
} else if (singular.matches(".+[A-Z_-].*")
&& !isNoun(singular.replaceAll(".*(?=[A-Z])|.*[_-]", ""))) {
return singular;
} else if (singular.endsWith("s") && !singular.endsWith("ss")) {
return singular;
} else if (singular.endsWith("ed")) {
return singular;
} else if (singular.endsWith("y") && (singular.length() > 1)) {
char c = singular.charAt(singular.length() - 2);
if (c == 'a' || c == 'o' || c == 'e' || c == 'u' || c == 'i') {
return singular + "s";
} else {
return singular.substring(0, singular.length() - 1) + "ies";
}
} else if (singular.endsWith("s") || singular.endsWith("x")) {
return singular + "es";
} else {
return singular + "s";
}
}
/**
* If this is word is a thing in our repository it is a noun. An alternative
* is to use a wordnet database.
*/
private boolean isNoun(String word) {
if (nouns == null)
return false;
return nouns.contains(word.toLowerCase());
}
private String initcap(String str) {
if (str.length() == 0)
return "";
char[] name = str.toCharArray();
StringBuffer sb = new StringBuffer(name.length);
for (int i = 0; i < name.length; i++) {
if (i == 0) {
sb.append(Character.toUpperCase(name[i]));
} else if (name[i] == '-' || name[i] == '.') {
if (i == name.length - 1) {
sb.append('_');
} else {
name[i + 1] = Character.toUpperCase(name[i + 1]);
}
} else {
sb.append(name[i]);
}
}
return enc(sb.toString());
}
}