/*
 * 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.jps.builders.java.dependencyView;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.IntInlineKeyDescriptor;
import gnu.trove.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.incremental.storage.FileKeyDescriptor;
import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.Opcodes;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.annotation.RetentionPolicy;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author: db
 * Date: 28.01.11
 */
public class Mappings {
  private final static Logger LOG = Logger.getInstance("#org.jetbrains.ether.dependencyView.Mappings");

  private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab";
  private final static String CLASS_TO_CLASS = "classToClass.tab";
  private final static String SHORT_NAMES = "shortNames.tab";
  private final static String SOURCE_TO_CLASS = "sourceToClass.tab";
  private final static String CLASS_TO_SOURCE = "classToSource.tab";
  private static final IntInlineKeyDescriptor INT_KEY_DESCRIPTOR = new IntInlineKeyDescriptor();
  private static final int DEFAULT_SET_CAPACITY = 32;
  private static final float DEFAULT_SET_LOAD_FACTOR = 0.98f;
  private static final CollectionFactory<ClassRepr> ourClassSetConstructor = new CollectionFactory<ClassRepr>() {
    public Set<ClassRepr> create() {
      // for IDEA codebase on average there is no more than 2.5 classes out of one source file, so we use smaller estimate
      return new THashSet<ClassRepr>(5, DEFAULT_SET_LOAD_FACTOR);
    }
  };

  private final boolean myIsDelta;
  private final boolean myDeltaIsTransient;
  private boolean myIsDifferentiated = false;
  private boolean myIsRebuild = false;

  private final TIntHashSet myChangedClasses;
  private final THashSet<File> myChangedFiles;
  private final Set<Pair<ClassRepr, File>> myDeletedClasses;
  private final Set<ClassRepr> myAddedClasses;
  private final Object myLock;
  private final File myRootDir;

  private DependencyContext myContext;
  private final int myInitName;
  private final int myEmptyName;
  private final int myObjectClassName;
  private LoggerWrapper<Integer> myDebugS;

  private IntIntMultiMaplet myClassToSubclasses;

  /**
  key: the name of a class who is used;
  values: class names that use the class registered as the key
  */
  private IntIntMultiMaplet myClassToClassDependency;
  private ObjectObjectMultiMaplet<File, ClassRepr> mySourceFileToClasses;
  private IntObjectMultiMaplet<File> myClassToSourceFile;
  /**
   * [short className] -> list of FQ names
   */
  private IntIntMultiMaplet myShortClassNameIndex;

  private IntIntTransientMultiMaplet myRemovedSuperClasses;
  private IntIntTransientMultiMaplet myAddedSuperClasses;

  @Nullable
  private Collection<String> myRemovedFiles;

