package com.intellij.lang.javascript.flex.projectStructure.model.impl; import com.intellij.flex.model.bc.BuildConfigurationNature; import com.intellij.flex.model.bc.OutputType; import com.intellij.flex.model.bc.TargetPlatform; import com.intellij.lang.javascript.flex.build.FlexCompilerConfigFileUtil; import com.intellij.lang.javascript.flex.build.InfoFromConfigFile; import com.intellij.flex.model.bc.CompilerOptionInfo; import com.intellij.lang.javascript.flex.projectStructure.model.*; import com.intellij.lang.javascript.flex.projectStructure.options.BCUtils; import com.intellij.lang.javascript.flex.sdk.FlexSdkUtils; import com.intellij.lang.javascript.flex.sdk.FlexmojosSdkType; import com.intellij.openapi.components.ComponentManager; import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.*; class FlexBuildConfigurationImpl implements ModifiableFlexBuildConfiguration { @NotNull private String myName = UNNAMED; @NotNull private TargetPlatform myTargetPlatform = BuildConfigurationNature.DEFAULT.targetPlatform; private boolean myPureAs = BuildConfigurationNature.DEFAULT.pureAS; @NotNull private OutputType myOutputType = BuildConfigurationNature.DEFAULT.outputType; @NotNull private String myOptimizeFor = ""; @NotNull private String myMainClass = ""; @NotNull private String myOutputFileName = ""; @NotNull private String myOutputFolder = ""; private boolean myUseHtmlWrapper = false; @NotNull private String myWrapperTemplatePath = ""; @NotNull private String myRLMs = ""; @NotNull private String myCssFilesToCompile = ""; private boolean mySkipCompile = false; private final DependenciesImpl myDependencies = new DependenciesImpl(); private final CompilerOptionsImpl myCompilerOptions = new CompilerOptionsImpl(); private final AirDesktopPackagingOptionsImpl myAirDesktopPackagingOptions = new AirDesktopPackagingOptionsImpl(); private final AndroidPackagingOptionsImpl myAndroidPackagingOptions = new AndroidPackagingOptionsImpl(); private final IosPackagingOptionsImpl myIosPackagingOptions = new IosPackagingOptionsImpl(); private boolean myTempBCForCompilation = false; @Override @NotNull public String getName() { return myName; } @Override @NotNull public TargetPlatform getTargetPlatform() { return myTargetPlatform; } @Override public boolean isPureAs() { return myPureAs; } @Override @NotNull public OutputType getOutputType() { return myOutputType; } @Override @NotNull public String getOptimizeFor() { return myOptimizeFor; } @Override @NotNull public String getMainClass() { return myMainClass; } @Override @NotNull public String getOutputFileName() { return myOutputFileName; } @Override @NotNull public String getOutputFolder() { return myOutputFolder; } @Override public boolean isUseHtmlWrapper() { return myUseHtmlWrapper; } @Override @NotNull public String getWrapperTemplatePath() { return myWrapperTemplatePath; } @Override @NotNull public Collection<RLMInfo> getRLMs() { if (myRLMs.isEmpty()) return Collections.emptyList(); final List<String> entries = StringUtil.split(myRLMs, CompilerOptionInfo.LIST_ENTRIES_SEPARATOR); final ArrayList<RLMInfo> result = new ArrayList<>(entries.size()); for (String entry : entries) { final List<String> parts = StringUtil.split(entry, CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR, true, false); assert parts.size() == 3 : entry; result.add(new FlexBuildConfiguration.RLMInfo(parts.get(0), parts.get(1), Boolean.valueOf(parts.get(2)))); } return result; } @Override @NotNull public Collection<String> getCssFilesToCompile() { if (myCssFilesToCompile.isEmpty()) return Collections.emptyList(); return StringUtil.split(myCssFilesToCompile, CompilerOptionInfo.LIST_ENTRIES_SEPARATOR); } @Override public boolean isSkipCompile() { return mySkipCompile; } @Override public void setName(@NotNull String name) { myName = name; } @Override public void setNature(BuildConfigurationNature nature) { myTargetPlatform = nature.targetPlatform; myPureAs = nature.pureAS; myOutputType = nature.outputType; } @Override public void setTargetPlatform(@NotNull TargetPlatform targetPlatform) { myTargetPlatform = targetPlatform; } @Override public void setPureAs(boolean pureAs) { myPureAs = pureAs; } @Override public void setOutputType(@NotNull OutputType outputType) { myOutputType = outputType; } @Override public void setOptimizeFor(@NotNull String optimizeFor) { myOptimizeFor = optimizeFor; } @Override public void setMainClass(@NotNull String mainClass) { myMainClass = mainClass; } @Override public void setOutputFileName(@NotNull String outputFileName) { myOutputFileName = outputFileName; } @Override public void setOutputFolder(@NotNull String outputFolder) { myOutputFolder = StringUtil.trimEnd(outputFolder, "/"); } @Override public void setUseHtmlWrapper(boolean useHtmlWrapper) { myUseHtmlWrapper = useHtmlWrapper; } @Override public void setWrapperTemplatePath(@NotNull String wrapperTemplatePath) { myWrapperTemplatePath = wrapperTemplatePath; } @Override public void setRLMs(@NotNull Collection<RLMInfo> rlms) { if (rlms.isEmpty()) myRLMs = ""; myRLMs = StringUtil.join(rlms, info -> info.MAIN_CLASS + CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR + info.OUTPUT_FILE + CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR + info.OPTIMIZE, CompilerOptionInfo.LIST_ENTRIES_SEPARATOR); } @Override public void setCssFilesToCompile(@NotNull Collection<String> cssFilesToCompile) { myCssFilesToCompile = cssFilesToCompile.isEmpty() ? "" : StringUtil.join(cssFilesToCompile, CompilerOptionInfo.LIST_ENTRIES_SEPARATOR); } @Override public void setSkipCompile(boolean skipCompile) { mySkipCompile = skipCompile; } @NotNull @Override public ModifiableDependencies getDependencies() { return myDependencies; } @NotNull @Override public CompilerOptionsImpl getCompilerOptions() { return myCompilerOptions; } @NotNull @Override public ModifiableAirDesktopPackagingOptions getAirDesktopPackagingOptions() { return myAirDesktopPackagingOptions; } @NotNull @Override public ModifiableAndroidPackagingOptions getAndroidPackagingOptions() { return myAndroidPackagingOptions; } @NotNull @Override public ModifiableIosPackagingOptions getIosPackagingOptions() { return myIosPackagingOptions; } @Override public Icon getIcon() { return getNature().getIcon(); } @Override public String getShortText() { return myName; } @Override public String getDescription() { return myOutputType.getShortText(); } @Override public String getActualOutputFilePath() { final InfoFromConfigFile info = FlexCompilerConfigFileUtil.getInfoFromConfigFile(myCompilerOptions.getAdditionalConfigFilePath()); final String outputFolderPath = BCUtils.isFlexUnitBC(this) ? myOutputFolder : StringUtil.notNullize(info.getOutputFolderPath(), myOutputFolder); final String outputFileName = myTempBCForCompilation ? myOutputFileName : StringUtil.notNullize(info.getOutputFileName(), myOutputFileName); return outputFolderPath + (outputFolderPath.isEmpty() ? "" : "/") + outputFileName; } public FlexBuildConfigurationImpl getCopy() { FlexBuildConfigurationImpl copy = new FlexBuildConfigurationImpl(); applyTo(copy); return copy; } void applyTo(FlexBuildConfigurationImpl copy) { myAirDesktopPackagingOptions.applyTo(copy.myAirDesktopPackagingOptions); myAndroidPackagingOptions.applyTo(copy.myAndroidPackagingOptions); myCompilerOptions.applyTo(copy.myCompilerOptions); myDependencies.applyTo(copy.myDependencies); myIosPackagingOptions.applyTo(copy.myIosPackagingOptions); copy.myCssFilesToCompile = myCssFilesToCompile; copy.myMainClass = myMainClass; copy.myName = myName; copy.myOptimizeFor = myOptimizeFor; copy.myOutputFileName = myOutputFileName; copy.myOutputFolder = myOutputFolder; copy.myOutputType = myOutputType; copy.myPureAs = myPureAs; copy.myRLMs = myRLMs; copy.mySkipCompile = mySkipCompile; copy.myTargetPlatform = myTargetPlatform; copy.myUseHtmlWrapper = myUseHtmlWrapper; copy.myWrapperTemplatePath = myWrapperTemplatePath; } public boolean isEqual(FlexBuildConfiguration bc) { final FlexBuildConfigurationImpl other = (FlexBuildConfigurationImpl)bc; if (!myAirDesktopPackagingOptions.isEqual(other.myAirDesktopPackagingOptions)) return false; if (!myAndroidPackagingOptions.isEqual(other.myAndroidPackagingOptions)) return false; if (!myCompilerOptions.isEqual(other.myCompilerOptions)) return false; if (!myDependencies.isEqual(other.myDependencies)) return false; if (!myIosPackagingOptions.isEqual(other.myIosPackagingOptions)) return false; if (!other.myCssFilesToCompile.equals(myCssFilesToCompile)) return false; if (!other.myMainClass.equals(myMainClass)) return false; if (!other.myName.equals(myName)) return false; if (!other.myOptimizeFor.equals(myOptimizeFor)) return false; if (!other.myOutputFileName.equals(myOutputFileName)) return false; if (!other.myOutputFolder.equals(myOutputFolder)) return false; if (other.myOutputType != myOutputType) return false; if (other.myPureAs != myPureAs) return false; if (!other.myRLMs.equals(myRLMs)) return false; if (other.mySkipCompile != mySkipCompile) return false; if (other.myTargetPlatform != myTargetPlatform) return false; if (other.myUseHtmlWrapper != myUseHtmlWrapper) return false; if (!other.myWrapperTemplatePath.equals(myWrapperTemplatePath)) return false; return true; } @Override public BuildConfigurationNature getNature() { return new BuildConfigurationNature(myTargetPlatform, myPureAs, myOutputType); } @Override @Nullable public Sdk getSdk() { final SdkEntry sdkEntry = myDependencies.getSdkEntry(); return sdkEntry == null ? null : ContainerUtil.find(FlexSdkUtils.getFlexAndFlexmojosSdks(), sdk -> sdkEntry.getName().equals(sdk.getName())); } public boolean isTempBCForCompilation() { return myTempBCForCompilation; } void setTempBCForCompilation(final boolean tempBCForCompilation) { myTempBCForCompilation = tempBCForCompilation; } @Override public String toString() { return myName + ": " + getNature().toString(); } @Override public String getStatisticsEntry() { StringBuilder s = new StringBuilder(); switch (myTargetPlatform) { case Web: s.append("Web"); break; case Desktop: s.append("Desktop"); break; case Mobile: s.append("Mobile"); if (myAndroidPackagingOptions.isEnabled() && myIosPackagingOptions.isEnabled()) { s.append("(a+i)"); } else if (myAndroidPackagingOptions.isEnabled()) { s.append("(a)"); } else if (myIosPackagingOptions.isEnabled()) { s.append("(i)"); } break; default: assert false : myTargetPlatform; } s.append(" "); s.append(myPureAs ? "AS" : "Flex"); s.append(" "); switch (myOutputType) { case Application: s.append("app"); break; case Library: s.append("lib"); break; case RuntimeLoadedModule: s.append("rlm"); break; default: assert false : myOutputType; } Sdk sdk = getSdk(); if (sdk != null && sdk.getSdkType() == FlexmojosSdkType.getInstance()) { s.append(" (mvn)"); } return s.toString(); } public FlexBuildConfigurationState getState(final @Nullable ComponentManager componentManager) { FlexBuildConfigurationState state = new FlexBuildConfigurationState(); state.AIR_DESKTOP_PACKAGING_OPTIONS = myAirDesktopPackagingOptions.getState(); state.ANDROID_PACKAGING_OPTIONS = myAndroidPackagingOptions.getState(); state.COMPILER_OPTIONS = myCompilerOptions.getState(componentManager); state.DEPENDENCIES = myDependencies.getState(); state.IOS_PACKAGING_OPTIONS = myIosPackagingOptions.getState(); state.CSS_FILES_TO_COMPILE = collapsePaths(componentManager, myCssFilesToCompile); state.MAIN_CLASS = myMainClass; state.NAME = myName; state.OPTIMIZE_FOR = myOptimizeFor; state.OUTPUT_FILE_NAME = myOutputFileName; state.OUTPUT_FOLDER = myOutputFolder; state.OUTPUT_TYPE = myOutputType; state.PURE_ACTION_SCRIPT = myPureAs; state.RLMS = myRLMs; state.SKIP_COMPILE = mySkipCompile; state.TARGET_PLATFORM = myTargetPlatform; state.USE_HTML_WRAPPER = myUseHtmlWrapper; state.WRAPPER_TEMPLATE_PATH = myWrapperTemplatePath; return state; } public void loadState(final FlexBuildConfigurationState state, final Project project) { myAirDesktopPackagingOptions.loadState(state.AIR_DESKTOP_PACKAGING_OPTIONS); myAndroidPackagingOptions.loadState(state.ANDROID_PACKAGING_OPTIONS); myCompilerOptions.loadState(state.COMPILER_OPTIONS); myDependencies.loadState(state.DEPENDENCIES, project); myIosPackagingOptions.loadState(state.IOS_PACKAGING_OPTIONS); // no need in expanding paths, it is done automatically even if macros is not in the beginning of the string myCssFilesToCompile = state.CSS_FILES_TO_COMPILE; myMainClass = state.MAIN_CLASS; myName = state.NAME; myOptimizeFor = state.OPTIMIZE_FOR; myOutputFileName = state.OUTPUT_FILE_NAME; myOutputFolder = StringUtil.trimEnd(state.OUTPUT_FOLDER, "/"); myOutputType = state.OUTPUT_TYPE; myPureAs = state.PURE_ACTION_SCRIPT; myRLMs = state.RLMS; mySkipCompile = state.SKIP_COMPILE; myTargetPlatform = state.TARGET_PLATFORM; myUseHtmlWrapper = state.USE_HTML_WRAPPER; myWrapperTemplatePath = state.WRAPPER_TEMPLATE_PATH; } static String collapsePaths(final @Nullable ComponentManager componentManager, final String value) { if (componentManager == null) return value; if (!value.contains(CompilerOptionInfo.LIST_ENTRIES_SEPARATOR) && !value.contains(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR)) { return value; } final StringBuilder result = new StringBuilder(); final PathMacroManager pathMacroManager = PathMacroManager.getInstance(componentManager); final String delimiters = CompilerOptionInfo.LIST_ENTRIES_SEPARATOR + CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR; for (StringTokenizer tokenizer = new StringTokenizer(value, delimiters, true); tokenizer.hasMoreTokens(); ) { String token = tokenizer.nextToken(); if (token.length() > 1) { token = pathMacroManager.collapsePath(token); } result.append(token); } return result.toString(); } }