/** * Copyright 2011-2015 John Ericksen * * Licensed 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.androidtransfuse.gen; import com.sun.codemodel.JClass; import com.sun.codemodel.JDefinedClass; import org.androidtransfuse.adapter.ASTType; import org.androidtransfuse.adapter.PackageClass; import org.androidtransfuse.model.InjectionNode; import org.androidtransfuse.util.Namer; import javax.inject.Inject; import javax.inject.Singleton; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; /** * @author John Ericksen */ @Singleton public class ClassNamer { private static final Map<String, String> PROHIBITED_PACKAGES = new HashMap<String, String>(); static{ PROHIBITED_PACKAGES.put("java.", "java_."); PROHIBITED_PACKAGES.put("javax.", "javax_."); PROHIBITED_PACKAGES.put("com.sun.", "com.sun_."); } private final ConcurrentMap<String, AtomicInteger> nameMap = new ConcurrentHashMap<String, AtomicInteger>(); private final String namespace; @Inject public ClassNamer(){ this(null); } public ClassNamer(String namespace) { this.namespace = namespace; } public static final class ClassNameBuilder{ private final PackageClass packageClass; private final ClassNamer classNamer; private final String namespace; private boolean namespaced; private String appendment; public ClassNameBuilder(PackageClass packageClass, String namespace, ClassNamer classNamer) { this.packageClass = packageClass; this.namespace = namespace; this.classNamer = classNamer; } public ClassNameBuilder namespaced(){ this.namespaced = true; return this; } public ClassNameBuilder append(String appendment) { this.appendment = appendment; return this; } public PackageClass build(){ return new PackageClass( getPackage(packageClass.getPackage()), generateName(namespaced, packageClass.getClassName(), appendment, classNamer)); } private String getPackage(String inputPackage){ if(inputPackage == null){ return null; } // Avoid prohibited package names String validPackage = inputPackage; for (Map.Entry<String, String> prohibitedPackage : PROHIBITED_PACKAGES.entrySet()) { if(inputPackage.startsWith(prohibitedPackage.getKey())){ validPackage = inputPackage.replaceFirst(prohibitedPackage.getKey(), prohibitedPackage.getValue()); } } return validPackage; } private String generateName(boolean namespaced, String fullClassName, String appendment, ClassNamer classNamer) { //remove array notation String sanitizedFullClassName = fullClassName.replaceAll("\\[\\]", ""); String className = sanitizedFullClassName; if (fullClassName.contains(".")) { className = sanitizedFullClassName.substring(sanitizedFullClassName.lastIndexOf('.') + 1); } // build class name with the following format: // <lower case> + classname + _ + # Namer namer; if(namespaced && namespace != null){ namer = Namer.name(namespace).append(className); } else{ namer = Namer.name(className); } if(appendment != null){ namer.append(appendment); } String nameRoot = namer.build(); if(classNamer != null){ namer.append(classNamer.get(nameRoot)); } return namer.build(); } } public static ClassNameBuilder className(PackageClass packageClass) { return className(packageClass, null, null); } public static ClassNameBuilder className(InjectionNode injectionNode) { return className(injectionNode.getASTType()); } public static ClassNameBuilder className(ASTType astType) { return className(astType.getPackageClass()); } public static ClassNameBuilder className(JDefinedClass definedClass) { return className(new PackageClass(definedClass._package().name(), definedClass.name())); } private static ClassNameBuilder className(PackageClass packageClass, String namespace, ClassNamer classNamer){ return new ClassNameBuilder(packageClass, namespace, classNamer); } public ClassNameBuilder numberedClassName(PackageClass packageClass){ return className(packageClass, namespace, this); } public ClassNameBuilder numberedClassName(Class clazz) { return numberedClassName(new PackageClass(clazz)); } public ClassNameBuilder numberedClassName(ASTType astType) { return numberedClassName(astType.getPackageClass()); } public ClassNameBuilder numberedClassName(JClass definedClass) { return numberedClassName(new PackageClass(definedClass._package().name(), definedClass.name())); } private int get(String name){ AtomicInteger result = nameMap.get(name); if (result == null) { AtomicInteger value = new AtomicInteger(); result = nameMap.putIfAbsent(name, value); if (result == null) { result = value; } } return result.getAndIncrement(); } }