/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser; import gw.fs.IDirectory; import gw.fs.IFile; import gw.fs.IFileUtil; import gw.internal.gosu.parser.FileSystemGosuClassRepository.ClassFileInfo; import gw.lang.parser.IFileRepositoryBasedType; import gw.lang.reflect.IType; import gw.lang.reflect.ITypeLoader; import gw.lang.reflect.gs.IFileSystemGosuClassRepository; import gw.lang.reflect.gs.TypeName; import gw.lang.reflect.module.IModule; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** */ class PackageToClassPathEntryTreeMap { private String _strFullPackageName; private String _strRelativePackageName; private Map<String, PackageToClassPathEntryTreeMap> _children = new HashMap<String, PackageToClassPathEntryTreeMap>(); private List<IFileSystemGosuClassRepository.ClassPathEntry> _classPathEntries = new ArrayList<IFileSystemGosuClassRepository.ClassPathEntry>(); private PackageToClassPathEntryTreeMap _parent; private IModule _module; PackageToClassPathEntryTreeMap( PackageToClassPathEntryTreeMap parent, String packageName, IModule module ) { _parent = parent; _module = module; _strRelativePackageName = packageName; if( parent != null && !parent._strFullPackageName.isEmpty() ) { _strFullPackageName = parent._strFullPackageName + '.' + packageName; } else { _strFullPackageName = packageName; } } public void addClassPathEntry( IFileSystemGosuClassRepository.ClassPathEntry entry ) { if( !_classPathEntries.contains( entry ) ) { _classPathEntries.add( entry ); } } public PackageToClassPathEntryTreeMap createChildForDir( IFileSystemGosuClassRepository.ClassPathEntry entry, String packageName ) { PackageToClassPathEntryTreeMap packageTree = _children.get( packageName ); if( packageTree == null ) { packageTree = new PackageToClassPathEntryTreeMap( this, packageName, _module ); _children.put( packageName, packageTree ); } if(entry != null) { packageTree.addClassPathEntry( entry ); } return packageTree; } public PackageToClassPathEntryTreeMap getChild( String relativePackage ) { return _children.get( relativePackage ); } public FileSystemGosuClassRepository.ClassFileInfo resolveToClassFileInfo(String strQualifiedClassName, String[] extensions) { if (strQualifiedClassName.length() <= _strFullPackageName.length()) { return null; } String remainingPart = _strFullPackageName.isEmpty() ? strQualifiedClassName : strQualifiedClassName.substring(_strFullPackageName.length() + 1); int dotIndex = remainingPart.indexOf('.'); String fileName = remainingPart.substring(0, dotIndex == -1 ? remainingPart.length() : dotIndex); for (IFileSystemGosuClassRepository.ClassPathEntry classPathEntry : _classPathEntries) { FileSystemGosuClassRepository.ClassFileInfo info = getClassFileInfo(classPathEntry, fileName, dotIndex, remainingPart, extensions); if (info != null) { return info; } } return null; } public URL resolveToResource( String resourceName ) { if( resourceName.length() <= _strFullPackageName.length() ) { return null; } String remainingPart = resourceName.substring( _strFullPackageName.length() + 1 ); for( IFileSystemGosuClassRepository.ClassPathEntry classPathEntry : _classPathEntries ) { URL url = getResource( classPathEntry, remainingPart ); if( url != null ) { return url; } } return null; } private FileSystemGosuClassRepository.ClassFileInfo getClassFileInfo( IFileSystemGosuClassRepository.ClassPathEntry classPathEntry, String fileName, int dotIndex, String remainingPart, String[] extensions ) { ClassFileInfo file = getFile( classPathEntry, fileName, extensions ); if( file != null && dotIndex != -1 ) { IType outerMostClass; try { outerMostClass = TypeLoaderAccess.instance().getIntrinsicTypeByFullName( _strFullPackageName + "." + fileName ); } catch( ClassNotFoundException e ) { throw new RuntimeException( e ); } List<String> innerClassParts = splitInnerClassPartsIntoList( dotIndex, remainingPart ); if (!(outerMostClass instanceof IFileRepositoryBasedType)) { throw new RuntimeException("Type not a IFileRepositoryBasedType: " + outerMostClass); } return new FileSystemGosuClassRepository.ClassFileInfo( ((IFileRepositoryBasedType)outerMostClass).getSourceFileHandle(), ((IFileRepositoryBasedType) outerMostClass).getClassType(), _strFullPackageName + "." + fileName, innerClassParts, classPathEntry.isTestResource() ); } else { return file; } } public static List<String> splitInnerClassPartsIntoList( int dotIndex, String remainingPart ) { String[] parts = remainingPart.substring( dotIndex + 1 ).split("\\."); for( int i = 0; i < parts.length; i++ ) { parts[i] = parts[i].intern(); } return Arrays.asList( parts ); } private URL getResource( IFileSystemGosuClassRepository.ClassPathEntry root, String strFileName ) { try { IFile possibleFile = getFile(root, strFileName); return possibleFile == null ? null : possibleFile.toURI().toURL(); } catch (IOException ex) { throw new RuntimeException(ex); } } private IFile getFile( IFileSystemGosuClassRepository.ClassPathEntry root, String strFileName ) { IDirectory dir = getDir( root ); return getFileMatchCase( dir, strFileName ); } private ClassFileInfo getFile( IFileSystemGosuClassRepository.ClassPathEntry root, String strFileName, String[] extensions ) { IDirectory dir = getDir( root ); for( String ext : extensions ) { IFile file = getFileMatchCase( dir, strFileName + ext ); if( file != null ) { return new FileSystemGosuClassRepository.ClassFileInfo( root, file, root.isTestResource() ); } } return null; } private IFile getFileMatchCase( IDirectory dir, String strFileName ) { IFile file = dir.file( strFileName ); return file != null && file.exists() && IFileUtil.getBaseName( strFileName ).equals( file.getBaseName() ) ? file : null; } private IDirectory getDir(IFileSystemGosuClassRepository.ClassPathEntry root) { return _strFullPackageName.isEmpty() ? root.getPath() : root.getPath().dir(_strFullPackageName.replace('.', File.separatorChar)); } public void delete( IDirectory dir ) { if( _classPathEntries.size() == 1 ) { _parent.removeChild(this); } else { for( IFileSystemGosuClassRepository.ClassPathEntry entry: _classPathEntries ) { if( dir.equals( entry.getPath() ) || dir.isDescendantOf( entry.getPath() ) ) { _classPathEntries.remove( entry ); break; } } } } private void removeChild(PackageToClassPathEntryTreeMap pkg) { _children.remove(pkg._strRelativePackageName); } public PackageToClassPathEntryTreeMap getParent() { return _parent; } public int getSourceRootCount() { return _classPathEntries.size(); } @Override public String toString() { return _strFullPackageName; } public Set<TypeName> getTypeNames(Set<String> extensions, ITypeLoader loader) { Set<TypeName> names = new HashSet<TypeName>(); for (PackageToClassPathEntryTreeMap child : _children.values()) { String name = child._strFullPackageName; name = name.substring(name.lastIndexOf('.') + 1); names.add(new TypeName(name, loader, TypeName.Kind.NAMESPACE, TypeName.Visibility.PUBLIC)); } for (IFileSystemGosuClassRepository.ClassPathEntry classPathEntry : _classPathEntries) { IDirectory entryPath = classPathEntry.getPath().dir(_strFullPackageName.replace('.', '/')); List<? extends IFile> files = entryPath.listFiles(); for (IFile file : files) { String extension = "." + file.getExtension(); if (extensions.contains(extension)) { String fqn = entryPath.relativePath(file).replace('/', '.'); fqn = fqn.substring(0, fqn.lastIndexOf('.')); names.add(new TypeName(_strFullPackageName + "." + fqn, loader, TypeName.Kind.TYPE, TypeName.Visibility.PUBLIC)); } } } return names; } }