package com.google.jstestdriver.idea.assertFramework.library;
import com.intellij.lang.javascript.library.JSLibraryManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.webcore.ScriptingFrameworkDescriptor;
import com.intellij.webcore.libraries.ScriptingLibraryModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
/**
* @author Sergey Simonchik
*/
public class JsLibraryHelper {
private static final Logger LOG = Logger.getInstance(JsLibraryHelper.class);
private final List<VirtualFile> myLibraryFiles;
private final JSLibraryManager myJsLibraryManager;
private final String myAvailableLibraryName;
private final ScriptingLibraryModel myReusableJsLibraryModel;
public JsLibraryHelper(@NotNull Project project,
@NotNull String desiredLibraryName,
@NotNull List<VirtualFile> libraryFiles,
@NotNull ScriptingFrameworkDescriptor frameworkDescriptor) {
myJsLibraryManager = ServiceManager.getService(project, JSLibraryManager.class);
myAvailableLibraryName = findAvailableJsLibraryName(desiredLibraryName);
myLibraryFiles = libraryFiles;
myReusableJsLibraryModel = findReusableJavaScriptLibraryModel(myJsLibraryManager,
desiredLibraryName,
libraryFiles,
frameworkDescriptor);
}
@Nullable
private static ScriptingLibraryModel findReusableJavaScriptLibraryModel(@NotNull JSLibraryManager jsLibraryManager,
@NotNull String desiredLibraryName,
@NotNull List<VirtualFile> expectedSourceFiles,
@NotNull ScriptingFrameworkDescriptor frameworkDescriptor) {
ScriptingLibraryModel[] libraryModels = jsLibraryManager.getAllLibraries();
for (ScriptingLibraryModel libraryModel : libraryModels) {
if (libraryModel != null) {
ScriptingFrameworkDescriptor libraryFrameworkDescriptor = libraryModel.getFrameworkDescriptor();
if (libraryFrameworkDescriptor != null) {
String libraryFrameworkName = libraryFrameworkDescriptor.getFrameworkName();
if (libraryFrameworkName != null && libraryFrameworkName.equals(frameworkDescriptor.getFrameworkName())) {
return libraryModel;
}
}
else if (StringUtil.startsWith(libraryModel.getName(), desiredLibraryName)) {
if (scriptingLibraryModelConsistsOf(libraryModel, expectedSourceFiles)) {
return libraryModel;
}
}
}
}
return null;
}
private static boolean scriptingLibraryModelConsistsOf(@NotNull ScriptingLibraryModel libraryModel,
@NotNull Collection<VirtualFile> expectedSourceFiles) {
if (!isEmpty(libraryModel.getDocUrls()) || !isEmpty(libraryModel.getCompactFiles())) {
return false;
}
Collection<VirtualFile> sourceFiles = libraryModel.getSourceFiles();
if (sourceFiles.size() != expectedSourceFiles.size()) {
return false;
}
for (VirtualFile sourceFile : sourceFiles) {
boolean found = false;
for (VirtualFile expected : expectedSourceFiles) {
if (sourceFile.getName().equals(expected.getName())) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
public boolean hasReusableLibraryModel() {
return myReusableJsLibraryModel != null;
}
private static <E> boolean isEmpty(@Nullable Collection<E> collection) {
return collection == null || collection.isEmpty();
}
@NotNull
public String findAvailableJsLibraryName(@NotNull String initialLibraryName) {
myJsLibraryManager.reset();
String libraryName = initialLibraryName;
boolean available = myJsLibraryManager.getLibraryByName(libraryName) == null;
int id = 1;
while (!available) {
libraryName = initialLibraryName + " #" + id;
available = myJsLibraryManager.getLibraryByName(libraryName) == null;
id++;
}
return libraryName;
}
public boolean doesJavaScriptLibraryModelExist(@NotNull String libraryName) {
return myJsLibraryManager.getLibraryByName(libraryName) != null;
}
@NotNull
public String getJsLibraryName() {
if (myReusableJsLibraryModel != null) {
return myReusableJsLibraryModel.getName();
}
return myAvailableLibraryName;
}
@NotNull
public ScriptingLibraryModel getOrCreateJsLibraryModel(@NotNull String libraryName) {
if (myReusableJsLibraryModel != null) {
return myReusableJsLibraryModel;
}
ScriptingLibraryModel libraryModel = myJsLibraryManager.createLibrary(
libraryName,
VfsUtilCore.toVirtualFileArray(myLibraryFiles),
VirtualFile.EMPTY_ARRAY,
ArrayUtil.EMPTY_STRING_ARRAY,
ScriptingLibraryModel.LibraryLevel.GLOBAL,
false
);
LOG.info("JavaScript library '" + libraryModel.getName() + "' has been successfully created.");
return libraryModel;
}
public void commit() {
myJsLibraryManager.commitChanges();
}
}