/*******************************************************************************
 * Copyright 2000-2014 JetBrains s.r.o.
 *  
 * 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.jetbrains.kotlin.core.resolve.lang.java.structure;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import kotlin.Function1;

import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.load.java.structure.JavaClass;
import org.jetbrains.kotlin.load.java.structure.JavaElement;
import org.jetbrains.kotlin.load.java.structure.JavaPackage;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.core.log.KotlinLogger;
import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder;

import com.google.common.collect.Lists;

public class EclipseJavaPackage implements JavaElement, JavaPackage {
    
    private final List<IPackageFragment> packages = Lists.newArrayList();
    private final IJavaProject javaProject;

    public EclipseJavaPackage(List<IPackageFragment> packages) {
        this.packages.addAll(packages);
        this.javaProject = packages.get(0).getJavaProject();
    }
    
    public EclipseJavaPackage(IPackageFragment pckg) {
        this(Collections.singletonList(pckg));
    }
    
    @Override
    @NotNull
    public Collection<JavaClass> getClasses(@NotNull Function1<? super Name, ? extends Boolean> nameFilter) {
        List<JavaClass> javaClasses = Lists.newArrayList();
        for (IPackageFragment pckg : packages) {
            javaClasses.addAll(getClassesInPackage(pckg, nameFilter));
        }
        
        return javaClasses;
    }
    
    @Override
    @NotNull
    public Collection<JavaPackage> getSubPackages() {
        String thisPackageName = getFqName().asString();
        String pattern = thisPackageName.isEmpty() ? "*" : thisPackageName + ".";
        
        IPackageFragment[] packageFragments = EclipseJavaClassFinder.findPackageFragments(
                javaProject, pattern, true, true);

        int thisNestedLevel = thisPackageName.split("\\.").length;
        List<JavaPackage> javaPackages = Lists.newArrayList();
        if (packageFragments != null && packageFragments.length > 0) {
            for (IPackageFragment packageFragment : packageFragments) {
                int subNestedLevel = packageFragment.getElementName().split("\\.").length;
                boolean applicableForRootPackage = thisNestedLevel == 1 && thisNestedLevel == subNestedLevel;
                if (!packageFragment.getElementName().isEmpty() && 
                   (applicableForRootPackage || (thisNestedLevel + 1 == subNestedLevel))) {
                    javaPackages.add(new EclipseJavaPackage(packageFragment));
                }
            }
        }
        
        return javaPackages;
    }

    @Override
    @NotNull
    public FqName getFqName() {
        return new FqName(packages.get(0).getElementName()); // They all should have same names
    }
    
    private List<JavaClass> getClassesInPackage(IPackageFragment javaPackage, Function1<? super Name, ? extends Boolean> nameFilter) {
        try {
            List<JavaClass> javaClasses = Lists.newArrayList();
            for (IClassFile classFile : javaPackage.getClassFiles()) {
                IType type = classFile.getType();
                if (isOuterClass(classFile)) {
                    String elementName = classFile.getElementName();
                    if (Name.isValidIdentifier(elementName) && nameFilter.invoke(Name.identifier(elementName))) {
                        ITypeBinding typeBinding = EclipseJavaClassFinder.createTypeBinding(type);
                        if (typeBinding != null) {
                            javaClasses.add(new EclipseJavaClass(typeBinding));
                        }
                    }
                }
            }
            
            for (ICompilationUnit cu : javaPackage.getCompilationUnits()) {
                for (IType javaClass : cu.getAllTypes()) {
                    String elementName = javaClass.getElementName();
                    if (Name.isValidIdentifier(elementName) && nameFilter.invoke(Name.identifier(elementName))) {
                        ITypeBinding typeBinding = EclipseJavaClassFinder.createTypeBinding(javaClass);
                        if (typeBinding != null) {
                            javaClasses.add(new EclipseJavaClass(typeBinding));
                        }
                    }
                }
            }
            
            return javaClasses;
        } catch (JavaModelException e) {
            KotlinLogger.logAndThrow(e);
            throw new IllegalStateException(e);
        }
    }

    // TODO: Add correct resolve binding for all class files with $
    private boolean isOuterClass(IClassFile classFile) {
        return !classFile.getElementName().contains("$");
    }
}

@@ -1279,16 +1279,142 @@
 otNull;%0A
+import org.jetbrains.kotlin.core.log.KotlinLogger;%0Aimport org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder;%0A
 import o
@@ -1669,134 +1669,8 @@
 ame;
-%0Aimport org.jetbrains.kotlin.core.log.KotlinLogger;%0Aimport org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder;
 %0A%0Aim
@@ -4323,32 +4323,27 @@
 ementName = 
-classFil
+typ
 e.getElement

Fix getting class name