package com.intellij.lang.javascript.flex.projectStructure.conversion;
import com.intellij.conversion.CannotConvertException;
import com.intellij.conversion.ConversionContext;
import com.intellij.conversion.ModuleSettings;
import com.intellij.facet.impl.invalid.InvalidFacetManagerImpl;
import com.intellij.facet.impl.invalid.InvalidFacetType;
import com.intellij.facet.pointers.FacetPointersManager;
import com.intellij.flex.model.bc.BuildConfigurationNature;
import com.intellij.flex.model.bc.OutputType;
import com.intellij.lang.javascript.flex.build.FlexBuildConfiguration;
import com.intellij.lang.javascript.flex.library.FlexLibraryType;
import com.intellij.lang.javascript.flex.projectStructure.model.impl.FlexBuildConfigurationManagerImpl;
import com.intellij.lang.javascript.flex.sdk.FlexSdkType2;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.roots.impl.libraries.ApplicationLibraryTable;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.util.Pair;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.serialization.JDomSerializationUtil;
import org.jetbrains.jps.model.serialization.facet.JpsFacetSerializer;
import java.util.*;
public class ConversionParams {
public static final String OLD_FLEX_SDK_TYPE_NAME = "Flex SDK Type";
public static final String OLD_AIR_SDK_TYPE_NAME = "AIR SDK Type";
public static final String OLD_AIR_MOBIE_SDK_TYPE_NAME = "AIR Mobile SDK Type";
public static final String[] OLD_SDKS_TYPES = new String[]{OLD_FLEX_SDK_TYPE_NAME, OLD_AIR_SDK_TYPE_NAME, OLD_AIR_MOBIE_SDK_TYPE_NAME};
public String projectSdkName;
private final Collection<Pair<String, String>> myAppModuleAndBCNames = new ArrayList<>();
private final ConversionContext myContext;
private final Collection<String> myFacetsToIgnore = new HashSet<>();
private Collection<String> myProjectLibrariesNames;
private Set<String> myProjectLibrariesToMakeFlex = new HashSet<>();
public ConversionParams(ConversionContext context) {
myContext = context;
}
public void ignoreInvalidFacet(String moduleName, String type, String name) {
// this facet will be of type 'invalid'
myFacetsToIgnore.add(FacetPointersManager.constructId(moduleName, InvalidFacetType.TYPE_ID.toString(), name));
}
public void apply() throws CannotConvertException {
ignoreInvalidFacets();
}
private void ignoreInvalidFacets() throws CannotConvertException {
if (!myFacetsToIgnore.isEmpty()) {
Element invalidFacetManager = JDomSerializationUtil.findOrCreateComponentElement(myContext.getWorkspaceSettings().getRootElement(),
InvalidFacetManagerImpl.COMPONENT_NAME);
InvalidFacetManagerImpl.InvalidFacetManagerState state =
XmlSerializer.deserialize(invalidFacetManager, InvalidFacetManagerImpl.InvalidFacetManagerState.class);
state.getIgnoredFacets().addAll(myFacetsToIgnore);
XmlSerializer.serializeInto(state, invalidFacetManager);
}
}
public boolean libraryExists(final String libraryName, final String libraryLevel) throws CannotConvertException {
if (LibraryTablesRegistrar.APPLICATION_LEVEL.equals(libraryLevel)) {
final LibraryEx library = (LibraryEx)ApplicationLibraryTable.getApplicationTable().getLibraryByName(libraryName);
return library != null && isApplicableLibrary(library);
}
else if (LibraryTablesRegistrar.PROJECT_LEVEL.equals(libraryLevel)) {
return myProjectLibrariesNames.contains(libraryName);
}
else {
return false;
}
}
public String expandPath(final String path) {
return myContext.expandPath(path);
}
// keep old Flex SDKs for now, after IDEA 11.1 release we may decide to delete them
public static void convertFlexSdks() {
final ProjectJdkTable sdkTable = ProjectJdkTable.getInstance();
final Sdk[] allSdks = sdkTable.getAllJdks();
final FlexSdkType2 newSdkType = FlexSdkType2.getInstance();
Map<String, Sdk> homePathToNewSdk = new HashMap<>();
Collection<Sdk> sdksToAdd = new ArrayList<>();
for (Sdk sdk : allSdks) {
if (sdk.getSdkType() == newSdkType && sdk.getHomePath() != null) {
homePathToNewSdk.put(sdk.getHomePath(), sdk);
}
}
for (Sdk sdk : allSdks) {
if (!ArrayUtil.contains(sdk.getSdkType().getName(), OLD_SDKS_TYPES)) {
continue;
}
final String version = sdk.getVersionString();
if (version == null || (!version.startsWith("3.") && !version.startsWith("4."))) {
// ignore corrupt SDK
continue;
}
final String homePath = sdk.getHomePath();
if (homePath == null) {
continue;
}
if (homePathToNewSdk.containsKey(homePath)) {
continue;
}
String newSdkName = SdkConfigurationUtil.createUniqueSdkName(newSdkType, homePath, Arrays.asList(allSdks));
Sdk newSdk = new ProjectJdkImpl(newSdkName, newSdkType, homePath, "");
newSdkType.setupSdkPaths(newSdk);
sdksToAdd.add(newSdk);
homePathToNewSdk.put(homePath, newSdk);
}
WriteAction.run(() -> {
for (Sdk sdk : sdksToAdd) {
sdkTable.addJdk(sdk);
}
});
}
private static boolean isApplicableLibrary(final LibraryEx library) {
return library.getKind() == null || library.getKind() == FlexLibraryType.FLEX_LIBRARY;
}
public void changeLibraryTypeToFlex(final String libraryName, final String libraryLevel) throws CannotConvertException {
if (LibraryTablesRegistrar.APPLICATION_LEVEL.equals(libraryLevel)) {
final Library library = ApplicationLibraryTable.getApplicationTable().getLibraryByName(libraryName);
final LibraryEx.ModifiableModelEx model = (LibraryEx.ModifiableModelEx)library.getModifiableModel();
model.setKind(FlexLibraryType.FLEX_LIBRARY);
ApplicationManager.getApplication().runWriteAction(() -> model.commit());
}
else {
myProjectLibrariesToMakeFlex.add(libraryName);
}
}
public void setProjectLibrariesNames(final Collection<String> librariesNames) {
myProjectLibrariesNames = librariesNames;
}
public Set<String> getProjectLibrariesToMakeFlex() {
return myProjectLibrariesToMakeFlex;
}
@Nullable
public static Sdk findNewSdk(@NotNull final String homePath) {
final List<Sdk> sdks = ProjectJdkTable.getInstance().getSdksOfType(FlexSdkType2.getInstance());
return ContainerUtil.find(sdks, sdk -> homePath.equals(sdk.getHomePath()));
}
/**
* Run configurations will be created for these BCs
*/
void addAppModuleAndBCName(final String moduleName, final String bcName) {
myAppModuleAndBCNames.add(Pair.create(moduleName, bcName));
}
public Collection<Pair<String, String>> getAppModuleAndBCNames() {
return myAppModuleAndBCNames;
}
public Collection<String> getBcNamesForDependency(String moduleName, final BuildConfigurationNature dependantNature) {
ModuleSettings moduleSettings = myContext.getModuleSettings(moduleName);
if (moduleSettings == null) return Collections.emptyList(); // module is missing
if (FlexModuleConverter.isFlexModule(moduleSettings)) {
Element flexBuildConfigurationElement = moduleSettings.getComponentElement(FlexBuildConfiguration.COMPONENT_NAME);
if (flexBuildConfigurationElement != null) {
FlexBuildConfiguration oldConfiguration = XmlSerializer.deserialize(flexBuildConfigurationElement, FlexBuildConfiguration.class);
if (FlexBuildConfiguration.LIBRARY.equals(oldConfiguration.OUTPUT_TYPE)) {
return Collections.singletonList(FlexModuleConverter.generateModuleBcName(moduleSettings));
}
}
else {
// this module might have already been processed
Element buildConfigManagerElement = moduleSettings.getComponentElement(FlexBuildConfigurationManagerImpl.COMPONENT_NAME);
if (buildConfigManagerElement != null) {
FlexBuildConfigurationManagerImpl.State s =
XmlSerializer.deserialize(buildConfigManagerElement, FlexBuildConfigurationManagerImpl.State.class);
return ContainerUtil.mapNotNull(s.CONFIGURATIONS, bcState -> bcState.OUTPUT_TYPE == OutputType.Library ? bcState.NAME : null);
}
}
return Collections.emptyList();
}
final List<Element> facets = FlexModuleConverter.getFlexFacets(moduleSettings);
return ContainerUtil.mapNotNull(facets, facet -> {
Element oldConfigurationElement = facet.getChild(JpsFacetSerializer.CONFIGURATION_TAG);
if (oldConfigurationElement != null) {
FlexBuildConfiguration oldConfiguration = XmlSerializer.deserialize(oldConfigurationElement, FlexBuildConfiguration.class);
if (FlexBuildConfiguration.LIBRARY.equals(oldConfiguration.OUTPUT_TYPE)) {
return FlexModuleConverter.generateFacetBcName(facets, facet);
}
}
return null;
});
}
}