CodeOrchestraStreamHandler(
      SModelDescriptor modelDescriptor,
      IFile outputDir,
      CodeOrchestraGenerationFileProcessor processor) {
    myOriginalOutputDir = outputDir;

    CodeOrchestraGenerateManager codeOrchestraGenerateManager =
        processor.getProject().getComponent(CodeOrchestraGenerateManager.class);
    CodeOrchestraGenerationContext currentContext =
        codeOrchestraGenerateManager.getCurrentContext();
    if (currentContext == null) {
      myOutputDir = outputDir;
      myCachesOutputDir = FileGenerationUtil.getCachesDir(outputDir);
    } else {
      ModuleReference rootModuleReference = currentContext.getRootModule();

      // We override the output path for the AS & JS modules
      if (currentContext.isSingleOutputContext()) {
        IModule rootModule = MPSModuleRepository.getInstance().getModule(rootModuleReference);
        myOutputDir =
            FileSystem.getInstance().getFileByPath(rootModule.getOutputFor(modelDescriptor));
        myCachesOutputDir = FileGenerationUtil.getCachesDir(myOutputDir);
      } else {
        myOutputDir = outputDir;
        myCachesOutputDir = FileGenerationUtil.getCachesDir(outputDir);
      }
    }

    myModelDescriptor = modelDescriptor;
    myProcessor = processor;
  }
  private IFile fileForContent(String name, boolean isCache) {
    // RE-3090
    // RE-3635
    if (name.endsWith(TraceInfoCache.TRACE_FILE_NAME)) {
      // RE-3103
      if (myOriginalOutputDir instanceof IdeaFile) {
        IdeaFile originalOutputDirIdeaFile = (IdeaFile) myOriginalOutputDir;
        if (!originalOutputDirIdeaFile.isPackaged()) {
          return FileGenerationUtil.getDefaultOutputDir(myModelDescriptor, myOriginalOutputDir)
              .getDescendant(name);
        }
      }
    }

    IFile outputRootDir = isCache ? myCachesOutputDir : myOutputDir;

    CodeOrchestraGenerateManager codeOrchestraGenerateManager =
        myProcessor.getProject().getComponent(CodeOrchestraGenerateManager.class);
    CodeOrchestraGenerationContext currentContext =
        codeOrchestraGenerateManager.getCurrentContext();
    if (currentContext != null) {
      String fqName =
          NameUtil.longNameFromNamespaceAndShortName(
              myModelDescriptor.getLongName(), getRootNameFromFileName(name));
      if (fqName != null) {
        FileOverrideWrapper customMapping = currentContext.getCustomFileFqNameMapping(fqName);
        if (customMapping != null) {
          return FileGenerationUtil.getDefaultOutputDir(
                  NameUtil.namespaceFromLongName(customMapping.getTargetFqName()), outputRootDir)
              .getDescendant(
                  NameUtil.shortNameFromLongName(customMapping.getTargetFqName())
                      + customMapping.getExtension());
        }
      }
    }

    return FileGenerationUtil.getDefaultOutputDir(myModelDescriptor, outputRootDir)
        .getDescendant(name);
  }
  @Override
  public void dispose() {
    CodeOrchestraGenerateManager codeOrchestraGenerateManager =
        myProcessor.getProject().getComponent(CodeOrchestraGenerateManager.class);
    CodeOrchestraGenerationContext currentContext =
        codeOrchestraGenerateManager.getCurrentContext();

    List<String> relativeAssetsPaths;
    if (currentContext == null) {
      relativeAssetsPaths = Collections.emptyList();
    } else {
      relativeAssetsPaths = currentContext.getRelativeAssetsPaths();
    }

    Set<IFile> directories = new HashSet<IFile>();

    // RF-826
    // directories.add(myOutputDir);

    directories.add(myCachesOutputDir);
    for (IFile f : mySavedFiles) {
      // RE-3231
      if (f instanceof IdeaFile) {
        IdeaFile ideaFile = (IdeaFile) f;
        // RE-3635
        if (ideaFile.getName().endsWith(TraceInfoCache.TRACE_FILE_NAME)) {
          continue;
        }
      }
      directories.add(f.getParent());
    }

    // clear garbage
    final List<IFile> filesToDelete = new ArrayList<IFile>();
    for (IFile dir : directories) {
      for (IFile outputDirectoryFile : dir.getChildren()) {
        if (outputDirectoryFile.isDirectory()) continue;
        if (mySavedFiles.contains(outputDirectoryFile)) continue;

        if (outputDirectoryFile instanceof IdeaFile) {
          IdeaFile ideaFile = (IdeaFile) outputDirectoryFile;

          // Ignore assets
          for (String relativeAssetsPath : relativeAssetsPaths) {
            if (ideaFile.getPath().endsWith(relativeAssetsPath)) {
              continue;
            }
          }

          // Ignore debug file
          if (ASDebugGenFile.FILE_NAME.equals(ideaFile.getName())) {
            continue;
          }

          // Ignore generated model digest file
          if (ideaFile.getName().endsWith(".generated")) {
            continue;
          }
        }

        filesToDelete.add(outputDirectoryFile);
      }
    }

    myProcessor.filesToDelete(filesToDelete);
    myProcessor.invalidateModel(myModelDescriptor);
  }