package ru.csu.stan.java.classgen.util;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Реестр всех пакетов проекта и всех классов, описанных в них.
*
* @author mz
*
*/
public class PackageRegistry{
/** Словарь соответствия имени пакета и набора классов, в нем описанных. */
private Map<String, Set<String>> internal = new HashMap<String, Set<String>>();
/** Набор, содержащий абсолютно все классы проекта. Хранит полные имена классов */
private Set<String> allClasses = new HashSet<String>();
/**
* Получение словаря пакетов и классов в них по указанному пакету.
* Ищет вложенные пакеты, за счет чего и получается множественный результат.
* @param packageName
* @return
*/
public Map<String, Set<String>> getPackageClasses(String packageName){
Map<String, Set<String>> result = new HashMap<String, Set<String>>();
for (Entry<String, Set<String>> internalEntry : internal.entrySet())
if (internalEntry.getKey().startsWith(packageName))
result.put(internalEntry.getKey(), internalEntry.getValue());
return result;
}
/**
* Добавление класса в пакете в реестр.
* @param className короткое имя класса (в файле).
* @param packageName имя пакета.
* @return
*/
public boolean addClassToPackage(String className, String packageName){
if (!internal.containsKey(packageName))
internal.put(packageName, new HashSet<String>());
allClasses.add(packageName + '.' + className);
return internal.get(packageName).add(className);
}
/**
* Проверка на то, что указанный пакет существует в реестре.
* @param packageName
* @return
*/
public boolean existPackage(String packageName){
for (String name : internal.keySet())
if (name.indexOf(packageName) > 0)
return true;
return false;
}
/**
* Проверка на наличие класса в реестре по полному имени.
* @param className
* @return
*/
public boolean isClassInRegistry(String className){
return allClasses.contains(className);
}
/**
* Получение списка полных имен классов по префиксу и постфиксу.
* Префикс может быть задан в формате пакетного импорта,
* то есть как "импорт со звездочкой" com.example.* .
* @param prefix префикс полного имени класса.
* @param postfix постфикс полного имени класса.
* @return набор полных имен классов.
*/
public Set<String> getClassesByPrefixAndPostfix(String prefix, String postfix){
Set<String> result = new HashSet<String>();
String newPrefix;
if (prefix.lastIndexOf(".*") > 0)
newPrefix = prefix.substring(0, prefix.lastIndexOf(".*"));
else
newPrefix = prefix;
for (String className : allClasses)
if (className.startsWith(newPrefix) && className.endsWith(postfix))
result.add(className);
return result;
}
/**
* Поиск класса в указанном пакете по короткому имени.
* Возвращается полное имя класса из указанного пакета, если таковой был найден.
* @param packageName имя пакета для поиска.
* @param localName имя искомого класса.
* @return полное пакетное имя класса, если он был найден, иначе - null.
*/
public String findFullNameByShortInPackage(String packageName, String localName){
Map<String, Set<String>> classesFromStarPackage = this.getPackageClasses(packageName);
for (Entry<String, Set<String>> pkg: classesFromStarPackage.entrySet())
for (String cl : pkg.getValue())
if (cl.equals(localName)){
return pkg.getKey() + '.' + cl;
}
return null;
}
}