public static File getOrCreateConfigFile(
      final JpsFlexBuildConfiguration bc, final ProjectDescriptor projectDescriptor)
      throws IOException {
    final CompilerConfigGeneratorRt generator =
        new CompilerConfigGeneratorRt(
            bc,
            bc.getModule().getProperties().getModuleLevelCompilerOptions(),
            JpsFlexProjectLevelCompilerOptionsExtension.getProjectLevelCompilerOptions(
                bc.getModule().getProject()),
            projectDescriptor);
    String text = generator.generateConfigFileText();

    if (bc.isTempBCForCompilation()) {
      final JpsFlexBuildConfiguration originalBC =
          bc.getModule().getProperties().findConfigurationByName(bc.getName());
      final boolean makeExternalLibsMerged =
          FlexCommonUtils.isFlexUnitBC(bc)
              || (originalBC != null && originalBC.getOutputType() == OutputType.Library);
      final boolean makeIncludedLibsMerged = FlexCommonUtils.isRuntimeStyleSheetBC(bc);
      text =
          FlexCompilerConfigFileUtilBase.mergeWithCustomConfigFile(
              text,
              bc.getCompilerOptions().getAdditionalConfigFilePath(),
              makeExternalLibsMerged,
              makeIncludedLibsMerged);
    }

    final String name = getConfigFileName(bc, FlexCommonUtils.getBCSpecifier(bc));
    return getOrCreateConfigFile(name, text);
  }
 private static String getConfigFileName(
     final JpsFlexBuildConfiguration bc, final @Nullable String postfix) {
   final String prefix = "idea"; // PlatformUtils.getPlatformPrefix().toLowerCase()
   final String hash1 =
       Integer.toHexString(
               (SystemProperties.getUserName() + bc.getModule().getProject().getName()).hashCode())
           .toUpperCase();
   final String hash2 =
       Integer.toHexString(
               (bc.getModule().getName() + StringUtil.notNullize(bc.getName())).hashCode())
           .toUpperCase();
   return prefix
       + "-"
       + hash1
       + "-"
       + hash2
       + (postfix == null ? ".xml" : ("-" + StringUtil.replaceChar(postfix, ' ', '-') + ".xml"));
 }
  /**
   * @param forcedDebugStatus <code>true</code> or <code>false</code> means that this bc is compiled
   *     for further packaging and we need swf to have corresponding debug status; <code>null</code>
   *     means that bc is compiled as is (i.e. as configured) without any modifications
   */
  @NotNull
  public static FlexBuildTarget create(
      final @NotNull JpsFlexBuildConfiguration bc, final @Nullable Boolean forcedDebugStatus) {
    final String id =
        FlexCommonUtils.getBuildTargetId(bc.getModule().getName(), bc.getName(), forcedDebugStatus);

    if (forcedDebugStatus == null) {
      return new FlexBuildTarget(bc, id);
    } else {
      // must not use getTemporaryCopyForCompilation() here because additional config file must not
      // be merged with the generated one when compiling swf for release or AIR package
      final JpsFlexBuildConfiguration bcCopy = bc.getModule().getProperties().createCopy(bc);
      final String additionalOptions =
          FlexCommonUtils.removeOptions(
              bc.getCompilerOptions().getAdditionalOptions(), "debug", "compiler.debug");
      bcCopy
          .getCompilerOptions()
          .setAdditionalOptions(additionalOptions + " -debug=" + forcedDebugStatus.toString());
      return new FlexBuildTarget(bcCopy, id);
    }
  }
 private CompilerConfigGeneratorRt(
     final @NotNull JpsFlexBuildConfiguration bc,
     final @NotNull JpsFlexModuleOrProjectCompilerOptions moduleLevelCompilerOptions,
     final @NotNull JpsFlexModuleOrProjectCompilerOptions projectLevelCompilerOptions,
     final @NotNull ProjectDescriptor projectDescriptor)
     throws IOException {
   myProjectDescriptor = projectDescriptor;
   myModule = bc.getModule();
   myBC = bc;
   myFlexUnit = FlexCommonUtils.isFlexUnitBC(myBC);
   myCSS = FlexCommonUtils.isRuntimeStyleSheetBC(bc);
   mySdk = bc.getSdk();
   if (mySdk == null) {
     throw new IOException(
         FlexCommonBundle.message(
             "sdk.not.set.for.bc.0.of.module.1", bc.getName(), bc.getModule().getName()));
   }
   myFlexmojos = mySdk.getSdkType() == JpsFlexmojosSdkType.INSTANCE;
   myModuleLevelCompilerOptions = moduleLevelCompilerOptions;
   myProjectLevelCompilerOptions = projectLevelCompilerOptions;
 }
  public void writeConfiguration(ProjectDescriptor pd, final PrintWriter out) {
    out.println("id: " + myId);

    out.println(
        JDOMUtil.writeElement(XmlSerializer.serialize(JpsFlexBCState.getState(myBC)), "\n"));

    final JpsFlexModuleOrProjectCompilerOptions moduleOptions =
        myBC.getModule().getProperties().getModuleLevelCompilerOptions();
    out.println(
        JDOMUtil.writeElement(
            XmlSerializer.serialize(((JpsFlexCompilerOptionsImpl) moduleOptions).getState()),
            "\n"));

    final JpsFlexModuleOrProjectCompilerOptions projectOptions =
        JpsFlexProjectLevelCompilerOptionsExtension.getProjectLevelCompilerOptions(
            myBC.getModule().getProject());
    out.println(
        JDOMUtil.writeElement(
            XmlSerializer.serialize(((JpsFlexCompilerOptionsImpl) projectOptions).getState()),
            "\n"));
  }
  @Nullable
  private static String getCustomLinkReportPath(final JpsFlexBuildConfiguration rlmBC) {
    final JpsFlexBuildConfiguration appBC =
        rlmBC.getModule().getProperties().findConfigurationByName(rlmBC.getName());
    if (appBC != null) {
      final List<String> linkReports =
          FlexCommonUtils.getOptionValues(
              appBC.getCompilerOptions().getAdditionalOptions(), "link-report");
      if (!linkReports.isEmpty()) {
        final String path = linkReports.get(0);
        if (new File(path).isFile()) return path;
        final String absPath =
            FlexCommonUtils.getFlexCompilerWorkDirPath(appBC.getModule().getProject()) + "/" + path;
        if (new File(absPath).isFile()) return absPath;
      } else {
        final String configFilePath = appBC.getCompilerOptions().getAdditionalConfigFilePath();
        if (!configFilePath.isEmpty()) {
          final File configFile = new File(configFilePath);
          if (configFile.isFile()) {
            final String path =
                FlexCommonUtils.findXMLElement(configFile, "<flex-config><link-report>");
            if (path != null) {
              if (new File(path).isFile()) return path;
              // I have no idea why Flex compiler treats path relative to source root for
              // "link-report" option
              for (JpsModuleSourceRoot srcRoot :
                  appBC.getModule().getSourceRoots(JavaSourceRootType.SOURCE)) {
                final String absPath = srcRoot.getFile().getPath() + "/" + path;
                if (new File(absPath).isFile()) return absPath;
              }
            }
          }
        }
      }
    }

    return null;
  }
  public Collection<BuildTarget<?>> computeDependencies(
      BuildTargetRegistry targetRegistry, TargetOutputIndex outputIndex) {
    final ArrayList<BuildTarget<?>> result = new ArrayList<BuildTarget<?>>();

    final FlexResourceBuildTargetType type =
        FlexCommonUtils.isFlexUnitBC(myBC)
            ? FlexResourceBuildTargetType.TEST
            : FlexResourceBuildTargetType.PRODUCTION;
    result.add(new FlexResourceBuildTarget(type, myBC.getModule()));

    for (JpsFlexDependencyEntry entry : myBC.getDependencies().getEntries()) {
      if (entry instanceof JpsFlexBCDependencyEntry) {
        final JpsFlexBuildConfiguration dependencyBC = ((JpsFlexBCDependencyEntry) entry).getBC();
        if (dependencyBC != null) {
          result.add(create(dependencyBC, null));
        }
      }
    }
    result.trimToSize();
    return result;
  }
 @NotNull
 public String getPresentableName() {
   return FlexCommonBundle.message("bc.0.module.1", myBC.getName(), myBC.getModule().getName());
 }
  @NotNull
  public List<BuildRootDescriptor> computeRootDescriptors(
      final JpsModel model,
      final ModuleExcludeIndex index,
      final IgnoredFileIndex ignoredFileIndex,
      final BuildDataPaths dataPaths) {
    final List<BuildRootDescriptor> result = new ArrayList<BuildRootDescriptor>();

    final Collection<File> srcRoots = new ArrayList<File>();

    for (JpsModuleSourceRoot sourceRoot :
        myBC.getModule().getSourceRoots(JavaSourceRootType.SOURCE)) {
      final File root = JpsPathUtil.urlToFile(sourceRoot.getUrl());
      result.add(new FlexSourceRootDescriptor(this, root));
      srcRoots.add(root);
    }

    if (FlexCommonUtils.isFlexUnitBC(myBC)) {
      for (JpsModuleSourceRoot sourceRoot :
          myBC.getModule().getSourceRoots(JavaSourceRootType.TEST_SOURCE)) {
        final File root = JpsPathUtil.urlToFile(sourceRoot.getUrl());
        result.add(new FlexSourceRootDescriptor(this, root));
        srcRoots.add(root);
      }
    }

    for (final JpsFlexDependencyEntry entry : myBC.getDependencies().getEntries()) {
      if (entry instanceof JpsFlexBCDependencyEntry) {
        final JpsFlexBuildConfiguration dependencyBC = ((JpsFlexBCDependencyEntry) entry).getBC();
        if (dependencyBC != null) {
          result.add(
              new FlexSourceRootDescriptor(this, new File(dependencyBC.getActualOutputFilePath())));
        }
      } else if (entry instanceof JpsLibraryDependencyEntry) {
        final JpsLibrary library = ((JpsLibraryDependencyEntry) entry).getLibrary();
        if (library != null) {
          for (String rootUrl : library.getRootUrls(JpsOrderRootType.COMPILED)) {
            result.add(new FlexSourceRootDescriptor(this, JpsPathUtil.urlToFile(rootUrl)));
          }
        }
      }
    }

    final BuildConfigurationNature nature = myBC.getNature();

    if (nature.isWebPlatform()
        && nature.isApp()
        && myBC.isUseHtmlWrapper()
        && !myBC.getWrapperTemplatePath().isEmpty()) {
      addIfNotUnderRoot(result, new File(myBC.getWrapperTemplatePath()), srcRoots);
    }

    if (FlexCommonUtils.canHaveRLMsAndRuntimeStylesheets(myBC)) {
      for (String cssPath : myBC.getCssFilesToCompile()) {
        if (!cssPath.isEmpty()) {
          addIfNotUnderRoot(result, new File(cssPath), srcRoots);
        }
      }
    }

    if (!myBC.getCompilerOptions().getAdditionalConfigFilePath().isEmpty()) {
      addIfNotUnderRoot(
          result, new File(myBC.getCompilerOptions().getAdditionalConfigFilePath()), srcRoots);
    }

    if (nature.isApp()) {
      if (nature.isDesktopPlatform()) {
        addAirDescriptorPathIfCustom(result, myBC.getAirDesktopPackagingOptions(), srcRoots);
      } else if (nature.isMobilePlatform()) {
        if (myBC.getAndroidPackagingOptions().isEnabled()) {
          addAirDescriptorPathIfCustom(result, myBC.getAndroidPackagingOptions(), srcRoots);
        }
        if (myBC.getIosPackagingOptions().isEnabled()) {
          addAirDescriptorPathIfCustom(result, myBC.getIosPackagingOptions(), srcRoots);
        }
      }
    }

    return result;
  }