  private Mappings(final Mappings base) throws IOException {
    myLock = base.myLock;
    myIsDelta = true;
    myChangedClasses = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
    myChangedFiles = new THashSet(FileUtil.FILE_HASHING_STRATEGY);
    myDeletedClasses = new HashSet<Pair<ClassRepr, File>>(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
    myAddedClasses = new HashSet<ClassRepr>(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
    myDeltaIsTransient = base.myDeltaIsTransient;
    myRootDir = new File(FileUtil.toSystemIndependentName(base.myRootDir.getAbsolutePath()) + File.separatorChar + "myDelta");
    myContext = base.myContext;
    myInitName = myContext.get("<init>");
    myEmptyName = myContext.get("");
    myObjectClassName = myContext.get("java/lang/Object");
    myDebugS = base.myDebugS;
    createImplementation();
  }

  public Mappings(final File rootDir, final boolean transientDelta) throws IOException {
    myLock = new Object();
    myIsDelta = false;
    myChangedClasses = null;
    myChangedFiles = null;
    myDeletedClasses = null;
    myAddedClasses = null;
    myDeltaIsTransient = transientDelta;
    myRootDir = rootDir;
    createImplementation();
    myInitName = myContext.get("<init>");
    myEmptyName = myContext.get("");
    myObjectClassName = myContext.get("java/lang/Object");
  }

  private void createImplementation() throws IOException {
    if (!myIsDelta) {
      myContext = new DependencyContext(myRootDir);
      myDebugS = myContext.getLogger(LOG);
    }

    myRemovedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
    myAddedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;

    final CollectionFactory<File> fileCollectionFactory = new CollectionFactory<File>() {
      public Collection<File> create() {
        return new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY); // todo: do we really need set and not a list here?
      }
    };
    if (myIsDelta && myDeltaIsTransient) {
      myClassToSubclasses = new IntIntTransientMultiMaplet();
      myClassToClassDependency = new IntIntTransientMultiMaplet();
      myShortClassNameIndex = null;
      mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<File, ClassRepr>(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor);
      myClassToSourceFile = new IntObjectTransientMultiMaplet<File>(fileCollectionFactory);
    }
    else {
      if (myIsDelta) {
        myRootDir.mkdirs();
      }
      myClassToSubclasses = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_SUBCLASSES), INT_KEY_DESCRIPTOR);
      myClassToClassDependency = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_CLASS), INT_KEY_DESCRIPTOR);
      myShortClassNameIndex = myIsDelta? null : new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, SHORT_NAMES), INT_KEY_DESCRIPTOR);
      mySourceFileToClasses = new ObjectObjectPersistentMultiMaplet<File, ClassRepr>(
        DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext),
        ourClassSetConstructor
      );
      myClassToSourceFile = new IntObjectPersistentMultiMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), INT_KEY_DESCRIPTOR, new FileKeyDescriptor(), fileCollectionFactory);
    }
  }

  public String valueOf(final int name) {
    return myContext.getValue(name);
  }

  public int getName(final String string) {
    return myContext.get(string);
  }

  public Mappings createDelta() {
    synchronized (myLock) {
      try {
        return new Mappings(this);
      }
      catch (IOException e) {
        throw new BuildDataCorruptedException(e);
      }
    }
  }

  private void compensateRemovedContent(final Collection<File> compiled) {
    if (compiled != null) {
      for (final File file : compiled) {
        if (!mySourceFileToClasses.containsKey(file)) {
          mySourceFileToClasses.put(file, new HashSet<ClassRepr>());
        }
      }
    }
  }

  @Nullable
  private ClassRepr getReprByName(final @Nullable File source, final int qName) {
    final Collection<File> sources = source != null? Collections.singleton(source) : myClassToSourceFile.get(qName);
    if (sources != null) {
      for (File src : sources) {
        final Collection<ClassRepr> reprs = mySourceFileToClasses.get(src);

        if (reprs != null) {
          for (ClassRepr repr : reprs) {
            if (repr.name == qName) {
              return repr;
            }
          }
        }
      }
    }

    return null;
  }

  public void clean() throws IOException {
    if (myRootDir != null) {
      synchronized (myLock) {
        close();
        FileUtil.delete(myRootDir);
        createImplementation();
      }
    }
  }

  public IntIntTransientMultiMaplet getRemovedSuperClasses() {
    return myRemovedSuperClasses;
  }

  public IntIntTransientMultiMaplet getAddedSuperClasses() {
    return myAddedSuperClasses;
  }

  private final LinkedBlockingQueue<Runnable> myPostPasses = new LinkedBlockingQueue<Runnable>();

  private void runPostPasses() {
    final Set<Pair<ClassRepr, File>> deleted = myDeletedClasses;
    if (deleted != null) {
      for (Pair<ClassRepr, File> pair : deleted) {
        myChangedClasses.remove(pair.first.name);
      }
    }
    for (Runnable pass = myPostPasses.poll(); pass != null; pass = myPostPasses.poll()) {
      pass.run();
    }
  }

  private static final ClassRepr MOCK_CLASS = null;
  private static final MethodRepr MOCK_METHOD = null;

  private interface MemberComparator {
    boolean isSame(ProtoMember member);
  }

  private class Util {
    @Nullable
    private final Mappings myMappings;

    private Util() {
      myMappings = null;
    }

    private Util(@NotNull Mappings mappings) {
      myMappings = mappings;
    }

    void appendDependents(final ClassRepr c, final TIntHashSet result) {
      final TIntHashSet depClasses = myClassToClassDependency.get(c.name);

      if (depClasses != null) {
        addAll(result, depClasses);
      }
    }

    void propagateMemberAccessRec(final TIntHashSet acc, final boolean isField, final boolean root, final MemberComparator comparator, final int reflcass) {
      final ClassRepr repr = reprByName(reflcass);
      if (repr != null) {
        if (!root) {
          final Set<? extends ProtoMember> members = isField ? repr.getFields() : repr.getMethods();

          for (ProtoMember m : members) {
            if (comparator.isSame(m)) {
              return;
            }
          }

          acc.add(reflcass);
        }

        final TIntHashSet subclasses = myClassToSubclasses.get(reflcass);

        if (subclasses != null) {
          subclasses.forEach(new TIntProcedure() {
            @Override
            public boolean execute(int subclass) {
              propagateMemberAccessRec(acc, isField, false, comparator, subclass);
              return true;
            }
          });
        }
      }
    }

    TIntHashSet propagateMemberAccess(final boolean isField, final MemberComparator comparator, final int className) {
      final TIntHashSet acc = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
      propagateMemberAccessRec(acc, isField, true, comparator, className);
      return acc;
    }

    TIntHashSet propagateFieldAccess(final int name, final int className) {
      return propagateMemberAccess(true, new MemberComparator() {
        @Override
        public boolean isSame(ProtoMember member) {
          return member.name == name;
        }
      }, className);
    }

    TIntHashSet propagateMethodAccess(final MethodRepr m, final int className) {
      return propagateMemberAccess(false, new MemberComparator() {
        @Override
        public boolean isSame(ProtoMember member) {
          if (member instanceof MethodRepr) {
            final MethodRepr memberMethod = (MethodRepr)member;
            return memberMethod.name == m.name && Arrays.equals(memberMethod.myArgumentTypes, m.myArgumentTypes);
          }
          return member.name == m.name;
        }
      }, className);
    }

    MethodRepr.Predicate lessSpecific(final MethodRepr than) {
      return new MethodRepr.Predicate() {
        @Override
        public boolean satisfy(final MethodRepr m) {
          if (m.name == myInitName || m.name != than.name || m.myArgumentTypes.length != than.myArgumentTypes.length) {
            return false;
          }

          for (int i = 0; i < than.myArgumentTypes.length; i++) {
            final Boolean subtypeOf = isSubtypeOf(than.myArgumentTypes[i], m.myArgumentTypes[i]);
            if (subtypeOf != null && !subtypeOf) {
              return false;
            }
          }

          return true;
        }
      };
    }

    private void addOverridingMethods(final MethodRepr m, final ClassRepr fromClass, final MethodRepr.Predicate predicate, final Collection<Pair<MethodRepr, ClassRepr>> container) {
      final TIntHashSet subClasses = myClassToSubclasses.get(fromClass.name);
      if (subClasses == null) {
        return;
      }
      subClasses.forEach(new TIntProcedure() {
        @Override
        public boolean execute(int subClassName) {
          final ClassRepr r = reprByName(subClassName);

          if (r != null) {
            boolean cont = true;
            final Collection<MethodRepr> methods = r.findMethods(predicate);
            for (MethodRepr mm : methods) {
              if (isVisibleIn(fromClass, m, r)) {
                container.add(Pair.create(mm, r));
                cont = false;
              }
            }
            if (cont) {
              addOverridingMethods(m, r, predicate, container);
            }
          }
          return true;
        }
      });
    }

    private Collection<Pair<MethodRepr, ClassRepr>> findAllMethodsBySpecificity(final MethodRepr m, final ClassRepr c) {
      final MethodRepr.Predicate predicate = lessSpecific(m);
      final Collection<Pair<MethodRepr, ClassRepr>> result = new HashSet<Pair<MethodRepr, ClassRepr>>();
      addOverridenMethods(c, predicate, result);
      addOverridingMethods(m, c, predicate, result);
      return result;
    }

    private Collection<Pair<MethodRepr, ClassRepr>> findOverriddenMethods(final MethodRepr m, final ClassRepr c) {
      final Collection<Pair<MethodRepr, ClassRepr>> result = new HashSet<Pair<MethodRepr, ClassRepr>>();
      addOverridenMethods(c, MethodRepr.equalByJavaRules(m), result);
      return result;
    }

    private boolean hasOverriddenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate) {
      for (int superName : fromClass.getSupers()) {
        final ClassRepr superClass = reprByName(superName);
        if (superClass == null) {
          return true; // assumption
        }
        for (MethodRepr mm : superClass.findMethods(predicate)) {
          if (isVisibleIn(superClass, mm, fromClass)) {
            return true;
          }
        }
        if (hasOverriddenMethods(superClass, predicate)) {
          return true;
        }
      }
      return false;
    }

    private void addOverridenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate, final Collection<Pair<MethodRepr, ClassRepr>> container) {
      for (int superName : fromClass.getSupers()) {
        final ClassRepr superClass = reprByName(superName);
        if (superClass != null) {
          boolean cont = true;
          final Collection<MethodRepr> methods = superClass.findMethods(predicate);
          for (MethodRepr mm : methods) {
            if (isVisibleIn(superClass, mm, fromClass)) {
              container.add(Pair.create(mm, superClass));
              cont = false;
            }
          }
          if (cont) {
            addOverridenMethods(superClass, predicate, container);
          }
        }
        else {
          container.add(Pair.create(MOCK_METHOD, MOCK_CLASS));
        }
      }
    }

    void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection<Pair<FieldRepr, ClassRepr>> container) {
      for (int supername : fromClass.getSupers()) {
        final ClassRepr superClass = reprByName(supername);
        if (superClass != null) {
          final FieldRepr ff = superClass.findField(f.name);
          if (ff != null && isVisibleIn(superClass, ff, fromClass)) {
            container.add(Pair.create(ff, superClass));
          }
          else{
            addOverriddenFields(f, superClass, container);
          }
        }
      }
    }

    boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) {
      for (int supername : fromClass.getSupers()) {
        final ClassRepr superClass = reprByName(supername);
        if (superClass != null) {
          final FieldRepr ff = superClass.findField(f.name);
          if (ff != null && isVisibleIn(superClass, ff, fromClass)) {
            return true;
          }
          final boolean found = hasOverriddenFields(f, superClass);
          if (found) {
            return true;
          }
        }
      }
      return false;
    }

    @Nullable
    ClassRepr reprByName(final int name) {
      if (myMappings != null) {
        final ClassRepr r = myMappings.getReprByName(null, name);

        if (r != null) {
          return r;
        }
      }

      return getReprByName(null, name);
    }

    @Nullable
    private Boolean isInheritorOf(final int who, final int whom) {
      if (who == whom) {
        return Boolean.TRUE;
      }

      final ClassRepr repr = reprByName(who);

      if (repr != null) {
        for (int s : repr.getSupers()) {
          final Boolean inheritorOf = isInheritorOf(s, whom);
          if (inheritorOf != null && inheritorOf) {
            return inheritorOf;
          }
        }
      }

      return null;
    }

    @Nullable
    Boolean isSubtypeOf(final TypeRepr.AbstractType who, final TypeRepr.AbstractType whom) {
      if (who.equals(whom)) {
        return Boolean.TRUE;
      }

      if (who instanceof TypeRepr.PrimitiveType || whom instanceof TypeRepr.PrimitiveType) {
        return Boolean.FALSE;
      }

      if (who instanceof TypeRepr.ArrayType) {
        if (whom instanceof TypeRepr.ArrayType) {
          return isSubtypeOf(((TypeRepr.ArrayType)who).elementType, ((TypeRepr.ArrayType)whom).elementType);
        }

        final String descr = whom.getDescr(myContext);

        if (descr.equals("Ljava/lang/Cloneable") || descr.equals("Ljava/lang/Object") || descr.equals("Ljava/io/Serializable")) {
          return Boolean.TRUE;
        }

        return Boolean.FALSE;
      }

      if (whom instanceof TypeRepr.ClassType) {
        return isInheritorOf(((TypeRepr.ClassType)who).className, ((TypeRepr.ClassType)whom).className);
      }

      return Boolean.FALSE;
    }

    boolean isMethodVisible(final int className, final MethodRepr m) {
      final ClassRepr r = reprByName(className);
      if (r != null) {
        if (r.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0) {
          return true;
        }
        return hasOverriddenMethods(r, MethodRepr.equalByJavaRules(m));
      }
      return false;
    }

    boolean isFieldVisible(final int className, final FieldRepr field) {
      final ClassRepr r = reprByName(className);
      if (r == null || r.getFields().contains(field)) {
        return true;
      }
      return hasOverriddenFields(field, r);
    }

    void collectSupersRecursively(@NotNull final int className, @NotNull final TIntHashSet container) {
      final ClassRepr classRepr = reprByName(className);
      if (classRepr != null) {
        final int[] supers = classRepr.getSupers();
        container.addAll(supers);
        for (int aSuper : supers) {
          collectSupersRecursively(aSuper, container);
        }
      }
    }

    void affectSubclasses(final int className, final Collection<File> affectedFiles, final Collection<UsageRepr.Usage> affectedUsages, final TIntHashSet dependants, final boolean usages, final Collection<File> alreadyCompiledFiles) {
      debug("Affecting subclasses of class: ", className);

      final Collection<File> allSources = myClassToSourceFile.get(className);
      if (allSources == null || allSources.isEmpty()) {
        debug("No source file detected for class ", className);
        debug("End of affectSubclasses");
        return;
      }

      for (File fName : allSources) {
        debug("Source file name: ", fName);
        if (!alreadyCompiledFiles.contains(fName)) {
          affectedFiles.add(fName);
        }
      }

      if (usages) {
        debug("Class usages affection requested");

        final ClassRepr classRepr = reprByName(className);
        if (classRepr != null) {
          debug("Added class usage for ", classRepr.name);
          affectedUsages.add(classRepr.createUsage());
        }
      }

      final TIntHashSet depClasses = myClassToClassDependency.get(className);
      if (depClasses != null) {
        addAll(dependants, depClasses);
      }

      final TIntHashSet directSubclasses = myClassToSubclasses.get(className);
      if (directSubclasses != null) {
        directSubclasses.forEach(new TIntProcedure() {
          @Override
          public boolean execute(int subClass) {
            affectSubclasses(subClass, affectedFiles, affectedUsages, dependants, usages, alreadyCompiledFiles);
            return true;
          }
        });
      }
    }

    void affectFieldUsages(final FieldRepr field, final TIntHashSet classes, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
      affectedUsages.add(rootUsage);

      classes.forEach(new TIntProcedure() {
        @Override
        public boolean execute(int p) {
          final TIntHashSet deps = myClassToClassDependency.get(p);
          if (deps != null) {
            addAll(dependents, deps);
          }
          debug("Affect field usage referenced of class ", p);
          affectedUsages.add(rootUsage instanceof UsageRepr.FieldAssignUsage ? field.createAssignUsage(myContext, p) : field.createUsage(myContext, p));
          return true;
        }
      });
    }

    void affectMethodUsages(final MethodRepr method, final TIntHashSet subclasses, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
      affectedUsages.add(rootUsage);
      if (subclasses != null) {
        subclasses.forEach(new TIntProcedure() {
          @Override
          public boolean execute(int p) {
            final TIntHashSet deps = myClassToClassDependency.get(p);
            if (deps != null) {
              addAll(dependents, deps);
            }

            debug("Affect method usage referenced of class ", p);

            final UsageRepr.Usage usage =
              rootUsage instanceof UsageRepr.MetaMethodUsage ? method.createMetaUsage(myContext, p) : method.createUsage(myContext, p);
            affectedUsages.add(usage);
            return true;
          }
        });
      }
    }

    public abstract class UsageConstraint {
      public abstract boolean checkResidence(final int residence);
    }

    public class PackageConstraint extends UsageConstraint {
      public final String packageName;

      public PackageConstraint(final String packageName) {
        this.packageName = packageName;
      }

      @Override
      public boolean checkResidence(final int residence) {
        return !ClassRepr.getPackageName(myContext.getValue(residence)).equals(packageName);
      }
    }

    public class InheritanceConstraint extends PackageConstraint {
      public final int rootClass;

      public InheritanceConstraint(final int rootClass) {
        super(ClassRepr.getPackageName(myContext.getValue(rootClass)));
        this.rootClass = rootClass;
      }

      @Override
      public boolean checkResidence(final int residence) {
        final Boolean inheritorOf = isInheritorOf(residence, rootClass);
        return inheritorOf == null || !inheritorOf || super.checkResidence(residence);
      }
    }

    public class NegationConstraint extends UsageConstraint {
      final UsageConstraint x;

      public NegationConstraint(UsageConstraint x) {
        this.x = x;
      }

      @Override
      public boolean checkResidence(final int residence) {
        return !x.checkResidence(residence);
      }
    }

    public class IntersectionConstraint extends UsageConstraint {
      final UsageConstraint x;
      final UsageConstraint y;

      public IntersectionConstraint(final UsageConstraint x, final UsageConstraint y) {
        this.x = x;
        this.y = y;
      }

      @Override
      public boolean checkResidence(final int residence) {
        return x.checkResidence(residence) && y.checkResidence(residence);
      }
    }
  }

  void affectAll(final int className, @NotNull final File sourceFile, final Collection<File> affectedFiles, @Nullable final DependentFilesFilter filter) {
    final TIntHashSet dependants = myClassToClassDependency.get(className);
    if (dependants != null) {
      dependants.forEach(new TIntProcedure() {
        @Override
        public boolean execute(int depClass) {
          final Collection<File> allSources = myClassToSourceFile.get(depClass);
          if (allSources != null) {
            for (File depFile : allSources) {
              if (!FileUtil.filesEqual(depFile, sourceFile)) {
                if (filter == null || filter.accept(depFile)) {
                  affectedFiles.add(depFile);
                }
              }
            }
          }
          return true;
        }
      });
    }
  }

  private static boolean isVisibleIn(final ClassRepr c, final ProtoMember m, final ClassRepr scope) {
    final boolean privacy = m.isPrivate() && c.name != scope.name;
    final boolean packageLocality = m.isPackageLocal() && !c.getPackageName().equals(scope.getPackageName());
    return !privacy && !packageLocality;
  }

  private boolean isEmpty(final int s) {
    return s == myEmptyName;
  }

  @NotNull
  private TIntHashSet getAllSubclasses(final int root) {
    return addAllSubclasses(root, new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR));
  }

  private TIntHashSet addAllSubclasses(final int root, final TIntHashSet acc) {
    final TIntHashSet directSubclasses = myClassToSubclasses.get(root);

    acc.add(root);

    if (directSubclasses != null) {
      directSubclasses.forEach(new TIntProcedure() {
        @Override
        public boolean execute(int s) {
          if (!acc.contains(s)) {
            addAllSubclasses(s, acc);
          }
          return true;
        }
      });
    }
    return acc;
  }

  private boolean incrementalDecision(final int owner, final Proto member, final Collection<File> affectedFiles, final Collection<File> currentlyCompiled, @Nullable final DependentFilesFilter filter) {
    final boolean isField = member instanceof FieldRepr;
    final Util self = new Util();

    // Public branch --- hopeless
    if (member.isPublic()) {
      debug("Public access, switching to a non-incremental mode");
      return false;
    }

    final THashSet<File> toRecompile = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);

    // Protected branch
    if (member.isProtected()) {
      debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation");
      debug("Root class: ", owner);

      final TIntHashSet propagated = self.propagateFieldAccess(isField ? member.name : myEmptyName, owner);
      propagated.forEach(new TIntProcedure() {
        @Override
        public boolean execute(int className) {
          final Collection<File> fileNames = myClassToSourceFile.get(className);
          if (fileNames != null) {
            for (File fileName : fileNames) {
              debug("Adding ", fileName);
            }
            toRecompile.addAll(fileNames);
          }
          return true;
        }
      });
    }

    final String packageName = ClassRepr.getPackageName(myContext.getValue(isField ? owner : member.name));

    debug("Softening non-incremental decision: adding all package classes for a recompilation");
    debug("Package name: ", packageName);

    // Package-local branch
    myClassToSourceFile.forEachEntry(new TIntObjectProcedure<Collection<File>>() {
      @Override
      public boolean execute(int className, Collection<File> fileNames) {
        if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) {
          for (File fileName : fileNames) {
            if (filter == null || filter.accept(fileName)) {
              debug("Adding: ", fileName);
              toRecompile.add(fileName);
            }
          }
        }
        return true;
      }
    });

    // filtering already compiled and non-existing paths
    toRecompile.removeAll(currentlyCompiled);
    for (Iterator<File> it = toRecompile.iterator(); it.hasNext(); ) {
      final File file = it.next();
      if (!file.exists()) {
        it.remove();
      }
    }

    affectedFiles.addAll(toRecompile);

    return true;
  }

  public interface DependentFilesFilter {
    DependentFilesFilter ALL_FILES = new DependentFilesFilter() {
      @Override
      public boolean accept(File file) {
        return true;
      }

      @Override
      public boolean belongsToCurrentTargetChunk(File file) {
        return true;
      }
    };

    boolean accept(File file);
    
    boolean belongsToCurrentTargetChunk(File file);
  }

  private class Differential {
    private static final int DESPERATE_MASK = Opcodes.ACC_FINAL;

    final Mappings myDelta;
    final Collection<File> myFilesToCompile;
    final Collection<File> myCompiledFiles;
    final Collection<File> myAffectedFiles;
    @Nullable
    final DependentFilesFilter myFilter;
    @Nullable final Callbacks.ConstantAffectionResolver myConstantSearch;
    final DelayedWorks myDelayedWorks;

    final Util myFuture;
    final Util myPresent;

    final boolean myEasyMode; // true means: no need to search for affected files, only preprocess data for integrate

    private class DelayedWorks {
      class Triple {
        final int owner;
        final FieldRepr field;
        @Nullable
        final Future<Callbacks.ConstantAffection> affection;

        private Triple(final int owner, final FieldRepr field, @Nullable final Future<Callbacks.ConstantAffection> affection) {
          this.owner = owner;
          this.field = field;
          this.affection = affection;
        }

        Callbacks.ConstantAffection getAffection() {
          try {
            return affection != null ? affection.get() : Callbacks.ConstantAffection.EMPTY;
          }
          catch (Exception e) {
            throw new RuntimeException(e);
          }
        }
      }

      final Collection<Triple> myQueue = new LinkedList<Triple>();

      void addConstantWork(final int ownerClass, final FieldRepr changedField, final boolean isRemoved, boolean accessChanged) {
        final Future<Callbacks.ConstantAffection> future;
        if (myConstantSearch == null) {
          future = null;
        }
        else {
          final String className = myContext.getValue(ownerClass);
          final String fieldName = myContext.getValue(changedField.name);
          future = myConstantSearch.request(className.replace('/', '.'), fieldName, changedField.access, isRemoved, accessChanged);
        }
        myQueue.add(new Triple(ownerClass, changedField, future));
      }

      boolean doWork(@NotNull final Collection<File> affectedFiles) {
        if (!myQueue.isEmpty()) {
          debug("Starting delayed works.");

          for (final Triple t : myQueue) {
            final Callbacks.ConstantAffection affection = t.getAffection();

            debug("Class: ", t.owner);
            debug("Field: ", t.field.name);

            if (!affection.isKnown()) {
              if (myConstantSearch != null) {
                debug("No external dependency information available.");
              }
              else {
                debug("Constant search service not available.");
              }
              debug("Trying to soften non-incremental decision.");
              if (!incrementalDecision(t.owner, t.field, affectedFiles, myFilesToCompile, myFilter)) {
                debug("No luck.");
                debug("End of delayed work, returning false.");
                return false;
              }
            }
            else {
              debug("External dependency information retrieved.");
              final Collection<File> files = affection.getAffectedFiles();
              if (myFilter == null) {
                affectedFiles.addAll(files);
              }
              else {
                for (File file : files) {
                  if (myFilter.accept(file)) {
                    affectedFiles.add(file);
                  }
                }
              }
            }
          }

          debug("End of delayed work, returning true.");
        }
        return true;
      }
    }

    private class FileClasses {
      final File myFileName;
      final Set<ClassRepr> myFileClasses;

      FileClasses(File fileName, Collection<ClassRepr> fileClasses) {
        this.myFileName = fileName;
        this.myFileClasses = new HashSet<ClassRepr>(fileClasses);
      }
    }

    private class DiffState {
      final public TIntHashSet myDependants = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);

      final public Set<UsageRepr.Usage> myAffectedUsages = new HashSet<UsageRepr.Usage>();
      final public Set<UsageRepr.AnnotationUsage> myAnnotationQuery = new HashSet<UsageRepr.AnnotationUsage>();
      final public Map<UsageRepr.Usage, Util.UsageConstraint> myUsageConstraints = new HashMap<UsageRepr.Usage, Util.UsageConstraint>();

      final Difference.Specifier<ClassRepr> myClassDiff;

      private DiffState(Difference.Specifier<ClassRepr> classDiff) {
        this.myClassDiff = classDiff;
      }
    }

    private Differential(final Mappings delta) {
      this.myDelta = delta;
      this.myFilesToCompile = null;
      this.myCompiledFiles = null;
      this.myAffectedFiles = null;
      this.myFilter = null;
      this.myConstantSearch = null;

      myDelayedWorks = null;

      myFuture = null;
      myPresent = null;

      myEasyMode = true;

      delta.myIsRebuild = true;
    }

    private Differential(final Mappings delta, final Collection<String> removed, final Collection<File> filesToCompile) {
      delta.myRemovedFiles = removed;

      this.myDelta = delta;
      this.myFilesToCompile = filesToCompile;
      this.myCompiledFiles = null;
      this.myAffectedFiles = null;
      this.myFilter = null;
      this.myConstantSearch = null;

      myDelayedWorks = null;

      myFuture = new Util(delta);
      myPresent = new Util();
      myEasyMode = true;
    }

    private Differential(final Mappings delta,
                         final Collection<String> removed,
                         final Collection<File> filesToCompile,
                         final Collection<File> compiledFiles,
                         final Collection<File> affectedFiles,
                         @NotNull final DependentFilesFilter filter,
                         @Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
      delta.myRemovedFiles = removed;

      this.myDelta = delta;
      this.myFilesToCompile = filesToCompile;
      this.myCompiledFiles = compiledFiles;
      this.myAffectedFiles = affectedFiles;
      this.myFilter = filter;
      this.myConstantSearch = constantSearch;

      myDelayedWorks = new DelayedWorks();

      myFuture = new Util(delta);
      myPresent = new Util();

      myEasyMode = false;
    }

    private void processDisappearedClasses() {
      myDelta.compensateRemovedContent(myFilesToCompile);

      if (!myEasyMode) {
        final Collection<String> removed = myDelta.myRemovedFiles;

        if (removed != null) {
          for (final String file : removed) {
            final File sourceFile = new File(file);
            final Collection<ClassRepr> classes = mySourceFileToClasses.get(sourceFile);

            if (classes != null) {
              for (ClassRepr c : classes) {
                debug("Affecting usages of removed class ", c.name);
                affectAll(c.name, sourceFile, myAffectedFiles, myFilter);
              }
            }
          }
        }
      }
    }

    private void processAddedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
      final Collection<MethodRepr> added = diff.methods().added();
      if (added.isEmpty()) {
        return;
      }
      debug("Processing added methods: ");
      if (it.isAnnotation()) {
        debug("Class is annotation, skipping method analysis");
        return;
      }
      Ref<ClassRepr> oldItRef = null;
      for (final MethodRepr m : added) {
        debug("Method: ", m.name);
        if (it.isInterface() || it.isAbstract() || m.isAbstract()) {
          debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses");
          myFuture.affectSubclasses(it.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, false, myCompiledFiles);
        }

        TIntHashSet propagated = null;

        if (!m.isPrivate() && m.name != myInitName) {
          if (oldItRef == null) {
            oldItRef = new Ref<ClassRepr>(getReprByName(null, it.name)); // lazy init
          }
          final ClassRepr oldIt = oldItRef.get();

          if (oldIt != null && myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) {

          }
          else {
            if (m.myArgumentTypes.length > 0) {
              propagated = myFuture.propagateMethodAccess(m, it.name);
              debug("Conservative case on overriding methods, affecting method usages");
              myFuture.affectMethodUsages(m, propagated, m.createMetaUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
            }
          }
        }

        if (!m.isPrivate()) {
          final Collection<Pair<MethodRepr, ClassRepr>> affectedMethods = myFuture.findAllMethodsBySpecificity(m, it);
          final MethodRepr.Predicate overrides = MethodRepr.equalByJavaRules(m);

          if (propagated == null) {
            propagated = myFuture.propagateMethodAccess(m, it.name);
          }

          final Collection<MethodRepr> lessSpecific = it.findMethods(myFuture.lessSpecific(m));

          for (final MethodRepr mm : lessSpecific) {
            if (!mm.equals(m)) {
              debug("Found less specific method, affecting method usages");
              myFuture.affectMethodUsages(mm, propagated, mm.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
            }
          }

          debug("Processing affected by specificity methods");
          for (final Pair<MethodRepr, ClassRepr> pair : affectedMethods) {
            final MethodRepr method = pair.first;
            final ClassRepr methodClass = pair.second;

            if (methodClass == MOCK_CLASS) {
              continue;
            }
            final Boolean inheritorOf = myPresent.isInheritorOf(methodClass.name, it.name);
            final boolean isInheritor = inheritorOf != null && inheritorOf;

            debug("Method: ", method.name);
            debug("Class : ", methodClass.name);

            if (overrides.satisfy(method) && isInheritor) {
              debug("Current method overrides that found");

              final Collection<File> files = myClassToSourceFile.get(methodClass.name);
              if (files != null) {
                myAffectedFiles.addAll(files);
                for (File file : files) {
                  debug("Affecting file ", file);
                }
              }

            }
            else {
              debug("Current method does not override that found");

              final TIntHashSet yetPropagated = myPresent.propagateMethodAccess(method, it.name);

              if (isInheritor) {
                final TIntHashSet deps = myClassToClassDependency.get(methodClass.name);

                if (deps != null) {
                  addAll(state.myDependants, deps);
                }

                myFuture.affectMethodUsages(method, yetPropagated, method.createUsage(myContext, methodClass.name), state.myAffectedUsages,
                                             state.myDependants);
              }

              debug("Affecting method usages for that found");
              myFuture.affectMethodUsages(method, yetPropagated, method.createUsage(myContext, it.name), state.myAffectedUsages,
                                           state.myDependants);
            }
          }

          final TIntHashSet subClasses = getAllSubclasses(it.name);
          subClasses.forEach(new TIntProcedure() {
            @Override
            public boolean execute(int subClass) {
              final ClassRepr r = myFuture.reprByName(subClass);
              if (r == null) {
                return true;
              }
              final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
              if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
                final int outerClass = r.getOuterClassName();
                if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
                  myAffectedFiles.addAll(sourceFileNames);
                  for (File sourceFileName : sourceFileNames) {
                    debug("Affecting file due to local overriding: ", sourceFileName);
                  }
                }
              }
              return true;
            }
          });
        }
      }
      debug("End of added methods processing");
    }

    private void processRemovedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
      final Collection<MethodRepr> removed = diff.methods().removed();
      if (removed.isEmpty()) {
        return;
      }
      debug("Processing removed methods:");
      for (final MethodRepr m : removed) {
        debug("Method ", m.name);

        final Collection<Pair<MethodRepr, ClassRepr>> overridenMethods = myFuture.findOverriddenMethods(m, it);
        final TIntHashSet propagated = myFuture.propagateMethodAccess(m, it.name);

        if (overridenMethods.size() == 0) {
          debug("No overridden methods found, affecting method usages");
          myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
        }
        else {
          boolean clear = true;

          loop:
          for (final Pair<MethodRepr, ClassRepr> overriden : overridenMethods) {
            final MethodRepr mm = overriden.first;

            if (mm == MOCK_METHOD || !mm.myType.equals(m.myType) || !isEmpty(mm.signature) || !isEmpty(m.signature) || m.isMoreAccessibleThan(mm)) {
              clear = false;
              break loop;
            }
          }

          if (!clear) {
            debug("No clearly overridden methods found, affecting method usages");
            myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
          }
        }

        final Collection<Pair<MethodRepr, ClassRepr>> overridingMethods = new HashSet<Pair<MethodRepr, ClassRepr>>();

        myFuture.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods);

        for (final Pair<MethodRepr, ClassRepr> p : overridingMethods) {
          final Collection<File> fNames = myClassToSourceFile.get(p.second.name);
          if (fNames != null) {
            myAffectedFiles.addAll(fNames);
            for (File fName : fNames) {
              debug("Affecting file by overriding: ", fName);
            }
          }
        }

        if (!m.isAbstract()) {
          propagated.forEach(new TIntProcedure() {
            @Override
            public boolean execute(int p) {
              if (p != it.name) {
                final ClassRepr s = myFuture.reprByName(p);

                if (s != null) {
                  final Collection<Pair<MethodRepr, ClassRepr>> overridenInS = myFuture.findOverriddenMethods(m, s);

                  overridenInS.addAll(overridenMethods);

                  boolean allAbstract = true;
                  boolean visited = false;

                  for (final Pair<MethodRepr, ClassRepr> pp : overridenInS) {
                    final ClassRepr cc = pp.second;

                    if (cc == MOCK_CLASS) {
                      visited = true;
                      continue;
                    }

                    if (cc.name == it.name) {
                      continue;
                    }

                    visited = true;
                    allAbstract = pp.first.isAbstract() || cc.isInterface();

                    if (!allAbstract) {
                      break;
                    }
                  }

                  if (allAbstract && visited) {
                    final Collection<File> sources = myClassToSourceFile.get(p);

                    if (sources != null && !myCompiledFiles.containsAll(sources)) {
                      myAffectedFiles.addAll(sources);
                      debug("Removed method is not abstract & overrides some abstract method which is not then over-overridden in subclass ", p);
                      for (File source : sources) {
                        debug("Affecting subclass source file ", source);
                      }
                    }
                  }
                }
              }
              return true;
            }
          });
        }
      }
      debug("End of removed methods processing");
    }

    private void processChangedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
      final Collection<Pair<MethodRepr, Difference>> changed = diff.methods().changed();
      if (changed.isEmpty()) {
        return;
      }
      debug("Processing changed methods:");
      for (final Pair<MethodRepr, Difference> mr : changed) {
        final MethodRepr m = mr.first;
        final MethodRepr.Diff d = (MethodRepr.Diff)mr.second;
        final boolean throwsChanged = !d.exceptions().unchanged();

        debug("Method: ", m.name);

        if (it.isAnnotation()) {
          if (d.defaultRemoved()) {
            debug("Class is annotation, default value is removed => adding annotation query");
            final TIntHashSet l = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
            l.add(m.name);
            final UsageRepr.AnnotationUsage annotationUsage = (UsageRepr.AnnotationUsage)UsageRepr
              .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), l, null);
            state.myAnnotationQuery.add(annotationUsage);
          }
        }
        else if (d.base() != Difference.NONE || throwsChanged) {
          final TIntHashSet propagated = myFuture.propagateMethodAccess(m, it.name);

          boolean affected = false;
          boolean constrained = false;

          final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>();

          if (d.packageLocalOn()) {
            debug("Method became package-local, affecting method usages outside the package");
            myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);

            for (final UsageRepr.Usage usage : usages) {
              state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(it.name));
            }

            state.myAffectedUsages.addAll(usages);
            affected = true;
            constrained = true;
          }

          if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0 || throwsChanged) {
            if (!affected) {
              debug("Return type, throws list or signature changed --- affecting method usages");
              myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);

              final List<Pair<MethodRepr, ClassRepr>> overridingMethods = new LinkedList<Pair<MethodRepr, ClassRepr>>();

              myFuture.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods);

              for(final Pair<MethodRepr, ClassRepr> p : overridingMethods) {
                final ClassRepr aClass = p.getSecond();

                if (aClass != MOCK_CLASS) {
                  final Collection<File> fileNames = myClassToSourceFile.get(aClass.name);
                  if (fileNames != null) {
                    myAffectedFiles.addAll(fileNames);
                  }
                }
              }

              state.myAffectedUsages.addAll(usages);
            }
          }
          else if ((d.base() & Difference.ACCESS) > 0) {
            if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
                (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
                (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0) {
              if (!affected) {
                debug("Added static or private specifier or removed static specifier --- affecting method usages");
                myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);
                state.myAffectedUsages.addAll(usages);
              }

              if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0) {
                debug("Added static specifier --- affecting subclasses");
                myFuture.affectSubclasses(it.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, false, myCompiledFiles);
              }
            }
            else {
              if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0 ||
                  (d.addedModifiers() & Opcodes.ACC_PUBLIC) > 0 ||
                  (d.addedModifiers() & Opcodes.ACC_ABSTRACT) > 0) {
                debug("Added final, public or abstract specifier --- affecting subclasses");
                myFuture.affectSubclasses(it.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, false, myCompiledFiles);
              }

              if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0 && !((d.removedModifiers() & Opcodes.ACC_PRIVATE) > 0)) {
                if (!constrained) {
                  debug("Added public or package-local method became protected --- affect method usages with protected constraint");
                  if (!affected) {
                    myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);
                    state.myAffectedUsages.addAll(usages);
                  }

                  for (final UsageRepr.Usage usage : usages) {
                    state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(it.name));
                  }
                }
              }
            }
          }
        }
      }
      debug("End of changed methods processing");
    }

    private boolean processAddedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr classRepr) {
      final Collection<FieldRepr> added = diff.fields().added();
      if (added.isEmpty()) {
        return true;
      }
      debug("Processing added fields");

      for (final FieldRepr f : added) {
        debug("Field: ", f.name);

        if (!f.isPrivate()) {
          final TIntHashSet subClasses = getAllSubclasses(classRepr.name);
          subClasses.forEach(new TIntProcedure() {
            @Override
            public boolean execute(int subClass) {
              final ClassRepr r = myFuture.reprByName(subClass);
              if (r != null) {
                final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
                if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
                  if (r.isLocal()) {
                    for (File sourceFileName : sourceFileNames) {
                      debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
                    }
                    myAffectedFiles.addAll(sourceFileNames);
                  }
                  else {
                    final int outerClass = r.getOuterClassName();
                    if (!isEmpty(outerClass) && myFuture.isFieldVisible(outerClass, f)) {
                      for (File sourceFileName : sourceFileNames) {
                        debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
                      }
                      myAffectedFiles.addAll(sourceFileNames);
                    }
                  }
                }
              }

              debug("Affecting field usages referenced from subclass ", subClass);
              final TIntHashSet propagated = myFuture.propagateFieldAccess(f.name, subClass);
              myFuture.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), state.myAffectedUsages, state.myDependants);

              final TIntHashSet deps = myClassToClassDependency.get(subClass);

              if (deps != null) {
                addAll(state.myDependants, deps);
              }
              return true;
            }
          });
        }

        final Collection<Pair<FieldRepr, ClassRepr>> overriddenFields = new HashSet<Pair<FieldRepr, ClassRepr>>();
        myFuture.addOverriddenFields(f, classRepr, overriddenFields);

        for (final Pair<FieldRepr, ClassRepr> p : overriddenFields) {
          final FieldRepr ff = p.first;
          final ClassRepr cc = p.second;

          if (!ff.isPrivate()) {
            final TIntHashSet propagated = myPresent.propagateFieldAccess(ff.name, cc.name);
            final Set<UsageRepr.Usage> localUsages = new HashSet<UsageRepr.Usage>();

            debug("Affecting usages of overridden field in class ", cc.name);
            myFuture.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, state.myDependants);

            if (f.isPrivate() || (f.isPublic() && (ff.isPublic() || ff.isPackageLocal())) || (f.isProtected() && ff.isProtected()) || (f.isPackageLocal() && ff.isPackageLocal())) {
              // nothing
            }
            else {
              Util.UsageConstraint constaint;

              if ((ff.isProtected() && f.isPublic()) || (f.isProtected() && ff.isPublic()) || (ff.isPackageLocal() && f.isProtected())) {
                constaint = myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name));
              }
              else if (ff.isPublic() && ff.isPackageLocal()) {
                constaint = myFuture.new NegationConstraint(myFuture.new PackageConstraint(cc.getPackageName()));
              }
              else {
                constaint =
                  myFuture.new IntersectionConstraint(myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name)),
                                                       myFuture.new NegationConstraint(
                                                         myFuture.new PackageConstraint(cc.getPackageName())));
              }

              for (final UsageRepr.Usage usage : localUsages) {
                state.myUsageConstraints.put(usage, constaint);
              }
            }

            state.myAffectedUsages.addAll(localUsages);
          }
        }
      }
      debug("End of added fields processing");

      return true;
    }

    private boolean processRemovedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
      final Collection<FieldRepr> removed = diff.fields().removed();
      if (removed.isEmpty()) {
        return true;
      }
      debug("Processing removed fields:");

      for (final FieldRepr f : removed) {
        debug("Field: ", f.name);

        if (!f.isPrivate() && (f.access & DESPERATE_MASK) == DESPERATE_MASK && f.hasValue()) {
          debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
          if (myConstantSearch != null) {
            myDelayedWorks.addConstantWork(it.name, f, true, false);
          }
          else {
            if (!incrementalDecision(it.name, f, myAffectedFiles, myFilesToCompile, myFilter)) {
              debug("End of Differentiate, returning false");
              return false;
            }
          }
        }

        final TIntHashSet propagated = myFuture.propagateFieldAccess(f.name, it.name);
        myFuture.affectFieldUsages(f, propagated, f.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
      }
      debug("End of removed fields processing");

      return true;
    }

    private boolean processChangedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
      final Collection<Pair<FieldRepr, Difference>> changed = diff.fields().changed();
      if (changed.isEmpty()) {
        return true;
      }
      debug("Processing changed fields:");

      for (final Pair<FieldRepr, Difference> f : changed) {
        final Difference d = f.second;
        final FieldRepr field = f.first;

        debug("Field: ", field.name);

        if (!field.isPrivate() && (field.access & DESPERATE_MASK) == DESPERATE_MASK) {
          final int changedModifiers = d.addedModifiers() | d.removedModifiers();
          final boolean harmful = (changedModifiers & (Opcodes.ACC_STATIC | Opcodes.ACC_FINAL)) > 0;
          final boolean accessChanged = (changedModifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) > 0;
          final boolean valueChanged = (d.base() & Difference.VALUE) > 0 && d.hadValue();

          if (harmful || valueChanged || (accessChanged && !d.weakedAccess())) {
            debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
            if (myConstantSearch != null) {
              myDelayedWorks.addConstantWork(it.name, field, false, accessChanged);
            }
            else {
              if (!incrementalDecision(it.name, field, myAffectedFiles, myFilesToCompile, myFilter)) {
                debug("End of Differentiate, returning false");
                return false;
              }
            }
          }
        }

        if (d.base() != Difference.NONE) {
          final TIntHashSet propagated = myFuture.propagateFieldAccess(field.name, it.name);

          if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0) {
            debug("Type or signature changed --- affecting field usages");
            myFuture
              .affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
          }
          else if ((d.base() & Difference.ACCESS) > 0) {
            if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
                (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
                (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0 ||
                (d.addedModifiers() & Opcodes.ACC_VOLATILE) > 0) {
              debug("Added/removed static modifier or added private/volatile modifier --- affecting field usages");
              myFuture
                .affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
            }
            else {
              boolean affected = false;
              final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>();

              if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0) {
                debug("Added final modifier --- affecting field assign usages");
                myFuture.affectFieldUsages(field, propagated, field.createAssignUsage(myContext, it.name), usages, state.myDependants);
                state.myAffectedUsages.addAll(usages);
                affected = true;
              }

              if ((d.removedModifiers() & Opcodes.ACC_PUBLIC) > 0) {
                debug("Removed public modifier, affecting field usages with appropriate constraint");
                if (!affected) {
                  myFuture.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), usages, state.myDependants);
                  state.myAffectedUsages.addAll(usages);
                }

                for (final UsageRepr.Usage usage : usages) {
                  if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0) {
                    state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(it.name));
                  }
                  else {
                    state.myUsageConstraints.put(usage, myFuture.new PackageConstraint(it.getPackageName()));
                  }
                }
              }
            }
          }
        }
      }
      debug("End of changed fields processing");

      return true;
    }

    private boolean processChangedClasses(final DiffState state) {
      final Collection<Pair<ClassRepr, Difference>> changedClasses = state.myClassDiff.changed();
      if (!changedClasses.isEmpty()) {
        debug("Processing changed classes:");

        for (final Pair<ClassRepr, Difference> changed : changedClasses) {
          final ClassRepr changedClass = changed.first;
          final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second;

          myDelta.addChangedClass(changedClass.name);

          debug("Changed: ", changedClass.name);

          final int addedModifiers = diff.addedModifiers();

          final boolean superClassChanged = (diff.base() & Difference.SUPERCLASS) > 0;
          final boolean interfacesChanged = !diff.interfaces().unchanged();
          final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0;

          if (superClassChanged) {
            myDelta.registerRemovedSuperClass(changedClass.name, changedClass.getSuperClass().className);

            final ClassRepr newClass = myDelta.getReprByName(null, changedClass.name);

            assert (newClass != null);

            myDelta.registerAddedSuperClass(changedClass.name, newClass.getSuperClass().className);
          }

          if (interfacesChanged) {
            for (final TypeRepr.AbstractType typ : diff.interfaces().removed()) {
              myDelta.registerRemovedSuperClass(changedClass.name, ((TypeRepr.ClassType)typ).className);
            }

            for (final TypeRepr.AbstractType typ : diff.interfaces().added()) {
              myDelta.registerAddedSuperClass(changedClass.name, ((TypeRepr.ClassType)typ).className);
            }
          }

          if (myEasyMode) {
            continue;
          }

          myPresent.appendDependents(changedClass, state.myDependants);

          if (superClassChanged || interfacesChanged || signatureChanged) {
            debug("Superclass changed: ", superClassChanged);
            debug("Interfaces changed: ", interfacesChanged);
            debug("Signature changed ", signatureChanged);

            final boolean extendsChanged = superClassChanged && !diff.extendsAdded();
            final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty();

            debug("Extends changed: ", extendsChanged);
            debug("Interfaces removed: ", interfacesRemoved);

            myFuture.affectSubclasses(changedClass.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, extendsChanged || interfacesRemoved || signatureChanged, myCompiledFiles);

            if (!changedClass.isAnonymous()) {
              final TIntHashSet parents = new TIntHashSet();
              myPresent.collectSupersRecursively(changedClass.name, parents);
              final TIntHashSet futureParents = new TIntHashSet();
              myFuture.collectSupersRecursively(changedClass.name, futureParents);
              parents.removeAll(futureParents.toArray());
              parents.remove(myObjectClassName);
              if (!parents.isEmpty()) {
                parents.forEach(new TIntProcedure() {
                  @Override
                  public boolean execute(int className) {
                    debug("Affecting usages in generic type parameter bounds of class: ", className);
                    state.myAffectedUsages.add(UsageRepr.createClassAsGenericBoundUsage(myContext, className));

                    final TIntHashSet depClasses = myClassToClassDependency.get(className);
                    if (depClasses != null) {
                      addAll(state.myDependants, depClasses);
                    }
                    return true;
                  }
                });
              }
            }
          }

          if ((diff.addedModifiers() & Opcodes.ACC_INTERFACE) > 0 || (diff.removedModifiers() & Opcodes.ACC_INTERFACE) > 0) {
            debug("Class-to-interface or interface-to-class conversion detected, added class usage to affected usages");
            state.myAffectedUsages.add(changedClass.createUsage());
          }

          if (changedClass.isAnnotation() && changedClass.getRetentionPolicy() == RetentionPolicy.SOURCE) {
            debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested");
            if (!incrementalDecision(changedClass.getOuterClassName(), changedClass, myAffectedFiles, myFilesToCompile, myFilter)) {
              debug("End of Differentiate, returning false");
              return false;
            }
          }

          if ((addedModifiers & Opcodes.ACC_PROTECTED) > 0) {
            debug("Introduction of 'protected' modifier detected, adding class usage + inheritance constraint to affected usages");
            final UsageRepr.Usage usage = changedClass.createUsage();

            state.myAffectedUsages.add(usage);
            state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(changedClass.name));
          }

          if (diff.packageLocalOn()) {
            debug("Introduction of 'package local' access detected, adding class usage + package constraint to affected usages");
            final UsageRepr.Usage usage = changedClass.createUsage();

            state.myAffectedUsages.add(usage);
            state.myUsageConstraints.put(usage, myFuture.new PackageConstraint(changedClass.getPackageName()));
          }

          if ((addedModifiers & Opcodes.ACC_FINAL) > 0 || (addedModifiers & Opcodes.ACC_PRIVATE) > 0) {
            debug("Introduction of 'private' or 'final' modifier(s) detected, adding class usage to affected usages");
            state.myAffectedUsages.add(changedClass.createUsage());
          }

          if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0 || (addedModifiers & Opcodes.ACC_STATIC) > 0) {
            debug("Introduction of 'abstract' or 'static' modifier(s) detected, adding class new usage to affected usages");
            state.myAffectedUsages.add(UsageRepr.createClassNewUsage(myContext, changedClass.name));
          }

          if (changedClass.isAnnotation()) {
            debug("Class is annotation, performing annotation-specific analysis");

            if (diff.retentionChanged()) {
              debug("Retention policy change detected, adding class usage to affected usages");
              state.myAffectedUsages.add(changedClass.createUsage());
            }
            else {
              final Collection<ElemType> removedtargets = diff.targets().removed();

              if (removedtargets.contains(ElemType.LOCAL_VARIABLE)) {
                debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
                if (!incrementalDecision(changedClass.getOuterClassName(), changedClass, myAffectedFiles, myFilesToCompile, myFilter)) {
                  debug("End of Differentiate, returning false");
                  return false;
                }
              }

              if (!removedtargets.isEmpty()) {
                debug("Removed some annotation targets, adding annotation query");
                final UsageRepr.AnnotationUsage annotationUsage = (UsageRepr.AnnotationUsage)UsageRepr
                  .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, changedClass.name), null, EnumSet.copyOf(removedtargets));
                state.myAnnotationQuery.add(annotationUsage);
              }

              for (final MethodRepr m : diff.methods().added()) {
                if (!m.hasValue()) {
                  debug("Added method with no default value: ", m.name);
                  debug("Adding class usage to affected usages");
                  state.myAffectedUsages.add(changedClass.createUsage());
                }
              }
            }

            debug("End of annotation-specific analysis");
          }

          processAddedMethods(state, diff, changedClass);
          processRemovedMethods(state, diff, changedClass);
          processChangedMethods(state, diff, changedClass);

          if (!processAddedFields(state, diff, changedClass)) {
            return false;
          }

          if (!processRemovedFields(state, diff, changedClass)) {
            return false;
          }

          if (!processChangedFields(state, diff, changedClass)) {
            return false;
          }
        }
        debug("End of changed classes processing");
      }

      return !myEasyMode;
    }

    private void processRemovedClases(final DiffState state, @NotNull File fileName) {
      final Collection<ClassRepr> removed = state.myClassDiff.removed();
      if (removed.isEmpty()) {
        return;
      }
      myDelta.myChangedFiles.add(fileName);
      
      debug("Processing removed classes:");
      
      for (final ClassRepr c : removed) {
        myDelta.addDeletedClass(c, fileName);
        if (!myEasyMode) {
          myPresent.appendDependents(c, state.myDependants);
          debug("Adding usages of class ", c.name);
          state.myAffectedUsages.add(c.createUsage());
          debug("Affecting usages of removed class ", c.name);
          affectAll(c.name, fileName, myAffectedFiles, myFilter);
        }
      }
      debug("End of removed classes processing.");
    }

    private void processAddedClasses(final DiffState state, File srcFile) {
      final Collection<ClassRepr> addedClasses = state.myClassDiff.added();
      if (addedClasses.isEmpty()) {
        return;
      }

      debug("Processing added classes:");

      if (!myEasyMode && myFilter != null) {
        // checking if this newly added class duplicates already existing one
        for (ClassRepr c : addedClasses) {
          if (!c.isLocal() && !c.isAnonymous() && isEmpty(c.getOuterClassName())) {
            final Collection<File> currentSources = myClassToSourceFile.get(c.name);
            final File currentlyMappedTo = currentSources != null && currentSources.size() == 1? currentSources.iterator().next() : null;
            // only check, if exactly one file is mapped
            if (currentlyMappedTo != null && !FileUtil.filesEqual(currentlyMappedTo, srcFile) && currentlyMappedTo.exists() && myFilter.belongsToCurrentTargetChunk(currentlyMappedTo)) {
              // Same classes from different source files.
              // Schedule for recompilation both to make possible 'duplicate sources' error evident
              debug("Scheduling for recompilation duplicated sources: ", currentlyMappedTo.getPath() + "; " + srcFile.getPath());
              myAffectedFiles.add(currentlyMappedTo);
              myAffectedFiles.add(srcFile);
              return; // do not process this file because it should not be integrated
            }
            break;
          }
        }
      }

      for (final ClassRepr c : addedClasses) {
        debug("Class name: ", c.name);
        myDelta.addAddedClass(c);

        for (final int sup : c.getSupers()) {
          myDelta.registerAddedSuperClass(c.name, sup);
        }

        if (!myEasyMode && !c.isAnonymous() && !c.isLocal()) {
          final TIntHashSet toAffect = new TIntHashSet();
          toAffect.add(c.name);
          final TIntHashSet classes = myShortClassNameIndex.get(myContext.get(c.getShortName()));
          if (classes != null) {
            // affecting dependencies on all other classes with the same short name
            toAffect.addAll(classes.toArray());
          }
          toAffect.forEach(new TIntProcedure() {
            public boolean execute(int qName) {
              final TIntHashSet depClasses = myClassToClassDependency.get(qName);
              if (depClasses != null) {
                affectCorrespondingSourceFiles(depClasses);
              }
              return true;
            }
          });
        }
      }

      debug("End of added classes processing.");
    }

    private void affectCorrespondingSourceFiles(TIntHashSet toAffect) {
      toAffect.forEach(new TIntProcedure() {
        @Override
        public boolean execute(int depClass) {
          final Collection<File> fNames = myClassToSourceFile.get(depClass);
          if (fNames != null) {
            for (File fName : fNames) {
              if (myFilter == null || myFilter.accept(fName)) {
                debug("Adding dependent file ", fName);
                myAffectedFiles.add(fName);
              }
            }
          }
          return true;
        }
      });
    }

    private void calculateAffectedFiles(final DiffState state) {
      debug("Checking dependent classes:");

      state.myDependants.forEach(new TIntProcedure() {
        @Override
        public boolean execute(final int depClass) {
          final Collection<File> depFiles = myClassToSourceFile.get(depClass);
          if (depFiles != null) {
            for (File depFile : depFiles) {
              processDependentFile(depClass, depFile);
            }
          }
          return true;
        }

        private void processDependentFile(int depClass, @NotNull File depFile) {
          if (myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
            return;
          }

          debug("Dependent class: ", depClass);

          final ClassRepr classRepr = getReprByName(depFile, depClass);
          if (classRepr == null) {
            return;
          }

          final Set<UsageRepr.Usage> depUsages = classRepr.getUsages();
          if (depUsages == null || depUsages.isEmpty()) {
            return;
          }

          for (UsageRepr.Usage usage : depUsages) {
            if (usage instanceof UsageRepr.AnnotationUsage) {
              for (final UsageRepr.AnnotationUsage query : state.myAnnotationQuery) {
                if (query.satisfies(usage)) {
                  debug("Added file due to annotation query");
                  myAffectedFiles.add(depFile);
                  return;
                }
              }
            }
            else if (state.myAffectedUsages.contains(usage)) {
              final Util.UsageConstraint constraint = state.myUsageConstraints.get(usage);
              if (constraint == null) {
                debug("Added file with no constraints");
                myAffectedFiles.add(depFile);
                return;
              }
              if (constraint.checkResidence(depClass)) {
                debug("Added file with satisfied constraint");
                myAffectedFiles.add(depFile);
                return;
              }
            }
          }
        }
      });
    }

    boolean differentiate() {
      synchronized (myLock) {
        myDelta.myIsDifferentiated = true;

        if (myDelta.myIsRebuild) {
          return true;
        }

        debug("Begin of Differentiate:");
        debug("Easy mode: ", myEasyMode);

        processDisappearedClasses();

        final List<FileClasses> newClasses = new ArrayList<FileClasses>();
        myDelta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
          @Override
          public boolean execute(File fileName, Collection<ClassRepr> classes) {
            newClasses.add(new FileClasses(fileName, classes));
            return true;
          }
        });

        for (final FileClasses compiledFile : newClasses) {
          final File fileName = compiledFile.myFileName;
          final Set<ClassRepr> classes = compiledFile.myFileClasses;
          final Set<ClassRepr> pastClasses = (Set<ClassRepr>)mySourceFileToClasses.get(fileName);
          final DiffState state = new DiffState(Difference.make(pastClasses, classes));

          if (!processChangedClasses(state)) {
            if (!myEasyMode) {
              // turning non-incremental
              return false;
            }
          }

          processRemovedClases(state, fileName);
          processAddedClasses(state, fileName);

          if (!myEasyMode) {
            calculateAffectedFiles(state);
          }
        }

        debug("End of Differentiate.");

        if (myEasyMode) {
          return false;
        }

        final Collection<String> removed = myDelta.myRemovedFiles;
        if (removed != null) {
          for (final String r : removed) {
            myAffectedFiles.remove(new File(r));
          }
        }
        return myDelayedWorks.doWork(myAffectedFiles);
      }
    }
  }

  public void differentiateOnRebuild(final Mappings delta) {
    new Differential(delta).differentiate();
  }

  public void differentiateOnNonIncrementalMake(final Mappings delta,
                                                final Collection<String> removed,
                                                final Collection<File> filesToCompile) {
    new Differential(delta, removed, filesToCompile).differentiate();
  }

  public boolean differentiateOnIncrementalMake
    (final Mappings delta,
     final Collection<String> removed,
     final Collection<File> filesToCompile,
     final Collection<File> compiledFiles,
     final Collection<File> affectedFiles,
     @NotNull final DependentFilesFilter filter,
     @Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
    return new Differential(delta, removed, filesToCompile, compiledFiles, affectedFiles, filter, constantSearch).differentiate();
  }

  private void cleanupBackDependency(final int className,
                                     @Nullable Set<UsageRepr.Usage> usages,
                                     final IntIntMultiMaplet buffer) {
    if (usages == null) {
      final ClassRepr repr = getReprByName(null, className);

      if (repr != null) {
        usages = repr.getUsages();
      }
    }

    if (usages != null) {
      for (final UsageRepr.Usage u : usages) {
        buffer.put(u.getOwner(), className);
      }
    }
  }

  private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, File sourceFile, final Set<UsageRepr.Usage> usages, final IntIntMultiMaplet dependenciesTrashBin) {
    final int className = cr.name;

    // it is safe to cleanup class information if it is mapped to non-existing files only
    final Collection<File> currentlyMapped = myClassToSourceFile.get(className);
    if (currentlyMapped == null || currentlyMapped.isEmpty()) {
      return;
    }
    if (currentlyMapped.size() == 1) {
      if (!FileUtil.filesEqual(sourceFile, currentlyMapped.iterator().next())) {
        // if classname is already mapped to a different source, the class with such FQ name exists elsewhere, so
        // we cannot destroy all these links
        return;
      }
    }
    else {
      // many files
      for (File file : currentlyMapped) {
        if (!FileUtil.filesEqual(sourceFile, file) && file.exists()) {
          return;
        }
      }
    }

    for (final int superSomething : cr.getSupers()) {
      delta.registerRemovedSuperClass(className, superSomething);
    }

    cleanupBackDependency(className, usages, dependenciesTrashBin);

    myClassToClassDependency.remove(className);
    myClassToSubclasses.remove(className);
    myClassToSourceFile.remove(className);
    if (!cr.isLocal() && !cr.isAnonymous()) {
      myShortClassNameIndex.removeFrom(myContext.get(cr.getShortName()), className);
    }
  }

  public void integrate(final Mappings delta) {
    synchronized (myLock) {
      try {
        assert (delta.isDifferentiated());

        final Collection<String> removed = delta.myRemovedFiles;

        delta.runPostPasses();

        final IntIntMultiMaplet dependenciesTrashBin = new IntIntTransientMultiMaplet();

        if (removed != null) {
          for (final String file : removed) {
            final File deletedFile = new File(file);
            final Set<ClassRepr> fileClasses = (Set<ClassRepr>)mySourceFileToClasses.get(deletedFile);

            if (fileClasses != null) {
              for (final ClassRepr aClass : fileClasses) {
                cleanupRemovedClass(delta, aClass, deletedFile, aClass.getUsages(), dependenciesTrashBin);
              }
              mySourceFileToClasses.remove(deletedFile);
            }
          }
        }

        if (!delta.isRebuild()) {
          for (final Pair<ClassRepr, File> pair : delta.getDeletedClasses()) {
            final ClassRepr deletedClass = pair.first;
            cleanupRemovedClass(delta, deletedClass, pair.second, deletedClass.getUsages(), dependenciesTrashBin);
          }
          for (ClassRepr repr : delta.getAddedClasses()) {
            if (!repr.isAnonymous() && !repr.isLocal()) {
              myShortClassNameIndex.put(myContext.get(repr.getShortName()), repr.name);
            }
          }

          final TIntHashSet superClasses = new TIntHashSet();
          final IntIntTransientMultiMaplet addedSuperClasses = delta.getAddedSuperClasses();
          final IntIntTransientMultiMaplet removedSuperClasses = delta.getRemovedSuperClasses();

          addAllKeys(superClasses, addedSuperClasses);
          addAllKeys(superClasses, removedSuperClasses);

          superClasses.forEach(new TIntProcedure() {
            @Override
            public boolean execute(final int superClass) {
              final TIntHashSet added = addedSuperClasses.get(superClass);
              TIntHashSet removed = removedSuperClasses.get(superClass);

              final TIntHashSet old = myClassToSubclasses.get(superClass);

              if (old == null) {
                if (added != null && !added.isEmpty()) {
                  myClassToSubclasses.replace(superClass, added);
                }
              }
              else {
                boolean changed = false;
                final int[] addedAsArray = added != null && !added.isEmpty()? added.toArray() : null;
                if (removed != null && !removed.isEmpty()) {
                  if (addedAsArray != null) {
                    // optimization: avoid unnecessary changes in the set
                    removed = (TIntHashSet)removed.clone();
                    removed.removeAll(addedAsArray);
                  }
                  if (!removed.isEmpty()) {
                    changed = old.removeAll(removed.toArray());
                  }
                }

                if (addedAsArray != null) {
                  changed |= old.addAll(addedAsArray);
                }

                if (changed) {
                  myClassToSubclasses.replace(superClass, old);
                }
              }

              return true;
            }
          });

          delta.getChangedClasses().forEach(new TIntProcedure() {
            @Override
            public boolean execute(final int className) {
              final Collection<File> sourceFiles = delta.myClassToSourceFile.get(className);
              myClassToSourceFile.replace(className, sourceFiles);

              cleanupBackDependency(className, null, dependenciesTrashBin);

              return true;
            }
          });

          delta.getChangedFiles().forEach(new TObjectProcedure<File>() {
            @Override
            public boolean execute(final File fileName) {
              final Collection<ClassRepr> classes = delta.mySourceFileToClasses.get(fileName);
              mySourceFileToClasses.replace(fileName, classes);
              return true;
            }
          });
        }
        else {
          myClassToSubclasses.putAll(delta.myClassToSubclasses);
          myClassToSourceFile.replaceAll(delta.myClassToSourceFile);
          mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses);
          delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
            public boolean execute(File src, Collection<ClassRepr> classes) {
              for (ClassRepr repr : classes) {
                if (!repr.isAnonymous() && !repr.isLocal()) {
                  myShortClassNameIndex.put(myContext.get(repr.getShortName()), repr.name);
                }
              }
              return true;
            }
          });
        }

        // updating classToClass dependencies

        final TIntHashSet affectedClasses = new TIntHashSet();

        addAllKeys(affectedClasses, dependenciesTrashBin);
        addAllKeys(affectedClasses, delta.myClassToClassDependency);

        affectedClasses.forEach(new TIntProcedure() {
          @Override
          public boolean execute(int aClass) {
            final TIntHashSet now = delta.myClassToClassDependency.get(aClass);
            final TIntHashSet toRemove = dependenciesTrashBin.get(aClass);
            final boolean hasDataToAdd = now != null && !now.isEmpty();

            if (toRemove != null && !toRemove.isEmpty()) {
              final TIntHashSet current = myClassToClassDependency.get(aClass);
              if (current != null && !current.isEmpty()) {
                final TIntHashSet before = new TIntHashSet();
                addAll(before, current);

                final boolean removed = current.removeAll(toRemove.toArray());
                final boolean added = hasDataToAdd && current.addAll(now.toArray());

                if ((removed && !added) || (!removed && added) || !before.equals(current)) {
                  myClassToClassDependency.replace(aClass, current);
                }
              }
              else {
                if (hasDataToAdd) {
                  myClassToClassDependency.put(aClass, now);
                }
              }
            }
            else {
              // nothing to remove for this class
              if (hasDataToAdd) {
                myClassToClassDependency.put(aClass, now);
              }
            }
            return true;
          }
        });
      }
      finally {
        delta.close();
      }
    }
  }

  public Callbacks.Backend getCallback() {
    return new Callbacks.Backend() {

      public void associate(String classFileName, Collection<String> sources, ClassReader cr) {
        synchronized (myLock) {
          final int classFileNameS = myContext.get(classFileName);
          final Pair<ClassRepr, Set<UsageRepr.Usage>> result = new ClassfileAnalyzer(myContext).analyze(classFileNameS, cr);
          final ClassRepr repr = result.first;
          if (repr != null) {
            final Set<UsageRepr.Usage> localUsages = result.second;
            final int className = repr.name;

            for (String sourceFileName : sources) {
              final File sourceFile = new File(sourceFileName);
              myClassToSourceFile.put(className, sourceFile);
              mySourceFileToClasses.put(sourceFile, repr);
            }

            for (final int s : repr.getSupers()) {
              myClassToSubclasses.put(s, className);
            }

            for (final UsageRepr.Usage u : localUsages) {
              final int owner = u.getOwner();

              if (owner != className) {
                myClassToClassDependency.put(owner, className);
              }
            }
          }
        }
      }

      public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
        associate(classFileName, Collections.singleton(sourceFileName), cr);
      }

      @Override
      public void registerImports(final String className, final Collection<String> imports, Collection<String> staticImports) {
        final List<String> allImports = new ArrayList<String>();
        for (String anImport : imports) {
          if (!anImport.endsWith("*")) {
            allImports.add(anImport); // filter out wildcard imports
          }
        }
        for (final String s : staticImports) {
          int i = s.length() - 1;
          for (; s.charAt(i) != '.'; i--) ;
          final String anImport = s.substring(0, i);
          if (!anImport.endsWith("*")) {
            allImports.add(anImport); // filter out wildcard imports
          }
        }

        if (!allImports.isEmpty()) {
          myPostPasses.offer(new Runnable() {
            public void run() {
              final int rootClassName = myContext.get(className.replace(".", "/"));
              final Collection<File> fileNames = myClassToSourceFile.get(rootClassName);
              final ClassRepr repr = fileNames != null && !fileNames.isEmpty()? getReprByName(fileNames.iterator().next(), rootClassName) : null;

              for (final String i : allImports) {
                final int iname = myContext.get(i.replace('.', '/'));
                myClassToClassDependency.put(iname, rootClassName);
                if (repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname))) {
                  for (File fileName : fileNames) {
                    mySourceFileToClasses.put(fileName, repr);
                  }
                }
              }
            }
          });
        }
      }
    };
  }

  @Nullable
  public Set<ClassRepr> getClasses(final String sourceFileName) {
    synchronized (myLock) {
      return (Set<ClassRepr>)mySourceFileToClasses.get(new File(sourceFileName));
    }
  }

  public void close() {
    synchronized (myLock) {
      myClassToSubclasses.close();
      myClassToClassDependency.close();
      mySourceFileToClasses.close();
      myClassToSourceFile.close();

      if (!myIsDelta) {
        myShortClassNameIndex.close();
        // only close if you own the context
        final DependencyContext context = myContext;
        if (context != null) {
          context.close();
          myContext = null;
        }
      }
      else {
        if (!myDeltaIsTransient) {
          FileUtil.delete(myRootDir);
        }
      }
    }
  }

  public void flush(final boolean memoryCachesOnly) {
    synchronized (myLock) {
      myClassToSubclasses.flush(memoryCachesOnly);
      myClassToClassDependency.flush(memoryCachesOnly);
      mySourceFileToClasses.flush(memoryCachesOnly);
      myClassToSourceFile.flush(memoryCachesOnly);

      if (!myIsDelta) {
        myShortClassNameIndex.flush(memoryCachesOnly);
        // flush if you own the context
        final DependencyContext context = myContext;
        if (context != null) {
          context.clearMemoryCaches();
          if (!memoryCachesOnly) {
            context.flush();
          }
        }
      }
    }
  }

  private static boolean addAll(final TIntHashSet whereToAdd, TIntHashSet whatToAdd) {
    if (whatToAdd.isEmpty()) {
      return false;
    }
    final Ref<Boolean> changed = new Ref<Boolean>(Boolean.FALSE);
    whatToAdd.forEach(new TIntProcedure() {
      @Override
      public boolean execute(int value) {
        if (whereToAdd.add(value)) {
          changed.set(Boolean.TRUE);
        }
        return true;
      }
    });
    return changed.get();
  }

  private static void addAllKeys(final TIntHashSet whereToAdd, final IntIntMultiMaplet maplet) {
    maplet.forEachEntry(new TIntObjectProcedure<TIntHashSet>() {
      @Override
      public boolean execute(int key, TIntHashSet b) {
        whereToAdd.add(key);
        return true;
      }
    });
  }

  private void registerAddedSuperClass(final int aClass, final int superClass) {
    assert (myAddedSuperClasses != null);
    myAddedSuperClasses.put(superClass, aClass);
  }

  private void registerRemovedSuperClass(final int aClass, final int superClass) {
    assert (myRemovedSuperClasses != null);
    myRemovedSuperClasses.put(superClass, aClass);
  }

  private boolean isDifferentiated() {
    return myIsDifferentiated;
  }

  private boolean isRebuild() {
    return myIsRebuild;
  }

  private void addDeletedClass(final ClassRepr cr, File fileName) {
    assert (myDeletedClasses != null);

    myDeletedClasses.add(Pair.create(cr, fileName));

    addChangedClass(cr.name);
  }

  private void addAddedClass(final ClassRepr cr) {
    assert (myAddedClasses != null);

    myAddedClasses.add(cr);

    addChangedClass(cr.name);
  }

  private void addChangedClass(final int it) {
    assert (myChangedClasses != null && myChangedFiles != null);
    myChangedClasses.add(it);

    final Collection<File> files = myClassToSourceFile.get(it);

    if (files != null) {
      myChangedFiles.addAll(files);
    }
  }

  @NotNull
  private Set<Pair<ClassRepr, File>> getDeletedClasses() {
    return myDeletedClasses == null ? Collections.<Pair<ClassRepr, File>>emptySet() : Collections.unmodifiableSet(myDeletedClasses);
  }

  @NotNull
  private Set<ClassRepr> getAddedClasses() {
    return myAddedClasses == null ? Collections.<ClassRepr>emptySet() : Collections.unmodifiableSet(myAddedClasses);
  }

  private TIntHashSet getChangedClasses() {
    return myChangedClasses;
  }

  private THashSet<File> getChangedFiles() {
    return myChangedFiles;
  }

  private static void debug(final String s) {
    LOG.debug(s);
  }

  private void debug(final String comment, final int s) {
    myDebugS.debug(comment, s);
  }

  private void debug(final String comment, final File f) {
    debug(comment, f.getPath());
  }

  private void debug(final String comment, final String s) {
    myDebugS.debug(comment, s);
  }

  private void debug(final String comment, final boolean s) {
    myDebugS.debug(comment, s);
  }

  public void toStream(final PrintStream stream) {
    final Streamable[] data = {
      myClassToSubclasses,
      myClassToClassDependency,
      mySourceFileToClasses,
      myClassToSourceFile,
    };

    final String[] info = {
      "ClassToSubclasses",
      "ClassToClassDependency",
      "SourceFileToClasses",
      "ClassToSourceFile",
      "SourceFileToAnnotationUsages",
      "SourceFileToUsages"
    };

    for (int i = 0; i < data.length; i++) {
      stream.print("Begin Of ");
      stream.println(info[i]);

      data[i].toStream(myContext, stream);

      stream.print("End Of ");
      stream.println(info[i]);
    }
  }

  public void toStream(File outputRoot) {
    final Streamable[] data = {
      myClassToSubclasses,
      myClassToClassDependency,
      mySourceFileToClasses,
      myClassToSourceFile,
      myShortClassNameIndex
    };

    final String[] info = {
      "ClassToSubclasses",
      "ClassToClassDependency",
      "SourceFileToClasses",
      "ClassToSourceFile",
      "ShortClassNameIndex"
    };

    for (int i = 0; i < data.length; i++) {
      final File file = new File(outputRoot, info[i]);
      FileUtil.createIfDoesntExist(file);
      try {
        final PrintStream stream = new PrintStream(file);
        try {
          data[i].toStream(myContext, stream);
        }
        finally {
          stream.close();
        }
      }
      catch (FileNotFoundException e) {
        e.printStackTrace();
      }
    }
  }
}